Bug Summary

File:dev/pci/if_iwn.c
Warning:line 439, column 7
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name if_iwn.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/if_iwn.c
1/* $OpenBSD: if_iwn.c,v 1.260 2022/06/19 18:27:06 stsp 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
319const struct 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_NET0x4, 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) {
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
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(0x4);
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->rxon.flags &= ~htole32(IWN_RXON_HT_CHANMODE_MIXED2040 |((__uint32_t)((2 << 25) | (1 << 25) | (1 <<
22)))
1825 IWN_RXON_HT_CHANMODE_PURE40 | IWN_RXON_HT_HT40MINUS)((__uint32_t)((2 << 25) | (1 << 25) | (1 <<
22)))
;
1826 sc->calib.state = IWN_CALIB_STATE_INIT0;
1827 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
1828 if (error != 0)
1829 printf("%s: RXON command failed\n",
1830 sc->sc_dev.dv_xname);
1831 }
1832
1833 switch (nstate) {
1834 case IEEE80211_S_SCAN:
1835 /* Make the link LED blink while we're scanning. */
1836 iwn_set_led(sc, IWN_LED_LINK2, 10, 10);
1837
1838 if ((sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9)) == 0) {
1839 ieee80211_set_link_state(ic, LINK_STATE_DOWN2);
1840 ieee80211_node_cleanup(ic, ic->ic_bss);
1841 }
1842 if (ifp->if_flags & IFF_DEBUG0x4)
1843 printf("%s: %s -> %s\n", ifp->if_xname,
1844 ieee80211_state_name[ic->ic_state],
1845 ieee80211_state_name[nstate]);
1846 ic->ic_state = nstate;
1847 if ((error = iwn_scan(sc, IEEE80211_CHAN_2GHZ0x0080, 0)) != 0) {
1848 printf("%s: could not initiate scan\n",
1849 sc->sc_dev.dv_xname);
1850 }
1851 return error;
1852
1853 case IEEE80211_S_ASSOC:
1854 if (ic->ic_state != IEEE80211_S_RUN)
1855 break;
1856 /* FALLTHROUGH */
1857 case IEEE80211_S_AUTH:
1858 if ((error = iwn_auth(sc, arg)) != 0) {
1859 printf("%s: could not move to auth state\n",
1860 sc->sc_dev.dv_xname);
1861 return error;
1862 }
1863 break;
1864
1865 case IEEE80211_S_RUN:
1866 if ((error = iwn_run(sc)) != 0) {
1867 printf("%s: could not move to run state\n",
1868 sc->sc_dev.dv_xname);
1869 return error;
1870 }
1871 break;
1872
1873 case IEEE80211_S_INIT:
1874 sc->calib.state = IWN_CALIB_STATE_INIT0;
1875 break;
1876 }
1877
1878 return sc->sc_newstate(ic, nstate, arg);
1879}
1880
1881void
1882iwn_iter_func(void *arg, struct ieee80211_node *ni)
1883{
1884 struct iwn_softc *sc = arg;
1885 struct iwn_node *wn = (void *)ni;
1886
1887 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) == 0) {
1888 int old_txrate = ni->ni_txrate;
1889 ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
1890 if (old_txrate != ni->ni_txrate)
1891 iwn_set_link_quality(sc, ni);
1892 }
1893}
1894
1895void
1896iwn_calib_timeout(void *arg)
1897{
1898 struct iwn_softc *sc = arg;
1899 struct ieee80211com *ic = &sc->sc_ic;
1900 int s;
1901
1902 s = splnet()splraise(0x4);
1903 if (ic->ic_fixed_rate == -1) {
1904 if (ic->ic_opmode == IEEE80211_M_STA)
1905 iwn_iter_func(sc, ic->ic_bss);
1906 else
1907 ieee80211_iterate_nodes(ic, iwn_iter_func, sc);
1908 }
1909 /* Force automatic TX power calibration every 60 secs. */
1910 if (++sc->calib_cnt >= 120) {
1911 uint32_t flags = 0;
1912
1913 DPRINTFN(2, ("sending request for statistics\n"));
1914 (void)iwn_cmd(sc, IWN_CMD_GET_STATISTICS156, &flags,
1915 sizeof flags, 1);
1916 sc->calib_cnt = 0;
1917 }
1918 splx(s)spllower(s);
1919
1920 /* Automatic rate control triggered every 500ms. */
1921 timeout_add_msec(&sc->calib_to, 500);
1922}
1923
1924int
1925iwn_ccmp_decap(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1926{
1927 struct ieee80211com *ic = &sc->sc_ic;
1928 struct ieee80211_key *k = &ni->ni_pairwise_key;
1929 struct ieee80211_frame *wh;
1930 uint64_t pn, *prsc;
1931 uint8_t *ivp;
1932 uint8_t tid;
1933 int hdrlen, hasqos;
1934
1935 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
1936 hdrlen = ieee80211_get_hdrlen(wh);
1937 ivp = (uint8_t *)wh + hdrlen;
1938
1939 /* Check that ExtIV bit is set. */
1940 if (!(ivp[3] & IEEE80211_WEP_EXTIV0x20)) {
1941 DPRINTF(("CCMP decap ExtIV not set\n"));
1942 return 1;
1943 }
1944 hasqos = ieee80211_has_qos(wh);
1945 tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID0x000f : 0;
1946 prsc = &k->k_rsc[tid];
1947
1948 /* Extract the 48-bit PN from the CCMP header. */
1949 pn = (uint64_t)ivp[0] |
1950 (uint64_t)ivp[1] << 8 |
1951 (uint64_t)ivp[4] << 16 |
1952 (uint64_t)ivp[5] << 24 |
1953 (uint64_t)ivp[6] << 32 |
1954 (uint64_t)ivp[7] << 40;
1955 if (pn <= *prsc) {
1956 DPRINTF(("CCMP replayed\n"));
1957 ic->ic_stats.is_ccmp_replays++;
1958 return 1;
1959 }
1960 /* Last seen packet number is updated in ieee80211_inputm(). */
1961
1962 /* Strip MIC. IV will be stripped by ieee80211_inputm(). */
1963 m_adj(m, -IEEE80211_CCMP_MICLEN8);
1964 return 0;
1965}
1966
1967/*
1968 * Process an RX_PHY firmware notification. This is usually immediately
1969 * followed by an MPDU_RX_DONE notification.
1970 */
1971void
1972iwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *desc,
1973 struct iwn_rx_data *data)
1974{
1975 struct iwn_rx_stat *stat = (struct iwn_rx_stat *)(desc + 1);
1976
1977 DPRINTFN(2, ("received PHY stats\n"));
1978 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))
1979 sizeof (*stat), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stat)), (0x02))
;
1980
1981 /* Save RX statistics, they will be used on MPDU_RX_DONE. */
1982 memcpy(&sc->last_rx_stat, stat, sizeof (*stat))__builtin_memcpy((&sc->last_rx_stat), (stat), (sizeof (
*stat)))
;
1983 sc->last_rx_valid = IWN_LAST_RX_VALID0x01;
1984 /*
1985 * The firmware does not send separate RX_PHY
1986 * notifications for A-MPDU subframes.
1987 */
1988 if (stat->flags & htole16(IWN_STAT_FLAG_AGG)((__uint16_t)((1 << 7))))
1989 sc->last_rx_valid |= IWN_LAST_RX_AMPDU0x02;
1990}
1991
1992/*
1993 * Process an RX_DONE (4965AGN only) or MPDU_RX_DONE firmware notification.
1994 * Each MPDU_RX_DONE notification must be preceded by an RX_PHY one.
1995 */
1996void
1997iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
1998 struct iwn_rx_data *data, struct mbuf_list *ml)
1999{
2000 struct iwn_ops *ops = &sc->ops;
2001 struct ieee80211com *ic = &sc->sc_ic;
2002 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2003 struct iwn_rx_ring *ring = &sc->rxq;
2004 struct ieee80211_frame *wh;
2005 struct ieee80211_rxinfo rxi;
2006 struct ieee80211_node *ni;
2007 struct mbuf *m, *m1;
2008 struct iwn_rx_stat *stat;
2009 caddr_t head;
2010 uint32_t flags;
2011 int error, len, rssi;
2012 uint16_t chan;
2013
2014 if (desc->type == IWN_MPDU_RX_DONE193) {
2015 /* Check for prior RX_PHY notification. */
2016 if (!sc->last_rx_valid) {
2017 DPRINTF(("missing RX_PHY\n"));
2018 return;
2019 }
2020 sc->last_rx_valid &= ~IWN_LAST_RX_VALID0x01;
2021 stat = &sc->last_rx_stat;
2022 if ((sc->last_rx_valid & IWN_LAST_RX_AMPDU0x02) &&
2023 (stat->flags & htole16(IWN_STAT_FLAG_AGG)((__uint16_t)((1 << 7)))) == 0) {
2024 DPRINTF(("missing RX_PHY (expecting A-MPDU)\n"));
2025 return;
2026 }
2027 if ((sc->last_rx_valid & IWN_LAST_RX_AMPDU0x02) == 0 &&
2028 (stat->flags & htole16(IWN_STAT_FLAG_AGG)((__uint16_t)((1 << 7))))) {
2029 DPRINTF(("missing RX_PHY (unexpected A-MPDU)\n"));
2030 return;
2031 }
2032 } else
2033 stat = (struct iwn_rx_stat *)(desc + 1);
2034
2035 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))
2036 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), ((4 * 1024)), (0x02))
;
2037
2038 if (stat->cfg_phy_len > IWN_STAT_MAXLEN20) {
2039 printf("%s: invalid RX statistic header\n",
2040 sc->sc_dev.dv_xname);
2041 return;
2042 }
2043 if (desc->type == IWN_MPDU_RX_DONE193) {
2044 struct iwn_rx_mpdu *mpdu = (struct iwn_rx_mpdu *)(desc + 1);
2045 head = (caddr_t)(mpdu + 1);
2046 len = letoh16(mpdu->len)((__uint16_t)(mpdu->len));
2047 } else {
2048 head = (caddr_t)(stat + 1) + stat->cfg_phy_len;
2049 len = letoh16(stat->len)((__uint16_t)(stat->len));
2050 }
2051
2052 flags = letoh32(*(uint32_t *)(head + len))((__uint32_t)(*(uint32_t *)(head + len)));
2053
2054 /* Discard frames with a bad FCS early. */
2055 if ((flags & IWN_RX_NOERROR((1 << 0) | (1 << 1))) != IWN_RX_NOERROR((1 << 0) | (1 << 1))) {
2056 DPRINTFN(2, ("RX flags error %x\n", flags));
2057 ifp->if_ierrorsif_data.ifi_ierrors++;
2058 return;
2059 }
2060 /* Discard frames that are too short. */
2061 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
2062 /* Allow control frames in monitor mode. */
2063 if (len < sizeof (struct ieee80211_frame_cts)) {
2064 DPRINTF(("frame too short: %d\n", len));
2065 ic->ic_stats.is_rx_tooshort++;
2066 ifp->if_ierrorsif_data.ifi_ierrors++;
2067 return;
2068 }
2069 } else if (len < sizeof (*wh)) {
2070 DPRINTF(("frame too short: %d\n", len));
2071 ic->ic_stats.is_rx_tooshort++;
2072 ifp->if_ierrorsif_data.ifi_ierrors++;
2073 return;
2074 }
2075
2076 m1 = MCLGETL(NULL, M_DONTWAIT, IWN_RBUF_SIZE)m_clget((((void *)0)), (0x0002), ((4 * 1024)));
2077 if (m1 == NULL((void *)0)) {
2078 ic->ic_stats.is_rx_nombuf++;
2079 ifp->if_ierrorsif_data.ifi_ierrors++;
2080 return;
2081 }
2082 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
2083
2084 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))
2085 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))
;
2086 if (error != 0) {
2087 m_freem(m1);
2088
2089 /* Try to reload the old mbuf. */
2090 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))
2091 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))
2092 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))
;
2093 if (error != 0) {
2094 panic("%s: could not load old RX mbuf",
2095 sc->sc_dev.dv_xname);
2096 }
2097 /* Physical address may have changed. */
2098 ring->desc[ring->cur] =
2099 htole32(data->map->dm_segs[0].ds_addr >> 8)((__uint32_t)(data->map->dm_segs[0].ds_addr >> 8)
)
;
2100 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))
2101 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))
2102 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
;
2103 ifp->if_ierrorsif_data.ifi_ierrors++;
2104 return;
2105 }
2106
2107 m = data->m;
2108 data->m = m1;
2109 /* Update RX descriptor. */
2110 ring->desc[ring->cur] = htole32(data->map->dm_segs[0].ds_addr >> 8)((__uint32_t)(data->map->dm_segs[0].ds_addr >> 8)
)
;
2111 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))
2112 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))
2113 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
desc_dma.map), (ring->cur * sizeof (uint32_t)), (sizeof (uint32_t
)), (0x04))
;
2114
2115 /* Finalize mbuf. */
2116 m->m_datam_hdr.mh_data = head;
2117 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = len;
2118
2119 /*
2120 * Grab a reference to the source node. Note that control frames are
2121 * shorter than struct ieee80211_frame but ieee80211_find_rxnode()
2122 * is being careful about control frames.
2123 */
2124 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
2125 if (len < sizeof (*wh) &&
2126 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) != IEEE80211_FC0_TYPE_CTL0x04) {
2127 ic->ic_stats.is_rx_tooshort++;
2128 ifp->if_ierrorsif_data.ifi_ierrors++;
2129 m_freem(m);
2130 return;
2131 }
2132 ni = ieee80211_find_rxnode(ic, wh);
2133
2134 memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi)));
2135 if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c) != IEEE80211_FC0_TYPE_CTL0x04)
2136 && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) &&
2137 !IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
2138 (ni->ni_flags & IEEE80211_NODE_RXPROT0x0008) &&
2139 ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {
2140 if ((flags & IWN_RX_CIPHER_MASK(7 << 8)) != IWN_RX_CIPHER_CCMP(2 << 8)) {
2141 ic->ic_stats.is_ccmp_dec_errs++;
2142 ifp->if_ierrorsif_data.ifi_ierrors++;
2143 m_freem(m);
2144 ieee80211_release_node(ic, ni);
2145 return;
2146 }
2147 /* Check whether decryption was successful or not. */
2148 if ((desc->type == IWN_MPDU_RX_DONE193 &&
2149 (flags & (IWN_RX_MPDU_DEC(1 << 11) | IWN_RX_MPDU_MIC_OK(1 << 6))) !=
2150 (IWN_RX_MPDU_DEC(1 << 11) | IWN_RX_MPDU_MIC_OK(1 << 6))) ||
2151 (desc->type != IWN_MPDU_RX_DONE193 &&
2152 (flags & IWN_RX_DECRYPT_MASK(3 << 11)) != IWN_RX_DECRYPT_OK(3 << 11))) {
2153 DPRINTF(("CCMP decryption failed 0x%x\n", flags));
2154 ic->ic_stats.is_ccmp_dec_errs++;
2155 ifp->if_ierrorsif_data.ifi_ierrors++;
2156 m_freem(m);
2157 ieee80211_release_node(ic, ni);
2158 return;
2159 }
2160 if (iwn_ccmp_decap(sc, m, ni) != 0) {
2161 ifp->if_ierrorsif_data.ifi_ierrors++;
2162 m_freem(m);
2163 ieee80211_release_node(ic, ni);
2164 return;
2165 }
2166 rxi.rxi_flags |= IEEE80211_RXI_HWDEC0x00000001;
2167 }
2168
2169 rssi = ops->get_rssi(stat);
2170
2171 chan = stat->chan;
2172 if (chan > IEEE80211_CHAN_MAX255)
2173 chan = IEEE80211_CHAN_MAX255;
2174
2175#if NBPFILTER1 > 0
2176 if (sc->sc_drvbpf != NULL((void *)0)) {
2177 struct iwn_rx_radiotap_header *tap = &sc->sc_rxtapsc_rxtapu.th;
2178 uint16_t chan_flags;
2179
2180 tap->wr_flags = 0;
2181 if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE)((__uint16_t)((1 << 2))))
2182 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE0x02;
2183 tap->wr_chan_freq = htole16(ic->ic_channels[chan].ic_freq)((__uint16_t)(ic->ic_channels[chan].ic_freq));
2184 chan_flags = ic->ic_channels[chan].ic_flags;
2185 if (ic->ic_curmode != IEEE80211_MODE_11N)
2186 chan_flags &= ~IEEE80211_CHAN_HT0x2000;
2187 tap->wr_chan_flags = htole16(chan_flags)((__uint16_t)(chan_flags));
2188 tap->wr_dbm_antsignal = (int8_t)rssi;
2189 tap->wr_dbm_antnoise = (int8_t)sc->noise;
2190 tap->wr_tsft = stat->tstamp;
2191 if (stat->rflags & IWN_RFLAG_MCS(1 << 0)) {
2192 tap->wr_rate = (0x80 | stat->rate); /* HT MCS index */
2193 } else {
2194 switch (stat->rate) {
2195 /* CCK rates. */
2196 case 10: tap->wr_rate = 2; break;
2197 case 20: tap->wr_rate = 4; break;
2198 case 55: tap->wr_rate = 11; break;
2199 case 110: tap->wr_rate = 22; break;
2200 /* OFDM rates. */
2201 case 0xd: tap->wr_rate = 12; break;
2202 case 0xf: tap->wr_rate = 18; break;
2203 case 0x5: tap->wr_rate = 24; break;
2204 case 0x7: tap->wr_rate = 36; break;
2205 case 0x9: tap->wr_rate = 48; break;
2206 case 0xb: tap->wr_rate = 72; break;
2207 case 0x1: tap->wr_rate = 96; break;
2208 case 0x3: tap->wr_rate = 108; break;
2209 /* Unknown rate: should not happen. */
2210 default: tap->wr_rate = 0;
2211 }
2212 }
2213
2214 bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_rxtap_len,
2215 m, BPF_DIRECTION_IN(1 << 0));
2216 }
2217#endif
2218
2219 /* Send the frame to the 802.11 layer. */
2220 rxi.rxi_rssi = rssi;
2221 rxi.rxi_chan = chan;
2222 ieee80211_inputm(ifp, m, ni, &rxi, ml);
2223
2224 /* Node is no longer needed. */
2225 ieee80211_release_node(ic, ni);
2226}
2227
2228void
2229iwn_ra_choose(struct iwn_softc *sc, struct ieee80211_node *ni)
2230{
2231 struct ieee80211com *ic = &sc->sc_ic;
2232 struct iwn_node *wn = (void *)ni;
2233 int old_txmcs = ni->ni_txmcs;
2234
2235 ieee80211_ra_choose(&wn->rn, ic, ni);
2236
2237 /* Update firmware's LQ retry table if RA has chosen a new MCS. */
2238 if (ni->ni_txmcs != old_txmcs)
2239 iwn_set_link_quality(sc, ni);
2240}
2241
2242void
2243iwn_ampdu_rate_control(struct iwn_softc *sc, struct ieee80211_node *ni,
2244 struct iwn_tx_ring *txq, uint16_t seq, uint16_t ssn)
2245{
2246 struct ieee80211com *ic = &sc->sc_ic;
2247 struct iwn_node *wn = (void *)ni;
2248 int idx, end_idx;
2249
2250 /*
2251 * Update Tx rate statistics for A-MPDUs before firmware's BA window.
2252 */
2253 idx = IWN_AGG_SSN_TO_TXQ_IDX(seq)((seq) & (256 - 1));
2254 end_idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1));
2255 while (idx != end_idx) {
2256 struct iwn_tx_data *txdata = &txq->data[idx];
2257 if (txdata->m != NULL((void *)0) && txdata->ampdu_nframes > 1) {
2258 /*
2259 * We can assume that this subframe has been ACKed
2260 * because ACK failures come as single frames and
2261 * before failing an A-MPDU subframe the firmware
2262 * sends it as a single frame at least once.
2263 */
2264 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni,
2265 txdata->ampdu_txmcs, 1, 0);
2266
2267 /* Report this frame only once. */
2268 txdata->ampdu_nframes = 0;
2269 }
2270
2271 idx = (idx + 1) % IWN_TX_RING_COUNT256;
2272 }
2273
2274 iwn_ra_choose(sc, ni);
2275}
2276
2277void
2278iwn_ht_single_rate_control(struct iwn_softc *sc, struct ieee80211_node *ni,
2279 uint8_t rate, uint8_t rflags, uint8_t ackfailcnt, int txfail)
2280{
2281 struct ieee80211com *ic = &sc->sc_ic;
2282 struct iwn_node *wn = (void *)ni;
2283 int mcs = rate;
2284 const struct ieee80211_ht_rateset *rs =
2285 ieee80211_ra_get_ht_rateset(rate,
2286 ieee80211_node_supports_ht_chan40(ni),
2287 ieee80211_ra_use_ht_sgi(ni));
2288 unsigned int retries = 0, i;
2289
2290 /*
2291 * Ignore Tx reports which don't match our last LQ command.
2292 */
2293 if (rate != ni->ni_txmcs) {
2294 if (++wn->lq_rate_mismatch > 15) {
2295 /* Try to sync firmware with driver. */
2296 iwn_set_link_quality(sc, ni);
2297 wn->lq_rate_mismatch = 0;
2298 }
2299 return;
2300 }
2301
2302 wn->lq_rate_mismatch = 0;
2303
2304 /*
2305 * Firmware has attempted rates in this rate set in sequence.
2306 * Retries at a basic rate are counted against the minimum MCS.
2307 */
2308 for (i = 0; i < ackfailcnt; i++) {
2309 if (mcs > rs->min_mcs) {
2310 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, 1, 1);
2311 mcs--;
2312 } else
2313 retries++;
2314 }
2315
2316 if (txfail && ackfailcnt == 0)
2317 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, 1, 1);
2318 else
2319 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni, mcs, retries + 1, retries);
2320
2321 iwn_ra_choose(sc, ni);
2322}
2323
2324/*
2325 * Process an incoming Compressed BlockAck.
2326 * Note that these block ack notifications are generated by firmware and do
2327 * not necessarily correspond to contents of block ack frames seen on the air.
2328 */
2329void
2330iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2331 struct iwn_rx_data *data)
2332{
2333 struct iwn_compressed_ba *cba = (struct iwn_compressed_ba *)(desc + 1);
2334 struct ieee80211com *ic = &sc->sc_ic;
2335 struct ieee80211_node *ni;
2336 struct ieee80211_tx_ba *ba;
2337 struct iwn_tx_ring *txq;
2338 uint16_t seq, ssn;
2339 int qid;
2340
2341 if (ic->ic_state != IEEE80211_S_RUN)
2342 return;
2343
2344 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))
2345 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*cba)), (0x02))
;
2346
2347 if (!IEEE80211_ADDR_EQ(ic->ic_bss->ni_macaddr, cba->macaddr)(__builtin_memcmp((ic->ic_bss->ni_macaddr), (cba->macaddr
), (6)) == 0)
)
2348 return;
2349
2350 ni = ic->ic_bss;
2351
2352 qid = le16toh(cba->qid)((__uint16_t)(cba->qid));
2353 if (qid < sc->first_agg_txq || qid >= sc->ntxqs)
2354 return;
2355
2356 txq = &sc->txq[qid];
2357
2358 /* Protect against a firmware bug where the queue/TID are off. */
2359 if (qid != sc->first_agg_txq + cba->tid)
2360 return;
2361
2362 ba = &ni->ni_tx_ba[cba->tid];
2363 if (ba->ba_state != IEEE80211_BA_AGREED2)
2364 return;
2365
2366 /*
2367 * The first bit in cba->bitmap corresponds to the sequence number
2368 * stored in the sequence control field cba->seq.
2369 * Multiple BA notifications in a row may be using this number, with
2370 * additional bits being set in cba->bitmap. It is unclear how the
2371 * firmware decides to shift this window forward.
2372 * We rely on ba->ba_winstart instead.
2373 */
2374 seq = le16toh(cba->seq)((__uint16_t)(cba->seq)) >> IEEE80211_SEQ_SEQ_SHIFT4;
2375
2376 /*
2377 * The firmware's new BA window starting sequence number
2378 * corresponds to the first hole in cba->bitmap, implying
2379 * that all frames between 'seq' and 'ssn' (non-inclusive)
2380 * have been acked.
2381 */
2382 ssn = le16toh(cba->ssn)((__uint16_t)(cba->ssn));
2383
2384 if (SEQ_LT(ssn, ba->ba_winstart)((((u_int16_t)(ssn) - (u_int16_t)(ba->ba_winstart)) & 0xfff
) > 2048)
)
2385 return;
2386
2387 /* Skip rate control if our Tx rate is fixed. */
2388 if (ic->ic_fixed_mcs == -1)
2389 iwn_ampdu_rate_control(sc, ni, txq, ba->ba_winstart, ssn);
2390
2391 /*
2392 * SSN corresponds to the first (perhaps not yet transmitted) frame
2393 * in firmware's BA window. Firmware is not going to retransmit any
2394 * frames before its BA window so mark them all as done.
2395 */
2396 ieee80211_output_ba_move_window(ic, ni, cba->tid, ssn);
2397 iwn_ampdu_txq_advance(sc, txq, qid,
2398 IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1)));
2399 iwn_clear_oactive(sc, txq);
2400}
2401
2402/*
2403 * Process a CALIBRATION_RESULT notification sent by the initialization
2404 * firmware on response to a CMD_CALIB_CONFIG command (5000 only).
2405 */
2406void
2407iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2408 struct iwn_rx_data *data)
2409{
2410 struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1);
2411 int len, idx = -1;
2412
2413 /* Runtime firmware should not send such a notification. */
2414 if (sc->sc_flags & IWN_FLAG_CALIB_DONE(1 << 2))
2415 return;
2416
2417 len = (letoh32(desc->len)((__uint32_t)(desc->len)) & IWN_RX_DESC_LEN_MASK0x00003fff) - 4;
2418 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))
2419 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
;
2420
2421 switch (calib->code) {
2422 case IWN5000_PHY_CALIB_DC8:
2423 if (sc->hw_type == IWN_HW_REV_TYPE_51504 ||
2424 sc->hw_type == IWN_HW_REV_TYPE_203012 ||
2425 sc->hw_type == IWN_HW_REV_TYPE_200016 ||
2426 sc->hw_type == IWN_HW_REV_TYPE_13518 ||
2427 sc->hw_type == IWN_HW_REV_TYPE_10517)
2428 idx = 0;
2429 break;
2430 case IWN5000_PHY_CALIB_LO9:
2431 idx = 1;
2432 break;
2433 case IWN5000_PHY_CALIB_TX_IQ11:
2434 idx = 2;
2435 break;
2436 case IWN5000_PHY_CALIB_TX_IQ_PERIODIC17:
2437 if (sc->hw_type < IWN_HW_REV_TYPE_60007 &&
2438 sc->hw_type != IWN_HW_REV_TYPE_51504)
2439 idx = 3;
2440 break;
2441 case IWN5000_PHY_CALIB_BASE_BAND16:
2442 idx = 4;
2443 break;
2444 }
2445 if (idx == -1) /* Ignore other results. */
2446 return;
2447
2448 /* Save calibration result. */
2449 if (sc->calibcmd[idx].buf != NULL((void *)0))
2450 free(sc->calibcmd[idx].buf, M_DEVBUF2, 0);
2451 sc->calibcmd[idx].buf = malloc(len, M_DEVBUF2, M_NOWAIT0x0002);
2452 if (sc->calibcmd[idx].buf == NULL((void *)0)) {
2453 DPRINTF(("not enough memory for calibration result %d\n",
2454 calib->code));
2455 return;
2456 }
2457 DPRINTF(("saving calibration result code=%d len=%d\n",
2458 calib->code, len));
2459 sc->calibcmd[idx].len = len;
2460 memcpy(sc->calibcmd[idx].buf, calib, len)__builtin_memcpy((sc->calibcmd[idx].buf), (calib), (len));
2461}
2462
2463/*
2464 * Process an RX_STATISTICS or BEACON_STATISTICS firmware notification.
2465 * The latter is sent by the firmware after each received beacon.
2466 */
2467void
2468iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2469 struct iwn_rx_data *data)
2470{
2471 struct iwn_ops *ops = &sc->ops;
2472 struct ieee80211com *ic = &sc->sc_ic;
2473 struct iwn_calib_state *calib = &sc->calib;
2474 struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
2475 int temp;
2476
2477 /* Ignore statistics received during a scan. */
2478 if (ic->ic_state != IEEE80211_S_RUN)
2479 return;
2480
2481 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))
2482 sizeof (*stats), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stats)), (0x02))
;
2483
2484 DPRINTFN(3, ("received statistics (cmd=%d)\n", desc->type));
2485 sc->calib_cnt = 0; /* Reset TX power calibration timeout. */
2486
2487 sc->rx_stats_flags = htole32(stats->flags)((__uint32_t)(stats->flags));
2488
2489 /* Test if temperature has changed. */
2490 if (stats->general.temp != sc->rawtemp) {
2491 /* Convert "raw" temperature to degC. */
2492 sc->rawtemp = stats->general.temp;
2493 temp = ops->get_temperature(sc);
2494 DPRINTFN(2, ("temperature=%dC\n", temp));
2495
2496 /* Update TX power if need be (4965AGN only). */
2497 if (sc->hw_type == IWN_HW_REV_TYPE_49650)
2498 iwn4965_power_calibration(sc, temp);
2499 }
2500
2501 if (desc->type != IWN_BEACON_STATISTICS157)
2502 return; /* Reply to a statistics request. */
2503
2504 sc->noise = iwn_get_noise(&stats->rx.general);
2505
2506 /* Test that RSSI and noise are present in stats report. */
2507 if (sc->noise == -127)
2508 return;
2509
2510 if (letoh32(stats->rx.general.flags)((__uint32_t)(stats->rx.general.flags)) != 1) {
2511 DPRINTF(("received statistics without RSSI\n"));
2512 return;
2513 }
2514
2515 /*
2516 * XXX Differential gain calibration makes the 6005 firmware
2517 * crap out, so skip it for now. This effectively disables
2518 * sensitivity tuning as well.
2519 */
2520 if (sc->hw_type == IWN_HW_REV_TYPE_600511)
2521 return;
2522
2523 if (calib->state == IWN_CALIB_STATE_ASSOC1)
2524 iwn_collect_noise(sc, &stats->rx.general);
2525 else if (calib->state == IWN_CALIB_STATE_RUN2)
2526 iwn_tune_sensitivity(sc, &stats->rx);
2527}
2528
2529void
2530iwn_ampdu_txq_advance(struct iwn_softc *sc, struct iwn_tx_ring *txq, int qid,
2531 int idx)
2532{
2533 struct iwn_ops *ops = &sc->ops;
2534
2535 DPRINTFN(3, ("%s: txq->cur=%d txq->read=%d txq->queued=%d qid=%d "
2536 "idx=%d\n", __func__, txq->cur, txq->read, txq->queued, qid, idx));
2537
2538 while (txq->read != idx) {
2539 struct iwn_tx_data *txdata = &txq->data[txq->read];
2540 if (txdata->m != NULL((void *)0)) {
2541 ops->reset_sched(sc, qid, txq->read);
2542 iwn_tx_done_free_txdata(sc, txdata);
2543 txq->queued--;
2544 }
2545 txq->read = (txq->read + 1) % IWN_TX_RING_COUNT256;
2546 }
2547}
2548
2549/*
2550 * Handle A-MPDU Tx queue status report.
2551 * Tx failures come as single frames (perhaps out of order), and before failing
2552 * an A-MPDU subframe the firmware transmits it as a single frame at least once.
2553 * Frames successfully transmitted in an A-MPDU are completed when a compressed
2554 * block ack notification is received.
2555 */
2556void
2557iwn_ampdu_tx_done(struct iwn_softc *sc, struct iwn_tx_ring *txq,
2558 struct iwn_rx_desc *desc, uint16_t status, uint8_t ackfailcnt,
2559 uint8_t rate, uint8_t rflags, int nframes, uint32_t ssn,
2560 struct iwn_txagg_status *agg_status)
2561{
2562 struct ieee80211com *ic = &sc->sc_ic;
2563 int tid = desc->qid - sc->first_agg_txq;
2564 struct iwn_tx_data *txdata = &txq->data[desc->idx];
2565 struct ieee80211_node *ni = txdata->ni;
2566 int txfail = (status != IWN_TX_STATUS_SUCCESS0x01 &&
2567 status != IWN_TX_STATUS_DIRECT_DONE0x02);
2568 struct ieee80211_tx_ba *ba;
2569 uint16_t seq;
2570
2571 sc->sc_tx_timer = 0;
2572
2573 if (ic->ic_state != IEEE80211_S_RUN)
2574 return;
2575
2576 if (nframes > 1) {
2577 int i;
2578
2579 /*
2580 * Collect information about this A-MPDU.
2581 */
2582 for (i = 0; i < nframes; i++) {
2583 uint8_t qid = agg_status[i].qid;
2584 uint8_t idx = agg_status[i].idx;
2585 uint16_t txstatus = (le16toh(agg_status[i].status)((__uint16_t)(agg_status[i].status)) &
2586 IWN_AGG_TX_STATUS_MASK0x0fff);
2587
2588 if (txstatus != IWN_AGG_TX_STATE_TRANSMITTED0x0000)
2589 continue;
2590
2591 if (qid != desc->qid)
2592 continue;
2593
2594 txdata = &txq->data[idx];
2595 if (txdata->ni == NULL((void *)0))
2596 continue;
2597
2598 /* The Tx rate was the same for all subframes. */
2599 txdata->ampdu_txmcs = rate;
2600 txdata->ampdu_nframes = nframes;
2601 }
2602 return;
2603 }
2604
2605 if (ni == NULL((void *)0))
2606 return;
2607
2608 ba = &ni->ni_tx_ba[tid];
2609 if (ba->ba_state != IEEE80211_BA_AGREED2)
2610 return;
2611 if (SEQ_LT(ssn, ba->ba_winstart)((((u_int16_t)(ssn) - (u_int16_t)(ba->ba_winstart)) & 0xfff
) > 2048)
)
2612 return;
2613
2614 /* This was a final single-frame Tx attempt for frame SSN-1. */
2615 seq = (ssn - 1) & 0xfff;
2616
2617 /*
2618 * Skip rate control if our Tx rate is fixed.
2619 */
2620 if (ic->ic_fixed_mcs == -1) {
2621 if (txdata->ampdu_nframes > 1) {
2622 struct iwn_node *wn = (void *)ni;
2623 /*
2624 * This frame was once part of an A-MPDU.
2625 * Report one failed A-MPDU Tx attempt.
2626 * The firmware might have made several such
2627 * attempts but we don't keep track of this.
2628 */
2629 ieee80211_ra_add_stats_ht(&wn->rn, ic, ni,
2630 txdata->ampdu_txmcs, 1, 1);
2631 }
2632
2633 /* Report the final single-frame Tx attempt. */
2634 if (rflags & IWN_RFLAG_MCS(1 << 0))
2635 iwn_ht_single_rate_control(sc, ni, rate, rflags,
2636 ackfailcnt, txfail);
2637 }
2638
2639 if (txfail)
2640 ieee80211_tx_compressed_bar(ic, ni, tid, ssn);
2641
2642 /*
2643 * SSN corresponds to the first (perhaps not yet transmitted) frame
2644 * in firmware's BA window. Firmware is not going to retransmit any
2645 * frames before its BA window so mark them all as done.
2646 */
2647 ieee80211_output_ba_move_window(ic, ni, tid, ssn);
2648 iwn_ampdu_txq_advance(sc, txq, desc->qid, IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1)));
2649 iwn_clear_oactive(sc, txq);
2650}
2651
2652/*
2653 * Process a TX_DONE firmware notification. Unfortunately, the 4965AGN
2654 * and 5000 adapters have different incompatible TX status formats.
2655 */
2656void
2657iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2658 struct iwn_rx_data *data)
2659{
2660 struct iwn4965_tx_stat *stat = (struct iwn4965_tx_stat *)(desc + 1);
2661 struct iwn_tx_ring *ring;
2662 size_t len = (letoh32(desc->len)((__uint32_t)(desc->len)) & IWN_RX_DESC_LEN_MASK0x00003fff);
2663 uint16_t status = letoh32(stat->stat.status)((__uint32_t)(stat->stat.status)) & 0xff;
2664 uint32_t ssn;
2665
2666 if (desc->qid > IWN4965_NTXQUEUES16)
2667 return;
2668
2669 ring = &sc->txq[desc->qid];
2670
2671 bus_dmamap_sync(sc->sc_dmat, data->map, sizeof (*desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
2672 len, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (len), (0x02))
;
2673
2674 /* Sanity checks. */
2675 if (sizeof(*stat) > len)
2676 return;
2677 if (stat->nframes < 1 || stat->nframes > IWN_AMPDU_MAX63)
2678 return;
2679 if (desc->qid < sc->first_agg_txq && stat->nframes > 1)
2680 return;
2681 if (desc->qid >= sc->first_agg_txq && sizeof(*stat) + sizeof(ssn) +
2682 stat->nframes * sizeof(stat->stat) > len)
2683 return;
2684
2685 if (desc->qid < sc->first_agg_txq) {
2686 /* XXX 4965 does not report byte count */
2687 struct iwn_tx_data *txdata = &ring->data[desc->idx];
2688 uint16_t framelen = txdata->totlen + IEEE80211_CRC_LEN4;
2689 int txfail = (status != IWN_TX_STATUS_SUCCESS0x01 &&
2690 status != IWN_TX_STATUS_DIRECT_DONE0x02);
2691
2692 iwn_tx_done(sc, desc, stat->ackfailcnt, stat->rate,
2693 stat->rflags, txfail, desc->qid, framelen);
2694 } else {
2695 memcpy(&ssn, &stat->stat.status + stat->nframes, sizeof(ssn))__builtin_memcpy((&ssn), (&stat->stat.status + stat
->nframes), (sizeof(ssn)))
;
2696 ssn = le32toh(ssn)((__uint32_t)(ssn)) & 0xfff;
2697 iwn_ampdu_tx_done(sc, ring, desc, status, stat->ackfailcnt,
2698 stat->rate, stat->rflags, stat->nframes, ssn,
2699 stat->stat.agg_status);
2700 }
2701}
2702
2703void
2704iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2705 struct iwn_rx_data *data)
2706{
2707 struct iwn5000_tx_stat *stat = (struct iwn5000_tx_stat *)(desc + 1);
2708 struct iwn_tx_ring *ring;
2709 size_t len = (letoh32(desc->len)((__uint32_t)(desc->len)) & IWN_RX_DESC_LEN_MASK0x00003fff);
2710 uint16_t status = letoh32(stat->stat.status)((__uint32_t)(stat->stat.status)) & 0xff;
2711 uint32_t ssn;
2712
2713 if (desc->qid > IWN5000_NTXQUEUES20)
2714 return;
2715
2716 ring = &sc->txq[desc->qid];
2717
2718 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))
2719 sizeof (*stat), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*stat)), (0x02))
;
2720
2721 /* Sanity checks. */
2722 if (sizeof(*stat) > len)
2723 return;
2724 if (stat->nframes < 1 || stat->nframes > IWN_AMPDU_MAX63)
2725 return;
2726 if (desc->qid < sc->first_agg_txq && stat->nframes > 1)
2727 return;
2728 if (desc->qid >= sc->first_agg_txq && sizeof(*stat) + sizeof(ssn) +
2729 stat->nframes * sizeof(stat->stat) > len)
2730 return;
2731
2732 /* If this was not an aggregated frame, complete it now. */
2733 if (desc->qid < sc->first_agg_txq) {
2734 int txfail = (status != IWN_TX_STATUS_SUCCESS0x01 &&
2735 status != IWN_TX_STATUS_DIRECT_DONE0x02);
2736
2737 /* Reset TX scheduler slot. */
2738 iwn5000_reset_sched(sc, desc->qid, desc->idx);
2739
2740 iwn_tx_done(sc, desc, stat->ackfailcnt, stat->rate,
2741 stat->rflags, txfail, desc->qid, letoh16(stat->len)((__uint16_t)(stat->len)));
2742 } else {
2743 memcpy(&ssn, &stat->stat.status + stat->nframes, sizeof(ssn))__builtin_memcpy((&ssn), (&stat->stat.status + stat
->nframes), (sizeof(ssn)))
;
2744 ssn = le32toh(ssn)((__uint32_t)(ssn)) & 0xfff;
2745 iwn_ampdu_tx_done(sc, ring, desc, status, stat->ackfailcnt,
2746 stat->rate, stat->rflags, stat->nframes, ssn,
2747 stat->stat.agg_status);
2748 }
2749}
2750
2751void
2752iwn_tx_done_free_txdata(struct iwn_softc *sc, struct iwn_tx_data *data)
2753{
2754 struct ieee80211com *ic = &sc->sc_ic;
2755
2756 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))
2757 BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
;
2758 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
2759 m_freem(data->m);
2760 data->m = NULL((void *)0);
2761 ieee80211_release_node(ic, data->ni);
2762 data->ni = NULL((void *)0);
2763 data->totlen = 0;
2764 data->ampdu_nframes = 0;
2765 data->ampdu_txmcs = 0;
2766}
2767
2768void
2769iwn_clear_oactive(struct iwn_softc *sc, struct iwn_tx_ring *ring)
2770{
2771 struct ieee80211com *ic = &sc->sc_ic;
2772 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2773
2774 if (ring->queued < IWN_TX_RING_LOMARK192) {
2775 sc->qfullmsk &= ~(1 << ring->qid);
2776 if (sc->qfullmsk == 0 && ifq_is_oactive(&ifp->if_snd)) {
2777 ifq_clr_oactive(&ifp->if_snd);
2778 (*ifp->if_start)(ifp);
2779 }
2780 }
2781}
2782
2783/*
2784 * Adapter-independent backend for TX_DONE firmware notifications.
2785 * This handles Tx status for non-aggregation queues.
2786 */
2787void
2788iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
2789 uint8_t ackfailcnt, uint8_t rate, uint8_t rflags, int txfail,
2790 int qid, uint16_t len)
2791{
2792 struct ieee80211com *ic = &sc->sc_ic;
2793 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2794 struct iwn_tx_ring *ring = &sc->txq[qid];
2795 struct iwn_tx_data *data = &ring->data[desc->idx];
2796 struct iwn_node *wn = (void *)data->ni;
2797
2798 if (data->ni == NULL((void *)0))
2799 return;
2800
2801 if (data->ni->ni_flags & IEEE80211_NODE_HT0x0400) {
2802 if (ic->ic_state == IEEE80211_S_RUN &&
2803 ic->ic_fixed_mcs == -1 && (rflags & IWN_RFLAG_MCS(1 << 0))) {
2804 iwn_ht_single_rate_control(sc, data->ni, rate, rflags,
2805 ackfailcnt, txfail);
2806 }
2807 } else {
2808 if (rate != data->ni->ni_txrate) {
2809 if (++wn->lq_rate_mismatch > 15) {
2810 /* Try to sync firmware with driver. */
2811 iwn_set_link_quality(sc, data->ni);
2812 wn->lq_rate_mismatch = 0;
2813 }
2814 } else {
2815 wn->lq_rate_mismatch = 0;
2816
2817 wn->amn.amn_txcnt++;
2818 if (ackfailcnt > 0)
2819 wn->amn.amn_retrycnt++;
2820 if (txfail)
2821 wn->amn.amn_retrycnt++;
2822 }
2823 }
2824 if (txfail)
2825 ifp->if_oerrorsif_data.ifi_oerrors++;
2826
2827 iwn_tx_done_free_txdata(sc, data);
2828
2829 sc->sc_tx_timer = 0;
2830 ring->queued--;
2831 iwn_clear_oactive(sc, ring);
2832}
2833
2834/*
2835 * Process a "command done" firmware notification. This is where we wakeup
2836 * processes waiting for a synchronous command completion.
2837 */
2838void
2839iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
2840{
2841 struct iwn_tx_ring *ring = &sc->txq[4];
2842 struct iwn_tx_data *data;
2843
2844 if ((desc->qid & 0xf) != 4)
2845 return; /* Not a command ack. */
2846
2847 data = &ring->data[desc->idx];
2848
2849 /* If the command was mapped in an mbuf, free it. */
2850 if (data->m != NULL((void *)0)) {
2851 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))
2852 data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x08))
;
2853 bus_dmamap_unload(sc->sc_dmat, data->map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (data
->map))
;
2854 m_freem(data->m);
2855 data->m = NULL((void *)0);
2856 }
2857 wakeup(&ring->desc[desc->idx]);
2858}
2859
2860/*
2861 * Process an INT_FH_RX or INT_SW_RX interrupt.
2862 */
2863void
2864iwn_notif_intr(struct iwn_softc *sc)
2865{
2866 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
2867 struct iwn_ops *ops = &sc->ops;
2868 struct ieee80211com *ic = &sc->sc_ic;
2869 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
2870 uint16_t hw;
2871
2872 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))
2873 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))
;
2874
2875 hw = letoh16(sc->rxq.stat->closed_count)((__uint16_t)(sc->rxq.stat->closed_count)) & 0xfff;
2876 while (sc->rxq.cur != hw) {
2877 struct iwn_rx_data *data = &sc->rxq.data[sc->rxq.cur];
2878 struct iwn_rx_desc *desc;
2879
2880 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))
2881 BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (sizeof (*desc)), (0x02))
;
2882 desc = mtod(data->m, struct iwn_rx_desc *)((struct iwn_rx_desc *)((data->m)->m_hdr.mh_data));
2883
2884 DPRINTFN(4, ("notification qid=%d idx=%d flags=%x type=%d\n",
2885 desc->qid & 0xf, desc->idx, desc->flags, desc->type));
2886
2887 if (!(desc->qid & 0x80)) /* Reply to a command. */
2888 iwn_cmd_done(sc, desc);
2889
2890 switch (desc->type) {
2891 case IWN_RX_PHY192:
2892 iwn_rx_phy(sc, desc, data);
2893 break;
2894
2895 case IWN_RX_DONE195: /* 4965AGN only. */
2896 case IWN_MPDU_RX_DONE193:
2897 /* An 802.11 frame has been received. */
2898 iwn_rx_done(sc, desc, data, &ml);
2899 break;
2900 case IWN_RX_COMPRESSED_BA197:
2901 /* A Compressed BlockAck has been received. */
2902 iwn_rx_compressed_ba(sc, desc, data);
2903 break;
2904 case IWN_TX_DONE28:
2905 /* An 802.11 frame has been transmitted. */
2906 ops->tx_done(sc, desc, data);
2907 break;
2908
2909 case IWN_RX_STATISTICS156:
2910 case IWN_BEACON_STATISTICS157:
2911 iwn_rx_statistics(sc, desc, data);
2912 break;
2913
2914 case IWN_BEACON_MISSED162:
2915 {
2916 struct iwn_beacon_missed *miss =
2917 (struct iwn_beacon_missed *)(desc + 1);
2918 uint32_t missed;
2919
2920 if ((ic->ic_opmode != IEEE80211_M_STA) ||
2921 (ic->ic_state != IEEE80211_S_RUN))
2922 break;
2923
2924 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))
2925 sizeof (*miss), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*miss)), (0x02))
;
2926 missed = letoh32(miss->consecutive)((__uint32_t)(miss->consecutive));
2927
2928 /*
2929 * If more than 5 consecutive beacons are missed,
2930 * reinitialize the sensitivity state machine.
2931 */
2932 if (missed > 5)
2933 (void)iwn_init_sensitivity(sc);
2934
2935 /*
2936 * Rather than go directly to scan state, try to send a
2937 * directed probe request first. If that fails then the
2938 * state machine will drop us into scanning after timing
2939 * out waiting for a probe response.
2940 */
2941 if (missed > ic->ic_bmissthres && !ic->ic_mgt_timer) {
2942 if (ic->ic_ific_ac.ac_if.if_flags & IFF_DEBUG0x4)
2943 printf("%s: receiving no beacons from "
2944 "%s; checking if this AP is still "
2945 "responding to probe requests\n",
2946 sc->sc_dev.dv_xname, ether_sprintf(
2947 ic->ic_bss->ni_macaddr));
2948 IEEE80211_SEND_MGMT(ic, ic->ic_bss,((*(ic)->ic_send_mgmt)(ic, ic->ic_bss, 0x40, 0, 0))
2949 IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0)((*(ic)->ic_send_mgmt)(ic, ic->ic_bss, 0x40, 0, 0));
2950 }
2951 break;
2952 }
2953 case IWN_UC_READY1:
2954 {
2955 struct iwn_ucode_info *uc =
2956 (struct iwn_ucode_info *)(desc + 1);
2957
2958 /* The microcontroller is ready. */
2959 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))
2960 sizeof (*uc), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*uc)), (0x02))
;
2961 DPRINTF(("microcode alive notification version=%d.%d "
2962 "subtype=%x alive=%x\n", uc->major, uc->minor,
2963 uc->subtype, letoh32(uc->valid)));
2964
2965 if (letoh32(uc->valid)((__uint32_t)(uc->valid)) != 1) {
2966 printf("%s: microcontroller initialization "
2967 "failed\n", sc->sc_dev.dv_xname);
2968 break;
2969 }
2970 if (uc->subtype == IWN_UCODE_INIT9) {
2971 /* Save microcontroller report. */
2972 memcpy(&sc->ucode_info, uc, sizeof (*uc))__builtin_memcpy((&sc->ucode_info), (uc), (sizeof (*uc
)))
;
2973 }
2974 /* Save the address of the error log in SRAM. */
2975 sc->errptr = letoh32(uc->errptr)((__uint32_t)(uc->errptr));
2976 break;
2977 }
2978 case IWN_STATE_CHANGED161:
2979 {
2980 uint32_t *status = (uint32_t *)(desc + 1);
2981
2982 /* Enabled/disabled notification. */
2983 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))
2984 sizeof (*status), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*status)), (0x02))
;
2985 DPRINTF(("state changed to %x\n", letoh32(*status)));
2986
2987 if (letoh32(*status)((__uint32_t)(*status)) & 1) {
2988 /* Radio transmitter is off, power down. */
2989 iwn_stop(ifp);
2990 return; /* No further processing. */
2991 }
2992 break;
2993 }
2994 case IWN_START_SCAN130:
2995 {
2996 struct iwn_start_scan *scan =
2997 (struct iwn_start_scan *)(desc + 1);
2998
2999 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))
3000 sizeof (*scan), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*scan)), (0x02))
;
3001 DPRINTFN(2, ("scan start: chan %d status %x\n",
3002 scan->chan, letoh32(scan->status)));
3003
3004 if (sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9))
3005 break;
3006
3007 /* Fix current channel. */
3008 ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];
3009 break;
3010 }
3011 case IWN_STOP_SCAN132:
3012 {
3013 struct iwn_stop_scan *scan =
3014 (struct iwn_stop_scan *)(desc + 1);
3015
3016 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))
3017 sizeof (*scan), BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (sizeof (*desc)), (sizeof (*scan)), (0x02))
;
3018 DPRINTFN(2, ("scan stop: nchan=%d status=%d chan=%d\n",
3019 scan->nchan, scan->status, scan->chan));
3020
3021 if (scan->status == 1 && scan->chan <= 14 &&
3022 (sc->sc_flags & IWN_FLAG_HAS_5GHZ(1 << 0))) {
3023 int error;
3024 /*
3025 * We just finished scanning 2GHz channels,
3026 * start scanning 5GHz ones.
3027 */
3028 error = iwn_scan(sc, IEEE80211_CHAN_5GHZ0x0100,
3029 (sc->sc_flags & IWN_FLAG_BGSCAN(1 << 9)) ? 1 : 0);
3030 if (error == 0)
3031 break;
3032 }
3033 sc->sc_flags &= ~IWN_FLAG_SCANNING(1 << 10);
3034 sc->sc_flags &= ~IWN_FLAG_BGSCAN(1 << 9);
3035 ieee80211_end_scan(ifp);
3036 break;
3037 }
3038 case IWN5000_CALIBRATION_RESULT102:
3039 iwn5000_rx_calib_results(sc, desc, data);
3040 break;
3041
3042 case IWN5000_CALIBRATION_DONE103:
3043 sc->sc_flags |= IWN_FLAG_CALIB_DONE(1 << 2);
3044 wakeup(sc);
3045 break;
3046 }
3047
3048 sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT(1 << 6);
3049 }
3050 if_input(&sc->sc_ic.ic_ific_ac.ac_if, &ml);
3051
3052 /* Tell the firmware what we have processed. */
3053 hw = (hw == 0) ? IWN_RX_RING_COUNT(1 << 6) - 1 : hw - 1;
3054 IWN_WRITE(sc, IWN_FH_RX_WPTR, hw & ~7)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc8)), (
(hw & ~7))))
;
3055}
3056
3057/*
3058 * Process an INT_WAKEUP interrupt raised when the microcontroller wakes up
3059 * from power-down sleep mode.
3060 */
3061void
3062iwn_wakeup_intr(struct iwn_softc *sc)
3063{
3064 int qid;
3065
3066 DPRINTF(("ucode wakeup from power-down sleep\n"));
3067
3068 /* Wakeup RX and TX rings. */
3069 IWN_WRITE(sc, IWN_FH_RX_WPTR, sc->rxq.cur & ~7)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc8)), (
(sc->rxq.cur & ~7))))
;
3070 for (qid = 0; qid < sc->ntxqs; qid++) {
3071 struct iwn_tx_ring *ring = &sc->txq[qid];
3072 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | ring->cur)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | ring->cur))))
;
3073 }
3074}
3075
3076/*
3077 * Dump the error log of the firmware when a firmware panic occurs. Although
3078 * we can't debug the firmware because it is neither open source nor free, it
3079 * can help us to identify certain classes of problems.
3080 */
3081void
3082iwn_fatal_intr(struct iwn_softc *sc)
3083{
3084 struct iwn_fw_dump dump;
3085 int i;
3086
3087 /* Check that the error log address is valid. */
3088 if (sc->errptr < IWN_FW_DATA_BASE0x00800000 ||
3089 sc->errptr + sizeof (dump) >
3090 IWN_FW_DATA_BASE0x00800000 + sc->fw_data_maxsz) {
3091 printf("%s: bad firmware error log address 0x%08x\n",
3092 sc->sc_dev.dv_xname, sc->errptr);
3093 return;
3094 }
3095 if (iwn_nic_lock(sc) != 0) {
3096 printf("%s: could not read firmware error log\n",
3097 sc->sc_dev.dv_xname);
3098 return;
3099 }
3100 /* Read firmware error log from SRAM. */
3101 iwn_mem_read_region_4(sc, sc->errptr, (uint32_t *)&dump,
3102 sizeof (dump) / sizeof (uint32_t));
3103 iwn_nic_unlock(sc);
3104
3105 if (dump.valid == 0) {
3106 printf("%s: firmware error log is empty\n",
3107 sc->sc_dev.dv_xname);
3108 return;
3109 }
3110 printf("firmware error log:\n");
3111 printf(" error type = \"%s\" (0x%08X)\n",
3112 (dump.id < nitems(iwn_fw_errmsg)(sizeof((iwn_fw_errmsg)) / sizeof((iwn_fw_errmsg)[0]))) ?
3113 iwn_fw_errmsg[dump.id] : "UNKNOWN",
3114 dump.id);
3115 printf(" program counter = 0x%08X\n", dump.pc);
3116 printf(" source line = 0x%08X\n", dump.src_line);
3117 printf(" error data = 0x%08X%08X\n",
3118 dump.error_data[0], dump.error_data[1]);
3119 printf(" branch link = 0x%08X%08X\n",
3120 dump.branch_link[0], dump.branch_link[1]);
3121 printf(" interrupt link = 0x%08X%08X\n",
3122 dump.interrupt_link[0], dump.interrupt_link[1]);
3123 printf(" time = %u\n", dump.time[0]);
3124
3125 /* Dump driver status (TX and RX rings) while we're here. */
3126 printf("driver status:\n");
3127 for (i = 0; i < sc->ntxqs; i++) {
3128 struct iwn_tx_ring *ring = &sc->txq[i];
3129 printf(" tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n",
3130 i, ring->qid, ring->cur, ring->queued);
3131 }
3132 printf(" rx ring: cur=%d\n", sc->rxq.cur);
3133 printf(" 802.11 state %d\n", sc->sc_ic.ic_state);
3134}
3135
3136int
3137iwn_intr(void *arg)
3138{
3139 struct iwn_softc *sc = arg;
3140 struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if;
3141 uint32_t r1, r2, tmp;
3142
3143 /* Disable interrupts. */
3144 IWN_WRITE(sc, IWN_INT_MASK, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
0))))
;
3145
3146 /* Read interrupts from ICT (fast) or from registers (slow). */
3147 if (sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3)) {
3148 tmp = 0;
3149 while (sc->ict[sc->ict_cur] != 0) {
3150 tmp |= sc->ict[sc->ict_cur];
3151 sc->ict[sc->ict_cur] = 0; /* Acknowledge. */
3152 sc->ict_cur = (sc->ict_cur + 1) % IWN_ICT_COUNT(4096 / sizeof (uint32_t));
3153 }
3154 tmp = letoh32(tmp)((__uint32_t)(tmp));
3155 if (tmp == 0xffffffff) /* Shouldn't happen. */
3156 tmp = 0;
3157 else if (tmp & 0xc0000) /* Workaround a HW bug. */
3158 tmp |= 0x8000;
3159 r1 = (tmp & 0xff00) << 16 | (tmp & 0xff);
3160 r2 = 0; /* Unused. */
3161 } else {
3162 r1 = IWN_READ(sc, IWN_INT)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x008))));
3163 if (r1 == 0xffffffff || (r1 & 0xfffffff0) == 0xa5a5a5a0)
3164 return 0; /* Hardware gone! */
3165 r2 = IWN_READ(sc, IWN_FH_INT)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x010))));
3166 }
3167 if (r1 == 0 && r2 == 0) {
3168 if (ifp->if_flags & IFF_UP0x1)
3169 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
3170 return 0; /* Interrupt not for us. */
3171 }
3172
3173 /* Acknowledge interrupts. */
3174 IWN_WRITE(sc, IWN_INT, r1)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
r1))))
;
3175 if (!(sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3)))
3176 IWN_WRITE(sc, IWN_FH_INT, r2)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x010)), ((
r2))))
;
3177
3178 if (r1 & IWN_INT_RF_TOGGLED(1U << 7)) {
3179 tmp = IWN_READ(sc, IWN_GP_CNTRL)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) & IWN_GP_CNTRL_RFKILL(1 << 27);
3180 printf("%s: RF switch: radio %s\n", sc->sc_dev.dv_xname,
3181 tmp ? "enabled" : "disabled");
3182 if (tmp)
3183 task_add(systq, &sc->init_task);
3184 }
3185 if (r1 & IWN_INT_CT_REACHED(1U << 6)) {
3186 printf("%s: critical temperature reached!\n",
3187 sc->sc_dev.dv_xname);
3188 }
3189 if (r1 & (IWN_INT_SW_ERR(1U << 25) | IWN_INT_HW_ERR(1U << 29))) {
3190 printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname);
3191
3192 /* Force a complete recalibration on next init. */
3193 sc->sc_flags &= ~IWN_FLAG_CALIB_DONE(1 << 2);
3194
3195 /* Dump firmware error log and stop. */
3196 if (ifp->if_flags & IFF_DEBUG0x4)
3197 iwn_fatal_intr(sc);
3198 iwn_stop(ifp);
3199 task_add(systq, &sc->init_task);
3200 return 1;
3201 }
3202 if ((r1 & (IWN_INT_FH_RX(1U << 31) | IWN_INT_SW_RX(1U << 3) | IWN_INT_RX_PERIODIC(1U << 28))) ||
3203 (r2 & IWN_FH_INT_RX((1 << ((0) + 16)) | (1 << ((1) + 16)) | (1 <<
30))
)) {
3204 if (sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3)) {
3205 if (r1 & (IWN_INT_FH_RX(1U << 31) | IWN_INT_SW_RX(1U << 3)))
3206 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))))))
;
3207 IWN_WRITE_1(sc, IWN_INT_PERIODIC,(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0x00))))
3208 IWN_INT_PERIODIC_DIS)(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0x00))))
;
3209 iwn_notif_intr(sc);
3210 if (r1 & (IWN_INT_FH_RX(1U << 31) | IWN_INT_SW_RX(1U << 3))) {
3211 IWN_WRITE_1(sc, IWN_INT_PERIODIC,(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0xff))))
3212 IWN_INT_PERIODIC_ENA)(((sc)->sc_st)->write_1(((sc)->sc_sh), ((0x005)), ((
0xff))))
;
3213 }
3214 } else
3215 iwn_notif_intr(sc);
3216 }
3217
3218 if ((r1 & IWN_INT_FH_TX(1U << 27)) || (r2 & IWN_FH_INT_TX((1 << (0)) | (1 << (1))))) {
3219 if (sc->sc_flags & IWN_FLAG_USE_ICT(1 << 3))
3220 IWN_WRITE(sc, IWN_FH_INT, IWN_FH_INT_TX)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x010)), ((
((1 << (0)) | (1 << (1)))))))
;
3221 wakeup(sc); /* FH DMA transfer completed. */
3222 }
3223
3224 if (r1 & IWN_INT_ALIVE(1U << 0))
3225 wakeup(sc); /* Firmware is alive. */
3226
3227 if (r1 & IWN_INT_WAKEUP(1U << 1))
3228 iwn_wakeup_intr(sc);
3229
3230 /* Re-enable interrupts. */
3231 if (ifp->if_flags & IFF_UP0x1)
3232 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
3233
3234 return 1;
3235}
3236
3237/*
3238 * Update TX scheduler ring when transmitting an 802.11 frame (4965AGN and
3239 * 5000 adapters use a slightly different format).
3240 */
3241void
3242iwn4965_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,
3243 uint16_t len)
3244{
3245 uint16_t *w = &sc->sched[qid * IWN4965_SCHED_COUNT512 + idx];
3246
3247 *w = htole16(len + 8)((__uint16_t)(len + 8));
3248 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))
3249 (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))
3250 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))
;
3251 if (idx < IWN_SCHED_WINSZ64) {
3252 *(w + IWN_TX_RING_COUNT256) = *w;
3253 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))
3254 (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))
3255 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))
;
3256 }
3257}
3258
3259void
3260iwn4965_reset_sched(struct iwn_softc *sc, int qid, int idx)
3261{
3262 /* TBD */
3263}
3264
3265void
3266iwn5000_update_sched(struct iwn_softc *sc, int qid, int idx, uint8_t id,
3267 uint16_t len)
3268{
3269 uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT(256 + 64) + idx];
3270
3271 *w = htole16(id << 12 | (len + 8))((__uint16_t)(id << 12 | (len + 8)));
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 - sc->sched_dma.vaddr), (sizeof
(uint16_t)), (0x04))
3273 (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))
3274 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))
;
3275 if (idx < IWN_SCHED_WINSZ64) {
3276 *(w + IWN_TX_RING_COUNT256) = *w;
3277 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))
3278 (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))
3279 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))
;
3280 }
3281}
3282
3283void
3284iwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx)
3285{
3286 uint16_t *w = &sc->sched[qid * IWN5000_SCHED_COUNT(256 + 64) + idx];
3287
3288 *w = (*w & htole16(0xf000)((__uint16_t)(0xf000))) | htole16(1)((__uint16_t)(1));
3289 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))
3290 (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))
3291 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))
;
3292 if (idx < IWN_SCHED_WINSZ64) {
3293 *(w + IWN_TX_RING_COUNT256) = *w;
3294 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))
3295 (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))
3296 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))
;
3297 }
3298}
3299
3300int
3301iwn_rval2ridx(int rval)
3302{
3303 int ridx;
3304
3305 for (ridx = 0; ridx < nitems(iwn_rates)(sizeof((iwn_rates)) / sizeof((iwn_rates)[0])); ridx++) {
3306 if (rval == iwn_rates[ridx].rate)
3307 break;
3308 }
3309
3310 return ridx;
3311}
3312
3313int
3314iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
3315{
3316 struct iwn_ops *ops = &sc->ops;
3317 struct ieee80211com *ic = &sc->sc_ic;
3318 struct iwn_node *wn = (void *)ni;
3319 struct iwn_tx_ring *ring;
3320 struct iwn_tx_desc *desc;
3321 struct iwn_tx_data *data;
3322 struct iwn_tx_cmd *cmd;
3323 struct iwn_cmd_data *tx;
3324 const struct iwn_rate *rinfo;
3325 struct ieee80211_frame *wh;
3326 struct ieee80211_key *k = NULL((void *)0);
3327 enum ieee80211_edca_ac ac;
3328 int qid;
3329 uint32_t flags;
3330 uint16_t qos;
3331 u_int hdrlen;
3332 bus_dma_segment_t *seg;
3333 uint8_t *ivp, tid, ridx, txant, type, subtype;
3334 int i, totlen, hasqos, error, pad;
3335
3336 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
3337 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c;
3338 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK0xf0;
3339 if (type == IEEE80211_FC0_TYPE_CTL0x04)
3340 hdrlen = sizeof(struct ieee80211_frame_min);
3341 else
3342 hdrlen = ieee80211_get_hdrlen(wh);
3343
3344 if ((hasqos = ieee80211_has_qos(wh))) {
3345 /* Select EDCA Access Category and TX ring for this frame. */
3346 struct ieee80211_tx_ba *ba;
3347 qos = ieee80211_get_qos(wh);
3348 tid = qos & IEEE80211_QOS_TID0x000f;
3349 ac = ieee80211_up_to_ac(ic, tid);
3350 qid = ac;
3351
3352 /* If possible, put this frame on an aggregation queue. */
3353 if (sc->sc_tx_ba[tid].wn == wn) {
3354 ba = &ni->ni_tx_ba[tid];
3355 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
3356 ba->ba_state == IEEE80211_BA_AGREED2) {
3357 qid = sc->first_agg_txq + tid;
3358 if (sc->qfullmsk & (1 << qid)) {
3359 m_freem(m);
3360 return ENOBUFS55;
3361 }
3362 }
3363 }
3364 } else {
3365 qos = 0;
3366 tid = IWN_NONQOS_TID8;
3367 ac = EDCA_AC_BE;
3368 qid = ac;
3369 }
3370
3371 ring = &sc->txq[qid];
3372 desc = &ring->desc[ring->cur];
3373 data = &ring->data[ring->cur];
3374
3375 /* Choose a TX rate index. */
3376 if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
3377 type != IEEE80211_FC0_TYPE_DATA0x08)
3378 ridx = iwn_rval2ridx(ieee80211_min_basic_rate(ic));
3379 else if (ic->ic_fixed_mcs != -1)
3380 ridx = sc->fixed_ridx;
3381 else if (ic->ic_fixed_rate != -1)
3382 ridx = sc->fixed_ridx;
3383 else {
3384 if (ni->ni_flags & IEEE80211_NODE_HT0x0400)
3385 ridx = iwn_mcs2ridx[ni->ni_txmcs];
3386 else
3387 ridx = wn->ridx[ni->ni_txrate];
3388 }
3389 rinfo = &iwn_rates[ridx];
3390#if NBPFILTER1 > 0
3391 if (sc->sc_drvbpf != NULL((void *)0)) {
3392 struct iwn_tx_radiotap_header *tap = &sc->sc_txtapsc_txtapu.th;
3393 uint16_t chan_flags;
3394
3395 tap->wt_flags = 0;
3396 tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq)((__uint16_t)(ni->ni_chan->ic_freq));
3397 chan_flags = ni->ni_chan->ic_flags;
3398 if (ic->ic_curmode != IEEE80211_MODE_11N)
3399 chan_flags &= ~IEEE80211_CHAN_HT0x2000;
3400 tap->wt_chan_flags = htole16(chan_flags)((__uint16_t)(chan_flags));
3401 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) &&
3402 !IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) &&
3403 type == IEEE80211_FC0_TYPE_DATA0x08) {
3404 tap->wt_rate = (0x80 | ni->ni_txmcs);
3405 } else
3406 tap->wt_rate = rinfo->rate;
3407 if ((ic->ic_flags & IEEE80211_F_WEPON0x00000100) &&
3408 (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40))
3409 tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP0x04;
3410
3411 bpf_mtap_hdr(sc->sc_drvbpf, tap, sc->sc_txtap_len,
3412 m, BPF_DIRECTION_OUT(1 << 1));
3413 }
3414#endif
3415
3416 totlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
3417
3418 /* Encrypt the frame if need be. */
3419 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) {
3420 /* Retrieve key for TX. */
3421 k = ieee80211_get_txkey(ic, wh, ni);
3422 if (k->k_cipher != IEEE80211_CIPHER_CCMP) {
3423 /* Do software encryption. */
3424 if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0))
3425 return ENOBUFS55;
3426 /* 802.11 header may have moved. */
3427 wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data));
3428 totlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
3429
3430 } else /* HW appends CCMP MIC. */
3431 totlen += IEEE80211_CCMP_HDRLEN8;
3432 }
3433
3434 data->totlen = totlen;
3435
3436 /* Prepare TX firmware command. */
3437 cmd = &ring->cmd[ring->cur];
3438 cmd->code = IWN_CMD_TX_DATA28;
3439 cmd->flags = 0;
3440 cmd->qid = ring->qid;
3441 cmd->idx = ring->cur;
3442
3443 tx = (struct iwn_cmd_data *)cmd->data;
3444 /* NB: No need to clear tx, all fields are reinitialized here. */
3445 tx->scratch = 0; /* clear "scratch" area */
3446
3447 flags = 0;
3448 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
3449 /* Unicast frame, check if an ACK is expected. */
3450 if (!hasqos || (qos & IEEE80211_QOS_ACK_POLICY_MASK0x0060) !=
3451 IEEE80211_QOS_ACK_POLICY_NOACK0x0020)
3452 flags |= IWN_TX_NEED_ACK(1 << 3);
3453 }
3454 if (type == IEEE80211_FC0_TYPE_CTL0x04 &&
3455 subtype == IEEE80211_FC0_SUBTYPE_BAR0x80) {
3456 struct ieee80211_frame_min *mwh;
3457 uint8_t *barfrm;
3458 uint16_t ctl;
3459 mwh = mtod(m, struct ieee80211_frame_min *)((struct ieee80211_frame_min *)((m)->m_hdr.mh_data));
3460 barfrm = (uint8_t *)&mwh[1];
3461 ctl = LE_READ_2(barfrm)((u_int16_t) ((((const u_int8_t *)(barfrm))[0]) | (((const u_int8_t
*)(barfrm))[1] << 8)))
;
3462 tid = (ctl & IEEE80211_BA_TID_INFO_MASK0xf000) >>
3463 IEEE80211_BA_TID_INFO_SHIFT12;
3464 flags |= (IWN_TX_NEED_ACK(1 << 3) | IWN_TX_IMM_BA(1 << 6));
3465 }
3466
3467 if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG0x04)
3468 flags |= IWN_TX_MORE_FRAG(1 << 14); /* Cannot happen yet. */
3469
3470 /* Check if frame must be protected using RTS/CTS or CTS-to-self. */
3471 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) {
3472 /* NB: Group frames are sent using CCK in 802.11b/g/n (2GHz). */
3473 if (totlen + IEEE80211_CRC_LEN4 > ic->ic_rtsthreshold) {
3474 flags |= IWN_TX_NEED_RTS(1 << 1);
3475 } else if ((ic->ic_flags & IEEE80211_F_USEPROT0x00100000) &&
3476 ridx >= IWN_RIDX_OFDM64) {
3477 if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
3478 flags |= IWN_TX_NEED_CTS(1 << 2);
3479 else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
3480 flags |= IWN_TX_NEED_RTS(1 << 1);
3481 }
3482
3483 if (flags & (IWN_TX_NEED_RTS(1 << 1) | IWN_TX_NEED_CTS(1 << 2))) {
3484 if (sc->hw_type != IWN_HW_REV_TYPE_49650) {
3485 /* 5000 autoselects RTS/CTS or CTS-to-self. */
3486 flags &= ~(IWN_TX_NEED_RTS(1 << 1) | IWN_TX_NEED_CTS(1 << 2));
3487 flags |= IWN_TX_NEED_PROTECTION(1 << 0);
3488 } else
3489 flags |= IWN_TX_FULL_TXOP(1 << 7);
3490 }
3491 }
3492
3493 if (type == IEEE80211_FC0_TYPE_CTL0x04 &&
3494 subtype == IEEE80211_FC0_SUBTYPE_BAR0x80)
3495 tx->id = wn->id;
3496 else if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01) ||
3497 type != IEEE80211_FC0_TYPE_DATA0x08)
3498 tx->id = sc->broadcast_id;
3499 else
3500 tx->id = wn->id;
3501
3502 if (type == IEEE80211_FC0_TYPE_MGT0x00) {
3503#ifndef IEEE80211_STA_ONLY
3504 /* Tell HW to set timestamp in probe responses. */
3505 if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP0x50)
3506 flags |= IWN_TX_INSERT_TSTAMP(1 << 16);
3507#endif
3508 if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ0x00 ||
3509 subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ0x20)
3510 tx->timeout = htole16(3)((__uint16_t)(3));
3511 else
3512 tx->timeout = htole16(2)((__uint16_t)(2));
3513 } else
3514 tx->timeout = htole16(0)((__uint16_t)(0));
3515
3516 if (hdrlen & 3) {
3517 /* First segment length must be a multiple of 4. */
3518 flags |= IWN_TX_NEED_PADDING(1 << 20);
3519 pad = 4 - (hdrlen & 3);
3520 } else
3521 pad = 0;
3522
3523 tx->len = htole16(totlen)((__uint16_t)(totlen));
3524 tx->tid = tid;
3525 tx->rts_ntries = 60;
3526 tx->data_ntries = 15;
3527 tx->lifetime = htole32(IWN_LIFETIME_INFINITE)((__uint32_t)(0xffffffff));
3528
3529 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) &&
3530 tx->id != sc->broadcast_id)
3531 tx->plcp = rinfo->ht_plcp;
3532 else
3533 tx->plcp = rinfo->plcp;
3534
3535 if ((ni->ni_flags & IEEE80211_NODE_HT0x0400) &&
3536 tx->id != sc->broadcast_id) {
3537 tx->rflags = rinfo->ht_flags;
3538 if (iwn_rxon_ht40_enabled(sc))
3539 tx->rflags |= IWN_RFLAG_HT40(1 << 3);
3540 if (ieee80211_ra_use_ht_sgi(ni))
3541 tx->rflags |= IWN_RFLAG_SGI(1 << 5);
3542 }
3543 else
3544 tx->rflags = rinfo->flags;
3545 if (tx->id == sc->broadcast_id || ic->ic_fixed_mcs != -1 ||
3546 ic->ic_fixed_rate != -1) {
3547 /* Group or management frame, or fixed Tx rate. */
3548 tx->linkq = 0;
3549 /* XXX Alternate between antenna A and B? */
3550 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
3551 tx->rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3552 } else {
3553 tx->linkq = 0; /* initial index into firmware LQ retry table */
3554 flags |= IWN_TX_LINKQ(1 << 4); /* enable multi-rate retry */
3555 }
3556 /* Set physical address of "scratch area". */
3557 tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr))((__uint32_t)(((uint32_t)(data->scratch_paddr))));
3558 tx->hiaddr = IWN_HIADDR(data->scratch_paddr)(((data->scratch_paddr) >> 32) & 0xf);
3559
3560 /* Copy 802.11 header in TX command. */
3561 memcpy((uint8_t *)(tx + 1), wh, hdrlen)__builtin_memcpy(((uint8_t *)(tx + 1)), (wh), (hdrlen));
3562
3563 if (k != NULL((void *)0) && k->k_cipher == IEEE80211_CIPHER_CCMP) {
3564 /* Trim 802.11 header and prepend CCMP IV. */
3565 m_adj(m, hdrlen - IEEE80211_CCMP_HDRLEN8);
3566 ivp = mtod(m, uint8_t *)((uint8_t *)((m)->m_hdr.mh_data));
3567 k->k_tsc++;
3568 ivp[0] = k->k_tsc;
3569 ivp[1] = k->k_tsc >> 8;
3570 ivp[2] = 0;
3571 ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV0x20;
3572 ivp[4] = k->k_tsc >> 16;
3573 ivp[5] = k->k_tsc >> 24;
3574 ivp[6] = k->k_tsc >> 32;
3575 ivp[7] = k->k_tsc >> 40;
3576
3577 tx->security = IWN_CIPHER_CCMP2;
3578 if (qid >= sc->first_agg_txq)
3579 flags |= IWN_TX_AMPDU_CCMP(1 << 22);
3580 memcpy(tx->key, k->k_key, k->k_len)__builtin_memcpy((tx->key), (k->k_key), (k->k_len));
3581
3582 /* TX scheduler includes CCMP MIC len w/5000 Series. */
3583 if (sc->hw_type != IWN_HW_REV_TYPE_49650)
3584 totlen += IEEE80211_CCMP_MICLEN8;
3585 } else {
3586 /* Trim 802.11 header. */
3587 m_adj(m, hdrlen);
3588 tx->security = 0;
3589 }
3590 tx->flags = htole32(flags)((__uint32_t)(flags));
3591
3592 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))
3593 BUS_DMA_NOWAIT | BUS_DMA_WRITE)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
data->map), (m), (0x0001 | 0x0400))
;
3594 if (error != 0 && error != EFBIG27) {
3595 printf("%s: can't map mbuf (error %d)\n",
3596 sc->sc_dev.dv_xname, error);
3597 m_freem(m);
3598 return error;
3599 }
3600 if (error != 0) {
3601 /* Too many DMA segments, linearize mbuf. */
3602 if (m_defrag(m, M_DONTWAIT0x0002)) {
3603 m_freem(m);
3604 return ENOBUFS55;
3605 }
3606 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))
3607 BUS_DMA_NOWAIT | BUS_DMA_WRITE)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), (
data->map), (m), (0x0001 | 0x0400))
;
3608 if (error != 0) {
3609 printf("%s: can't map mbuf (error %d)\n",
3610 sc->sc_dev.dv_xname, error);
3611 m_freem(m);
3612 return error;
3613 }
3614 }
3615
3616 data->m = m;
3617 data->ni = ni;
3618 data->ampdu_txmcs = ni->ni_txmcs; /* updated upon Tx interrupt */
3619
3620 DPRINTFN(4, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n",
3621 ring->qid, ring->cur, m->m_pkthdr.len, data->map->dm_nsegs));
3622
3623 /* Fill TX descriptor. */
3624 desc->nsegs = 1 + data->map->dm_nsegs;
3625 /* First DMA segment is used by the TX command. */
3626 desc->segs[0].addr = htole32(IWN_LOADDR(data->cmd_paddr))((__uint32_t)(((uint32_t)(data->cmd_paddr))));
3627 desc->segs[0].len = htole16(IWN_HIADDR(data->cmd_paddr) |((__uint16_t)((((data->cmd_paddr) >> 32) & 0xf) |
(4 + sizeof (*tx) + hdrlen + pad) << 4))
3628 (4 + sizeof (*tx) + hdrlen + pad) << 4)((__uint16_t)((((data->cmd_paddr) >> 32) & 0xf) |
(4 + sizeof (*tx) + hdrlen + pad) << 4))
;
3629 /* Other DMA segments are for data payload. */
3630 seg = data->map->dm_segs;
3631 for (i = 1; i <= data->map->dm_nsegs; i++) {
3632 desc->segs[i].addr = htole32(IWN_LOADDR(seg->ds_addr))((__uint32_t)(((uint32_t)(seg->ds_addr))));
3633 desc->segs[i].len = htole16(IWN_HIADDR(seg->ds_addr) |((__uint16_t)((((seg->ds_addr) >> 32) & 0xf) | seg
->ds_len << 4))
3634 seg->ds_len << 4)((__uint16_t)((((seg->ds_addr) >> 32) & 0xf) | seg
->ds_len << 4))
;
3635 seg++;
3636 }
3637
3638 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))
3639 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (data->map->dm_mapsize), (0x04))
;
3640 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))
3641 (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))
3642 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))
;
3643 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))
3644 (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))
3645 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))
;
3646
3647 /* Update TX scheduler. */
3648 ops->update_sched(sc, ring->qid, ring->cur, tx->id, totlen);
3649
3650 /* Kick TX ring. */
3651 ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT256;
3652 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))))
;
3653
3654 /* Mark TX ring as full if we reach a certain threshold. */
3655 if (++ring->queued > IWN_TX_RING_HIMARK224)
3656 sc->qfullmsk |= 1 << ring->qid;
3657
3658 return 0;
3659}
3660
3661void
3662iwn_start(struct ifnet *ifp)
3663{
3664 struct iwn_softc *sc = ifp->if_softc;
3665 struct ieee80211com *ic = &sc->sc_ic;
3666 struct ieee80211_node *ni;
3667 struct mbuf *m;
3668
3669 if (!(ifp->if_flags & IFF_RUNNING0x40) || ifq_is_oactive(&ifp->if_snd))
3670 return;
3671
3672 for (;;) {
3673 if (sc->qfullmsk != 0) {
3674 ifq_set_oactive(&ifp->if_snd);
3675 break;
3676 }
3677
3678 /* Send pending management frames first. */
3679 m = mq_dequeue(&ic->ic_mgtq);
3680 if (m != NULL((void *)0)) {
3681 ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie;
3682 goto sendit;
3683 }
3684 if (ic->ic_state != IEEE80211_S_RUN ||
3685 (ic->ic_xflags & IEEE80211_F_TX_MGMT_ONLY0x00000001))
3686 break;
3687
3688 /* Encapsulate and send data frames. */
3689 m = ifq_dequeue(&ifp->if_snd);
3690 if (m == NULL((void *)0))
3691 break;
3692#if NBPFILTER1 > 0
3693 if (ifp->if_bpf != NULL((void *)0))
3694 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
3695#endif
3696 if ((m = ieee80211_encap(ifp, m, &ni)) == NULL((void *)0))
3697 continue;
3698sendit:
3699#if NBPFILTER1 > 0
3700 if (ic->ic_rawbpf != NULL((void *)0))
3701 bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1));
3702#endif
3703 if (iwn_tx(sc, m, ni) != 0) {
3704 ieee80211_release_node(ic, ni);
3705 ifp->if_oerrorsif_data.ifi_oerrors++;
3706 continue;
3707 }
3708
3709 sc->sc_tx_timer = 5;
3710 ifp->if_timer = 1;
3711 }
3712}
3713
3714void
3715iwn_watchdog(struct ifnet *ifp)
3716{
3717 struct iwn_softc *sc = ifp->if_softc;
3718
3719 ifp->if_timer = 0;
3720
3721 if (sc->sc_tx_timer > 0) {
3722 if (--sc->sc_tx_timer == 0) {
3723 printf("%s: device timeout\n", sc->sc_dev.dv_xname);
3724 iwn_stop(ifp);
3725 ifp->if_oerrorsif_data.ifi_oerrors++;
3726 return;
3727 }
3728 ifp->if_timer = 1;
3729 }
3730
3731 ieee80211_watchdog(ifp);
3732}
3733
3734int
3735iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
3736{
3737 struct iwn_softc *sc = ifp->if_softc;
3738 struct ieee80211com *ic = &sc->sc_ic;
3739 int s, error = 0;
3740
3741 error = rw_enter(&sc->sc_rwlock, RW_WRITE0x0001UL | RW_INTR0x0010UL);
3742 if (error)
3743 return error;
3744 s = splnet()splraise(0x4);
3745
3746 switch (cmd) {
3747 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
3748 ifp->if_flags |= IFF_UP0x1;
3749 /* FALLTHROUGH */
3750 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
3751 if (ifp->if_flags & IFF_UP0x1) {
3752 if (!(ifp->if_flags & IFF_RUNNING0x40))
3753 error = iwn_init(ifp);
3754 } else {
3755 if (ifp->if_flags & IFF_RUNNING0x40)
3756 iwn_stop(ifp);
3757 }
3758 break;
3759
3760 case SIOCS80211POWER((unsigned long)0x80000000 | ((sizeof(struct ieee80211_power)
& 0x1fff) << 16) | ((('i')) << 8) | ((234)))
:
3761 error = ieee80211_ioctl(ifp, cmd, data);
3762 if (error != ENETRESET52)
3763 break;
3764 if (ic->ic_state == IEEE80211_S_RUN &&
3765 sc->calib.state == IWN_CALIB_STATE_RUN2) {
3766 if (ic->ic_flags & IEEE80211_F_PMGTON0x00000400)
3767 error = iwn_set_pslevel(sc, 0, 3, 0);
3768 else /* back to CAM */
3769 error = iwn_set_pslevel(sc, 0, 0, 0);
3770 } else {
3771 /* Defer until transition to IWN_CALIB_STATE_RUN. */
3772 error = 0;
3773 }
3774 break;
3775
3776 default:
3777 error = ieee80211_ioctl(ifp, cmd, data);
3778 }
3779
3780 if (error == ENETRESET52) {
3781 error = 0;
3782 if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) ==
3783 (IFF_UP0x1 | IFF_RUNNING0x40)) {
3784 iwn_stop(ifp);
3785 error = iwn_init(ifp);
3786 }
3787 }
3788
3789 splx(s)spllower(s);
3790 rw_exit_write(&sc->sc_rwlock);
3791 return error;
3792}
3793
3794/*
3795 * Send a command to the firmware.
3796 */
3797int
3798iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
3799{
3800 struct iwn_ops *ops = &sc->ops;
3801 struct iwn_tx_ring *ring = &sc->txq[4];
3802 struct iwn_tx_desc *desc;
3803 struct iwn_tx_data *data;
3804 struct iwn_tx_cmd *cmd;
3805 struct mbuf *m;
3806 bus_addr_t paddr;
3807 int totlen, error;
3808
3809 desc = &ring->desc[ring->cur];
3810 data = &ring->data[ring->cur];
3811 totlen = 4 + size;
3812
3813 if (size > sizeof cmd->data) {
3814 /* Command is too large to fit in a descriptor. */
3815 if (totlen > MCLBYTES(1 << 11))
3816 return EINVAL22;
3817 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
3818 if (m == NULL((void *)0))
3819 return ENOMEM12;
3820 if (totlen > MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) {
3821 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
3822 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
3823 m_freem(m);
3824 return ENOMEM12;
3825 }
3826 }
3827 cmd = mtod(m, struct iwn_tx_cmd *)((struct iwn_tx_cmd *)((m)->m_hdr.mh_data));
3828 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))
3829 NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (data->
map), (cmd), (totlen), (((void *)0)), (0x0001 | 0x0400))
;
3830 if (error != 0) {
3831 m_freem(m);
3832 return error;
3833 }
3834 data->m = m;
3835 paddr = data->map->dm_segs[0].ds_addr;
3836 } else {
3837 cmd = &ring->cmd[ring->cur];
3838 paddr = data->cmd_paddr;
3839 }
3840
3841 cmd->code = code;
3842 cmd->flags = 0;
3843 cmd->qid = ring->qid;
3844 cmd->idx = ring->cur;
3845 memcpy(cmd->data, buf, size)__builtin_memcpy((cmd->data), (buf), (size));
3846
3847 desc->nsegs = 1;
3848 desc->segs[0].addr = htole32(IWN_LOADDR(paddr))((__uint32_t)(((uint32_t)(paddr))));
3849 desc->segs[0].len = htole16(IWN_HIADDR(paddr) | totlen << 4)((__uint16_t)((((paddr) >> 32) & 0xf) | totlen <<
4))
;
3850
3851 if (size > sizeof cmd->data) {
3852 bus_dmamap_sync(sc->sc_dmat, data->map, 0, totlen,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (totlen), (0x04))
3853 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (data->
map), (0), (totlen), (0x04))
;
3854 } else {
3855 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))
3856 (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))
3857 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (ring->
cmd_dma.map), ((caddr_t)cmd - ring->cmd_dma.vaddr), (totlen
), (0x04))
;
3858 }
3859 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))
3860 (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))
3861 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))
;
3862
3863 /* Update TX scheduler. */
3864 ops->update_sched(sc, ring->qid, ring->cur, 0, 0);
3865
3866 /* Kick command ring. */
3867 ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT256;
3868 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))))
;
3869
3870 return async ? 0 : tsleep_nsec(desc, PCATCH0x100, "iwncmd", SEC_TO_NSEC(1));
3871}
3872
3873int
3874iwn4965_add_node(struct iwn_softc *sc, struct iwn_node_info *node, int async)
3875{
3876 struct iwn4965_node_info hnode;
3877 caddr_t src, dst;
3878
3879 /*
3880 * We use the node structure for 5000 Series internally (it is
3881 * a superset of the one for 4965AGN). We thus copy the common
3882 * fields before sending the command.
3883 */
3884 src = (caddr_t)node;
3885 dst = (caddr_t)&hnode;
3886 memcpy(dst, src, 48)__builtin_memcpy((dst), (src), (48));
3887 /* Skip TSC, RX MIC and TX MIC fields from ``src''. */
3888 memcpy(dst + 48, src + 72, 20)__builtin_memcpy((dst + 48), (src + 72), (20));
3889 return iwn_cmd(sc, IWN_CMD_ADD_NODE24, &hnode, sizeof hnode, async);
3890}
3891
3892int
3893iwn5000_add_node(struct iwn_softc *sc, struct iwn_node_info *node, int async)
3894{
3895 /* Direct mapping. */
3896 return iwn_cmd(sc, IWN_CMD_ADD_NODE24, node, sizeof (*node), async);
3897}
3898
3899int
3900iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
3901{
3902 struct ieee80211com *ic = &sc->sc_ic;
3903 struct iwn_node *wn = (void *)ni;
3904 struct iwn_cmd_link_quality linkq;
3905 const struct iwn_rate *rinfo;
3906 uint8_t txant;
3907 int i;
3908
3909 /* Use the first valid TX antenna. */
3910 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
3911
3912 memset(&linkq, 0, sizeof linkq)__builtin_memset((&linkq), (0), (sizeof linkq));
3913 linkq.id = wn->id;
3914 linkq.antmsk_1stream = txant;
3915 linkq.antmsk_2stream = IWN_ANT_AB((1 << 0) | (1 << 1));
3916 linkq.ampdu_max = IWN_AMPDU_MAX63;
3917 linkq.ampdu_threshold = 3;
3918 linkq.ampdu_limit = htole16(4000)((__uint16_t)(4000)); /* 4ms */
3919
3920 i = 0;
3921 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
3922 int txmcs;
3923 for (txmcs = ni->ni_txmcs; txmcs >= 0; txmcs--) {
3924 rinfo = &iwn_rates[iwn_mcs2ridx[txmcs]];
3925 linkq.retry[i].plcp = rinfo->ht_plcp;
3926 linkq.retry[i].rflags = rinfo->ht_flags;
3927
3928 /* XXX set correct ant mask for MIMO rates here */
3929 linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3930
3931 /* First two Tx attempts may use 40MHz/SGI. */
3932 if (i < 2) {
3933 if (iwn_rxon_ht40_enabled(sc))
3934 linkq.retry[i].rflags |= IWN_RFLAG_HT40(1 << 3);
3935 if (ieee80211_ra_use_ht_sgi(ni))
3936 linkq.retry[i].rflags |= IWN_RFLAG_SGI(1 << 5);
3937 }
3938
3939 if (++i >= IWN_MAX_TX_RETRIES16)
3940 break;
3941 }
3942 } else {
3943 int txrate;
3944 for (txrate = ni->ni_txrate; txrate >= 0; txrate--) {
3945 rinfo = &iwn_rates[wn->ridx[txrate]];
3946 linkq.retry[i].plcp = rinfo->plcp;
3947 linkq.retry[i].rflags = rinfo->flags;
3948 linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3949 if (++i >= IWN_MAX_TX_RETRIES16)
3950 break;
3951 }
3952 }
3953
3954 /* Fill the rest with the lowest basic rate. */
3955 rinfo = &iwn_rates[iwn_rval2ridx(ieee80211_min_basic_rate(ic))];
3956 while (i < IWN_MAX_TX_RETRIES16) {
3957 linkq.retry[i].plcp = rinfo->plcp;
3958 linkq.retry[i].rflags = rinfo->flags;
3959 linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
3960 i++;
3961 }
3962
3963 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY78, &linkq, sizeof linkq, 1);
3964}
3965
3966/*
3967 * Broadcast node is used to send group-addressed and management frames.
3968 */
3969int
3970iwn_add_broadcast_node(struct iwn_softc *sc, int async, int ridx)
3971{
3972 struct iwn_ops *ops = &sc->ops;
3973 struct iwn_node_info node;
3974 struct iwn_cmd_link_quality linkq;
3975 const struct iwn_rate *rinfo;
3976 uint8_t txant;
3977 int i, error;
3978
3979 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
3980 IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr)__builtin_memcpy((node.macaddr), (etherbroadcastaddr), (6));
3981 node.id = sc->broadcast_id;
3982 DPRINTF(("adding broadcast node\n"));
3983 if ((error = ops->add_node(sc, &node, async)) != 0)
3984 return error;
3985
3986 /* Use the first valid TX antenna. */
3987 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
3988
3989 memset(&linkq, 0, sizeof linkq)__builtin_memset((&linkq), (0), (sizeof linkq));
3990 linkq.id = sc->broadcast_id;
3991 linkq.antmsk_1stream = txant;
3992 linkq.antmsk_2stream = IWN_ANT_AB((1 << 0) | (1 << 1));
3993 linkq.ampdu_max = IWN_AMPDU_MAX_NO_AGG1;
3994 linkq.ampdu_threshold = 3;
3995 linkq.ampdu_limit = htole16(4000)((__uint16_t)(4000)); /* 4ms */
3996
3997 /* Use lowest mandatory bit-rate. */
3998 rinfo = &iwn_rates[ridx];
3999 linkq.retry[0].plcp = rinfo->plcp;
4000 linkq.retry[0].rflags = rinfo->flags;
4001 linkq.retry[0].rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
4002 /* Use same bit-rate for all TX retries. */
4003 for (i = 1; i < IWN_MAX_TX_RETRIES16; i++) {
4004 linkq.retry[i].plcp = linkq.retry[0].plcp;
4005 linkq.retry[i].rflags = linkq.retry[0].rflags;
4006 }
4007 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY78, &linkq, sizeof linkq, async);
4008}
4009
4010void
4011iwn_updateedca(struct ieee80211com *ic)
4012{
4013#define IWN_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
4014 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
4015 struct iwn_edca_params cmd;
4016 int aci;
4017
4018 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4019 cmd.flags = htole32(IWN_EDCA_UPDATE)((__uint32_t)((1 << 0)));
4020 for (aci = 0; aci < EDCA_NUM_AC4; aci++) {
4021 const struct ieee80211_edca_ac_params *ac =
4022 &ic->ic_edca_ac[aci];
4023 cmd.ac[aci].aifsn = ac->ac_aifsn;
4024 cmd.ac[aci].cwmin = htole16(IWN_EXP2(ac->ac_ecwmin))((__uint16_t)(IWN_EXP2(ac->ac_ecwmin)));
4025 cmd.ac[aci].cwmax = htole16(IWN_EXP2(ac->ac_ecwmax))((__uint16_t)(IWN_EXP2(ac->ac_ecwmax)));
4026 cmd.ac[aci].txoplimit =
4027 htole16(IEEE80211_TXOP_TO_US(ac->ac_txoplimit))((__uint16_t)(((ac->ac_txoplimit) * 32)));
4028 }
4029 (void)iwn_cmd(sc, IWN_CMD_EDCA_PARAMS19, &cmd, sizeof cmd, 1);
4030#undef IWN_EXP2
4031}
4032
4033void
4034iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on)
4035{
4036 struct iwn_cmd_led led;
4037
4038 /* Clear microcode LED ownership. */
4039 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))))))
;
4040
4041 led.which = which;
4042 led.unit = htole32(10000)((__uint32_t)(10000)); /* on/off in unit of 100ms */
4043 led.off = off;
4044 led.on = on;
4045 (void)iwn_cmd(sc, IWN_CMD_SET_LED72, &led, sizeof led, 1);
4046}
4047
4048/*
4049 * Set the critical temperature at which the firmware will stop the radio
4050 * and notify us.
4051 */
4052int
4053iwn_set_critical_temp(struct iwn_softc *sc)
4054{
4055 struct iwn_critical_temp crit;
4056 int32_t temp;
4057
4058 IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CTEMP_STOP_RF)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x05c)), ((
(1 << 3)))))
;
4059
4060 if (sc->hw_type == IWN_HW_REV_TYPE_51504)
4061 temp = (IWN_CTOK(110)((110) + 273) - sc->temp_off) * -5;
4062 else if (sc->hw_type == IWN_HW_REV_TYPE_49650)
4063 temp = IWN_CTOK(110)((110) + 273);
4064 else
4065 temp = 110;
4066 memset(&crit, 0, sizeof crit)__builtin_memset((&crit), (0), (sizeof crit));
4067 crit.tempR = htole32(temp)((__uint32_t)(temp));
4068 DPRINTF(("setting critical temperature to %d\n", temp));
4069 return iwn_cmd(sc, IWN_CMD_SET_CRITICAL_TEMP164, &crit, sizeof crit, 0);
4070}
4071
4072int
4073iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
4074{
4075 struct iwn_cmd_timing cmd;
4076 uint64_t val, mod;
4077
4078 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4079 memcpy(&cmd.tstamp, ni->ni_tstamp, sizeof (uint64_t))__builtin_memcpy((&cmd.tstamp), (ni->ni_tstamp), (sizeof
(uint64_t)))
;
4080 cmd.bintval = htole16(ni->ni_intval)((__uint16_t)(ni->ni_intval));
4081 cmd.lintval = htole16(10)((__uint16_t)(10));
4082
4083 /* Compute remaining time until next beacon. */
4084 val = (uint64_t)ni->ni_intval * IEEE80211_DUR_TU1024;
4085 mod = letoh64(cmd.tstamp)((__uint64_t)(cmd.tstamp)) % val;
4086 cmd.binitval = htole32((uint32_t)(val - mod))((__uint32_t)((uint32_t)(val - mod)));
4087
4088 DPRINTF(("timing bintval=%u, tstamp=%llu, init=%u\n",
4089 ni->ni_intval, letoh64(cmd.tstamp), (uint32_t)(val - mod)));
4090
4091 return iwn_cmd(sc, IWN_CMD_TIMING20, &cmd, sizeof cmd, 1);
4092}
4093
4094void
4095iwn4965_power_calibration(struct iwn_softc *sc, int temp)
4096{
4097 /* Adjust TX power if need be (delta >= 3 degC). */
4098 DPRINTF(("temperature %d->%d\n", sc->temp, temp));
4099 if (abs(temp - sc->temp) >= 3) {
4100 /* Record temperature of last calibration. */
4101 sc->temp = temp;
4102 (void)iwn4965_set_txpower(sc, 1);
4103 }
4104}
4105
4106/*
4107 * Set TX power for current channel (each rate has its own power settings).
4108 * This function takes into account the regulatory information from EEPROM,
4109 * the current temperature and the current voltage.
4110 */
4111int
4112iwn4965_set_txpower(struct iwn_softc *sc, int async)
4113{
4114/* Fixed-point arithmetic division using a n-bit fractional part. */
4115#define fdivround(a, b, n) \
4116 ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
4117/* Linear interpolation. */
4118#define interpolate(x, x1, y1, x2, y2, n) \
4119 ((y1) + fdivround(((int)(x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
4120
4121 static const int tdiv[IWN_NATTEN_GROUPS5] = { 9, 8, 8, 8, 6 };
4122 struct ieee80211com *ic = &sc->sc_ic;
4123 struct iwn_ucode_info *uc = &sc->ucode_info;
4124 struct ieee80211_channel *ch;
4125 struct iwn4965_cmd_txpower cmd;
4126 struct iwn4965_eeprom_chan_samples *chans;
4127 const uint8_t *rf_gain, *dsp_gain;
4128 int32_t vdiff, tdiff;
4129 int i, c, grp, maxpwr, is_ht40 = 0;
4130 uint8_t chan, ext_chan;
4131
4132 /* Retrieve current channel from last RXON. */
4133 chan = sc->rxon.chan;
4134 DPRINTF(("setting TX power for channel %d\n", chan));
4135 ch = &ic->ic_channels[chan];
4136
4137 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4138 cmd.band = IEEE80211_IS_CHAN_5GHZ(ch)(((ch)->ic_flags & 0x0100) != 0) ? 0 : 1;
4139 cmd.chan = chan;
4140
4141 if (IEEE80211_IS_CHAN_5GHZ(ch)(((ch)->ic_flags & 0x0100) != 0)) {
4142 maxpwr = sc->maxpwr5GHz;
4143 rf_gain = iwn4965_rf_gain_5ghz;
4144 dsp_gain = iwn4965_dsp_gain_5ghz;
4145 } else {
4146 maxpwr = sc->maxpwr2GHz;
4147 rf_gain = iwn4965_rf_gain_2ghz;
4148 dsp_gain = iwn4965_dsp_gain_2ghz;
4149 }
4150
4151 /* Compute voltage compensation. */
4152 vdiff = ((int32_t)letoh32(uc->volt)((__uint32_t)(uc->volt)) - sc->eeprom_voltage) / 7;
4153 if (vdiff > 0)
4154 vdiff *= 2;
4155 if (abs(vdiff) > 2)
4156 vdiff = 0;
4157 DPRINTF(("voltage compensation=%d (UCODE=%d, EEPROM=%d)\n",
4158 vdiff, letoh32(uc->volt), sc->eeprom_voltage));
4159
4160 /* Get channel attenuation group. */
4161 if (chan <= 20) /* 1-20 */
4162 grp = 4;
4163 else if (chan <= 43) /* 34-43 */
4164 grp = 0;
4165 else if (chan <= 70) /* 44-70 */
4166 grp = 1;
4167 else if (chan <= 124) /* 71-124 */
4168 grp = 2;
4169 else /* 125-200 */
4170 grp = 3;
4171 DPRINTF(("chan %d, attenuation group=%d\n", chan, grp));
4172
4173 /* Get channel sub-band. */
4174 for (i = 0; i < IWN_NBANDS8; i++)
4175 if (sc->bands[i].lo != 0 &&
4176 sc->bands[i].lo <= chan && chan <= sc->bands[i].hi)
4177 break;
4178 if (i == IWN_NBANDS8) /* Can't happen in real-life. */
4179 return EINVAL22;
4180 chans = sc->bands[i].chans;
4181 DPRINTF(("chan %d sub-band=%d\n", chan, i));
4182
4183 if (iwn_rxon_ht40_enabled(sc)) {
4184 is_ht40 = 1;
4185 if (le32toh(sc->rxon.flags)((__uint32_t)(sc->rxon.flags)) & IWN_RXON_HT_HT40MINUS(1 << 22))
4186 ext_chan = chan - 2;
4187 else
4188 ext_chan = chan + 2;
4189 } else
4190 ext_chan = chan;
4191
4192 for (c = 0; c < 2; c++) {
4193 uint8_t power, gain, temp;
4194 int maxchpwr, pwr, ridx, idx;
4195
4196 power = interpolate(ext_chan,
4197 chans[0].num, chans[0].samples[c][1].power,
4198 chans[1].num, chans[1].samples[c][1].power, 1);
4199 gain = interpolate(ext_chan,
4200 chans[0].num, chans[0].samples[c][1].gain,
4201 chans[1].num, chans[1].samples[c][1].gain, 1);
4202 temp = interpolate(ext_chan,
4203 chans[0].num, chans[0].samples[c][1].temp,
4204 chans[1].num, chans[1].samples[c][1].temp, 1);
4205 DPRINTF(("TX chain %d: power=%d gain=%d temp=%d\n",
4206 c, power, gain, temp));
4207
4208 /* Compute temperature compensation. */
4209 tdiff = ((sc->temp - temp) * 2) / tdiv[grp];
4210 DPRINTF(("temperature compensation=%d (current=%d, "
4211 "EEPROM=%d)\n", tdiff, sc->temp, temp));
4212
4213 for (ridx = 0; ridx <= IWN_RIDX_MAX32; ridx++) {
4214 /* Convert dBm to half-dBm. */
4215 if (is_ht40)
4216 maxchpwr = sc->maxpwr40[chan] * 2;
4217 else
4218 maxchpwr = sc->maxpwr[chan] * 2;
4219#ifdef notyet
4220 if (ridx > iwn_mcs2ridx[7] && ridx < iwn_mcs2ridx[16])
4221 maxchpwr -= 6; /* MIMO 2T: -3dB */
4222#endif
4223
4224 pwr = maxpwr;
4225
4226 /* Adjust TX power based on rate. */
4227 if ((ridx % 8) == 5)
4228 pwr -= 15; /* OFDM48: -7.5dB */
4229 else if ((ridx % 8) == 6)
4230 pwr -= 17; /* OFDM54: -8.5dB */
4231 else if ((ridx % 8) == 7)
4232 pwr -= 20; /* OFDM60: -10dB */
4233 else
4234 pwr -= 10; /* Others: -5dB */
4235
4236 /* Do not exceed channel max TX power. */
4237 if (pwr > maxchpwr)
4238 pwr = maxchpwr;
4239
4240 idx = gain - (pwr - power) - tdiff - vdiff;
4241 if (ridx > iwn_mcs2ridx[7]) /* MIMO */
4242 idx += (int32_t)letoh32(uc->atten[grp][c])((__uint32_t)(uc->atten[grp][c]));
4243
4244 if (cmd.band == 0)
4245 idx += 9; /* 5GHz */
4246 if (ridx == IWN_RIDX_MAX32)
4247 idx += 5; /* CCK */
4248
4249 /* Make sure idx stays in a valid range. */
4250 if (idx < 0)
4251 idx = 0;
4252 else if (idx > IWN4965_MAX_PWR_INDEX107)
4253 idx = IWN4965_MAX_PWR_INDEX107;
4254
4255 DPRINTF(("TX chain %d, rate idx %d: power=%d\n",
4256 c, ridx, idx));
4257 cmd.power[ridx].rf_gain[c] = rf_gain[idx];
4258 cmd.power[ridx].dsp_gain[c] = dsp_gain[idx];
4259 }
4260 }
4261
4262 DPRINTF(("setting TX power for chan %d\n", chan));
4263 return iwn_cmd(sc, IWN_CMD_TXPOWER151, &cmd, sizeof cmd, async);
4264
4265#undef interpolate
4266#undef fdivround
4267}
4268
4269int
4270iwn5000_set_txpower(struct iwn_softc *sc, int async)
4271{
4272 struct iwn5000_cmd_txpower cmd;
4273
4274 /*
4275 * TX power calibration is handled automatically by the firmware
4276 * for 5000 Series.
4277 */
4278 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4279 cmd.global_limit = 2 * IWN5000_TXPOWER_MAX_DBM16; /* 16 dBm */
4280 cmd.flags = IWN5000_TXPOWER_NO_CLOSED(1 << 6);
4281 cmd.srv_limit = IWN5000_TXPOWER_AUTO0x7f;
4282 DPRINTF(("setting TX power\n"));
4283 return iwn_cmd(sc, IWN_CMD_TXPOWER_DBM149, &cmd, sizeof cmd, async);
4284}
4285
4286/*
4287 * Retrieve the maximum RSSI (in dBm) among receivers.
4288 */
4289int
4290iwn4965_get_rssi(const struct iwn_rx_stat *stat)
4291{
4292 struct iwn4965_rx_phystat *phy = (void *)stat->phybuf;
4293 uint8_t mask, agc;
4294 int rssi;
4295
4296 mask = (letoh16(phy->antenna)((__uint16_t)(phy->antenna)) >> 4) & IWN_ANT_ABC((1 << 0) | (1 << 1) | (1 << 2));
4297 agc = (letoh16(phy->agc)((__uint16_t)(phy->agc)) >> 7) & 0x7f;
4298
4299 rssi = 0;
4300 if (mask & IWN_ANT_A(1 << 0))
4301 rssi = MAX(rssi, phy->rssi[0])(((rssi)>(phy->rssi[0]))?(rssi):(phy->rssi[0]));
4302 if (mask & IWN_ANT_B(1 << 1))
4303 rssi = MAX(rssi, phy->rssi[2])(((rssi)>(phy->rssi[2]))?(rssi):(phy->rssi[2]));
4304 if (mask & IWN_ANT_C(1 << 2))
4305 rssi = MAX(rssi, phy->rssi[4])(((rssi)>(phy->rssi[4]))?(rssi):(phy->rssi[4]));
4306
4307 return rssi - agc - IWN_RSSI_TO_DBM44;
4308}
4309
4310int
4311iwn5000_get_rssi(const struct iwn_rx_stat *stat)
4312{
4313 struct iwn5000_rx_phystat *phy = (void *)stat->phybuf;
4314 uint8_t agc;
4315 int rssi;
4316
4317 agc = (letoh32(phy->agc)((__uint32_t)(phy->agc)) >> 9) & 0x7f;
4318
4319 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)
)
4320 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)
)
;
4321 rssi = MAX(letoh16(phy->rssi[2]) & 0xff, rssi)(((((__uint16_t)(phy->rssi[2])) & 0xff)>(rssi))?(((
__uint16_t)(phy->rssi[2])) & 0xff):(rssi))
;
4322
4323 return rssi - agc - IWN_RSSI_TO_DBM44;
4324}
4325
4326/*
4327 * Retrieve the average noise (in dBm) among receivers.
4328 */
4329int
4330iwn_get_noise(const struct iwn_rx_general_stats *stats)
4331{
4332 int i, total, nbant, noise;
4333
4334 total = nbant = 0;
4335 for (i = 0; i < 3; i++) {
4336 if ((noise = letoh32(stats->noise[i])((__uint32_t)(stats->noise[i])) & 0xff) == 0)
4337 continue;
4338 total += noise;
4339 nbant++;
4340 }
4341 /* There should be at least one antenna but check anyway. */
4342 return (nbant == 0) ? -127 : (total / nbant) - 107;
4343}
4344
4345/*
4346 * Compute temperature (in degC) from last received statistics.
4347 */
4348int
4349iwn4965_get_temperature(struct iwn_softc *sc)
4350{
4351 struct iwn_ucode_info *uc = &sc->ucode_info;
4352 int32_t r1, r2, r3, r4, temp;
4353
4354 if (sc->rx_stats_flags & IWN_STATS_FLAGS_BAND_HT400x08) {
4355 r1 = letoh32(uc->temp[0].chan40MHz)((__uint32_t)(uc->temp[0].chan40MHz));
4356 r2 = letoh32(uc->temp[1].chan40MHz)((__uint32_t)(uc->temp[1].chan40MHz));
4357 r3 = letoh32(uc->temp[2].chan40MHz)((__uint32_t)(uc->temp[2].chan40MHz));
4358 } else {
4359 r1 = letoh32(uc->temp[0].chan20MHz)((__uint32_t)(uc->temp[0].chan20MHz));
4360 r2 = letoh32(uc->temp[1].chan20MHz)((__uint32_t)(uc->temp[1].chan20MHz));
4361 r3 = letoh32(uc->temp[2].chan20MHz)((__uint32_t)(uc->temp[2].chan20MHz));
4362 }
4363 r4 = letoh32(sc->rawtemp)((__uint32_t)(sc->rawtemp));
4364
4365 if (r1 == r3) /* Prevents division by 0 (should not happen). */
4366 return 0;
4367
4368 /* Sign-extend 23-bit R4 value to 32-bit. */
4369 r4 = ((r4 & 0xffffff) ^ 0x800000) - 0x800000;
4370 /* Compute temperature in Kelvin. */
4371 temp = (259 * (r4 - r2)) / (r3 - r1);
4372 temp = (temp * 97) / 100 + 8;
4373
4374 DPRINTF(("temperature %dK/%dC\n", temp, IWN_KTOC(temp)));
4375 return IWN_KTOC(temp)((temp) - 273);
4376}
4377
4378int
4379iwn5000_get_temperature(struct iwn_softc *sc)
4380{
4381 int32_t temp;
4382
4383 /*
4384 * Temperature is not used by the driver for 5000 Series because
4385 * TX power calibration is handled by firmware.
4386 */
4387 temp = letoh32(sc->rawtemp)((__uint32_t)(sc->rawtemp));
4388 if (sc->hw_type == IWN_HW_REV_TYPE_51504) {
4389 temp = (temp / -5) + sc->temp_off;
4390 temp = IWN_KTOC(temp)((temp) - 273);
4391 }
4392 return temp;
4393}
4394
4395/*
4396 * Initialize sensitivity calibration state machine.
4397 */
4398int
4399iwn_init_sensitivity(struct iwn_softc *sc)
4400{
4401 struct iwn_ops *ops = &sc->ops;
4402 struct iwn_calib_state *calib = &sc->calib;
4403 uint32_t flags;
4404 int error;
4405
4406 /* Reset calibration state machine. */
4407 memset(calib, 0, sizeof (*calib))__builtin_memset((calib), (0), (sizeof (*calib)));
4408 calib->state = IWN_CALIB_STATE_INIT0;
4409 calib->cck_state = IWN_CCK_STATE_HIFA2;
4410 /* Set initial correlation values. */
4411 calib->ofdm_x1 = sc->limits->min_ofdm_x1;
4412 calib->ofdm_mrc_x1 = sc->limits->min_ofdm_mrc_x1;
4413 calib->ofdm_x4 = sc->limits->min_ofdm_x4;
4414 calib->ofdm_mrc_x4 = sc->limits->min_ofdm_mrc_x4;
4415 calib->cck_x4 = 125;
4416 calib->cck_mrc_x4 = sc->limits->min_cck_mrc_x4;
4417 calib->energy_cck = sc->limits->energy_cck;
4418
4419 /* Write initial sensitivity. */
4420 if ((error = iwn_send_sensitivity(sc)) != 0)
4421 return error;
4422
4423 /* Write initial gains. */
4424 if ((error = ops->init_gains(sc)) != 0)
4425 return error;
4426
4427 /* Request statistics at each beacon interval. */
4428 flags = 0;
4429 DPRINTFN(2, ("sending request for statistics\n"));
4430 return iwn_cmd(sc, IWN_CMD_GET_STATISTICS156, &flags, sizeof flags, 1);
4431}
4432
4433/*
4434 * Collect noise and RSSI statistics for the first 20 beacons received
4435 * after association and use them to determine connected antennas and
4436 * to set differential gains.
4437 */
4438void
4439iwn_collect_noise(struct iwn_softc *sc,
4440 const struct iwn_rx_general_stats *stats)
4441{
4442 struct iwn_ops *ops = &sc->ops;
4443 struct iwn_calib_state *calib = &sc->calib;
4444 uint32_t val;
4445 int i;
4446
4447 /* Accumulate RSSI and noise for all 3 antennas. */
4448 for (i = 0; i < 3; i++) {
4449 calib->rssi[i] += letoh32(stats->rssi[i])((__uint32_t)(stats->rssi[i])) & 0xff;
4450 calib->noise[i] += letoh32(stats->noise[i])((__uint32_t)(stats->noise[i])) & 0xff;
4451 }
4452 /* NB: We update differential gains only once after 20 beacons. */
4453 if (++calib->nbeacons < 20)
4454 return;
4455
4456 /* Determine highest average RSSI. */
4457 val = MAX(calib->rssi[0], calib->rssi[1])(((calib->rssi[0])>(calib->rssi[1]))?(calib->rssi
[0]):(calib->rssi[1]))
;
4458 val = MAX(calib->rssi[2], val)(((calib->rssi[2])>(val))?(calib->rssi[2]):(val));
4459
4460 /* Determine which antennas are connected. */
4461 sc->chainmask = sc->rxchainmask;
4462 for (i = 0; i < 3; i++)
4463 if (val - calib->rssi[i] > 15 * 20)
4464 sc->chainmask &= ~(1 << i);
4465 DPRINTF(("RX chains mask: theoretical=0x%x, actual=0x%x\n",
4466 sc->rxchainmask, sc->chainmask));
4467
4468 /* If none of the TX antennas are connected, keep at least one. */
4469 if ((sc->chainmask & sc->txchainmask) == 0)
4470 sc->chainmask |= IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
4471
4472 (void)ops->set_gains(sc);
4473 calib->state = IWN_CALIB_STATE_RUN2;
4474
4475#ifdef notyet
4476 /* XXX Disable RX chains with no antennas connected. */
4477 sc->rxon.rxchain = htole16(IWN_RXCHAIN_SEL(sc->chainmask))((__uint16_t)(IWN_RXCHAIN_SEL(sc->chainmask)));
4478 (void)iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
4479#endif
4480
4481 /* Enable power-saving mode if requested by user. */
4482 if (sc->sc_ic.ic_flags & IEEE80211_F_PMGTON0x00000400)
4483 (void)iwn_set_pslevel(sc, 0, 3, 1);
4484}
4485
4486int
4487iwn4965_init_gains(struct iwn_softc *sc)
4488{
4489 struct iwn_phy_calib_gain cmd;
4490
4491 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4492 cmd.code = IWN4965_PHY_CALIB_DIFF_GAIN7;
4493 /* Differential gains initially set to 0 for all 3 antennas. */
4494 DPRINTF(("setting initial differential gains\n"));
4495 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4496}
4497
4498int
4499iwn5000_init_gains(struct iwn_softc *sc)
4500{
4501 struct iwn_phy_calib cmd;
4502
4503 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4504 cmd.code = sc->reset_noise_gain;
4505 cmd.ngroups = 1;
4506 cmd.isvalid = 1;
4507 DPRINTF(("setting initial differential gains\n"));
4508 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4509}
4510
4511int
4512iwn4965_set_gains(struct iwn_softc *sc)
4513{
4514 struct iwn_calib_state *calib = &sc->calib;
4515 struct iwn_phy_calib_gain cmd;
4516 int i, delta, noise;
4517
4518 /* Get minimal noise among connected antennas. */
4519 noise = INT_MAX0x7fffffff; /* NB: There's at least one antenna. */
4520 for (i = 0; i < 3; i++)
4521 if (sc->chainmask & (1 << i))
4522 noise = MIN(calib->noise[i], noise)(((calib->noise[i])<(noise))?(calib->noise[i]):(noise
))
;
4523
4524 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4525 cmd.code = IWN4965_PHY_CALIB_DIFF_GAIN7;
4526 /* Set differential gains for connected antennas. */
4527 for (i = 0; i < 3; i++) {
4528 if (sc->chainmask & (1 << i)) {
4529 /* Compute attenuation (in unit of 1.5dB). */
4530 delta = (noise - (int32_t)calib->noise[i]) / 30;
4531 /* NB: delta <= 0 */
4532 /* Limit to [-4.5dB,0]. */
4533 cmd.gain[i] = MIN(abs(delta), 3)(((abs(delta))<(3))?(abs(delta)):(3));
4534 if (delta < 0)
4535 cmd.gain[i] |= 1 << 2; /* sign bit */
4536 }
4537 }
4538 DPRINTF(("setting differential gains Ant A/B/C: %x/%x/%x (%x)\n",
4539 cmd.gain[0], cmd.gain[1], cmd.gain[2], sc->chainmask));
4540 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4541}
4542
4543int
4544iwn5000_set_gains(struct iwn_softc *sc)
4545{
4546 struct iwn_calib_state *calib = &sc->calib;
4547 struct iwn_phy_calib_gain cmd;
4548 int i, ant, div, delta;
4549
4550 /* We collected 20 beacons and !=6050 need a 1.5 factor. */
4551 div = (sc->hw_type == IWN_HW_REV_TYPE_60508) ? 20 : 30;
4552
4553 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4554 cmd.code = sc->noise_gain;
4555 cmd.ngroups = 1;
4556 cmd.isvalid = 1;
4557 /*
4558 * Get first available RX antenna as referential.
4559 * IWN_LSB() return values start with 1, but antenna gain array
4560 * cmd.gain[] and noise array calib->noise[] start with 0.
4561 */
4562 ant = IWN_LSB(sc->rxchainmask)((((sc->rxchainmask) - 1) & (sc->rxchainmask)) ^ (sc
->rxchainmask))
- 1;
4563
4564 /* Set differential gains for other antennas. */
4565 for (i = ant + 1; i < 3; i++) {
4566 if (sc->chainmask & (1 << i)) {
4567 /* The delta is relative to antenna "ant". */
4568 delta = ((int32_t)calib->noise[ant] -
4569 (int32_t)calib->noise[i]) / div;
4570 DPRINTF(("Ant[%d] vs. Ant[%d]: delta %d\n", ant, i, delta));
4571 /* Limit to [-4.5dB,+4.5dB]. */
4572 cmd.gain[i] = MIN(abs(delta), 3)(((abs(delta))<(3))?(abs(delta)):(3));
4573 if (delta < 0)
4574 cmd.gain[i] |= 1 << 2; /* sign bit */
4575 DPRINTF(("Setting differential gains for antenna %d: %x\n",
4576 i, cmd.gain[i]));
4577 }
4578 }
4579 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 1);
4580}
4581
4582/*
4583 * Tune RF RX sensitivity based on the number of false alarms detected
4584 * during the last beacon period.
4585 */
4586void
4587iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
4588{
4589#define inc(val, inc, max) \
4590 if ((val) < (max)) { \
4591 if ((val) < (max) - (inc)) \
4592 (val) += (inc); \
4593 else \
4594 (val) = (max); \
4595 needs_update = 1; \
4596 }
4597#define dec(val, dec, min) \
4598 if ((val) > (min)) { \
4599 if ((val) > (min) + (dec)) \
4600 (val) -= (dec); \
4601 else \
4602 (val) = (min); \
4603 needs_update = 1; \
4604 }
4605
4606 const struct iwn_sensitivity_limits *limits = sc->limits;
4607 struct iwn_calib_state *calib = &sc->calib;
4608 uint32_t val, rxena, fa;
4609 uint32_t energy[3], energy_min;
4610 uint8_t noise[3], noise_ref;
4611 int i, needs_update = 0;
4612
4613 /* Check that we've been enabled long enough. */
4614 if ((rxena = letoh32(stats->general.load)((__uint32_t)(stats->general.load))) == 0)
4615 return;
4616
4617 /* Compute number of false alarms since last call for OFDM. */
4618 fa = letoh32(stats->ofdm.bad_plcp)((__uint32_t)(stats->ofdm.bad_plcp)) - calib->bad_plcp_ofdm;
4619 fa += letoh32(stats->ofdm.fa)((__uint32_t)(stats->ofdm.fa)) - calib->fa_ofdm;
4620 fa *= 200 * IEEE80211_DUR_TU1024; /* 200TU */
4621
4622 /* Save counters values for next call. */
4623 calib->bad_plcp_ofdm = letoh32(stats->ofdm.bad_plcp)((__uint32_t)(stats->ofdm.bad_plcp));
4624 calib->fa_ofdm = letoh32(stats->ofdm.fa)((__uint32_t)(stats->ofdm.fa));
4625
4626 if (fa > 50 * rxena) {
4627 /* High false alarm count, decrease sensitivity. */
4628 DPRINTFN(2, ("OFDM high false alarm count: %u\n", fa));
4629 inc(calib->ofdm_x1, 1, limits->max_ofdm_x1);
4630 inc(calib->ofdm_mrc_x1, 1, limits->max_ofdm_mrc_x1);
4631 inc(calib->ofdm_x4, 1, limits->max_ofdm_x4);
4632 inc(calib->ofdm_mrc_x4, 1, limits->max_ofdm_mrc_x4);
4633
4634 } else if (fa < 5 * rxena) {
4635 /* Low false alarm count, increase sensitivity. */
4636 DPRINTFN(2, ("OFDM low false alarm count: %u\n", fa));
4637 dec(calib->ofdm_x1, 1, limits->min_ofdm_x1);
4638 dec(calib->ofdm_mrc_x1, 1, limits->min_ofdm_mrc_x1);
4639 dec(calib->ofdm_x4, 1, limits->min_ofdm_x4);
4640 dec(calib->ofdm_mrc_x4, 1, limits->min_ofdm_mrc_x4);
4641 }
4642
4643 /* Compute maximum noise among 3 receivers. */
4644 for (i = 0; i < 3; i++)
4645 noise[i] = (letoh32(stats->general.noise[i])((__uint32_t)(stats->general.noise[i])) >> 8) & 0xff;
4646 val = MAX(noise[0], noise[1])(((noise[0])>(noise[1]))?(noise[0]):(noise[1]));
4647 val = MAX(noise[2], val)(((noise[2])>(val))?(noise[2]):(val));
4648 /* Insert it into our samples table. */
4649 calib->noise_samples[calib->cur_noise_sample] = val;
4650 calib->cur_noise_sample = (calib->cur_noise_sample + 1) % 20;
4651
4652 /* Compute maximum noise among last 20 samples. */
4653 noise_ref = calib->noise_samples[0];
4654 for (i = 1; i < 20; i++)
4655 noise_ref = MAX(noise_ref, calib->noise_samples[i])(((noise_ref)>(calib->noise_samples[i]))?(noise_ref):(calib
->noise_samples[i]))
;
4656
4657 /* Compute maximum energy among 3 receivers. */
4658 for (i = 0; i < 3; i++)
4659 energy[i] = letoh32(stats->general.energy[i])((__uint32_t)(stats->general.energy[i]));
4660 val = MIN(energy[0], energy[1])(((energy[0])<(energy[1]))?(energy[0]):(energy[1]));
4661 val = MIN(energy[2], val)(((energy[2])<(val))?(energy[2]):(val));
4662 /* Insert it into our samples table. */
4663 calib->energy_samples[calib->cur_energy_sample] = val;
4664 calib->cur_energy_sample = (calib->cur_energy_sample + 1) % 10;
4665
4666 /* Compute minimum energy among last 10 samples. */
4667 energy_min = calib->energy_samples[0];
4668 for (i = 1; i < 10; i++)
4669 energy_min = MAX(energy_min, calib->energy_samples[i])(((energy_min)>(calib->energy_samples[i]))?(energy_min)
:(calib->energy_samples[i]))
;
4670 energy_min += 6;
4671
4672 /* Compute number of false alarms since last call for CCK. */
4673 fa = letoh32(stats->cck.bad_plcp)((__uint32_t)(stats->cck.bad_plcp)) - calib->bad_plcp_cck;
4674 fa += letoh32(stats->cck.fa)((__uint32_t)(stats->cck.fa)) - calib->fa_cck;
4675 fa *= 200 * IEEE80211_DUR_TU1024; /* 200TU */
4676
4677 /* Save counters values for next call. */
4678 calib->bad_plcp_cck = letoh32(stats->cck.bad_plcp)((__uint32_t)(stats->cck.bad_plcp));
4679 calib->fa_cck = letoh32(stats->cck.fa)((__uint32_t)(stats->cck.fa));
4680
4681 if (fa > 50 * rxena) {
4682 /* High false alarm count, decrease sensitivity. */
4683 DPRINTFN(2, ("CCK high false alarm count: %u\n", fa));
4684 calib->cck_state = IWN_CCK_STATE_HIFA2;
4685 calib->low_fa = 0;
4686
4687 if (calib->cck_x4 > 160) {
4688 calib->noise_ref = noise_ref;
4689 if (calib->energy_cck > 2)
4690 dec(calib->energy_cck, 2, energy_min);
4691 }
4692 if (calib->cck_x4 < 160) {
4693 calib->cck_x4 = 161;
4694 needs_update = 1;
4695 } else
4696 inc(calib->cck_x4, 3, limits->max_cck_x4);
4697
4698 inc(calib->cck_mrc_x4, 3, limits->max_cck_mrc_x4);
4699
4700 } else if (fa < 5 * rxena) {
4701 /* Low false alarm count, increase sensitivity. */
4702 DPRINTFN(2, ("CCK low false alarm count: %u\n", fa));
4703 calib->cck_state = IWN_CCK_STATE_LOFA1;
4704 calib->low_fa++;
4705
4706 if (calib->cck_state != IWN_CCK_STATE_INIT0 &&
4707 (((int32_t)calib->noise_ref - (int32_t)noise_ref) > 2 ||
4708 calib->low_fa > 100)) {
4709 inc(calib->energy_cck, 2, limits->min_energy_cck);
4710 dec(calib->cck_x4, 3, limits->min_cck_x4);
4711 dec(calib->cck_mrc_x4, 3, limits->min_cck_mrc_x4);
4712 }
4713 } else {
4714 /* Not worth to increase or decrease sensitivity. */
4715 DPRINTFN(2, ("CCK normal false alarm count: %u\n", fa));
4716 calib->low_fa = 0;
4717 calib->noise_ref = noise_ref;
4718
4719 if (calib->cck_state == IWN_CCK_STATE_HIFA2) {
4720 /* Previous interval had many false alarms. */
4721 dec(calib->energy_cck, 8, energy_min);
4722 }
4723 calib->cck_state = IWN_CCK_STATE_INIT0;
4724 }
4725
4726 if (needs_update)
4727 (void)iwn_send_sensitivity(sc);
4728#undef dec
4729#undef inc
4730}
4731
4732int
4733iwn_send_sensitivity(struct iwn_softc *sc)
4734{
4735 struct iwn_calib_state *calib = &sc->calib;
4736 struct iwn_enhanced_sensitivity_cmd cmd;
4737 int len;
4738
4739 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4740 len = sizeof (struct iwn_sensitivity_cmd);
4741 cmd.which = IWN_SENSITIVITY_WORKTBL1;
4742 /* OFDM modulation. */
4743 cmd.corr_ofdm_x1 = htole16(calib->ofdm_x1)((__uint16_t)(calib->ofdm_x1));
4744 cmd.corr_ofdm_mrc_x1 = htole16(calib->ofdm_mrc_x1)((__uint16_t)(calib->ofdm_mrc_x1));
4745 cmd.corr_ofdm_x4 = htole16(calib->ofdm_x4)((__uint16_t)(calib->ofdm_x4));
4746 cmd.corr_ofdm_mrc_x4 = htole16(calib->ofdm_mrc_x4)((__uint16_t)(calib->ofdm_mrc_x4));
4747 cmd.energy_ofdm = htole16(sc->limits->energy_ofdm)((__uint16_t)(sc->limits->energy_ofdm));
4748 cmd.energy_ofdm_th = htole16(62)((__uint16_t)(62));
4749 /* CCK modulation. */
4750 cmd.corr_cck_x4 = htole16(calib->cck_x4)((__uint16_t)(calib->cck_x4));
4751 cmd.corr_cck_mrc_x4 = htole16(calib->cck_mrc_x4)((__uint16_t)(calib->cck_mrc_x4));
4752 cmd.energy_cck = htole16(calib->energy_cck)((__uint16_t)(calib->energy_cck));
4753 /* Barker modulation: use default values. */
4754 cmd.corr_barker = htole16(190)((__uint16_t)(190));
4755 cmd.corr_barker_mrc = htole16(390)((__uint16_t)(390));
4756 if (!(sc->sc_flags & IWN_FLAG_ENH_SENS(1 << 7)))
4757 goto send;
4758 /* Enhanced sensitivity settings. */
4759 len = sizeof (struct iwn_enhanced_sensitivity_cmd);
4760 cmd.ofdm_det_slope_mrc = htole16(668)((__uint16_t)(668));
4761 cmd.ofdm_det_icept_mrc = htole16(4)((__uint16_t)(4));
4762 cmd.ofdm_det_slope = htole16(486)((__uint16_t)(486));
4763 cmd.ofdm_det_icept = htole16(37)((__uint16_t)(37));
4764 cmd.cck_det_slope_mrc = htole16(853)((__uint16_t)(853));
4765 cmd.cck_det_icept_mrc = htole16(4)((__uint16_t)(4));
4766 cmd.cck_det_slope = htole16(476)((__uint16_t)(476));
4767 cmd.cck_det_icept = htole16(99)((__uint16_t)(99));
4768send:
4769 return iwn_cmd(sc, IWN_CMD_SET_SENSITIVITY168, &cmd, len, 1);
4770}
4771
4772/*
4773 * Set STA mode power saving level (between 0 and 5).
4774 * Level 0 is CAM (Continuously Aware Mode), 5 is for maximum power saving.
4775 */
4776int
4777iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async)
4778{
4779 struct iwn_pmgt_cmd cmd;
4780 const struct iwn_pmgt *pmgt;
4781 uint32_t max, skip_dtim;
4782 pcireg_t reg;
4783 int i;
4784
4785 /* Select which PS parameters to use. */
4786 if (dtim <= 2)
4787 pmgt = &iwn_pmgt[0][level];
4788 else if (dtim <= 10)
4789 pmgt = &iwn_pmgt[1][level];
4790 else
4791 pmgt = &iwn_pmgt[2][level];
4792
4793 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4794 if (level != 0) /* not CAM */
4795 cmd.flags |= htole16(IWN_PS_ALLOW_SLEEP)((__uint16_t)((1 << 0)));
4796 if (level == 5)
4797 cmd.flags |= htole16(IWN_PS_FAST_PD)((__uint16_t)((1 << 4)));
4798 /* Retrieve PCIe Active State Power Management (ASPM). */
4799 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
4800 sc->sc_cap_off + PCI_PCIE_LCSR0x10);
4801 if (!(reg & PCI_PCIE_LCSR_ASPM_L0S0x00000001)) /* L0s Entry disabled. */
4802 cmd.flags |= htole16(IWN_PS_PCI_PMGT)((__uint16_t)((1 << 3)));
4803 cmd.rxtimeout = htole32(pmgt->rxtimeout * 1024)((__uint32_t)(pmgt->rxtimeout * 1024));
4804 cmd.txtimeout = htole32(pmgt->txtimeout * 1024)((__uint32_t)(pmgt->txtimeout * 1024));
4805
4806 if (dtim == 0) {
4807 dtim = 1;
4808 skip_dtim = 0;
4809 } else
4810 skip_dtim = pmgt->skip_dtim;
4811 if (skip_dtim != 0) {
4812 cmd.flags |= htole16(IWN_PS_SLEEP_OVER_DTIM)((__uint16_t)((1 << 2)));
4813 max = pmgt->intval[4];
4814 if (max == (uint32_t)-1)
4815 max = dtim * (skip_dtim + 1);
4816 else if (max > dtim)
4817 max = (max / dtim) * dtim;
4818 } else
4819 max = dtim;
4820 for (i = 0; i < 5; i++)
4821 cmd.intval[i] = htole32(MIN(max, pmgt->intval[i]))((__uint32_t)((((max)<(pmgt->intval[i]))?(max):(pmgt->
intval[i]))))
;
4822
4823 DPRINTF(("setting power saving level to %d\n", level));
4824 return iwn_cmd(sc, IWN_CMD_SET_POWER_MODE119, &cmd, sizeof cmd, async);
4825}
4826
4827int
4828iwn_send_btcoex(struct iwn_softc *sc)
4829{
4830 struct iwn_bluetooth cmd;
4831
4832 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4833 cmd.flags = IWN_BT_COEX_CHAN_ANN(1 << 0) | IWN_BT_COEX_BT_PRIO(1 << 1);
4834 cmd.lead_time = IWN_BT_LEAD_TIME_DEF30;
4835 cmd.max_kill = IWN_BT_MAX_KILL_DEF5;
4836 DPRINTF(("configuring bluetooth coexistence\n"));
4837 return iwn_cmd(sc, IWN_CMD_BT_COEX155, &cmd, sizeof(cmd), 0);
4838}
4839
4840int
4841iwn_send_advanced_btcoex(struct iwn_softc *sc)
4842{
4843 static const uint32_t btcoex_3wire[12] = {
4844 0xaaaaaaaa, 0xaaaaaaaa, 0xaeaaaaaa, 0xaaaaaaaa,
4845 0xcc00ff28, 0x0000aaaa, 0xcc00aaaa, 0x0000aaaa,
4846 0xc0004000, 0x00004000, 0xf0005000, 0xf0005000,
4847 };
4848 struct iwn_btcoex_priotable btprio;
4849 struct iwn_btcoex_prot btprot;
4850 int error, i;
4851
4852 if (sc->hw_type == IWN_HW_REV_TYPE_203012 ||
4853 sc->hw_type == IWN_HW_REV_TYPE_13518) {
4854 struct iwn2000_btcoex_config btconfig;
4855
4856 memset(&btconfig, 0, sizeof btconfig)__builtin_memset((&btconfig), (0), (sizeof btconfig));
4857 btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION1 |
4858 (IWN_BT_COEX6000_MODE_3W2 << IWN_BT_COEX6000_MODE_SHIFT3) |
4859 IWN_BT_SYNC_2_BT_DISABLE(1<<7);
4860 btconfig.max_kill = 5;
4861 btconfig.bt3_t7_timer = 1;
4862 btconfig.kill_ack = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4863 btconfig.kill_cts = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4864 btconfig.sample_time = 2;
4865 btconfig.bt3_t2_timer = 0xc;
4866 for (i = 0; i < 12; i++)
4867 btconfig.lookup_table[i] = htole32(btcoex_3wire[i])((__uint32_t)(btcoex_3wire[i]));
4868 btconfig.valid = htole16(0xff)((__uint16_t)(0xff));
4869 btconfig.prio_boost = htole32(0xf0)((__uint32_t)(0xf0));
4870 DPRINTF(("configuring advanced bluetooth coexistence\n"));
4871 error = iwn_cmd(sc, IWN_CMD_BT_COEX155, &btconfig,
4872 sizeof(btconfig), 1);
4873 if (error != 0)
4874 return (error);
4875 } else {
4876 struct iwn6000_btcoex_config btconfig;
4877
4878 memset(&btconfig, 0, sizeof btconfig)__builtin_memset((&btconfig), (0), (sizeof btconfig));
4879 btconfig.flags = IWN_BT_COEX6000_CHAN_INHIBITION1 |
4880 (IWN_BT_COEX6000_MODE_3W2 << IWN_BT_COEX6000_MODE_SHIFT3) |
4881 IWN_BT_SYNC_2_BT_DISABLE(1<<7);
4882 btconfig.max_kill = 5;
4883 btconfig.bt3_t7_timer = 1;
4884 btconfig.kill_ack = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4885 btconfig.kill_cts = htole32(0xffff0000)((__uint32_t)(0xffff0000));
4886 btconfig.sample_time = 2;
4887 btconfig.bt3_t2_timer = 0xc;
4888 for (i = 0; i < 12; i++)
4889 btconfig.lookup_table[i] = htole32(btcoex_3wire[i])((__uint32_t)(btcoex_3wire[i]));
4890 btconfig.valid = htole16(0xff)((__uint16_t)(0xff));
4891 btconfig.prio_boost = 0xf0;
4892 DPRINTF(("configuring advanced bluetooth coexistence\n"));
4893 error = iwn_cmd(sc, IWN_CMD_BT_COEX155, &btconfig,
4894 sizeof(btconfig), 1);
4895 if (error != 0)
4896 return (error);
4897 }
4898
4899 memset(&btprio, 0, sizeof btprio)__builtin_memset((&btprio), (0), (sizeof btprio));
4900 btprio.calib_init1 = 0x6;
4901 btprio.calib_init2 = 0x7;
4902 btprio.calib_periodic_low1 = 0x2;
4903 btprio.calib_periodic_low2 = 0x3;
4904 btprio.calib_periodic_high1 = 0x4;
4905 btprio.calib_periodic_high2 = 0x5;
4906 btprio.dtim = 0x6;
4907 btprio.scan52 = 0x8;
4908 btprio.scan24 = 0xa;
4909 error = iwn_cmd(sc, IWN_CMD_BT_COEX_PRIOTABLE204, &btprio, sizeof(btprio),
4910 1);
4911 if (error != 0)
4912 return (error);
4913
4914 /* Force BT state machine change */
4915 memset(&btprot, 0, sizeof btprot)__builtin_memset((&btprot), (0), (sizeof btprot));
4916 btprot.open = 1;
4917 btprot.type = 1;
4918 error = iwn_cmd(sc, IWN_CMD_BT_COEX_PROT205, &btprot, sizeof(btprot), 1);
4919 if (error != 0)
4920 return (error);
4921
4922 btprot.open = 0;
4923 return (iwn_cmd(sc, IWN_CMD_BT_COEX_PROT205, &btprot, sizeof(btprot), 1));
4924}
4925
4926int
4927iwn5000_runtime_calib(struct iwn_softc *sc)
4928{
4929 struct iwn5000_calib_config cmd;
4930
4931 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
4932 cmd.ucode.once.enable = 0xffffffff;
4933 cmd.ucode.once.start = IWN5000_CALIB_DC(1 << 1);
4934 DPRINTF(("configuring runtime calibration\n"));
4935 return iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG101, &cmd, sizeof(cmd), 0);
4936}
4937
4938int
4939iwn_config(struct iwn_softc *sc)
4940{
4941 struct iwn_ops *ops = &sc->ops;
4942 struct ieee80211com *ic = &sc->sc_ic;
4943 struct ifnet *ifp = &ic->ic_ific_ac.ac_if;
4944 uint32_t txmask;
4945 uint16_t rxchain;
4946 int error, ridx;
4947
4948 /* Set radio temperature sensor offset. */
4949 if (sc->hw_type == IWN_HW_REV_TYPE_600511) {
4950 error = iwn6000_temp_offset_calib(sc);
4951 if (error != 0) {
4952 printf("%s: could not set temperature offset\n",
4953 sc->sc_dev.dv_xname);
4954 return error;
4955 }
4956 }
4957
4958 if (sc->hw_type == IWN_HW_REV_TYPE_203012 ||
4959 sc->hw_type == IWN_HW_REV_TYPE_200016 ||
4960 sc->hw_type == IWN_HW_REV_TYPE_13518 ||
4961 sc->hw_type == IWN_HW_REV_TYPE_10517) {
4962 error = iwn2000_temp_offset_calib(sc);
4963 if (error != 0) {
4964 printf("%s: could not set temperature offset\n",
4965 sc->sc_dev.dv_xname);
4966 return error;
4967 }
4968 }
4969
4970 if (sc->hw_type == IWN_HW_REV_TYPE_60508 ||
4971 sc->hw_type == IWN_HW_REV_TYPE_600511) {
4972 /* Configure runtime DC calibration. */
4973 error = iwn5000_runtime_calib(sc);
4974 if (error != 0) {
4975 printf("%s: could not configure runtime calibration\n",
4976 sc->sc_dev.dv_xname);
4977 return error;
4978 }
4979 }
4980
4981 /* Configure valid TX chains for >=5000 Series. */
4982 if (sc->hw_type != IWN_HW_REV_TYPE_49650) {
4983 txmask = htole32(sc->txchainmask)((__uint32_t)(sc->txchainmask));
4984 DPRINTF(("configuring valid TX chains 0x%x\n", txmask));
4985 error = iwn_cmd(sc, IWN5000_CMD_TX_ANT_CONFIG152, &txmask,
4986 sizeof txmask, 0);
4987 if (error != 0) {
4988 printf("%s: could not configure valid TX chains\n",
4989 sc->sc_dev.dv_xname);
4990 return error;
4991 }
4992 }
4993
4994 /* Configure bluetooth coexistence. */
4995 if (sc->sc_flags & IWN_FLAG_ADV_BT_COEX(1 << 8))
4996 error = iwn_send_advanced_btcoex(sc);
4997 else
4998 error = iwn_send_btcoex(sc);
4999 if (error != 0) {
5000 printf("%s: could not configure bluetooth coexistence\n",
5001 sc->sc_dev.dv_xname);
5002 return error;
5003 }
5004
5005 /* Set mode, channel, RX filter and enable RX. */
5006 memset(&sc->rxon, 0, sizeof (struct iwn_rxon))__builtin_memset((&sc->rxon), (0), (sizeof (struct iwn_rxon
)))
;
5007 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))
;
5008 IEEE80211_ADDR_COPY(sc->rxon.myaddr, ic->ic_myaddr)__builtin_memcpy((sc->rxon.myaddr), (ic->ic_myaddr), (6
))
;
5009 IEEE80211_ADDR_COPY(sc->rxon.wlap, ic->ic_myaddr)__builtin_memcpy((sc->rxon.wlap), (ic->ic_myaddr), (6));
5010 sc->rxon.chan = ieee80211_chan2ieee(ic, ic->ic_ibss_chan);
5011 sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF)((__uint32_t)((1 << 15) | (1 << 30)));
5012 if (IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan)(((ic->ic_ibss_chan)->ic_flags & 0x0080) != 0)) {
5013 sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ)((__uint32_t)((1 << 2) | (1 << 0)));
5014 if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)
5015 sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5016 DPRINTF(("%s: 2ghz prot 0x%x\n", __func__,
5017 le32toh(sc->rxon.flags)));
5018 }
5019 switch (ic->ic_opmode) {
5020 case IEEE80211_M_STA:
5021 sc->rxon.mode = IWN_MODE_STA3;
5022 sc->rxon.filter = htole32(IWN_FILTER_MULTICAST)((__uint32_t)((1 << 2)));
5023 break;
5024 case IEEE80211_M_MONITOR:
5025 sc->rxon.mode = IWN_MODE_MONITOR6;
5026 sc->rxon.filter = htole32(IWN_FILTER_MULTICAST |((__uint32_t)((1 << 2) | (1 << 1) | (1 << 0
)))
5027 IWN_FILTER_CTL | IWN_FILTER_PROMISC)((__uint32_t)((1 << 2) | (1 << 1) | (1 << 0
)))
;
5028 break;
5029 default:
5030 /* Should not get there. */
5031 break;
5032 }
5033 sc->rxon.cck_mask = 0x0f; /* not yet negotiated */
5034 sc->rxon.ofdm_mask = 0xff; /* not yet negotiated */
5035 sc->rxon.ht_single_mask = 0xff;
5036 sc->rxon.ht_dual_mask = 0xff;
5037 sc->rxon.ht_triple_mask = 0xff;
5038 rxchain =
5039 IWN_RXCHAIN_VALID(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 1)
|
5040 IWN_RXCHAIN_MIMO_COUNT(sc->nrxchains)((sc->nrxchains) << 12) |
5041 IWN_RXCHAIN_IDLE_COUNT(sc->nrxchains)((sc->nrxchains) << 10);
5042 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
5043 rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 4)
;
5044 rxchain |= IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 7)
;
5045 rxchain |= (IWN_RXCHAIN_DRIVER_FORCE(1 << 0) | IWN_RXCHAIN_MIMO_FORCE(1 << 14));
5046 }
5047 sc->rxon.rxchain = htole16(rxchain)((__uint16_t)(rxchain));
5048 DPRINTF(("setting configuration\n"));
5049 DPRINTF(("%s: rxon chan %d flags %x cck %x ofdm %x rxchain %x\n",
5050 __func__, sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,
5051 sc->rxon.ofdm_mask, sc->rxon.rxchain));
5052 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 0);
5053 if (error != 0) {
5054 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
5055 return error;
5056 }
5057
5058 ridx = (sc->sc_ic.ic_curmode == IEEE80211_MODE_11A) ?
5059 IWN_RIDX_OFDM64 : IWN_RIDX_CCK10;
5060 if ((error = iwn_add_broadcast_node(sc, 0, ridx)) != 0) {
5061 printf("%s: could not add broadcast node\n",
5062 sc->sc_dev.dv_xname);
5063 return error;
5064 }
5065
5066 /* Configuration has changed, set TX power accordingly. */
5067 if ((error = ops->set_txpower(sc, 0)) != 0) {
5068 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5069 return error;
5070 }
5071
5072 if ((error = iwn_set_critical_temp(sc)) != 0) {
5073 printf("%s: could not set critical temperature\n",
5074 sc->sc_dev.dv_xname);
5075 return error;
5076 }
5077
5078 /* Set power saving level to CAM during initialization. */
5079 if ((error = iwn_set_pslevel(sc, 0, 0, 0)) != 0) {
5080 printf("%s: could not set power saving level\n",
5081 sc->sc_dev.dv_xname);
5082 return error;
5083 }
5084 return 0;
5085}
5086
5087uint16_t
5088iwn_get_active_dwell_time(struct iwn_softc *sc,
5089 uint16_t flags, uint8_t n_probes)
5090{
5091 /* No channel? Default to 2GHz settings */
5092 if (flags & IEEE80211_CHAN_2GHZ0x0080) {
5093 return (IWN_ACTIVE_DWELL_TIME_2GHZ(30) +
5094 IWN_ACTIVE_DWELL_FACTOR_2GHZ(3) * (n_probes + 1));
5095 }
5096
5097 /* 5GHz dwell time */
5098 return (IWN_ACTIVE_DWELL_TIME_5GHZ(20) +
5099 IWN_ACTIVE_DWELL_FACTOR_5GHZ(2) * (n_probes + 1));
5100}
5101
5102/*
5103 * Limit the total dwell time to 85% of the beacon interval.
5104 *
5105 * Returns the dwell time in milliseconds.
5106 */
5107uint16_t
5108iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)
5109{
5110 struct ieee80211com *ic = &sc->sc_ic;
5111 struct ieee80211_node *ni = ic->ic_bss;
5112 int bintval = 0;
5113
5114 /* bintval is in TU (1.024mS) */
5115 if (ni != NULL((void *)0))
5116 bintval = ni->ni_intval;
5117
5118 /*
5119 * If it's non-zero, we should calculate the minimum of
5120 * it and the DWELL_BASE.
5121 *
5122 * XXX Yes, the math should take into account that bintval
5123 * is 1.024mS, not 1mS..
5124 */
5125 if (ic->ic_state == IEEE80211_S_RUN && bintval > 0)
5126 return (MIN(IWN_PASSIVE_DWELL_BASE, ((bintval * 85) / 100))((((100))<(((bintval * 85) / 100)))?((100)):(((bintval * 85
) / 100)))
);
5127
5128 /* No association context? Default */
5129 return dwell_time;
5130}
5131
5132uint16_t
5133iwn_get_passive_dwell_time(struct iwn_softc *sc, uint16_t flags)
5134{
5135 uint16_t passive;
5136 if (flags & IEEE80211_CHAN_2GHZ0x0080) {
5137 passive = IWN_PASSIVE_DWELL_BASE(100) + IWN_PASSIVE_DWELL_TIME_2GHZ(20);
5138 } else {
5139 passive = IWN_PASSIVE_DWELL_BASE(100) + IWN_PASSIVE_DWELL_TIME_5GHZ(10);
5140 }
5141
5142 /* Clamp to the beacon interval if we're associated */
5143 return (iwn_limit_dwell(sc, passive));
5144}
5145
5146int
5147iwn_scan(struct iwn_softc *sc, uint16_t flags, int bgscan)
5148{
5149 struct ieee80211com *ic = &sc->sc_ic;
5150 struct iwn_scan_hdr *hdr;
5151 struct iwn_cmd_data *tx;
5152 struct iwn_scan_essid *essid;
5153 struct iwn_scan_chan *chan;
5154 struct ieee80211_frame *wh;
5155 struct ieee80211_rateset *rs;
5156 struct ieee80211_channel *c;
5157 uint8_t *buf, *frm;
5158 uint16_t rxchain, dwell_active, dwell_passive;
5159 uint8_t txant;
5160 int buflen, error, is_active;
5161
5162 buf = malloc(IWN_SCAN_MAXSZ((1 << 11) - 4), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008);
5163 if (buf == NULL((void *)0)) {
5164 printf("%s: could not allocate buffer for scan command\n",
5165 sc->sc_dev.dv_xname);
5166 return ENOMEM12;
5167 }
5168 hdr = (struct iwn_scan_hdr *)buf;
5169 /*
5170 * Move to the next channel if no frames are received within 10ms
5171 * after sending the probe request.
5172 */
5173 hdr->quiet_time = htole16(10)((__uint16_t)(10)); /* timeout in milliseconds */
5174 hdr->quiet_threshold = htole16(1)((__uint16_t)(1)); /* min # of packets */
5175
5176 if (bgscan) {
5177 int bintval;
5178
5179 /* Set maximum off-channel time. */
5180 hdr->max_out = htole32(200 * 1024)((__uint32_t)(200 * 1024));
5181
5182 /* Configure scan pauses which service on-channel traffic. */
5183 bintval = ic->ic_bss->ni_intval ? ic->ic_bss->ni_intval : 100;
5184 hdr->pause_scan = htole32(((100 / bintval) << 22) |((__uint32_t)(((100 / bintval) << 22) | ((100 % bintval
) * 1024)))
5185 ((100 % bintval) * 1024))((__uint32_t)(((100 / bintval) << 22) | ((100 % bintval
) * 1024)))
;
5186 }
5187
5188 /* Select antennas for scanning. */
5189 rxchain =
5190 IWN_RXCHAIN_VALID(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 1)
|
5191 IWN_RXCHAIN_FORCE_MIMO_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 7)
|
5192 IWN_RXCHAIN_DRIVER_FORCE(1 << 0);
5193 if ((flags & IEEE80211_CHAN_5GHZ0x0100) &&
5194 sc->hw_type == IWN_HW_REV_TYPE_49650) {
5195 /*
5196 * On 4965 ant A and C must be avoided in 5GHz because of a
5197 * HW bug which causes very weak RSSI values being reported.
5198 */
5199 rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_B)((((1 << 1)) & ((1 << 0) | (1 << 1) | (
1 << 2))) << 4)
;
5200 } else /* Use all available RX antennas. */
5201 rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask)(((sc->rxchainmask) & ((1 << 0) | (1 << 1)
| (1 << 2))) << 4)
;
5202 hdr->rxchain = htole16(rxchain)((__uint16_t)(rxchain));
5203 hdr->filter = htole32(IWN_FILTER_MULTICAST | IWN_FILTER_BEACON)((__uint32_t)((1 << 2) | (1 << 6)));
5204
5205 tx = (struct iwn_cmd_data *)(hdr + 1);
5206 tx->flags = htole32(IWN_TX_AUTO_SEQ)((__uint32_t)((1 << 13)));
5207 tx->id = sc->broadcast_id;
5208 tx->lifetime = htole32(IWN_LIFETIME_INFINITE)((__uint32_t)(0xffffffff));
5209
5210 if (flags & IEEE80211_CHAN_5GHZ0x0100) {
5211 /* Send probe requests at 6Mbps. */
5212 tx->plcp = iwn_rates[IWN_RIDX_OFDM64].plcp;
5213 rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
5214 } else {
5215 hdr->flags = htole32(IWN_RXON_24GHZ | IWN_RXON_AUTO)((__uint32_t)((1 << 0) | (1 << 2)));
5216 if (bgscan && sc->hw_type == IWN_HW_REV_TYPE_49650 &&
5217 sc->rxon.chan > 14) {
5218 /*
5219 * 4965 firmware can crash when sending probe requests
5220 * with CCK rates while associated to a 5GHz AP.
5221 * Send probe requests at 6Mbps OFDM as a workaround.
5222 */
5223 tx->plcp = iwn_rates[IWN_RIDX_OFDM64].plcp;
5224 } else {
5225 /* Send probe requests at 1Mbps. */
5226 tx->plcp = iwn_rates[IWN_RIDX_CCK10].plcp;
5227 tx->rflags = IWN_RFLAG_CCK(1 << 1);
5228 }
5229 rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
5230 }
5231 /* Use the first valid TX antenna. */
5232 txant = IWN_LSB(sc->txchainmask)((((sc->txchainmask) - 1) & (sc->txchainmask)) ^ (sc
->txchainmask))
;
5233 tx->rflags |= IWN_RFLAG_ANT(txant)((txant) << 6);
5234
5235 /*
5236 * Only do active scanning if we're announcing a probe request
5237 * for a given SSID (or more, if we ever add it to the driver.)
5238 */
5239 is_active = 0;
5240
5241 /*
5242 * If we're scanning for a specific SSID, add it to the command.
5243 */
5244 essid = (struct iwn_scan_essid *)(tx + 1);
5245 if (ic->ic_des_esslen != 0) {
5246 essid[0].id = IEEE80211_ELEMID_SSID;
5247 essid[0].len = ic->ic_des_esslen;
5248 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))
;
5249
5250 is_active = 1;
5251 }
5252 /*
5253 * Build a probe request frame. Most of the following code is a
5254 * copy & paste of what is done in net80211.
5255 */
5256 wh = (struct ieee80211_frame *)(essid + 20);
5257 wh->i_fc[0] = IEEE80211_FC0_VERSION_00x00 | IEEE80211_FC0_TYPE_MGT0x00 |
5258 IEEE80211_FC0_SUBTYPE_PROBE_REQ0x40;
5259 wh->i_fc[1] = IEEE80211_FC1_DIR_NODS0x00;
5260 IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr)__builtin_memcpy((wh->i_addr1), (etherbroadcastaddr), (6));
5261 IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr)__builtin_memcpy((wh->i_addr2), (ic->ic_myaddr), (6));
5262 IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr)__builtin_memcpy((wh->i_addr3), (etherbroadcastaddr), (6));
5263 *(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
5264 *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
5265
5266 frm = (uint8_t *)(wh + 1);
5267 frm = ieee80211_add_ssid(frm, NULL((void *)0), 0);
5268 frm = ieee80211_add_rates(frm, rs);
5269 if (rs->rs_nrates > IEEE80211_RATE_SIZE8)
5270 frm = ieee80211_add_xrates(frm, rs);
5271 if (ic->ic_flags & IEEE80211_F_HTON0x02000000)
5272 frm = ieee80211_add_htcaps(frm, ic);
5273
5274 /* Set length of probe request. */
5275 tx->len = htole16(frm - (uint8_t *)wh)((__uint16_t)(frm - (uint8_t *)wh));
5276
5277 /*
5278 * If active scanning is requested but a certain channel is
5279 * marked passive, we can do active scanning if we detect
5280 * transmissions.
5281 *
5282 * There is an issue with some firmware versions that triggers
5283 * a sysassert on a "good CRC threshold" of zero (== disabled),
5284 * on a radar channel even though this means that we should NOT
5285 * send probes.
5286 *
5287 * The "good CRC threshold" is the number of frames that we
5288 * need to receive during our dwell time on a channel before
5289 * sending out probes -- setting this to a huge value will
5290 * mean we never reach it, but at the same time work around
5291 * the aforementioned issue. Thus use IWN_GOOD_CRC_TH_NEVER
5292 * here instead of IWN_GOOD_CRC_TH_DISABLED.
5293 *
5294 * This was fixed in later versions along with some other
5295 * scan changes, and the threshold behaves as a flag in those
5296 * versions.
5297 */
5298
5299 /*
5300 * If we're doing active scanning, set the crc_threshold
5301 * to a suitable value. This is different to active veruss
5302 * passive scanning depending upon the channel flags; the
5303 * firmware will obey that particular check for us.
5304 */
5305 if (sc->tlv_feature_flags & IWN_UCODE_TLV_FLAGS_NEWSCAN)
5306 hdr->crc_threshold = is_active ?
5307 IWN_GOOD_CRC_TH_DEFAULT((__uint16_t)(1)) : IWN_GOOD_CRC_TH_DISABLED0;
5308 else
5309 hdr->crc_threshold = is_active ?
5310 IWN_GOOD_CRC_TH_DEFAULT((__uint16_t)(1)) : IWN_GOOD_CRC_TH_NEVER((__uint16_t)(0xffff));
5311
5312 chan = (struct iwn_scan_chan *)frm;
5313 for (c = &ic->ic_channels[1];
5314 c <= &ic->ic_channels[IEEE80211_CHAN_MAX255]; c++) {
5315 if ((c->ic_flags & flags) != flags)
5316 continue;
5317
5318 chan->chan = htole16(ieee80211_chan2ieee(ic, c))((__uint16_t)(ieee80211_chan2ieee(ic, c)));
5319 DPRINTFN(2, ("adding channel %d\n", chan->chan));
5320 chan->flags = 0;
5321 if (ic->ic_des_esslen != 0)
5322 chan->flags |= htole32(IWN_CHAN_NPBREQS(1))((__uint32_t)((((1 << (1)) - 1) << 1)));
5323
5324 if (c->ic_flags & IEEE80211_CHAN_PASSIVE0x0200)
5325 chan->flags |= htole32(IWN_CHAN_PASSIVE)((__uint32_t)((0 << 0)));
5326 else
5327 chan->flags |= htole32(IWN_CHAN_ACTIVE)((__uint32_t)((1 << 0)));
5328
5329 /*
5330 * Calculate the active/passive dwell times.
5331 */
5332
5333 dwell_active = iwn_get_active_dwell_time(sc, flags, is_active);
5334 dwell_passive = iwn_get_passive_dwell_time(sc, flags);
5335
5336 /* Make sure they're valid */
5337 if (dwell_passive <= dwell_active)
5338 dwell_passive = dwell_active + 1;
5339
5340 chan->active = htole16(dwell_active)((__uint16_t)(dwell_active));
5341 chan->passive = htole16(dwell_passive)((__uint16_t)(dwell_passive));
5342
5343 chan->dsp_gain = 0x6e;
5344 if (IEEE80211_IS_CHAN_5GHZ(c)(((c)->ic_flags & 0x0100) != 0)) {
5345 chan->rf_gain = 0x3b;
5346 } else {
5347 chan->rf_gain = 0x28;
5348 }
5349 hdr->nchan++;
5350 chan++;
5351 }
5352
5353 buflen = (uint8_t *)chan - buf;
5354 hdr->len = htole16(buflen)((__uint16_t)(buflen));
5355
5356 error = iwn_cmd(sc, IWN_CMD_SCAN128, buf, buflen, 1);
5357 if (error == 0) {
5358 /*
5359 * The current mode might have been fixed during association.
5360 * Ensure all channels get scanned.
5361 */
5362 if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media)((ic->ic_media.ifm_cur->ifm_media) & 0x000000ff00000000ULL
)
== IFM_AUTO0ULL)
5363 ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
5364
5365 sc->sc_flags |= IWN_FLAG_SCANNING(1 << 10);
5366 if (bgscan)
5367 sc->sc_flags |= IWN_FLAG_BGSCAN(1 << 9);
5368 }
5369 free(buf, M_DEVBUF2, IWN_SCAN_MAXSZ((1 << 11) - 4));
5370 return error;
5371}
5372
5373void
5374iwn_scan_abort(struct iwn_softc *sc)
5375{
5376 iwn_cmd(sc, IWN_CMD_SCAN_ABORT129, NULL((void *)0), 0, 1);
5377
5378 /* XXX Cannot wait for status response in interrupt context. */
5379 DELAY(100)(*delay_func)(100);
5380
5381 sc->sc_flags &= ~IWN_FLAG_SCANNING(1 << 10);
5382 sc->sc_flags &= ~IWN_FLAG_BGSCAN(1 << 9);
5383}
5384
5385int
5386iwn_bgscan(struct ieee80211com *ic)
5387{
5388 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5389 int error;
5390
5391 if (sc->sc_flags & IWN_FLAG_SCANNING(1 << 10))
5392 return 0;
5393
5394 error = iwn_scan(sc, IEEE80211_CHAN_2GHZ0x0080, 1);
5395 if (error)
5396 printf("%s: could not initiate background scan\n",
5397 sc->sc_dev.dv_xname);
5398 return error;
5399}
5400
5401void
5402iwn_rxon_configure_ht40(struct ieee80211com *ic, struct ieee80211_node *ni)
5403{
5404 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5405 uint8_t sco = (ni->ni_htop0 & IEEE80211_HTOP0_SCO_MASK0x03);
5406 enum ieee80211_htprot htprot = (ni->ni_htop1 &
5407 IEEE80211_HTOP1_PROT_MASK0x0003);
5408
5409 sc->rxon.flags &= ~htole32(IWN_RXON_HT_CHANMODE_MIXED2040 |((__uint32_t)((2 << 25) | (1 << 25) | (1 <<
22)))
5410 IWN_RXON_HT_CHANMODE_PURE40 | IWN_RXON_HT_HT40MINUS)((__uint32_t)((2 << 25) | (1 << 25) | (1 <<
22)))
;
5411
5412 if (ieee80211_node_supports_ht_chan40(ni) &&
5413 (sco == IEEE80211_HTOP0_SCO_SCA1 ||
5414 sco == IEEE80211_HTOP0_SCO_SCB3)) {
5415 if (sco == IEEE80211_HTOP0_SCO_SCB3)
5416 sc->rxon.flags |= htole32(IWN_RXON_HT_HT40MINUS)((__uint32_t)((1 << 22)));
5417 if (htprot == IEEE80211_HTPROT_20MHZ)
5418 sc->rxon.flags |= htole32(IWN_RXON_HT_CHANMODE_PURE40)((__uint32_t)((1 << 25)));
5419 else
5420 sc->rxon.flags |= htole32(((__uint32_t)((2 << 25)))
5421 IWN_RXON_HT_CHANMODE_MIXED2040)((__uint32_t)((2 << 25)));
5422 }
5423}
5424
5425int
5426iwn_rxon_ht40_enabled(struct iwn_softc *sc)
5427{
5428 return ((le32toh(sc->rxon.flags)((__uint32_t)(sc->rxon.flags)) & IWN_RXON_HT_CHANMODE_MIXED2040(2 << 25)) ||
5429 (le32toh(sc->rxon.flags)((__uint32_t)(sc->rxon.flags)) & IWN_RXON_HT_CHANMODE_PURE40(1 << 25))) ? 1 : 0;
5430}
5431
5432int
5433iwn_auth(struct iwn_softc *sc, int arg)
5434{
5435 struct iwn_ops *ops = &sc->ops;
5436 struct ieee80211com *ic = &sc->sc_ic;
5437 struct ieee80211_node *ni = ic->ic_bss;
5438 int error, ridx;
5439 int bss_switch =
5440 (!IEEE80211_ADDR_EQ(sc->bss_node_addr, etheranyaddr)(__builtin_memcmp((sc->bss_node_addr), (etheranyaddr), (6)
) == 0)
&&
5441 !IEEE80211_ADDR_EQ(sc->bss_node_addr, ni->ni_macaddr)(__builtin_memcmp((sc->bss_node_addr), (ni->ni_macaddr)
, (6)) == 0)
);
5442
5443 /* Update adapter configuration. */
5444 IEEE80211_ADDR_COPY(sc->rxon.bssid, ni->ni_bssid)__builtin_memcpy((sc->rxon.bssid), (ni->ni_bssid), (6));
5445 sc->rxon.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
5446 sc->rxon.flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF)((__uint32_t)((1 << 15) | (1 << 30)));
5447 if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)(((ni->ni_chan)->ic_flags & 0x0080) != 0)) {
5448 sc->rxon.flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ)((__uint32_t)((1 << 2) | (1 << 0)));
5449 if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)
5450 sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5451 DPRINTF(("%s: 2ghz prot 0x%x\n", __func__,
5452 le32toh(sc->rxon.flags)));
5453 }
5454 if (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)
5455 sc->rxon.flags |= htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5456 else
5457 sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5458 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
5459 sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5460 else
5461 sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5462 switch (ic->ic_curmode) {
5463 case IEEE80211_MODE_11A:
5464 sc->rxon.cck_mask = 0;
5465 sc->rxon.ofdm_mask = 0x15;
5466 break;
5467 case IEEE80211_MODE_11B:
5468 sc->rxon.cck_mask = 0x03;
5469 sc->rxon.ofdm_mask = 0;
5470 break;
5471 default: /* Assume 802.11b/g/n. */
5472 sc->rxon.cck_mask = 0x0f;
5473 sc->rxon.ofdm_mask = 0x15;
5474 }
5475 /* Configure 40MHz early to avoid problems on 6205 devices. */
5476 iwn_rxon_configure_ht40(ic, ni);
5477 DPRINTF(("%s: rxon chan %d flags %x cck %x ofdm %x\n", __func__,
5478 sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,
5479 sc->rxon.ofdm_mask));
5480 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
5481 if (error != 0) {
5482 printf("%s: RXON command failed\n", sc->sc_dev.dv_xname);
5483 return error;
5484 }
5485
5486 /* Configuration has changed, set TX power accordingly. */
5487 if ((error = ops->set_txpower(sc, 1)) != 0) {
5488 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5489 return error;
5490 }
5491 /*
5492 * Reconfiguring RXON clears the firmware nodes table so we must
5493 * add the broadcast node again.
5494 */
5495 ridx = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)(((ni->ni_chan)->ic_flags & 0x0100) != 0) ?
5496 IWN_RIDX_OFDM64 : IWN_RIDX_CCK10;
5497 if ((error = iwn_add_broadcast_node(sc, 1, ridx)) != 0) {
5498 printf("%s: could not add broadcast node\n",
5499 sc->sc_dev.dv_xname);
5500 return error;
5501 }
5502
5503 /*
5504 * Make sure the firmware gets to see a beacon before we send
5505 * the auth request. Otherwise the Tx attempt can fail due to
5506 * the firmware's built-in regulatory domain enforcement.
5507 * Delaying here for every incoming deauth frame can result in a DoS.
5508 * Don't delay if we're here because of an incoming frame (arg != -1)
5509 * or if we're already waiting for a response (ic_mgt_timer != 0).
5510 * If we are switching APs after a background scan then net80211 has
5511 * just faked the reception of a deauth frame from our old AP, so it
5512 * is safe to delay in that case.
5513 */
5514 if ((arg == -1 || bss_switch) && ic->ic_mgt_timer == 0)
5515 DELAY(ni->ni_intval * 3 * IEEE80211_DUR_TU)(*delay_func)(ni->ni_intval * 3 * 1024);
5516
5517 /* We can now clear the cached address of our previous AP. */
5518 memset(sc->bss_node_addr, 0, sizeof(sc->bss_node_addr))__builtin_memset((sc->bss_node_addr), (0), (sizeof(sc->
bss_node_addr)))
;
5519
5520 return 0;
5521}
5522
5523int
5524iwn_run(struct iwn_softc *sc)
5525{
5526 struct iwn_ops *ops = &sc->ops;
5527 struct ieee80211com *ic = &sc->sc_ic;
5528 struct ieee80211_node *ni = ic->ic_bss;
5529 struct iwn_node *wn = (void *)ni;
5530 struct iwn_node_info node;
5531 int error;
5532
5533 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
5534 /* Link LED blinks while monitoring. */
5535 iwn_set_led(sc, IWN_LED_LINK2, 50, 50);
5536 return 0;
5537 }
5538 if ((error = iwn_set_timing(sc, ni)) != 0) {
5539 printf("%s: could not set timing\n", sc->sc_dev.dv_xname);
5540 return error;
5541 }
5542
5543 /* Update adapter configuration. */
5544 sc->rxon.associd = htole16(IEEE80211_AID(ni->ni_associd))((__uint16_t)(((ni->ni_associd) &~ 0xc000)));
5545 /* Short preamble and slot time are negotiated when associating. */
5546 sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE | IWN_RXON_SHSLOT)((__uint32_t)((1 << 5) | (1 << 4)));
5547 if (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)
5548 sc->rxon.flags |= htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5549 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
5550 sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5551 sc->rxon.filter |= htole32(IWN_FILTER_BSS)((__uint32_t)((1 << 5)));
5552
5553 /* HT is negotiated when associating. */
5554 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
5555 enum ieee80211_htprot htprot =
5556 (ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK0x0003);
5557 DPRINTF(("%s: htprot = %d\n", __func__, htprot));
5558 sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot))((__uint32_t)(((htprot) << 23)));
5559 } else
5560 sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3))((__uint32_t)(((3) << 23)));
5561
5562 iwn_rxon_configure_ht40(ic, ni);
5563
5564 if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)(((ni->ni_chan)->ic_flags & 0x0100) != 0)) {
5565 /* 11a or 11n 5GHz */
5566 sc->rxon.cck_mask = 0;
5567 sc->rxon.ofdm_mask = 0x15;
5568 } else if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
5569 /* 11n 2GHz */
5570 sc->rxon.cck_mask = 0x0f;
5571 sc->rxon.ofdm_mask = 0x15;
5572 } else {
5573 if (ni->ni_rates.rs_nrates == 4) {
5574 /* 11b */
5575 sc->rxon.cck_mask = 0x03;
5576 sc->rxon.ofdm_mask = 0;
5577 } else {
5578 /* assume 11g */
5579 sc->rxon.cck_mask = 0x0f;
5580 sc->rxon.ofdm_mask = 0x15;
5581 }
5582 }
5583 DPRINTF(("%s: rxon chan %d flags %x cck %x ofdm %x\n", __func__,
5584 sc->rxon.chan, le32toh(sc->rxon.flags), sc->rxon.cck_mask,
5585 sc->rxon.ofdm_mask));
5586 error = iwn_cmd(sc, IWN_CMD_RXON16, &sc->rxon, sc->rxonsz, 1);
5587 if (error != 0) {
5588 printf("%s: could not update configuration\n",
5589 sc->sc_dev.dv_xname);
5590 return error;
5591 }
5592
5593 /* Configuration has changed, set TX power accordingly. */
5594 if ((error = ops->set_txpower(sc, 1)) != 0) {
5595 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5596 return error;
5597 }
5598
5599 /* Fake a join to initialize the TX rate. */
5600 ((struct iwn_node *)ni)->id = IWN_ID_BSS0;
5601 iwn_newassoc(ic, ni, 1);
5602
5603 /* Add BSS node. */
5604 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5605 IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr)__builtin_memcpy((node.macaddr), (ni->ni_macaddr), (6));
5606 node.id = IWN_ID_BSS0;
5607 if (ni->ni_flags & IEEE80211_NODE_HT0x0400) {
5608 node.htmask = (IWN_AMDPU_SIZE_FACTOR_MASK((0x3) << 19) |
5609 IWN_AMDPU_DENSITY_MASK((0x7) << 23));
5610 node.htflags = htole32(((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5611 IWN_AMDPU_SIZE_FACTOR(((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5612 (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_LE)) |((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5613 IWN_AMDPU_DENSITY(((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
5614 (ic->ic_ampdu_params & IEEE80211_AMPDU_PARAM_SS) >> 2))((__uint32_t)((((ic->ic_ampdu_params & 0x03)) <<
19) | (((ic->ic_ampdu_params & 0x1c) >> 2) <<
23)))
;
5615 if (iwn_rxon_ht40_enabled(sc))
5616 node.htflags |= htole32(IWN_40MHZ_ENABLE)((__uint32_t)((1 << 21)));
5617 }
5618 DPRINTF(("adding BSS node\n"));
5619 error = ops->add_node(sc, &node, 1);
5620 if (error != 0) {
5621 printf("%s: could not add BSS node\n", sc->sc_dev.dv_xname);
5622 return error;
5623 }
5624
5625 /* Cache address of AP in case it changes after a background scan. */
5626 IEEE80211_ADDR_COPY(sc->bss_node_addr, ni->ni_macaddr)__builtin_memcpy((sc->bss_node_addr), (ni->ni_macaddr),
(6))
;
5627
5628 DPRINTF(("setting link quality for node %d\n", node.id));
5629 if ((error = iwn_set_link_quality(sc, ni)) != 0) {
5630 printf("%s: could not setup link quality for node %d\n",
5631 sc->sc_dev.dv_xname, node.id);
5632 return error;
5633 }
5634
5635 if ((error = iwn_init_sensitivity(sc)) != 0) {
5636 printf("%s: could not set sensitivity\n",
5637 sc->sc_dev.dv_xname);
5638 return error;
5639 }
5640 /* Start periodic calibration timer. */
5641 sc->calib.state = IWN_CALIB_STATE_ASSOC1;
5642 sc->calib_cnt = 0;
5643 timeout_add_msec(&sc->calib_to, 500);
5644
5645 ieee80211_ra_node_init(&wn->rn);
5646
5647 /* Link LED always on while associated. */
5648 iwn_set_led(sc, IWN_LED_LINK2, 0, 1);
5649 return 0;
5650}
5651
5652/*
5653 * We support CCMP hardware encryption/decryption of unicast frames only.
5654 * HW support for TKIP really sucks. We should let TKIP die anyway.
5655 */
5656int
5657iwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni,
5658 struct ieee80211_key *k)
5659{
5660 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5661 struct iwn_ops *ops = &sc->ops;
5662 struct iwn_node *wn = (void *)ni;
5663 struct iwn_node_info node;
5664 uint16_t kflags;
5665
5666 if ((k->k_flags & IEEE80211_KEY_GROUP0x00000001) ||
5667 k->k_cipher != IEEE80211_CIPHER_CCMP)
5668 return ieee80211_set_key(ic, ni, k);
5669
5670 kflags = IWN_KFLAG_CCMP(1 << 1) | IWN_KFLAG_MAP(1 << 3) | IWN_KFLAG_KID(k->k_id)((k->k_id) << 8);
5671 if (k->k_flags & IEEE80211_KEY_GROUP0x00000001)
5672 kflags |= IWN_KFLAG_GROUP(1 << 14);
5673
5674 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5675 node.id = (k->k_flags & IEEE80211_KEY_GROUP0x00000001) ?
5676 sc->broadcast_id : wn->id;
5677 node.control = IWN_NODE_UPDATE(1 << 0);
5678 node.flags = IWN_FLAG_SET_KEY(1 << 0);
5679 node.kflags = htole16(kflags)((__uint16_t)(kflags));
5680 node.kid = k->k_id;
5681 memcpy(node.key, k->k_key, k->k_len)__builtin_memcpy((node.key), (k->k_key), (k->k_len));
5682 DPRINTF(("set key id=%d for node %d\n", k->k_id, node.id));
5683 return ops->add_node(sc, &node, 1);
5684}
5685
5686void
5687iwn_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
5688 struct ieee80211_key *k)
5689{
5690 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5691 struct iwn_ops *ops = &sc->ops;
5692 struct iwn_node *wn = (void *)ni;
5693 struct iwn_node_info node;
5694
5695 if ((k->k_flags & IEEE80211_KEY_GROUP0x00000001) ||
5696 k->k_cipher != IEEE80211_CIPHER_CCMP) {
5697 /* See comment about other ciphers above. */
5698 ieee80211_delete_key(ic, ni, k);
5699 return;
5700 }
5701 if (ic->ic_state != IEEE80211_S_RUN)
5702 return; /* Nothing to do. */
5703 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5704 node.id = (k->k_flags & IEEE80211_KEY_GROUP0x00000001) ?
5705 sc->broadcast_id : wn->id;
5706 node.control = IWN_NODE_UPDATE(1 << 0);
5707 node.flags = IWN_FLAG_SET_KEY(1 << 0);
5708 node.kflags = htole16(IWN_KFLAG_INVALID)((__uint16_t)((1 << 11)));
5709 node.kid = 0xff;
5710 DPRINTF(("delete keys for node %d\n", node.id));
5711 (void)ops->add_node(sc, &node, 1);
5712}
5713
5714void
5715iwn_updatechan(struct ieee80211com *ic)
5716{
5717 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5718
5719 if (ic->ic_state != IEEE80211_S_RUN)
5720 return;
5721
5722 iwn_rxon_configure_ht40(ic, ic->ic_bss);
5723 sc->ops.update_rxon(sc);
5724 iwn_set_link_quality(sc, ic->ic_bss);
5725}
5726
5727void
5728iwn_updateprot(struct ieee80211com *ic)
5729{
5730 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5731 enum ieee80211_htprot htprot;
5732
5733 if (ic->ic_state != IEEE80211_S_RUN)
5734 return;
5735
5736 /* Update ERP protection setting. */
5737 if (ic->ic_flags & IEEE80211_F_USEPROT0x00100000)
5738 sc->rxon.flags |= htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5739 else
5740 sc->rxon.flags &= ~htole32(IWN_RXON_TGG_PROT)((__uint32_t)((1 << 3)));
5741
5742 /* Update HT protection mode setting. */
5743 htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK0x0003) >>
5744 IEEE80211_HTOP1_PROT_SHIFT0;
5745 sc->rxon.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3))((__uint32_t)(((3) << 23)));
5746 sc->rxon.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot))((__uint32_t)(((htprot) << 23)));
5747
5748 sc->ops.update_rxon(sc);
5749}
5750
5751void
5752iwn_updateslot(struct ieee80211com *ic)
5753{
5754 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5755
5756 if (ic->ic_state != IEEE80211_S_RUN)
5757 return;
5758
5759 if (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)
5760 sc->rxon.flags |= htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5761 else
5762 sc->rxon.flags &= ~htole32(IWN_RXON_SHSLOT)((__uint32_t)((1 << 4)));
5763
5764 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000)
5765 sc->rxon.flags |= htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5766 else
5767 sc->rxon.flags &= ~htole32(IWN_RXON_SHPREAMBLE)((__uint32_t)((1 << 5)));
5768
5769 sc->ops.update_rxon(sc);
5770}
5771
5772void
5773iwn_update_rxon_restore_power(struct iwn_softc *sc)
5774{
5775 struct ieee80211com *ic = &sc->sc_ic;
5776 struct iwn_ops *ops = &sc->ops;
5777 int error;
5778
5779 DELAY(100)(*delay_func)(100);
5780
5781 /* All RXONs wipe the firmware's txpower table. Restore it. */
5782 error = ops->set_txpower(sc, 1);
5783 if (error != 0)
5784 printf("%s: could not set TX power\n", sc->sc_dev.dv_xname);
5785
5786 DELAY(100)(*delay_func)(100);
5787
5788 /* Restore power saving level */
5789 if (ic->ic_flags & IEEE80211_F_PMGTON0x00000400)
5790 error = iwn_set_pslevel(sc, 0, 3, 1);
5791 else
5792 error = iwn_set_pslevel(sc, 0, 0, 1);
5793 if (error != 0)
5794 printf("%s: could not set PS level\n", sc->sc_dev.dv_xname);
5795}
5796
5797void
5798iwn5000_update_rxon(struct iwn_softc *sc)
5799{
5800 struct iwn_rxon_assoc rxon_assoc;
5801 int s, error;
5802
5803 /* Update RXON config. */
5804 memset(&rxon_assoc, 0, sizeof(rxon_assoc))__builtin_memset((&rxon_assoc), (0), (sizeof(rxon_assoc))
)
;
5805 rxon_assoc.flags = sc->rxon.flags;
5806 rxon_assoc.filter = sc->rxon.filter;
5807 rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask;
5808 rxon_assoc.cck_mask = sc->rxon.cck_mask;
5809 rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask;
5810 rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask;
5811 rxon_assoc.ht_triple_mask = sc->rxon.ht_triple_mask;
5812 rxon_assoc.rxchain = sc->rxon.rxchain;
5813 rxon_assoc.acquisition = sc->rxon.acquisition;
5814
5815 s = splnet()splraise(0x4);
5816
5817 error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC17, &rxon_assoc,
5818 sizeof(rxon_assoc), 1);
5819 if (error != 0)
5820 printf("%s: RXON_ASSOC command failed\n", sc->sc_dev.dv_xname);
5821
5822 iwn_update_rxon_restore_power(sc);
5823
5824 splx(s)spllower(s);
5825}
5826
5827void
5828iwn4965_update_rxon(struct iwn_softc *sc)
5829{
5830 struct iwn4965_rxon_assoc rxon_assoc;
5831 int s, error;
5832
5833 /* Update RXON config. */
5834 memset(&rxon_assoc, 0, sizeof(rxon_assoc))__builtin_memset((&rxon_assoc), (0), (sizeof(rxon_assoc))
)
;
5835 rxon_assoc.flags = sc->rxon.flags;
5836 rxon_assoc.filter = sc->rxon.filter;
5837 rxon_assoc.ofdm_mask = sc->rxon.ofdm_mask;
5838 rxon_assoc.cck_mask = sc->rxon.cck_mask;
5839 rxon_assoc.ht_single_mask = sc->rxon.ht_single_mask;
5840 rxon_assoc.ht_dual_mask = sc->rxon.ht_dual_mask;
5841 rxon_assoc.rxchain = sc->rxon.rxchain;
5842
5843 s = splnet()splraise(0x4);
5844
5845 error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC17, &rxon_assoc,
5846 sizeof(rxon_assoc), 1);
5847 if (error != 0)
5848 printf("%s: RXON_ASSOC command failed\n", sc->sc_dev.dv_xname);
5849
5850 iwn_update_rxon_restore_power(sc);
5851
5852 splx(s)spllower(s);
5853}
5854
5855/*
5856 * This function is called by upper layer when an ADDBA request is received
5857 * from another STA and before the ADDBA response is sent.
5858 */
5859int
5860iwn_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
5861 uint8_t tid)
5862{
5863 struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
5864 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5865 struct iwn_ops *ops = &sc->ops;
5866 struct iwn_node *wn = (void *)ni;
5867 struct iwn_node_info node;
5868
5869 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5870 node.id = wn->id;
5871 node.control = IWN_NODE_UPDATE(1 << 0);
5872 node.flags = IWN_FLAG_SET_ADDBA(1 << 3);
5873 node.addba_tid = tid;
5874 node.addba_ssn = htole16(ba->ba_winstart)((__uint16_t)(ba->ba_winstart));
5875 DPRINTF(("ADDBA RA=%d TID=%d SSN=%d\n", wn->id, tid,
5876 ba->ba_winstart));
5877 /* XXX async command, so firmware may still fail to add BA agreement */
5878 return ops->add_node(sc, &node, 1);
5879}
5880
5881/*
5882 * This function is called by upper layer on teardown of an HT-immediate
5883 * Block Ack agreement (e.g., upon receipt of a DELBA frame).
5884 */
5885void
5886iwn_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
5887 uint8_t tid)
5888{
5889 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5890 struct iwn_ops *ops = &sc->ops;
5891 struct iwn_node *wn = (void *)ni;
5892 struct iwn_node_info node;
5893
5894 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5895 node.id = wn->id;
5896 node.control = IWN_NODE_UPDATE(1 << 0);
5897 node.flags = IWN_FLAG_SET_DELBA(1 << 4);
5898 node.delba_tid = tid;
5899 DPRINTF(("DELBA RA=%d TID=%d\n", wn->id, tid));
5900 (void)ops->add_node(sc, &node, 1);
5901}
5902
5903/*
5904 * This function is called by upper layer when an ADDBA response is received
5905 * from another STA.
5906 */
5907int
5908iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
5909 uint8_t tid)
5910{
5911 struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
5912 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5913 struct iwn_ops *ops = &sc->ops;
5914 struct iwn_node *wn = (void *)ni;
5915 struct iwn_node_info node;
5916 int qid = sc->first_agg_txq + tid;
5917 int error;
5918
5919 /* Ensure we can map this TID to an aggregation queue. */
5920 if (tid >= IWN_NUM_AMPDU_TID8 || ba->ba_winsize > IWN_SCHED_WINSZ64 ||
5921 qid > sc->ntxqs || (sc->agg_queue_mask & (1 << qid)))
5922 return ENOSPC28;
5923
5924 /* Enable TX for the specified RA/TID. */
5925 wn->disable_tid &= ~(1 << tid);
5926 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5927 node.id = wn->id;
5928 node.control = IWN_NODE_UPDATE(1 << 0);
5929 node.flags = IWN_FLAG_SET_DISABLE_TID(1 << 1);
5930 node.disable_tid = htole16(wn->disable_tid)((__uint16_t)(wn->disable_tid));
5931 error = ops->add_node(sc, &node, 1);
5932 if (error != 0)
5933 return error;
5934
5935 if ((error = iwn_nic_lock(sc)) != 0)
5936 return error;
5937 ops->ampdu_tx_start(sc, ni, tid, ba->ba_winstart);
5938 iwn_nic_unlock(sc);
5939
5940 sc->agg_queue_mask |= (1 << qid);
5941 sc->sc_tx_ba[tid].wn = wn;
5942 ba->ba_bitmap = 0;
5943
5944 return 0;
5945}
5946
5947void
5948iwn_ampdu_tx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
5949 uint8_t tid)
5950{
5951 struct ieee80211_tx_ba *ba = &ni->ni_tx_ba[tid];
5952 struct iwn_softc *sc = ic->ic_softcic_ac.ac_if.if_softc;
5953 struct iwn_ops *ops = &sc->ops;
5954 int qid = sc->first_agg_txq + tid;
5955 struct iwn_node *wn = (void *)ni;
5956 struct iwn_node_info node;
5957
5958 /* Discard all frames in the current window. */
5959 iwn_ampdu_txq_advance(sc, &sc->txq[qid], qid,
5960 IWN_AGG_SSN_TO_TXQ_IDX(ba->ba_winend)((ba->ba_winend) & (256 - 1)));
5961
5962 if (iwn_nic_lock(sc) != 0)
5963 return;
5964 ops->ampdu_tx_stop(sc, tid, ba->ba_winstart);
5965 iwn_nic_unlock(sc);
5966
5967 sc->agg_queue_mask &= ~(1 << qid);
5968 sc->sc_tx_ba[tid].wn = NULL((void *)0);
5969 ba->ba_bitmap = 0;
5970
5971 /* Disable TX for the specified RA/TID. */
5972 wn->disable_tid |= (1 << tid);
5973 memset(&node, 0, sizeof node)__builtin_memset((&node), (0), (sizeof node));
5974 node.id = wn->id;
5975 node.control = IWN_NODE_UPDATE(1 << 0);
5976 node.flags = IWN_FLAG_SET_DISABLE_TID(1 << 1);
5977 node.disable_tid = htole16(wn->disable_tid)((__uint16_t)(wn->disable_tid));
5978 ops->add_node(sc, &node, 1);
5979}
5980
5981void
5982iwn4965_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni,
5983 uint8_t tid, uint16_t ssn)
5984{
5985 struct iwn_node *wn = (void *)ni;
5986 int qid = IWN4965_FIRST_AGG_TXQUEUE7 + tid;
5987 uint16_t idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1));
5988
5989 /* Stop TX scheduler while we're changing its configuration. */
5990 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x104 + (qid) * 4),
5991 IWN4965_TXQ_STATUS_CHGACT(1 << 10));
5992
5993 /* Assign RA/TID translation to the queue. */
5994 iwn_mem_write_2(sc, sc->sched_base + IWN4965_SCHED_TRANS_TBL(qid)(0x500 + (qid) * 2),
5995 wn->id << 4 | tid);
5996
5997 /* Enable chain-building mode for the queue. */
5998 iwn_prph_setbits(sc, IWN4965_SCHED_QCHAIN_SEL(0xa02c00 + 0x0d0), 1 << qid);
5999
6000 /* Set starting sequence number from the ADDBA request. */
6001 sc->txq[qid].cur = sc->txq[qid].read = idx;
6002 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | idx))))
;
6003 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid)(0xa02c00 + 0x064 + (qid) * 4), ssn);
6004
6005 /* Set scheduler window size. */
6006 iwn_mem_write(sc, sc->sched_base + IWN4965_SCHED_QUEUE_OFFSET(qid)(0x380 + (qid) * 8),
6007 IWN_SCHED_WINSZ64);
6008 /* Set scheduler frame limit. */
6009 iwn_mem_write(sc, sc->sched_base + IWN4965_SCHED_QUEUE_OFFSET(qid)(0x380 + (qid) * 8) + 4,
6010 IWN_SCHED_LIMIT64 << 16);
6011
6012 /* Enable interrupts for the queue. */
6013 iwn_prph_setbits(sc, IWN4965_SCHED_INTR_MASK(0xa02c00 + 0x0e4), 1 << qid);
6014
6015 /* Mark the queue as active. */
6016 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x104 + (qid) * 4),
6017 IWN4965_TXQ_STATUS_ACTIVE0x0007fc01 | IWN4965_TXQ_STATUS_AGGR_ENA(1 << 5 | 1 << 8) |
6018 iwn_tid2fifo[tid] << 1);
6019}
6020
6021void
6022iwn4965_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn)
6023{
6024 int qid = IWN4965_FIRST_AGG_TXQUEUE7 + tid;
6025 uint16_t idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1));
6026
6027 /* Stop TX scheduler while we're changing its configuration. */
6028 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x104 + (qid) * 4),
6029 IWN4965_TXQ_STATUS_CHGACT(1 << 10));
6030
6031 /* Set starting sequence number from the ADDBA request. */
6032 sc->txq[qid].cur = sc->txq[qid].read = idx;
6033 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | idx))))
;
6034 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid)(0xa02c00 + 0x064 + (qid) * 4), ssn);
6035
6036 /* Disable interrupts for the queue. */
6037 iwn_prph_clrbits(sc, IWN4965_SCHED_INTR_MASK(0xa02c00 + 0x0e4), 1 << qid);
6038
6039 /* Mark the queue as inactive. */
6040 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x104 + (qid) * 4),
6041 IWN4965_TXQ_STATUS_INACTIVE0x0007fc00 | iwn_tid2fifo[tid] << 1);
6042}
6043
6044void
6045iwn5000_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni,
6046 uint8_t tid, uint16_t ssn)
6047{
6048 int qid = IWN5000_FIRST_AGG_TXQUEUE10 + tid;
6049 int idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1));
6050 struct iwn_node *wn = (void *)ni;
6051
6052 /* Stop TX scheduler while we're changing its configuration. */
6053 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x10c + (qid) * 4),
6054 IWN5000_TXQ_STATUS_CHGACT(1 << 19));
6055
6056 /* Assign RA/TID translation to the queue. */
6057 iwn_mem_write_2(sc, sc->sched_base + IWN5000_SCHED_TRANS_TBL(qid)(0x7e0 + (qid) * 2),
6058 wn->id << 4 | tid);
6059
6060 /* Enable chain-building mode for the queue. */
6061 iwn_prph_setbits(sc, IWN5000_SCHED_QCHAIN_SEL(0xa02c00 + 0x0e8), 1 << qid);
6062
6063 /* Enable aggregation for the queue. */
6064 iwn_prph_setbits(sc, IWN5000_SCHED_AGGR_SEL(0xa02c00 + 0x248), 1 << qid);
6065
6066 /* Set starting sequence number from the ADDBA request. */
6067 sc->txq[qid].cur = sc->txq[qid].read = idx;
6068 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | idx))))
;
6069 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid)(0xa02c00 + 0x068 + (qid) * 4), ssn);
6070
6071 /* Set scheduler window size and frame limit. */
6072 iwn_mem_write(sc, sc->sched_base + IWN5000_SCHED_QUEUE_OFFSET(qid)(0x600 + (qid) * 8) + 4,
6073 IWN_SCHED_LIMIT64 << 16 | IWN_SCHED_WINSZ64);
6074
6075 /* Enable interrupts for the queue. */
6076 iwn_prph_setbits(sc, IWN5000_SCHED_INTR_MASK(0xa02c00 + 0x108), 1 << qid);
6077
6078 /* Mark the queue as active. */
6079 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x10c + (qid) * 4),
6080 IWN5000_TXQ_STATUS_ACTIVE0x00ff0018 | iwn_tid2fifo[tid]);
6081}
6082
6083void
6084iwn5000_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn)
6085{
6086 int qid = IWN5000_FIRST_AGG_TXQUEUE10 + tid;
6087 int idx = IWN_AGG_SSN_TO_TXQ_IDX(ssn)((ssn) & (256 - 1));
6088
6089 /* Stop TX scheduler while we're changing its configuration. */
6090 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x10c + (qid) * 4),
6091 IWN5000_TXQ_STATUS_CHGACT(1 << 19));
6092
6093 /* Disable aggregation for the queue. */
6094 iwn_prph_clrbits(sc, IWN5000_SCHED_AGGR_SEL(0xa02c00 + 0x248), 1 << qid);
6095
6096 /* Set starting sequence number from the ADDBA request. */
6097 sc->txq[qid].cur = sc->txq[qid].read = idx;
6098 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | idx)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | idx))))
;
6099 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid)(0xa02c00 + 0x068 + (qid) * 4), ssn);
6100
6101 /* Disable interrupts for the queue. */
6102 iwn_prph_clrbits(sc, IWN5000_SCHED_INTR_MASK(0xa02c00 + 0x108), 1 << qid);
6103
6104 /* Mark the queue as inactive. */
6105 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x10c + (qid) * 4),
6106 IWN5000_TXQ_STATUS_INACTIVE0x00ff0010 | iwn_tid2fifo[tid]);
6107}
6108
6109/*
6110 * Query calibration tables from the initialization firmware. We do this
6111 * only once at first boot. Called from a process context.
6112 */
6113int
6114iwn5000_query_calibration(struct iwn_softc *sc)
6115{
6116 struct iwn5000_calib_config cmd;
6117 int error;
6118
6119 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
6120 cmd.ucode.once.enable = 0xffffffff;
6121 cmd.ucode.once.start = 0xffffffff;
6122 cmd.ucode.once.send = 0xffffffff;
6123 cmd.ucode.flags = 0xffffffff;
6124 DPRINTF(("sending calibration query\n"));
6125 error = iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG101, &cmd, sizeof cmd, 0);
6126 if (error != 0)
6127 return error;
6128
6129 /* Wait at most two seconds for calibration to complete. */
6130 if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE(1 << 2)))
6131 error = tsleep_nsec(sc, PCATCH0x100, "iwncal", SEC_TO_NSEC(2));
6132 return error;
6133}
6134
6135/*
6136 * Send calibration results to the runtime firmware. These results were
6137 * obtained on first boot from the initialization firmware.
6138 */
6139int
6140iwn5000_send_calibration(struct iwn_softc *sc)
6141{
6142 int idx, error;
6143
6144 for (idx = 0; idx < 5; idx++) {
6145 if (sc->calibcmd[idx].buf == NULL((void *)0))
6146 continue; /* No results available. */
6147 DPRINTF(("send calibration result idx=%d len=%d\n",
6148 idx, sc->calibcmd[idx].len));
6149 error = iwn_cmd(sc, IWN_CMD_PHY_CALIB176, sc->calibcmd[idx].buf,
6150 sc->calibcmd[idx].len, 0);
6151 if (error != 0) {
6152 printf("%s: could not send calibration result\n",
6153 sc->sc_dev.dv_xname);
6154 return error;
6155 }
6156 }
6157 return 0;
6158}
6159
6160int
6161iwn5000_send_wimax_coex(struct iwn_softc *sc)
6162{
6163 struct iwn5000_wimax_coex wimax;
6164
6165#ifdef notyet
6166 if (sc->hw_type == IWN_HW_REV_TYPE_60508) {
6167 /* Enable WiMAX coexistence for combo adapters. */
6168 wimax.flags =
6169 IWN_WIMAX_COEX_ASSOC_WA_UNMASK(1 << 3) |
6170 IWN_WIMAX_COEX_UNASSOC_WA_UNMASK(1 << 2) |
6171 IWN_WIMAX_COEX_STA_TABLE_VALID(1 << 0) |
6172 IWN_WIMAX_COEX_ENABLE(1 << 7);
6173 memcpy(wimax.events, iwn6050_wimax_events,__builtin_memcpy((wimax.events), (iwn6050_wimax_events), (sizeof
iwn6050_wimax_events))
6174 sizeof iwn6050_wimax_events)__builtin_memcpy((wimax.events), (iwn6050_wimax_events), (sizeof
iwn6050_wimax_events))
;
6175 } else
6176#endif
6177 {
6178 /* Disable WiMAX coexistence. */
6179 wimax.flags = 0;
6180 memset(wimax.events, 0, sizeof wimax.events)__builtin_memset((wimax.events), (0), (sizeof wimax.events));
6181 }
6182 DPRINTF(("Configuring WiMAX coexistence\n"));
6183 return iwn_cmd(sc, IWN5000_CMD_WIMAX_COEX90, &wimax, sizeof wimax, 0);
6184}
6185
6186int
6187iwn5000_crystal_calib(struct iwn_softc *sc)
6188{
6189 struct iwn5000_phy_calib_crystal cmd;
6190
6191 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
6192 cmd.code = IWN5000_PHY_CALIB_CRYSTAL15;
6193 cmd.ngroups = 1;
6194 cmd.isvalid = 1;
6195 cmd.cap_pin[0] = letoh32(sc->eeprom_crystal)((__uint32_t)(sc->eeprom_crystal)) & 0xff;
6196 cmd.cap_pin[1] = (letoh32(sc->eeprom_crystal)((__uint32_t)(sc->eeprom_crystal)) >> 16) & 0xff;
6197 DPRINTF(("sending crystal calibration %d, %d\n",
6198 cmd.cap_pin[0], cmd.cap_pin[1]));
6199 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 0);
6200}
6201
6202int
6203iwn6000_temp_offset_calib(struct iwn_softc *sc)
6204{
6205 struct iwn6000_phy_calib_temp_offset cmd;
6206
6207 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
6208 cmd.code = IWN6000_PHY_CALIB_TEMP_OFFSET18;
6209 cmd.ngroups = 1;
6210 cmd.isvalid = 1;
6211 if (sc->eeprom_temp != 0)
6212 cmd.offset = htole16(sc->eeprom_temp)((__uint16_t)(sc->eeprom_temp));
6213 else
6214 cmd.offset = htole16(IWN_DEFAULT_TEMP_OFFSET)((__uint16_t)(2700));
6215 DPRINTF(("setting radio sensor offset to %d\n", letoh16(cmd.offset)));
6216 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 0);
6217}
6218
6219int
6220iwn2000_temp_offset_calib(struct iwn_softc *sc)
6221{
6222 struct iwn2000_phy_calib_temp_offset cmd;
6223
6224 memset(&cmd, 0, sizeof cmd)__builtin_memset((&cmd), (0), (sizeof cmd));
6225 cmd.code = IWN2000_PHY_CALIB_TEMP_OFFSET18;
6226 cmd.ngroups = 1;
6227 cmd.isvalid = 1;
6228 if (sc->eeprom_rawtemp != 0) {
6229 cmd.offset_low = htole16(sc->eeprom_rawtemp)((__uint16_t)(sc->eeprom_rawtemp));
6230 cmd.offset_high = htole16(sc->eeprom_temp)((__uint16_t)(sc->eeprom_temp));
6231 } else {
6232 cmd.offset_low = htole16(IWN_DEFAULT_TEMP_OFFSET)((__uint16_t)(2700));
6233 cmd.offset_high = htole16(IWN_DEFAULT_TEMP_OFFSET)((__uint16_t)(2700));
6234 }
6235 cmd.burnt_voltage_ref = htole16(sc->eeprom_voltage)((__uint16_t)(sc->eeprom_voltage));
6236 DPRINTF(("setting radio sensor offset to %d:%d, voltage to %d\n",
6237 letoh16(cmd.offset_low), letoh16(cmd.offset_high),
6238 letoh16(cmd.burnt_voltage_ref)));
6239 return iwn_cmd(sc, IWN_CMD_PHY_CALIB176, &cmd, sizeof cmd, 0);
6240}
6241
6242/*
6243 * This function is called after the runtime firmware notifies us of its
6244 * readiness (called in a process context).
6245 */
6246int
6247iwn4965_post_alive(struct iwn_softc *sc)
6248{
6249 int error, qid;
6250
6251 if ((error = iwn_nic_lock(sc)) != 0)
6252 return error;
6253
6254 /* Clear TX scheduler state in SRAM. */
6255 sc->sched_base = iwn_prph_read(sc, IWN_SCHED_SRAM_ADDR(0xa02c00 + 0x000));
6256 iwn_mem_set_region_4(sc, sc->sched_base + IWN4965_SCHED_CTX_OFF0x380, 0,
6257 IWN4965_SCHED_CTX_LEN416 / sizeof (uint32_t));
6258
6259 /* Set physical address of TX scheduler rings (1KB aligned). */
6260 iwn_prph_write(sc, IWN4965_SCHED_DRAM_ADDR(0xa02c00 + 0x010), sc->sched_dma.paddr >> 10);
6261
6262 IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1e98)), (
((((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x1e98)))) |
((1 << 1))))))
;
6263
6264 /* Disable chain mode for all our 16 queues. */
6265 iwn_prph_write(sc, IWN4965_SCHED_QCHAIN_SEL(0xa02c00 + 0x0d0), 0);
6266
6267 for (qid = 0; qid < IWN4965_NTXQUEUES16; qid++) {
6268 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_RDPTR(qid)(0xa02c00 + 0x064 + (qid) * 4), 0);
6269 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | 0))))
;
6270
6271 /* Set scheduler window size. */
6272 iwn_mem_write(sc, sc->sched_base +
6273 IWN4965_SCHED_QUEUE_OFFSET(qid)(0x380 + (qid) * 8), IWN_SCHED_WINSZ64);
6274 /* Set scheduler frame limit. */
6275 iwn_mem_write(sc, sc->sched_base +
6276 IWN4965_SCHED_QUEUE_OFFSET(qid)(0x380 + (qid) * 8) + 4,
6277 IWN_SCHED_LIMIT64 << 16);
6278 }
6279
6280 /* Enable interrupts for all our 16 queues. */
6281 iwn_prph_write(sc, IWN4965_SCHED_INTR_MASK(0xa02c00 + 0x0e4), 0xffff);
6282 /* Identify TX FIFO rings (0-7). */
6283 iwn_prph_write(sc, IWN4965_SCHED_TXFACT(0xa02c00 + 0x01c), 0xff);
6284
6285 /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
6286 for (qid = 0; qid < 7; qid++) {
6287 static uint8_t qid2fifo[] = { 3, 2, 1, 0, 4, 5, 6 };
6288 iwn_prph_write(sc, IWN4965_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x104 + (qid) * 4),
6289 IWN4965_TXQ_STATUS_ACTIVE0x0007fc01 | qid2fifo[qid] << 1);
6290 }
6291 iwn_nic_unlock(sc);
6292 return 0;
6293}
6294
6295/*
6296 * This function is called after the initialization or runtime firmware
6297 * notifies us of its readiness (called in a process context).
6298 */
6299int
6300iwn5000_post_alive(struct iwn_softc *sc)
6301{
6302 int error, qid;
6303
6304 /* Switch to using ICT interrupt mode. */
6305 iwn5000_ict_reset(sc);
6306
6307 if ((error = iwn_nic_lock(sc)) != 0)
6308 return error;
6309
6310 /* Clear TX scheduler state in SRAM. */
6311 sc->sched_base = iwn_prph_read(sc, IWN_SCHED_SRAM_ADDR(0xa02c00 + 0x000));
6312 iwn_mem_set_region_4(sc, sc->sched_base + IWN5000_SCHED_CTX_OFF0x600, 0,
6313 IWN5000_SCHED_CTX_LEN520 / sizeof (uint32_t));
6314
6315 /* Set physical address of TX scheduler rings (1KB aligned). */
6316 iwn_prph_write(sc, IWN5000_SCHED_DRAM_ADDR(0xa02c00 + 0x008), sc->sched_dma.paddr >> 10);
6317
6318 /* Disable scheduler chain extension (enabled by default in HW). */
6319 iwn_prph_write(sc, IWN5000_SCHED_CHAINEXT_EN(0xa02c00 + 0x244), 0);
6320
6321 IWN_SETBITS(sc, IWN_FH_TX_CHICKEN, IWN_FH_TX_CHICKEN_SCHED_RETRY)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1e98)), (
((((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x1e98)))) |
((1 << 1))))))
;
6322
6323 /* Enable chain mode for all queues, except command queue. */
6324 iwn_prph_write(sc, IWN5000_SCHED_QCHAIN_SEL(0xa02c00 + 0x0e8), 0xfffef);
6325 iwn_prph_write(sc, IWN5000_SCHED_AGGR_SEL(0xa02c00 + 0x248), 0);
6326
6327 for (qid = 0; qid < IWN5000_NTXQUEUES20; qid++) {
6328 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_RDPTR(qid)(0xa02c00 + 0x068 + (qid) * 4), 0);
6329 IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, qid << 8 | 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x460)), ((
qid << 8 | 0))))
;
6330
6331 iwn_mem_write(sc, sc->sched_base +
6332 IWN5000_SCHED_QUEUE_OFFSET(qid)(0x600 + (qid) * 8), 0);
6333 /* Set scheduler window size and frame limit. */
6334 iwn_mem_write(sc, sc->sched_base +
6335 IWN5000_SCHED_QUEUE_OFFSET(qid)(0x600 + (qid) * 8) + 4,
6336 IWN_SCHED_LIMIT64 << 16 | IWN_SCHED_WINSZ64);
6337 }
6338
6339 /* Enable interrupts for all our 20 queues. */
6340 iwn_prph_write(sc, IWN5000_SCHED_INTR_MASK(0xa02c00 + 0x108), 0xfffff);
6341 /* Identify TX FIFO rings (0-7). */
6342 iwn_prph_write(sc, IWN5000_SCHED_TXFACT(0xa02c00 + 0x010), 0xff);
6343
6344 /* Mark TX rings (4 EDCA + cmd + 2 HCCA) as active. */
6345 for (qid = 0; qid < 7; qid++) {
6346 static uint8_t qid2fifo[] = { 3, 2, 1, 0, 7, 5, 6 };
6347 iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid)(0xa02c00 + 0x10c + (qid) * 4),
6348 IWN5000_TXQ_STATUS_ACTIVE0x00ff0018 | qid2fifo[qid]);
6349 }
6350 iwn_nic_unlock(sc);
6351
6352 /* Configure WiMAX coexistence for combo adapters. */
6353 error = iwn5000_send_wimax_coex(sc);
6354 if (error != 0) {
6355 printf("%s: could not configure WiMAX coexistence\n",
6356 sc->sc_dev.dv_xname);
6357 return error;
6358 }
6359 if (sc->hw_type != IWN_HW_REV_TYPE_51504) {
6360 /* Perform crystal calibration. */
6361 error = iwn5000_crystal_calib(sc);
6362 if (error != 0) {
6363 printf("%s: crystal calibration failed\n",
6364 sc->sc_dev.dv_xname);
6365 return error;
6366 }
6367 }
6368 if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE(1 << 2))) {
6369 /* Query calibration from the initialization firmware. */
6370 if ((error = iwn5000_query_calibration(sc)) != 0) {
6371 printf("%s: could not query calibration\n",
6372 sc->sc_dev.dv_xname);
6373 return error;
6374 }
6375 /*
6376 * We have the calibration results now, reboot with the
6377 * runtime firmware (call ourselves recursively!)
6378 */
6379 iwn_hw_stop(sc);
6380 error = iwn_hw_init(sc);
6381 } else {
6382 /* Send calibration results to runtime firmware. */
6383 error = iwn5000_send_calibration(sc);
6384 }
6385 return error;
6386}
6387
6388/*
6389 * The firmware boot code is small and is intended to be copied directly into
6390 * the NIC internal memory (no DMA transfer).
6391 */
6392int
6393iwn4965_load_bootcode(struct iwn_softc *sc, const uint8_t *ucode, int size)
6394{
6395 int error, ntries;
6396
6397 size /= sizeof (uint32_t);
6398
6399 if ((error = iwn_nic_lock(sc)) != 0)
6400 return error;
6401
6402 /* Copy microcode image into NIC memory. */
6403 iwn_prph_write_region_4(sc, IWN_BSM_SRAM_BASE0x3800,
6404 (const uint32_t *)ucode, size);
6405
6406 iwn_prph_write(sc, IWN_BSM_WR_MEM_SRC0x3404, 0);
6407 iwn_prph_write(sc, IWN_BSM_WR_MEM_DST0x3408, IWN_FW_TEXT_BASE0x00000000);
6408 iwn_prph_write(sc, IWN_BSM_WR_DWCOUNT0x340c, size);
6409
6410 /* Start boot load now. */
6411 iwn_prph_write(sc, IWN_BSM_WR_CTRL0x3400, IWN_BSM_WR_CTRL_START(1U << 31));
6412
6413 /* Wait for transfer to complete. */
6414 for (ntries = 0; ntries < 1000; ntries++) {
6415 if (!(iwn_prph_read(sc, IWN_BSM_WR_CTRL0x3400) &
6416 IWN_BSM_WR_CTRL_START(1U << 31)))
6417 break;
6418 DELAY(10)(*delay_func)(10);
6419 }
6420 if (ntries == 1000) {
6421 printf("%s: could not load boot firmware\n",
6422 sc->sc_dev.dv_xname);
6423 iwn_nic_unlock(sc);
6424 return ETIMEDOUT60;
6425 }
6426
6427 /* Enable boot after power up. */
6428 iwn_prph_write(sc, IWN_BSM_WR_CTRL0x3400, IWN_BSM_WR_CTRL_START_EN(1U << 30));
6429
6430 iwn_nic_unlock(sc);
6431 return 0;
6432}
6433
6434int
6435iwn4965_load_firmware(struct iwn_softc *sc)
6436{
6437 struct iwn_fw_info *fw = &sc->fw;
6438 struct iwn_dma_info *dma = &sc->fw_dma;
6439 int error;
6440
6441 /* Copy initialization sections into pre-allocated DMA-safe memory. */
6442 memcpy(dma->vaddr, fw->init.data, fw->init.datasz)__builtin_memcpy((dma->vaddr), (fw->init.data), (fw->
init.datasz))
;
6443 bus_dmamap_sync(sc->sc_dmat, dma->map, 0, fw->init.datasz,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (0), (fw->init.datasz), (0x04))
6444 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (0), (fw->init.datasz), (0x04))
;
6445 memcpy(dma->vaddr + IWN4965_FW_DATA_MAXSZ,__builtin_memcpy((dma->vaddr + ( 40 * 1024)), (fw->init
.text), (fw->init.textsz))
6446 fw->init.text, fw->init.textsz)__builtin_memcpy((dma->vaddr + ( 40 * 1024)), (fw->init
.text), (fw->init.textsz))
;
6447 bus_dmamap_sync(sc->sc_dmat, dma->map, IWN4965_FW_DATA_MAXSZ,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (( 40 * 1024)), (fw->init.textsz), (0x04))
6448 fw->init.textsz, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (( 40 * 1024)), (fw->init.textsz), (0x04))
;
6449
6450 /* Tell adapter where to find initialization sections. */
6451 if ((error = iwn_nic_lock(sc)) != 0)
6452 return error;
6453 iwn_prph_write(sc, IWN_BSM_DRAM_DATA_ADDR0x3498, dma->paddr >> 4);
6454 iwn_prph_write(sc, IWN_BSM_DRAM_DATA_SIZE0x349c, fw->init.datasz);
6455 iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_ADDR0x3490,
6456 (dma->paddr + IWN4965_FW_DATA_MAXSZ( 40 * 1024)) >> 4);
6457 iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_SIZE0x3494, fw->init.textsz);
6458 iwn_nic_unlock(sc);
6459
6460 /* Load firmware boot code. */
6461 error = iwn4965_load_bootcode(sc, fw->boot.text, fw->boot.textsz);
6462 if (error != 0) {
6463 printf("%s: could not load boot firmware\n",
6464 sc->sc_dev.dv_xname);
6465 return error;
6466 }
6467 /* Now press "execute". */
6468 IWN_WRITE(sc, IWN_RESET, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x020)), ((
0))))
;
6469
6470 /* Wait at most one second for first alive notification. */
6471 if ((error = tsleep_nsec(sc, PCATCH0x100, "iwninit", SEC_TO_NSEC(1))) != 0) {
6472 printf("%s: timeout waiting for adapter to initialize\n",
6473 sc->sc_dev.dv_xname);
6474 return error;
6475 }
6476
6477 /* Retrieve current temperature for initial TX power calibration. */
6478 sc->rawtemp = sc->ucode_info.temp[3].chan20MHz;
6479 sc->temp = iwn4965_get_temperature(sc);
6480
6481 /* Copy runtime sections into pre-allocated DMA-safe memory. */
6482 memcpy(dma->vaddr, fw->main.data, fw->main.datasz)__builtin_memcpy((dma->vaddr), (fw->main.data), (fw->
main.datasz))
;
6483 bus_dmamap_sync(sc->sc_dmat, dma->map, 0, fw->main.datasz,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (0), (fw->main.datasz), (0x04))
6484 BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (0), (fw->main.datasz), (0x04))
;
6485 memcpy(dma->vaddr + IWN4965_FW_DATA_MAXSZ,__builtin_memcpy((dma->vaddr + ( 40 * 1024)), (fw->main
.text), (fw->main.textsz))
6486 fw->main.text, fw->main.textsz)__builtin_memcpy((dma->vaddr + ( 40 * 1024)), (fw->main
.text), (fw->main.textsz))
;
6487 bus_dmamap_sync(sc->sc_dmat, dma->map, IWN4965_FW_DATA_MAXSZ,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (( 40 * 1024)), (fw->main.textsz), (0x04))
6488 fw->main.textsz, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (( 40 * 1024)), (fw->main.textsz), (0x04))
;
6489
6490 /* Tell adapter where to find runtime sections. */
6491 if ((error = iwn_nic_lock(sc)) != 0)
6492 return error;
6493 iwn_prph_write(sc, IWN_BSM_DRAM_DATA_ADDR0x3498, dma->paddr >> 4);
6494 iwn_prph_write(sc, IWN_BSM_DRAM_DATA_SIZE0x349c, fw->main.datasz);
6495 iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_ADDR0x3490,
6496 (dma->paddr + IWN4965_FW_DATA_MAXSZ( 40 * 1024)) >> 4);
6497 iwn_prph_write(sc, IWN_BSM_DRAM_TEXT_SIZE0x3494,
6498 IWN_FW_UPDATED(1U << 31) | fw->main.textsz);
6499 iwn_nic_unlock(sc);
6500
6501 return 0;
6502}
6503
6504int
6505iwn5000_load_firmware_section(struct iwn_softc *sc, uint32_t dst,
6506 const uint8_t *section, int size)
6507{
6508 struct iwn_dma_info *dma = &sc->fw_dma;
6509 int error;
6510
6511 /* Copy firmware section into pre-allocated DMA-safe memory. */
6512 memcpy(dma->vaddr, section, size)__builtin_memcpy((dma->vaddr), (section), (size));
6513 bus_dmamap_sync(sc->sc_dmat, dma->map, 0, size, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (dma->
map), (0), (size), (0x04))
;
6514
6515 if ((error = iwn_nic_lock(sc)) != 0)
6516 return error;
6517
6518 IWN_WRITE(sc, IWN_FH_TX_CONFIG(IWN_SRVC_DMACHNL),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
9) * 32))), ((0))))
6519 IWN_FH_TX_CONFIG_DMA_PAUSE)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
9) * 32))), ((0))))
;
6520
6521 IWN_WRITE(sc, IWN_FH_SRAM_ADDR(IWN_SRVC_DMACHNL), dst)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x19a4 + (
9) * 4))), ((dst))))
;
6522 IWN_WRITE(sc, IWN_FH_TFBD_CTRL0(IWN_SRVC_DMACHNL),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1900 + (
9) * 8))), ((((uint32_t)(dma->paddr))))))
6523 IWN_LOADDR(dma->paddr))(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1900 + (
9) * 8))), ((((uint32_t)(dma->paddr))))))
;
6524 IWN_WRITE(sc, IWN_FH_TFBD_CTRL1(IWN_SRVC_DMACHNL),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1904 + (
9) * 8))), (((((dma->paddr) >> 32) & 0xf) <<
28 | size))))
6525 IWN_HIADDR(dma->paddr) << 28 | size)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1904 + (
9) * 8))), (((((dma->paddr) >> 32) & 0xf) <<
28 | size))))
;
6526 IWN_WRITE(sc, IWN_FH_TXBUF_STATUS(IWN_SRVC_DMACHNL),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d08 + (
9) * 32))), ((((1) << 20) | ((1) << 12) | 3))))
6527 IWN_FH_TXBUF_STATUS_TBNUM(1) |(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d08 + (
9) * 32))), ((((1) << 20) | ((1) << 12) | 3))))
6528 IWN_FH_TXBUF_STATUS_TBIDX(1) |(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d08 + (
9) * 32))), ((((1) << 20) | ((1) << 12) | 3))))
6529 IWN_FH_TXBUF_STATUS_TFBD_VALID)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d08 + (
9) * 32))), ((((1) << 20) | ((1) << 12) | 3))))
;
6530
6531 /* Kick Flow Handler to start DMA transfer. */
6532 IWN_WRITE(sc, IWN_FH_TX_CONFIG(IWN_SRVC_DMACHNL),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
9) * 32))), (((1U << 31) | (1U << 20)))))
6533 IWN_FH_TX_CONFIG_DMA_ENA | IWN_FH_TX_CONFIG_CIRQ_HOST_ENDTFD)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
9) * 32))), (((1U << 31) | (1U << 20)))))
;
6534
6535 iwn_nic_unlock(sc);
6536
6537 /* Wait at most five seconds for FH DMA transfer to complete. */
6538 return tsleep_nsec(sc, PCATCH0x100, "iwninit", SEC_TO_NSEC(5));
6539}
6540
6541int
6542iwn5000_load_firmware(struct iwn_softc *sc)
6543{
6544 struct iwn_fw_part *fw;
6545 int error;
6546
6547 /* Load the initialization firmware on first boot only. */
6548 fw = (sc->sc_flags & IWN_FLAG_CALIB_DONE(1 << 2)) ?
6549 &sc->fw.main : &sc->fw.init;
6550
6551 error = iwn5000_load_firmware_section(sc, IWN_FW_TEXT_BASE0x00000000,
6552 fw->text, fw->textsz);
6553 if (error != 0) {
6554 printf("%s: could not load firmware %s section\n",
6555 sc->sc_dev.dv_xname, ".text");
6556 return error;
6557 }
6558 error = iwn5000_load_firmware_section(sc, IWN_FW_DATA_BASE0x00800000,
6559 fw->data, fw->datasz);
6560 if (error != 0) {
6561 printf("%s: could not load firmware %s section\n",
6562 sc->sc_dev.dv_xname, ".data");
6563 return error;
6564 }
6565
6566 /* Now press "execute". */
6567 IWN_WRITE(sc, IWN_RESET, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x020)), ((
0))))
;
6568 return 0;
6569}
6570
6571/*
6572 * Extract text and data sections from a legacy firmware image.
6573 */
6574int
6575iwn_read_firmware_leg(struct iwn_softc *sc, struct iwn_fw_info *fw)
6576{
6577 const uint32_t *ptr;
6578 size_t hdrlen = 24;
6579 uint32_t rev;
6580
6581 ptr = (const uint32_t *)fw->data;
6582 rev = letoh32(*ptr++)((__uint32_t)(*ptr++));
6583
6584 /* Check firmware API version. */
6585 if (IWN_FW_API(rev)(((rev) >> 8) & 0xff) <= 1) {
6586 printf("%s: bad firmware, need API version >=2\n",
6587 sc->sc_dev.dv_xname);
6588 return EINVAL22;
6589 }
6590 if (IWN_FW_API(rev)(((rev) >> 8) & 0xff) >= 3) {
6591 /* Skip build number (version 2 header). */
6592 hdrlen += 4;
6593 ptr++;
6594 }
6595 if (fw->size < hdrlen) {
6596 printf("%s: firmware too short: %zu bytes\n",
6597 sc->sc_dev.dv_xname, fw->size);
6598 return EINVAL22;
6599 }
6600 fw->main.textsz = letoh32(*ptr++)((__uint32_t)(*ptr++));
6601 fw->main.datasz = letoh32(*ptr++)((__uint32_t)(*ptr++));
6602 fw->init.textsz = letoh32(*ptr++)((__uint32_t)(*ptr++));
6603 fw->init.datasz = letoh32(*ptr++)((__uint32_t)(*ptr++));
6604 fw->boot.textsz = letoh32(*ptr++)((__uint32_t)(*ptr++));
6605
6606 /* Check that all firmware sections fit. */
6607 if (fw->size < hdrlen + fw->main.textsz + fw->main.datasz +
6608 fw->init.textsz + fw->init.datasz + fw->boot.textsz) {
6609 printf("%s: firmware too short: %zu bytes\n",
6610 sc->sc_dev.dv_xname, fw->size);
6611 return EINVAL22;
6612 }
6613
6614 /* Get pointers to firmware sections. */
6615 fw->main.text = (const uint8_t *)ptr;
6616 fw->main.data = fw->main.text + fw->main.textsz;
6617 fw->init.text = fw->main.data + fw->main.datasz;
6618 fw->init.data = fw->init.text + fw->init.textsz;
6619 fw->boot.text = fw->init.data + fw->init.datasz;
6620 return 0;
6621}
6622
6623/*
6624 * Extract text and data sections from a TLV firmware image.
6625 */
6626int
6627iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,
6628 uint16_t alt)
6629{
6630 const struct iwn_fw_tlv_hdr *hdr;
6631 const struct iwn_fw_tlv *tlv;
6632 const uint8_t *ptr, *end;
6633 uint64_t altmask;
6634 uint32_t len;
6635
6636 if (fw->size < sizeof (*hdr)) {
6637 printf("%s: firmware too short: %zu bytes\n",
6638 sc->sc_dev.dv_xname, fw->size);
6639 return EINVAL22;
6640 }
6641 hdr = (const struct iwn_fw_tlv_hdr *)fw->data;
6642 if (hdr->signature != htole32(IWN_FW_SIGNATURE)((__uint32_t)(0x0a4c5749))) {
6643 printf("%s: bad firmware signature 0x%08x\n",
6644 sc->sc_dev.dv_xname, letoh32(hdr->signature)((__uint32_t)(hdr->signature)));
6645 return EINVAL22;
6646 }
6647 DPRINTF(("FW: \"%.64s\", build 0x%x\n", hdr->descr,
6648 letoh32(hdr->build)));
6649
6650 /*
6651 * Select the closest supported alternative that is less than
6652 * or equal to the specified one.
6653 */
6654 altmask = letoh64(hdr->altmask)((__uint64_t)(hdr->altmask));
6655 while (alt > 0 && !(altmask & (1ULL << alt)))
6656 alt--; /* Downgrade. */
6657 DPRINTF(("using alternative %d\n", alt));
6658
6659 ptr = (const uint8_t *)(hdr + 1);
6660 end = (const uint8_t *)(fw->data + fw->size);
6661
6662 /* Parse type-length-value fields. */
6663 while (ptr + sizeof (*tlv) <= end) {
6664 tlv = (const struct iwn_fw_tlv *)ptr;
6665 len = letoh32(tlv->len)((__uint32_t)(tlv->len));
6666
6667 ptr += sizeof (*tlv);
6668 if (ptr + len > end) {
6669 printf("%s: firmware too short: %zu bytes\n",
6670 sc->sc_dev.dv_xname, fw->size);
6671 return EINVAL22;
6672 }
6673 /* Skip other alternatives. */
6674 if (tlv->alt != 0 && tlv->alt != htole16(alt)((__uint16_t)(alt)))
6675 goto next;
6676
6677 switch (letoh16(tlv->type)((__uint16_t)(tlv->type))) {
6678 case IWN_FW_TLV_MAIN_TEXT1:
6679 fw->main.text = ptr;
6680 fw->main.textsz = len;
6681 break;
6682 case IWN_FW_TLV_MAIN_DATA2:
6683 fw->main.data = ptr;
6684 fw->main.datasz = len;
6685 break;
6686 case IWN_FW_TLV_INIT_TEXT3:
6687 fw->init.text = ptr;
6688 fw->init.textsz = len;
6689 break;
6690 case IWN_FW_TLV_INIT_DATA4:
6691 fw->init.data = ptr;
6692 fw->init.datasz = len;
6693 break;
6694 case IWN_FW_TLV_BOOT_TEXT5:
6695 fw->boot.text = ptr;
6696 fw->boot.textsz = len;
6697 break;
6698 case IWN_FW_TLV_ENH_SENS14:
6699 if (len != 0) {
6700 printf("%s: TLV type %d has invalid size %u\n",
6701 sc->sc_dev.dv_xname, letoh16(tlv->type)((__uint16_t)(tlv->type)),
6702 len);
6703 goto next;
6704 }
6705 sc->sc_flags |= IWN_FLAG_ENH_SENS(1 << 7);
6706 break;
6707 case IWN_FW_TLV_PHY_CALIB15:
6708 if (len != sizeof(uint32_t)) {
6709 printf("%s: TLV type %d has invalid size %u\n",
6710 sc->sc_dev.dv_xname, letoh16(tlv->type)((__uint16_t)(tlv->type)),
6711 len);
6712 goto next;
6713 }
6714 if (letoh32(*ptr)((__uint32_t)(*ptr)) <= IWN5000_PHY_CALIB_MAX253) {
6715 sc->reset_noise_gain = letoh32(*ptr)((__uint32_t)(*ptr));
6716 sc->noise_gain = letoh32(*ptr)((__uint32_t)(*ptr)) + 1;
6717 }
6718 break;
6719 case IWN_FW_TLV_FLAGS18:
6720 if (len < sizeof(uint32_t))
6721 break;
6722 if (len % sizeof(uint32_t))
6723 break;
6724 sc->tlv_feature_flags = letoh32(*ptr)((__uint32_t)(*ptr));
6725 DPRINTF(("feature: 0x%08x\n", sc->tlv_feature_flags));
6726 break;
6727 default:
6728 DPRINTF(("TLV type %d not handled\n",
6729 letoh16(tlv->type)));
6730 break;
6731 }
6732 next: /* TLV fields are 32-bit aligned. */
6733 ptr += (len + 3) & ~3;
6734 }
6735 return 0;
6736}
6737
6738int
6739iwn_read_firmware(struct iwn_softc *sc)
6740{
6741 struct iwn_fw_info *fw = &sc->fw;
6742 int error;
6743
6744 /*
6745 * Some PHY calibration commands are firmware-dependent; these
6746 * are the default values that will be overridden if
6747 * necessary.
6748 */
6749 sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN18;
6750 sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN19;
6751
6752 memset(fw, 0, sizeof (*fw))__builtin_memset((fw), (0), (sizeof (*fw)));
6753
6754 /* Read firmware image from filesystem. */
6755 if ((error = loadfirmware(sc->fwname, &fw->data, &fw->size)) != 0) {
6756 printf("%s: could not read firmware %s (error %d)\n",
6757 sc->sc_dev.dv_xname, sc->fwname, error);
6758 return error;
6759 }
6760 if (fw->size < sizeof (uint32_t)) {
6761 printf("%s: firmware too short: %zu bytes\n",
6762 sc->sc_dev.dv_xname, fw->size);
6763 free(fw->data, M_DEVBUF2, fw->size);
6764 return EINVAL22;
6765 }
6766
6767 /* Retrieve text and data sections. */
6768 if (*(const uint32_t *)fw->data != 0) /* Legacy image. */
6769 error = iwn_read_firmware_leg(sc, fw);
6770 else
6771 error = iwn_read_firmware_tlv(sc, fw, 1);
6772 if (error != 0) {
6773 printf("%s: could not read firmware sections\n",
6774 sc->sc_dev.dv_xname);
6775 free(fw->data, M_DEVBUF2, fw->size);
6776 return error;
6777 }
6778
6779 /* Make sure text and data sections fit in hardware memory. */
6780 if (fw->main.textsz > sc->fw_text_maxsz ||
6781 fw->main.datasz > sc->fw_data_maxsz ||
6782 fw->init.textsz > sc->fw_text_maxsz ||
6783 fw->init.datasz > sc->fw_data_maxsz ||
6784 fw->boot.textsz > IWN_FW_BOOT_TEXT_MAXSZ1024 ||
6785 (fw->boot.textsz & 3) != 0) {
6786 printf("%s: firmware sections too large\n",
6787 sc->sc_dev.dv_xname);
6788 free(fw->data, M_DEVBUF2, fw->size);
6789 return EINVAL22;
6790 }
6791
6792 /* We can proceed with loading the firmware. */
6793 return 0;
6794}
6795
6796int
6797iwn_clock_wait(struct iwn_softc *sc)
6798{
6799 int ntries;
6800
6801 /* Set "initialization complete" bit. */
6802 IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_INIT_DONE)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x024)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) | (
(1 << 2))))))
;
6803
6804 /* Wait for clock stabilization. */
6805 for (ntries = 0; ntries < 2500; ntries++) {
6806 if (IWN_READ(sc, IWN_GP_CNTRL)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) & IWN_GP_CNTRL_MAC_CLOCK_READY(1 << 0))
6807 return 0;
6808 DELAY(10)(*delay_func)(10);
6809 }
6810 printf("%s: timeout waiting for clock stabilization\n",
6811 sc->sc_dev.dv_xname);
6812 return ETIMEDOUT60;
6813}
6814
6815int
6816iwn_apm_init(struct iwn_softc *sc)
6817{
6818 pcireg_t reg;
6819 int error;
6820
6821 /* Disable L0s exit timer (NMI bug workaround). */
6822 IWN_SETBITS(sc, IWN_GIO_CHICKEN, IWN_GIO_CHICKEN_DIS_L0S_TIMER)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x100)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x100)))) | (
(1 << 29))))))
;
6823 /* Don't wait for ICH L0s (ICH bug workaround). */
6824 IWN_SETBITS(sc, IWN_GIO_CHICKEN, IWN_GIO_CHICKEN_L1A_NO_L0S_RX)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x100)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x100)))) | (
(1 << 23))))))
;
6825
6826 /* Set FH wait threshold to max (HW bug under stress workaround). */
6827 IWN_SETBITS(sc, IWN_DBG_HPET_MEM, 0xffff0000)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x240)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x240)))) | (
0xffff0000)))))
;
6828
6829 /* Enable HAP INTA to move adapter from L1a to L0s. */
6830 IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_HAP_WAKE_L1A)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 23))))))
;
6831
6832 /* Retrieve PCIe Active State Power Management (ASPM). */
6833 reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
6834 sc->sc_cap_off + PCI_PCIE_LCSR0x10);
6835 /* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
6836 if (reg & PCI_PCIE_LCSR_ASPM_L10x00000002) /* L1 Entry enabled. */
6837 IWN_SETBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x03c)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x03c)))) | (
(1 << 1))))))
;
6838 else
6839 IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x03c)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x03c)))) &
~((1 << 1))))))
;
6840
6841 if (sc->hw_type != IWN_HW_REV_TYPE_49650 &&
6842 sc->hw_type <= IWN_HW_REV_TYPE_10006)
6843 IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x20c)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x20c)))) | (
0x00880300)))))
;
6844
6845 /* Wait for clock stabilization before accessing prph. */
6846 if ((error = iwn_clock_wait(sc)) != 0)
6847 return error;
6848
6849 if ((error = iwn_nic_lock(sc)) != 0)
6850 return error;
6851 if (sc->hw_type == IWN_HW_REV_TYPE_49650) {
6852 /* Enable DMA and BSM (Bootstrap State Machine). */
6853 iwn_prph_write(sc, IWN_APMG_CLK_EN0x3004,
6854 IWN_APMG_CLK_CTRL_DMA_CLK_RQT(1 << 9) |
6855 IWN_APMG_CLK_CTRL_BSM_CLK_RQT(1 << 11));
6856 } else {
6857 /* Enable DMA. */
6858 iwn_prph_write(sc, IWN_APMG_CLK_EN0x3004,
6859 IWN_APMG_CLK_CTRL_DMA_CLK_RQT(1 << 9));
6860 }
6861 DELAY(20)(*delay_func)(20);
6862 /* Disable L1-Active. */
6863 iwn_prph_setbits(sc, IWN_APMG_PCI_STT0x3010, IWN_APMG_PCI_STT_L1A_DIS(1 << 11));
6864 iwn_nic_unlock(sc);
6865
6866 return 0;
6867}
6868
6869void
6870iwn_apm_stop_master(struct iwn_softc *sc)
6871{
6872 int ntries;
6873
6874 /* Stop busmaster DMA activity. */
6875 IWN_SETBITS(sc, IWN_RESET, IWN_RESET_STOP_MASTER)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x020)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x020)))) | (
(1U << 9))))))
;
6876 for (ntries = 0; ntries < 100; ntries++) {
6877 if (IWN_READ(sc, IWN_RESET)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x020)))) & IWN_RESET_MASTER_DISABLED(1U << 8))
6878 return;
6879 DELAY(10)(*delay_func)(10);
6880 }
6881 printf("%s: timeout waiting for master\n", sc->sc_dev.dv_xname);
6882}
6883
6884void
6885iwn_apm_stop(struct iwn_softc *sc)
6886{
6887 iwn_apm_stop_master(sc);
6888
6889 /* Reset the entire device. */
6890 IWN_SETBITS(sc, IWN_RESET, IWN_RESET_SW)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x020)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x020)))) | (
(1U << 7))))))
;
6891 DELAY(10)(*delay_func)(10);
6892 /* Clear "initialization complete" bit. */
6893 IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_INIT_DONE)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x024)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) &
~((1 << 2))))))
;
6894}
6895
6896int
6897iwn4965_nic_config(struct iwn_softc *sc)
6898{
6899 if (IWN_RFCFG_TYPE(sc->rfcfg)(((sc->rfcfg) >> 0) & 0x3) == 1) {
6900 /*
6901 * I don't believe this to be correct but this is what the
6902 * vendor driver is doing. Probably the bits should not be
6903 * shifted in IWN_RFCFG_*.
6904 */
6905 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)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
6906 IWN_RFCFG_TYPE(sc->rfcfg) |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
6907 IWN_RFCFG_STEP(sc->rfcfg) |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
6908 IWN_RFCFG_DASH(sc->rfcfg))(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
;
6909 }
6910 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 << 9) | (1 << 8))))))
6911 IWN_HW_IF_CONFIG_RADIO_SI | IWN_HW_IF_CONFIG_MAC_SI)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 9) | (1 << 8))))))
;
6912 return 0;
6913}
6914
6915int
6916iwn5000_nic_config(struct iwn_softc *sc)
6917{
6918 uint32_t tmp;
6919 int error;
6920
6921 if (IWN_RFCFG_TYPE(sc->rfcfg)(((sc->rfcfg) >> 0) & 0x3) < 3) {
6922 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)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
6923 IWN_RFCFG_TYPE(sc->rfcfg) |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
6924 IWN_RFCFG_STEP(sc->rfcfg) |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
6925 IWN_RFCFG_DASH(sc->rfcfg))(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(((sc->rfcfg) >> 0) & 0x3) | (((sc->rfcfg) >>
2) & 0x3) | (((sc->rfcfg) >> 4) & 0x3))))))
;
6926 }
6927 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 << 9) | (1 << 8))))))
6928 IWN_HW_IF_CONFIG_RADIO_SI | IWN_HW_IF_CONFIG_MAC_SI)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 9) | (1 << 8))))))
;
6929
6930 if ((error = iwn_nic_lock(sc)) != 0)
6931 return error;
6932 iwn_prph_setbits(sc, IWN_APMG_PS0x300c, IWN_APMG_PS_EARLY_PWROFF_DIS(1 << 22));
6933
6934 if (sc->hw_type == IWN_HW_REV_TYPE_10006) {
6935 /*
6936 * Select first Switching Voltage Regulator (1.32V) to
6937 * solve a stability issue related to noisy DC2DC line
6938 * in the silicon of 1000 Series.
6939 */
6940 tmp = iwn_prph_read(sc, IWN_APMG_DIGITAL_SVR0x3058);
6941 tmp &= ~IWN_APMG_DIGITAL_SVR_VOLTAGE_MASK(((0xf) & 0xf) << 5);
6942 tmp |= IWN_APMG_DIGITAL_SVR_VOLTAGE_1_32(((3) & 0xf) << 5);
6943 iwn_prph_write(sc, IWN_APMG_DIGITAL_SVR0x3058, tmp);
6944 }
6945 iwn_nic_unlock(sc);
6946
6947 if (sc->sc_flags & IWN_FLAG_INTERNAL_PA(1 << 4)) {
6948 /* Use internal power amplifier only. */
6949 IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x050)), ((
(2 << 0)))))
;
6950 }
6951 if ((sc->hw_type == IWN_HW_REV_TYPE_60508 ||
6952 sc->hw_type == IWN_HW_REV_TYPE_600511) && sc->calib_ver >= 6) {
6953 /* Indicate that ROM calibration version is >=6. */
6954 IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x050)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x050)))) | (
(1 << 2))))))
;
6955 }
6956 if (sc->hw_type == IWN_HW_REV_TYPE_600511)
6957 IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_6050_1X2)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x050)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x050)))) | (
(1 << 3))))))
;
6958 if (sc->hw_type == IWN_HW_REV_TYPE_203012 ||
6959 sc->hw_type == IWN_HW_REV_TYPE_200016 ||
6960 sc->hw_type == IWN_HW_REV_TYPE_13518 ||
6961 sc->hw_type == IWN_HW_REV_TYPE_10517)
6962 IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_IQ_INVERT)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x050)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x050)))) | (
(1 << 7))))))
;
6963 return 0;
6964}
6965
6966/*
6967 * Take NIC ownership over Intel Active Management Technology (AMT).
6968 */
6969int
6970iwn_hw_prepare(struct iwn_softc *sc)
6971{
6972 int ntries;
6973
6974 /* Check if hardware is ready. */
6975 IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_NIC_READY)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 22))))))
;
6976 for (ntries = 0; ntries < 5; ntries++) {
6977 if (IWN_READ(sc, IWN_HW_IF_CONFIG)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) &
6978 IWN_HW_IF_CONFIG_NIC_READY(1 << 22))
6979 return 0;
6980 DELAY(10)(*delay_func)(10);
6981 }
6982
6983 /* Hardware not ready, force into ready state. */
6984 IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_PREPARE)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 27))))))
;
6985 for (ntries = 0; ntries < 15000; ntries++) {
6986 if (!(IWN_READ(sc, IWN_HW_IF_CONFIG)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) &
6987 IWN_HW_IF_CONFIG_PREPARE_DONE(1 << 25)))
6988 break;
6989 DELAY(10)(*delay_func)(10);
6990 }
6991 if (ntries == 15000)
6992 return ETIMEDOUT60;
6993
6994 /* Hardware should be ready now. */
6995 IWN_SETBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_NIC_READY)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x000)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) | (
(1 << 22))))))
;
6996 for (ntries = 0; ntries < 5; ntries++) {
6997 if (IWN_READ(sc, IWN_HW_IF_CONFIG)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x000)))) &
6998 IWN_HW_IF_CONFIG_NIC_READY(1 << 22))
6999 return 0;
7000 DELAY(10)(*delay_func)(10);
7001 }
7002 return ETIMEDOUT60;
7003}
7004
7005int
7006iwn_hw_init(struct iwn_softc *sc)
7007{
7008 struct iwn_ops *ops = &sc->ops;
7009 int error, chnl, qid;
7010
7011 /* Clear pending interrupts. */
7012 IWN_WRITE(sc, IWN_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
0xffffffff))))
;
7013
7014 if ((error = iwn_apm_init(sc)) != 0) {
7015 printf("%s: could not power on adapter\n",
7016 sc->sc_dev.dv_xname);
7017 return error;
7018 }
7019
7020 /* Select VMAIN power source. */
7021 if ((error = iwn_nic_lock(sc)) != 0)
7022 return error;
7023 iwn_prph_clrbits(sc, IWN_APMG_PS0x300c, IWN_APMG_PS_PWR_SRC_MASK((3) << 24));
7024 iwn_nic_unlock(sc);
7025
7026 /* Perform adapter-specific initialization. */
7027 if ((error = ops->nic_config(sc)) != 0)
7028 return error;
7029
7030 /* Initialize RX ring. */
7031 if ((error = iwn_nic_lock(sc)) != 0)
7032 return error;
7033 IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
(0))))
;
7034 IWN_WRITE(sc, IWN_FH_RX_WPTR, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc8)), (
(0))))
;
7035 /* Set physical address of RX ring (256-byte aligned). */
7036 IWN_WRITE(sc, IWN_FH_RX_BASE, sc->rxq.desc_dma.paddr >> 8)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc4)), (
(sc->rxq.desc_dma.paddr >> 8))))
;
7037 /* Set physical address of RX status (16-byte aligned). */
7038 IWN_WRITE(sc, IWN_FH_STATUS_WPTR, sc->rxq.stat_dma.paddr >> 4)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc0)), (
(sc->rxq.stat_dma.paddr >> 4))))
;
7039 /* Enable RX. */
7040 IWN_WRITE(sc, IWN_FH_RX_CONFIG,(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
7041 IWN_FH_RX_CONFIG_ENA |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
7042 IWN_FH_RX_CONFIG_IGN_RXF_EMPTY | /* HW bug workaround */(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
7043 IWN_FH_RX_CONFIG_IRQ_DST_HOST |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
7044 IWN_FH_RX_CONFIG_SINGLE_FRAME |(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
7045 IWN_FH_RX_CONFIG_RB_TIMEOUT(0x11) | /* about 1/2 msec */(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
7046 IWN_FH_RX_CONFIG_NRBD(IWN_RX_RING_COUNT_LOG))(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1c00)), (
((1U << 31) | (1U << 2) | (1U << 12) | (1U <<
15) | ((0x11) << 4) | ((6) << 20)))))
;
7047 iwn_nic_unlock(sc);
7048 IWN_WRITE(sc, IWN_FH_RX_WPTR, (IWN_RX_RING_COUNT - 1) & ~7)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x1bc8)), (
(((1 << 6) - 1) & ~7))))
;
7049
7050 if ((error = iwn_nic_lock(sc)) != 0)
7051 return error;
7052
7053 /* Initialize TX scheduler. */
7054 iwn_prph_write(sc, sc->sched_txfact_addr, 0);
7055
7056 /* Set physical address of "keep warm" page (16-byte aligned). */
7057 IWN_WRITE(sc, IWN_FH_KW_ADDR, sc->kw_dma.paddr >> 4)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x197c)), (
(sc->kw_dma.paddr >> 4))))
;
7058
7059 /* Initialize TX rings. */
7060 for (qid = 0; qid < sc->ntxqs; qid++) {
7061 struct iwn_tx_ring *txq = &sc->txq[qid];
7062
7063 /* Set physical address of TX ring (256-byte aligned). */
7064 IWN_WRITE(sc, IWN_FH_CBBC_QUEUE(qid),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x19d0 + (
qid) * 4))), ((txq->desc_dma.paddr >> 8))))
7065 txq->desc_dma.paddr >> 8)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x19d0 + (
qid) * 4))), ((txq->desc_dma.paddr >> 8))))
;
7066 }
7067 iwn_nic_unlock(sc);
7068
7069 /* Enable DMA channels. */
7070 for (chnl = 0; chnl < sc->ndmachnls; chnl++) {
7071 IWN_WRITE(sc, IWN_FH_TX_CONFIG(chnl),(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
chnl) * 32))), (((1U << 31) | (1U << 3)))))
7072 IWN_FH_TX_CONFIG_DMA_ENA |(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
chnl) * 32))), (((1U << 31) | (1U << 3)))))
7073 IWN_FH_TX_CONFIG_DMA_CREDIT_ENA)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
chnl) * 32))), (((1U << 31) | (1U << 3)))))
;
7074 }
7075
7076 /* Clear "radio off" and "commands blocked" bits. */
7077 IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x05c)), ((
(1 << 1)))))
;
7078 IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_CMD_BLOCKED)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x05c)), ((
(1 << 2)))))
;
7079
7080 /* Clear pending interrupts. */
7081 IWN_WRITE(sc, IWN_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
0xffffffff))))
;
7082 /* Enable interrupt coalescing. */
7083 IWN_WRITE(sc, IWN_INT_COALESCING, 512 / 8)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x004)), ((
512 / 8))))
;
7084 /* Enable interrupts. */
7085 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
7086
7087 /* _Really_ make sure "radio off" bit is cleared! */
7088 IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x05c)), ((
(1 << 1)))))
;
7089 IWN_WRITE(sc, IWN_UCODE_GP1_CLR, IWN_UCODE_GP1_RFKILL)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x05c)), ((
(1 << 1)))))
;
7090
7091 /* Enable shadow registers. */
7092 if (sc->hw_type >= IWN_HW_REV_TYPE_60007)
7093 IWN_SETBITS(sc, IWN_SHADOW_REG_CTRL, 0x800fffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x0a8)), ((
(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x0a8)))) | (
0x800fffff)))))
;
7094
7095 if ((error = ops->load_firmware(sc)) != 0) {
7096 printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
7097 return error;
7098 }
7099 /* Wait at most one second for firmware alive notification. */
7100 if ((error = tsleep_nsec(sc, PCATCH0x100, "iwninit", SEC_TO_NSEC(1))) != 0) {
7101 printf("%s: timeout waiting for adapter to initialize\n",
7102 sc->sc_dev.dv_xname);
7103 return error;
7104 }
7105 /* Do post-firmware initialization. */
7106 return ops->post_alive(sc);
7107}
7108
7109void
7110iwn_hw_stop(struct iwn_softc *sc)
7111{
7112 int chnl, qid, ntries;
7113
7114 IWN_WRITE(sc, IWN_RESET, IWN_RESET_NEVO)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x020)), ((
(1U << 0)))))
;
7115
7116 /* Disable interrupts. */
7117 IWN_WRITE(sc, IWN_INT_MASK, 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
0))))
;
7118 IWN_WRITE(sc, IWN_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
0xffffffff))))
;
7119 IWN_WRITE(sc, IWN_FH_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x010)), ((
0xffffffff))))
;
7120 sc->sc_flags &= ~IWN_FLAG_USE_ICT(1 << 3);
7121
7122 /* Make sure we no longer hold the NIC lock. */
7123 iwn_nic_unlock(sc);
7124
7125 /* Stop TX scheduler. */
7126 iwn_prph_write(sc, sc->sched_txfact_addr, 0);
7127
7128 /* Stop all DMA channels. */
7129 if (iwn_nic_lock(sc) == 0) {
7130 for (chnl = 0; chnl < sc->ndmachnls; chnl++) {
7131 IWN_WRITE(sc, IWN_FH_TX_CONFIG(chnl), 0)(((sc)->sc_st)->write_4(((sc)->sc_sh), (((0x1d00 + (
chnl) * 32))), ((0))))
;
7132 for (ntries = 0; ntries < 200; ntries++) {
7133 if (IWN_READ(sc, IWN_FH_TX_STATUS)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x1eb0)))) &
7134 IWN_FH_TX_STATUS_IDLE(chnl)(1 << ((chnl) + 16)))
7135 break;
7136 DELAY(10)(*delay_func)(10);
7137 }
7138 }
7139 iwn_nic_unlock(sc);
7140 }
7141
7142 /* Stop RX ring. */
7143 iwn_reset_rx_ring(sc, &sc->rxq);
7144
7145 /* Reset all TX rings. */
7146 for (qid = 0; qid < sc->ntxqs; qid++)
7147 iwn_reset_tx_ring(sc, &sc->txq[qid]);
7148
7149 if (iwn_nic_lock(sc) == 0) {
7150 iwn_prph_write(sc, IWN_APMG_CLK_DIS0x3008,
7151 IWN_APMG_CLK_CTRL_DMA_CLK_RQT(1 << 9));
7152 iwn_nic_unlock(sc);
7153 }
7154 DELAY(5)(*delay_func)(5);
7155 /* Power OFF adapter. */
7156 iwn_apm_stop(sc);
7157}
7158
7159int
7160iwn_init(struct ifnet *ifp)
7161{
7162 struct iwn_softc *sc = ifp->if_softc;
7163 struct ieee80211com *ic = &sc->sc_ic;
7164 int error;
7165
7166 memset(sc->bss_node_addr, 0, sizeof(sc->bss_node_addr))__builtin_memset((sc->bss_node_addr), (0), (sizeof(sc->
bss_node_addr)))
;
7167 sc->agg_queue_mask = 0;
7168 memset(sc->sc_tx_ba, 0, sizeof(sc->sc_tx_ba))__builtin_memset((sc->sc_tx_ba), (0), (sizeof(sc->sc_tx_ba
)))
;
7169
7170 if ((error = iwn_hw_prepare(sc)) != 0) {
7171 printf("%s: hardware not ready\n", sc->sc_dev.dv_xname);
7172 goto fail;
7173 }
7174
7175 /* Initialize interrupt mask to default value. */
7176 sc->int_mask = IWN_INT_MASK_DEF((1U << 25) | (1U << 29) | (1U << 27) | (1U
<< 31) | (1U << 0) | (1U << 1) | (1U <<
3) | (1U << 6) | (1U << 7))
;
7177 sc->sc_flags &= ~IWN_FLAG_USE_ICT(1 << 3);
7178
7179 /* Check that the radio is not disabled by hardware switch. */
7180 if (!(IWN_READ(sc, IWN_GP_CNTRL)(((sc)->sc_st)->read_4(((sc)->sc_sh), ((0x024)))) & IWN_GP_CNTRL_RFKILL(1 << 27))) {
7181 printf("%s: radio is disabled by hardware switch\n",
7182 sc->sc_dev.dv_xname);
7183 error = EPERM1; /* :-) */
7184 /* Re-enable interrupts. */
7185 IWN_WRITE(sc, IWN_INT, 0xffffffff)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x008)), ((
0xffffffff))))
;
7186 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask)(((sc)->sc_st)->write_4(((sc)->sc_sh), ((0x00c)), ((
sc->int_mask))))
;
7187 return error;
7188 }
7189
7190 /* Read firmware images from the filesystem. */
7191 if ((error = iwn_read_firmware(sc)) != 0) {
7192 printf("%s: could not read firmware\n", sc->sc_dev.dv_xname);
7193 goto fail;
7194 }
7195
7196 /* Initialize hardware and upload firmware. */
7197 error = iwn_hw_init(sc);
7198 free(sc->fw.data, M_DEVBUF2, sc->fw.size);
7199 if (error != 0) {
7200 printf("%s: could not initialize hardware\n",
7201 sc->sc_dev.dv_xname);
7202 goto fail;
7203 }
7204
7205 /* Configure adapter now that it is ready. */
7206 if ((error = iwn_config(sc)) != 0) {
7207 printf("%s: could not configure device\n",
7208 sc->sc_dev.dv_xname);
7209 goto fail;
7210 }
7211
7212 ifq_clr_oactive(&ifp->if_snd);
7213 ifp->if_flags |= IFF_RUNNING0x40;
7214
7215 if (ic->ic_opmode != IEEE80211_M_MONITOR)
7216 ieee80211_begin_scan(ifp);
7217 else
7218 ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1)));
7219
7220 return 0;
7221
7222fail: iwn_stop(ifp);
7223 return error;
7224}
7225
7226void
7227iwn_stop(struct ifnet *ifp)
7228{
7229 struct iwn_softc *sc = ifp->if_softc;
7230 struct ieee80211com *ic = &sc->sc_ic;
7231
7232 timeout_del(&sc->calib_to);
7233 ifp->if_timer = sc->sc_tx_timer = 0;
7234 ifp->if_flags &= ~IFF_RUNNING0x40;
7235 ifq_clr_oactive(&ifp->if_snd);
7236
7237 ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1)));
7238
7239 /* Power OFF hardware. */
7240 iwn_hw_stop(sc);
7241}