add subdevice id 0x5260 for iwn 6035 series
[dragonfly.git] / sys / dev / netif / iwn / if_iwn.c
CommitLineData
ffd7c74a 1/*-
4b420e05
MD
2 * Copyright (c) 2007-2009 Damien Bergamini <damien.bergamini@free.fr>
3 * Copyright (c) 2008 Benjamin Close <benjsc@FreeBSD.org>
ffd7c74a 4 * Copyright (c) 2008 Sam Leffler, Errno Consulting
4b420e05
MD
5 * Copyright (c) 2011 Intel Corporation
6 * Copyright (c) 2013 Cedric GROSS <c.gross@kreiz-it.fr>
7 * Copyright (c) 2013 Adrian Chadd <adrian@FreeBSD.org>
ffd7c74a
JT
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network
24 * adapters.
25 */
26
05538f72
MD
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD$");
29
da10ea93
MD
30#include "opt_wlan.h"
31#include "opt_iwn.h"
32
ffd7c74a
JT
33#include <sys/param.h>
34#include <sys/sockio.h>
35#include <sys/sysctl.h>
36#include <sys/mbuf.h>
37#include <sys/kernel.h>
38#include <sys/socket.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/bus.h>
977fc0db 42#include <sys/conf.h>
ffd7c74a
JT
43#include <sys/rman.h>
44#include <sys/endian.h>
45#include <sys/firmware.h>
46#include <sys/limits.h>
47#include <sys/module.h>
977fc0db 48#include <sys/priv.h>
ffd7c74a
JT
49#include <sys/queue.h>
50#include <sys/taskqueue.h>
977fc0db
MD
51#if defined(__DragonFly__)
52#include <sys/device.h>
53#endif
ffd7c74a 54
977fc0db
MD
55#if defined(__DragonFly__)
56/* empty */
57#else
58#include <machine/bus.h>
59#include <machine/resource.h>
ffd7c74a 60#include <machine/clock.h>
977fc0db 61#endif
ffd7c74a 62
977fc0db 63#if defined(__DragonFly__)
101554a6
MD
64#include <bus/pci/pcireg.h>
65#include <bus/pci/pcivar.h>
977fc0db
MD
66#else
67#include <dev/pci/pcireg.h>
68#include <dev/pci/pcivar.h>
69#endif
ffd7c74a 70
ffd7c74a 71#include <net/if.h>
da10ea93 72#include <net/if_var.h>
ffd7c74a
JT
73#include <net/if_dl.h>
74#include <net/if_media.h>
ffd7c74a
JT
75
76#include <netinet/in.h>
ffd7c74a 77#include <netinet/if_ether.h>
ffd7c74a 78
101554a6
MD
79#include <netproto/802_11/ieee80211_var.h>
80#include <netproto/802_11/ieee80211_radiotap.h>
81#include <netproto/802_11/ieee80211_regdomain.h>
82#include <netproto/802_11/ieee80211_ratectl.h>
da10ea93 83
05538f72
MD
84#include <dev/netif/iwn/if_iwnreg.h>
85#include <dev/netif/iwn/if_iwnvar.h>
86#include <dev/netif/iwn/if_iwn_devid.h>
87#include <dev/netif/iwn/if_iwn_chip_cfg.h>
88#include <dev/netif/iwn/if_iwn_debug.h>
89#include <dev/netif/iwn/if_iwn_ioctl.h>
fd49669c 90
da10ea93
MD
91struct iwn_ident {
92 uint16_t vendor;
93 uint16_t device;
94 const char *name;
95};
ffd7c74a 96
da10ea93
MD
97static const struct iwn_ident iwn_ident_table[] = {
98 { 0x8086, IWN_DID_6x05_1, "Intel Centrino Advanced-N 6205" },
99 { 0x8086, IWN_DID_1000_1, "Intel Centrino Wireless-N 1000" },
100 { 0x8086, IWN_DID_1000_2, "Intel Centrino Wireless-N 1000" },
101 { 0x8086, IWN_DID_6x05_2, "Intel Centrino Advanced-N 6205" },
102 { 0x8086, IWN_DID_6050_1, "Intel Centrino Advanced-N + WiMAX 6250" },
103 { 0x8086, IWN_DID_6050_2, "Intel Centrino Advanced-N + WiMAX 6250" },
104 { 0x8086, IWN_DID_x030_1, "Intel Centrino Wireless-N 1030" },
105 { 0x8086, IWN_DID_x030_2, "Intel Centrino Wireless-N 1030" },
106 { 0x8086, IWN_DID_x030_3, "Intel Centrino Advanced-N 6230" },
107 { 0x8086, IWN_DID_x030_4, "Intel Centrino Advanced-N 6230" },
108 { 0x8086, IWN_DID_6150_1, "Intel Centrino Wireless-N + WiMAX 6150" },
109 { 0x8086, IWN_DID_6150_2, "Intel Centrino Wireless-N + WiMAX 6150" },
110 { 0x8086, IWN_DID_2x00_1, "Intel(R) Centrino(R) Wireless-N 2200 BGN" },
111 { 0x8086, IWN_DID_2x00_2, "Intel(R) Centrino(R) Wireless-N 2200 BGN" },
112 /* XXX 2200D is IWN_SDID_2x00_4; there's no way to express this here! */
113 { 0x8086, IWN_DID_2x30_1, "Intel Centrino Wireless-N 2230" },
114 { 0x8086, IWN_DID_2x30_2, "Intel Centrino Wireless-N 2230" },
115 { 0x8086, IWN_DID_130_1, "Intel Centrino Wireless-N 130" },
116 { 0x8086, IWN_DID_130_2, "Intel Centrino Wireless-N 130" },
117 { 0x8086, IWN_DID_100_1, "Intel Centrino Wireless-N 100" },
118 { 0x8086, IWN_DID_100_2, "Intel Centrino Wireless-N 100" },
fd49669c
MN
119 { 0x8086, IWN_DID_105_1, "Intel Centrino Wireless-N 105" },
120 { 0x8086, IWN_DID_105_2, "Intel Centrino Wireless-N 105" },
121 { 0x8086, IWN_DID_135_1, "Intel Centrino Wireless-N 135" },
122 { 0x8086, IWN_DID_135_2, "Intel Centrino Wireless-N 135" },
da10ea93
MD
123 { 0x8086, IWN_DID_4965_1, "Intel Wireless WiFi Link 4965" },
124 { 0x8086, IWN_DID_6x00_1, "Intel Centrino Ultimate-N 6300" },
125 { 0x8086, IWN_DID_6x00_2, "Intel Centrino Advanced-N 6200" },
126 { 0x8086, IWN_DID_4965_2, "Intel Wireless WiFi Link 4965" },
127 { 0x8086, IWN_DID_4965_3, "Intel Wireless WiFi Link 4965" },
128 { 0x8086, IWN_DID_5x00_1, "Intel WiFi Link 5100" },
129 { 0x8086, IWN_DID_4965_4, "Intel Wireless WiFi Link 4965" },
130 { 0x8086, IWN_DID_5x00_3, "Intel Ultimate N WiFi Link 5300" },
131 { 0x8086, IWN_DID_5x00_4, "Intel Ultimate N WiFi Link 5300" },
132 { 0x8086, IWN_DID_5x00_2, "Intel WiFi Link 5100" },
133 { 0x8086, IWN_DID_6x00_3, "Intel Centrino Ultimate-N 6300" },
134 { 0x8086, IWN_DID_6x00_4, "Intel Centrino Advanced-N 6200" },
135 { 0x8086, IWN_DID_5x50_1, "Intel WiMAX/WiFi Link 5350" },
136 { 0x8086, IWN_DID_5x50_2, "Intel WiMAX/WiFi Link 5350" },
137 { 0x8086, IWN_DID_5x50_3, "Intel WiMAX/WiFi Link 5150" },
138 { 0x8086, IWN_DID_5x50_4, "Intel WiMAX/WiFi Link 5150" },
da10ea93 139 { 0x8086, IWN_DID_6035_1, "Intel Centrino Advanced 6235" },
da10ea93 140 { 0x8086, IWN_DID_6035_2, "Intel Centrino Advanced 6235" },
da10ea93
MD
141 { 0, 0, NULL }
142};
ffd7c74a 143
05538f72
MD
144static int iwn_probe(device_t);
145static int iwn_attach(device_t);
da10ea93
MD
146static int iwn4965_attach(struct iwn_softc *, uint16_t);
147static int iwn5000_attach(struct iwn_softc *, uint16_t);
148static int iwn_config_specific(struct iwn_softc *, uint16_t);
ffd7c74a 149static void iwn_radiotap_attach(struct iwn_softc *);
da10ea93 150static void iwn_sysctlattach(struct iwn_softc *);
ffd7c74a 151static struct ieee80211vap *iwn_vap_create(struct ieee80211com *,
da10ea93
MD
152 const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
153 const uint8_t [IEEE80211_ADDR_LEN],
154 const uint8_t [IEEE80211_ADDR_LEN]);
ffd7c74a 155static void iwn_vap_delete(struct ieee80211vap *);
05538f72
MD
156static int iwn_detach(device_t);
157static int iwn_shutdown(device_t);
158static int iwn_suspend(device_t);
159static int iwn_resume(device_t);
ffd7c74a
JT
160static int iwn_nic_lock(struct iwn_softc *);
161static int iwn_eeprom_lock(struct iwn_softc *);
162static int iwn_init_otprom(struct iwn_softc *);
163static int iwn_read_prom_data(struct iwn_softc *, uint32_t, void *, int);
164static void iwn_dma_map_addr(void *, bus_dma_segment_t *, int, int);
165static int iwn_dma_contig_alloc(struct iwn_softc *, struct iwn_dma_info *,
da10ea93 166 void **, bus_size_t, bus_size_t);
ffd7c74a
JT
167static void iwn_dma_contig_free(struct iwn_dma_info *);
168static int iwn_alloc_sched(struct iwn_softc *);
169static void iwn_free_sched(struct iwn_softc *);
170static int iwn_alloc_kw(struct iwn_softc *);
171static void iwn_free_kw(struct iwn_softc *);
172static int iwn_alloc_ict(struct iwn_softc *);
173static void iwn_free_ict(struct iwn_softc *);
174static int iwn_alloc_fwmem(struct iwn_softc *);
175static void iwn_free_fwmem(struct iwn_softc *);
176static int iwn_alloc_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
177static void iwn_reset_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
178static void iwn_free_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
179static int iwn_alloc_tx_ring(struct iwn_softc *, struct iwn_tx_ring *,
180 int);
181static void iwn_reset_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);
182static void iwn_free_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);
183static void iwn5000_ict_reset(struct iwn_softc *);
184static int iwn_read_eeprom(struct iwn_softc *,
185 uint8_t macaddr[IEEE80211_ADDR_LEN]);
186static void iwn4965_read_eeprom(struct iwn_softc *);
da10ea93 187#ifdef IWN_DEBUG
ffd7c74a 188static void iwn4965_print_power_group(struct iwn_softc *, int);
da10ea93 189#endif
ffd7c74a
JT
190static void iwn5000_read_eeprom(struct iwn_softc *);
191static uint32_t iwn_eeprom_channel_flags(struct iwn_eeprom_chan *);
977fc0db
MD
192static void iwn_read_eeprom_band(struct iwn_softc *, int, int, int *,
193 struct ieee80211_channel[]);
194static void iwn_read_eeprom_ht40(struct iwn_softc *, int, int, int *,
195 struct ieee80211_channel[]);
da10ea93
MD
196static void iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t);
197static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *,
198 struct ieee80211_channel *);
977fc0db
MD
199static void iwn_getradiocaps(struct ieee80211com *, int, int *,
200 struct ieee80211_channel[]);
da10ea93
MD
201static int iwn_setregdomain(struct ieee80211com *,
202 struct ieee80211_regdomain *, int,
203 struct ieee80211_channel[]);
ffd7c74a
JT
204static void iwn_read_eeprom_enhinfo(struct iwn_softc *);
205static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *,
206 const uint8_t mac[IEEE80211_ADDR_LEN]);
207static void iwn_newassoc(struct ieee80211_node *, int);
208static int iwn_media_change(struct ifnet *);
209static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
da10ea93 210static void iwn_calib_timeout(void *);
ffd7c74a
JT
211static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *,
212 struct iwn_rx_data *);
ffd7c74a
JT
213static void iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *,
214 struct iwn_rx_data *);
ffd7c74a
JT
215static void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *,
216 struct iwn_rx_data *);
ffd7c74a
JT
217static void iwn5000_rx_calib_results(struct iwn_softc *,
218 struct iwn_rx_desc *, struct iwn_rx_data *);
219static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *,
220 struct iwn_rx_data *);
221static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
222 struct iwn_rx_data *);
223static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
224 struct iwn_rx_data *);
225static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int,
226 uint8_t);
05538f72 227static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, void *);
ffd7c74a
JT
228static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *);
229static void iwn_notif_intr(struct iwn_softc *);
230static void iwn_wakeup_intr(struct iwn_softc *);
231static void iwn_rftoggle_intr(struct iwn_softc *);
232static void iwn_fatal_intr(struct iwn_softc *);
233static void iwn_intr(void *);
234static void iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t,
235 uint16_t);
236static void iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t,
237 uint16_t);
238#ifdef notyet
239static void iwn5000_reset_sched(struct iwn_softc *, int, int);
240#endif
ffd7c74a 241static int iwn_tx_data(struct iwn_softc *, struct mbuf *,
da10ea93
MD
242 struct ieee80211_node *);
243static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *,
244 struct ieee80211_node *,
245 const struct ieee80211_bpf_params *params);
977fc0db 246static void iwn_xmit_task(void *arg0, int pending);
ffd7c74a
JT
247static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
248 const struct ieee80211_bpf_params *);
977fc0db 249static int iwn_transmit(struct ieee80211com *, struct mbuf *);
05538f72 250static void iwn_watchdog(void *);
977fc0db
MD
251static int iwn_ioctl(struct ieee80211com *, u_long , void *);
252static void iwn_parent(struct ieee80211com *);
ffd7c74a
JT
253static int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
254static int iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,
255 int);
256static int iwn5000_add_node(struct iwn_softc *, struct iwn_node_info *,
257 int);
da10ea93
MD
258static int iwn_set_link_quality(struct iwn_softc *,
259 struct ieee80211_node *);
ffd7c74a 260static int iwn_add_broadcast_node(struct iwn_softc *, int);
da10ea93 261static int iwn_updateedca(struct ieee80211com *);
4f898719 262static void iwn_update_mcast(struct ieee80211com *);
ffd7c74a
JT
263static void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t);
264static int iwn_set_critical_temp(struct iwn_softc *);
265static int iwn_set_timing(struct iwn_softc *, struct ieee80211_node *);
266static void iwn4965_power_calibration(struct iwn_softc *, int);
267static int iwn4965_set_txpower(struct iwn_softc *,
268 struct ieee80211_channel *, int);
269static int iwn5000_set_txpower(struct iwn_softc *,
270 struct ieee80211_channel *, int);
271static int iwn4965_get_rssi(struct iwn_softc *, struct iwn_rx_stat *);
272static int iwn5000_get_rssi(struct iwn_softc *, struct iwn_rx_stat *);
273static int iwn_get_noise(const struct iwn_rx_general_stats *);
274static int iwn4965_get_temperature(struct iwn_softc *);
275static int iwn5000_get_temperature(struct iwn_softc *);
276static int iwn_init_sensitivity(struct iwn_softc *);
277static void iwn_collect_noise(struct iwn_softc *,
278 const struct iwn_rx_general_stats *);
279static int iwn4965_init_gains(struct iwn_softc *);
280static int iwn5000_init_gains(struct iwn_softc *);
281static int iwn4965_set_gains(struct iwn_softc *);
282static int iwn5000_set_gains(struct iwn_softc *);
283static void iwn_tune_sensitivity(struct iwn_softc *,
284 const struct iwn_rx_stats *);
fd49669c
MN
285static void iwn_save_stats_counters(struct iwn_softc *,
286 const struct iwn_stats *);
ffd7c74a 287static int iwn_send_sensitivity(struct iwn_softc *);
fd49669c 288static void iwn_check_rx_recovery(struct iwn_softc *, struct iwn_stats *);
ffd7c74a 289static int iwn_set_pslevel(struct iwn_softc *, int, int, int);
da10ea93
MD
290static int iwn_send_btcoex(struct iwn_softc *);
291static int iwn_send_advanced_btcoex(struct iwn_softc *);
292static int iwn5000_runtime_calib(struct iwn_softc *);
ffd7c74a 293static int iwn_config(struct iwn_softc *);
fd49669c
MN
294static int iwn_scan(struct iwn_softc *, struct ieee80211vap *,
295 struct ieee80211_scan_state *, struct ieee80211_channel *);
ffd7c74a
JT
296static int iwn_auth(struct iwn_softc *, struct ieee80211vap *vap);
297static int iwn_run(struct iwn_softc *, struct ieee80211vap *vap);
da10ea93
MD
298static int iwn_ampdu_rx_start(struct ieee80211_node *,
299 struct ieee80211_rx_ampdu *, int, int, int);
300static void iwn_ampdu_rx_stop(struct ieee80211_node *,
301 struct ieee80211_rx_ampdu *);
302static int iwn_addba_request(struct ieee80211_node *,
303 struct ieee80211_tx_ampdu *, int, int, int);
304static int iwn_addba_response(struct ieee80211_node *,
305 struct ieee80211_tx_ampdu *, int, int, int);
ffd7c74a
JT
306static int iwn_ampdu_tx_start(struct ieee80211com *,
307 struct ieee80211_node *, uint8_t);
da10ea93
MD
308static void iwn_ampdu_tx_stop(struct ieee80211_node *,
309 struct ieee80211_tx_ampdu *);
ffd7c74a 310static void iwn4965_ampdu_tx_start(struct iwn_softc *,
da10ea93
MD
311 struct ieee80211_node *, int, uint8_t, uint16_t);
312static void iwn4965_ampdu_tx_stop(struct iwn_softc *, int,
313 uint8_t, uint16_t);
ffd7c74a 314static void iwn5000_ampdu_tx_start(struct iwn_softc *,
da10ea93
MD
315 struct ieee80211_node *, int, uint8_t, uint16_t);
316static void iwn5000_ampdu_tx_stop(struct iwn_softc *, int,
317 uint8_t, uint16_t);
ffd7c74a
JT
318static int iwn5000_query_calibration(struct iwn_softc *);
319static int iwn5000_send_calibration(struct iwn_softc *);
320static int iwn5000_send_wimax_coex(struct iwn_softc *);
da10ea93
MD
321static int iwn5000_crystal_calib(struct iwn_softc *);
322static int iwn5000_temp_offset_calib(struct iwn_softc *);
323static int iwn5000_temp_offset_calibv2(struct iwn_softc *);
ffd7c74a
JT
324static int iwn4965_post_alive(struct iwn_softc *);
325static int iwn5000_post_alive(struct iwn_softc *);
326static int iwn4965_load_bootcode(struct iwn_softc *, const uint8_t *,
327 int);
328static int iwn4965_load_firmware(struct iwn_softc *);
329static int iwn5000_load_firmware_section(struct iwn_softc *, uint32_t,
330 const uint8_t *, int);
331static int iwn5000_load_firmware(struct iwn_softc *);
da10ea93
MD
332static int iwn_read_firmware_leg(struct iwn_softc *,
333 struct iwn_fw_info *);
334static int iwn_read_firmware_tlv(struct iwn_softc *,
335 struct iwn_fw_info *, uint16_t);
ffd7c74a 336static int iwn_read_firmware(struct iwn_softc *);
977fc0db 337static void iwn_unload_firmware(struct iwn_softc *);
ffd7c74a
JT
338static int iwn_clock_wait(struct iwn_softc *);
339static int iwn_apm_init(struct iwn_softc *);
340static void iwn_apm_stop_master(struct iwn_softc *);
341static void iwn_apm_stop(struct iwn_softc *);
342static int iwn4965_nic_config(struct iwn_softc *);
343static int iwn5000_nic_config(struct iwn_softc *);
344static int iwn_hw_prepare(struct iwn_softc *);
345static int iwn_hw_init(struct iwn_softc *);
346static void iwn_hw_stop(struct iwn_softc *);
05538f72
MD
347static void iwn_radio_on(void *, int);
348static void iwn_radio_off(void *, int);
349static void iwn_panicked(void *, int);
ffd7c74a 350static void iwn_init_locked(struct iwn_softc *);
977fc0db 351static void iwn_init(struct iwn_softc *);
ffd7c74a 352static void iwn_stop_locked(struct iwn_softc *);
05538f72 353static void iwn_stop(struct iwn_softc *);
da10ea93
MD
354static void iwn_scan_start(struct ieee80211com *);
355static void iwn_scan_end(struct ieee80211com *);
356static void iwn_set_channel(struct ieee80211com *);
357static void iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long);
358static void iwn_scan_mindwell(struct ieee80211_scan_state *);
da10ea93
MD
359#ifdef IWN_DEBUG
360static char *iwn_get_csr_string(int);
361static void iwn_debug_register(struct iwn_softc *);
ffd7c74a
JT
362#endif
363
da10ea93
MD
364static device_method_t iwn_methods[] = {
365 /* Device interface */
05538f72
MD
366 DEVMETHOD(device_probe, iwn_probe),
367 DEVMETHOD(device_attach, iwn_attach),
368 DEVMETHOD(device_detach, iwn_detach),
369 DEVMETHOD(device_shutdown, iwn_shutdown),
370 DEVMETHOD(device_suspend, iwn_suspend),
371 DEVMETHOD(device_resume, iwn_resume),
fd49669c
MN
372
373 DEVMETHOD_END
ffd7c74a
JT
374};
375
da10ea93
MD
376static driver_t iwn_driver = {
377 "iwn",
378 iwn_methods,
379 sizeof(struct iwn_softc)
ffd7c74a 380};
da10ea93 381static devclass_t iwn_devclass;
ffd7c74a 382
101554a6 383DRIVER_MODULE(iwn, pci, iwn_driver, iwn_devclass, NULL, NULL);
ffd7c74a 384
da10ea93
MD
385MODULE_VERSION(iwn, 1);
386
387MODULE_DEPEND(iwn, firmware, 1, 1, 1);
388MODULE_DEPEND(iwn, pci, 1, 1, 1);
389MODULE_DEPEND(iwn, wlan, 1, 1, 1);
ffd7c74a 390
977fc0db
MD
391static d_ioctl_t iwn_cdev_ioctl;
392static d_open_t iwn_cdev_open;
393static d_close_t iwn_cdev_close;
394
395static struct dev_ops iwn_cdevsw = {
396#if defined(__DragonFly__)
397 /* none */
398 { "iwn", 0, 0 },
399#else
400 .d_version = D_VERSION,
401 .d_flags = 0,
402#endif
403 .d_open = iwn_cdev_open,
404 .d_close = iwn_cdev_close,
405 .d_ioctl = iwn_cdev_ioctl,
406#if defined(__DragonFly__)
407 /* none */
408#else
409 .d_name = "iwn",
410#endif
411};
412
ffd7c74a 413static int
05538f72 414iwn_probe(device_t dev)
ffd7c74a
JT
415{
416 const struct iwn_ident *ident;
417
418 for (ident = iwn_ident_table; ident->name != NULL; ident++) {
419 if (pci_get_vendor(dev) == ident->vendor &&
420 pci_get_device(dev) == ident->device) {
421 device_set_desc(dev, ident->name);
fd49669c 422 return (BUS_PROBE_DEFAULT);
ffd7c74a
JT
423 }
424 }
425 return ENXIO;
426}
427
428static int
05538f72
MD
429iwn_is_3stream_device(struct iwn_softc *sc)
430{
431 /* XXX for now only 5300, until the 5350 can be tested */
432 if (sc->hw_type == IWN_HW_REV_TYPE_5300)
433 return (1);
434 return (0);
435}
436
437static int
438iwn_attach(device_t dev)
ffd7c74a 439{
977fc0db 440 struct iwn_softc *sc = device_get_softc(dev);
ffd7c74a 441 struct ieee80211com *ic;
fd49669c 442 int i, error, rid;
b1ee9c70
MD
443#if defined(__DragonFly__)
444 int irq_flags;
445#endif
458fc9cf 446
ffd7c74a 447 sc->sc_dev = dev;
101554a6 448
da10ea93
MD
449#ifdef IWN_DEBUG
450 error = resource_int_value(device_get_name(sc->sc_dev),
451 device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug));
452 if (error != 0)
453 sc->sc_debug = 0;
454#else
455 sc->sc_debug = 0;
456#endif
3db796ac 457
da10ea93 458 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: begin\n",__func__);
ffd7c74a
JT
459
460 /*
461 * Get the offset of the PCI Express Capability Structure in PCI
462 * Configuration Space.
463 */
05538f72 464#if defined(__DragonFly__)
101554a6 465 error = pci_find_extcap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
05538f72
MD
466#else
467 error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
468#endif
ffd7c74a
JT
469 if (error != 0) {
470 device_printf(dev, "PCIe capability structure not found!\n");
05538f72 471 return error;
ffd7c74a
JT
472 }
473
474 /* Clear device-specific "PCI retry timeout" register (41h). */
475 pci_write_config(dev, 0x41, 0, 1);
476
ffd7c74a
JT
477 /* Enable bus-mastering. */
478 pci_enable_busmaster(dev);
479
fd49669c
MN
480 rid = PCIR_BAR(0);
481 sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
ffd7c74a 482 RF_ACTIVE);
da10ea93
MD
483 if (sc->mem == NULL) {
484 device_printf(dev, "can't map mem space\n");
ffd7c74a 485 error = ENOMEM;
05538f72 486 return error;
ffd7c74a 487 }
ffd7c74a
JT
488 sc->sc_st = rman_get_bustag(sc->mem);
489 sc->sc_sh = rman_get_bushandle(sc->mem);
da10ea93 490
977fc0db 491#if defined(__DragonFly__)
b1ee9c70
MD
492 pci_alloc_1intr(dev, 1, &rid, &irq_flags);
493 /* Install interrupt handler. */
494 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, irq_flags);
977fc0db 495#else
fd49669c 496 i = 1;
977fc0db 497 rid = 0;
fd49669c
MN
498 if (pci_alloc_msi(dev, &i) == 0)
499 rid = 1;
da10ea93 500 /* Install interrupt handler. */
fd49669c
MN
501 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
502 (rid != 0 ? 0 : RF_SHAREABLE));
b1ee9c70 503#endif
ffd7c74a 504 if (sc->irq == NULL) {
da10ea93 505 device_printf(dev, "can't map interrupt\n");
ffd7c74a
JT
506 error = ENOMEM;
507 goto fail;
508 }
509
05538f72
MD
510 IWN_LOCK_INIT(sc);
511
da10ea93
MD
512 /* Read hardware revision and attach. */
513 sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT)
514 & IWN_HW_REV_TYPE_MASK;
515 sc->subdevice_id = pci_get_subdevice(dev);
05538f72 516
da10ea93
MD
517 /*
518 * 4965 versus 5000 and later have different methods.
519 * Let's set those up first.
520 */
521 if (sc->hw_type == IWN_HW_REV_TYPE_4965)
522 error = iwn4965_attach(sc, pci_get_device(dev));
523 else
524 error = iwn5000_attach(sc, pci_get_device(dev));
525 if (error != 0) {
526 device_printf(dev, "could not attach device, error %d\n",
527 error);
ffd7c74a
JT
528 goto fail;
529 }
530
da10ea93
MD
531 /*
532 * Next, let's setup the various parameters of each NIC.
533 */
534 error = iwn_config_specific(sc, pci_get_device(dev));
ffd7c74a 535 if (error != 0) {
da10ea93
MD
536 device_printf(dev, "could not attach device, error %d\n",
537 error);
538 goto fail;
539 }
540
541 if ((error = iwn_hw_prepare(sc)) != 0) {
ffd7c74a
JT
542 device_printf(dev, "hardware not ready, error %d\n", error);
543 goto fail;
544 }
545
546 /* Allocate DMA memory for firmware transfers. */
da10ea93 547 if ((error = iwn_alloc_fwmem(sc)) != 0) {
ffd7c74a
JT
548 device_printf(dev,
549 "could not allocate memory for firmware, error %d\n",
550 error);
551 goto fail;
552 }
553
554 /* Allocate "Keep Warm" page. */
da10ea93 555 if ((error = iwn_alloc_kw(sc)) != 0) {
ffd7c74a 556 device_printf(dev,
da10ea93 557 "could not allocate keep warm page, error %d\n", error);
ffd7c74a
JT
558 goto fail;
559 }
560
561 /* Allocate ICT table for 5000 Series. */
562 if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
563 (error = iwn_alloc_ict(sc)) != 0) {
da10ea93
MD
564 device_printf(dev, "could not allocate ICT table, error %d\n",
565 error);
ffd7c74a
JT
566 goto fail;
567 }
568
569 /* Allocate TX scheduler "rings". */
da10ea93 570 if ((error = iwn_alloc_sched(sc)) != 0) {
ffd7c74a 571 device_printf(dev,
da10ea93 572 "could not allocate TX scheduler rings, error %d\n", error);
ffd7c74a
JT
573 goto fail;
574 }
575
da10ea93
MD
576 /* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */
577 for (i = 0; i < sc->ntxqs; i++) {
578 if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
ffd7c74a 579 device_printf(dev,
da10ea93
MD
580 "could not allocate TX ring %d, error %d\n", i,
581 error);
ffd7c74a
JT
582 goto fail;
583 }
584 }
585
586 /* Allocate RX ring. */
da10ea93
MD
587 if ((error = iwn_alloc_rx_ring(sc, &sc->rxq)) != 0) {
588 device_printf(dev, "could not allocate RX ring, error %d\n",
589 error);
ffd7c74a
JT
590 goto fail;
591 }
592
593 /* Clear pending interrupts. */
594 IWN_WRITE(sc, IWN_INT, 0xffffffff);
595
977fc0db 596 ic = &sc->sc_ic;
13f98998 597 ic->ic_softc = sc;
4f898719 598 ic->ic_name = device_get_nameunit(dev);
ffd7c74a
JT
599 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
600 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
601
602 /* Set device capabilities. */
603 ic->ic_caps =
604 IEEE80211_C_STA /* station mode supported */
605 | IEEE80211_C_MONITOR /* monitor mode supported */
977fc0db 606#if 0
da10ea93 607 | IEEE80211_C_BGSCAN /* background scanning */
977fc0db 608#endif
ffd7c74a
JT
609 | IEEE80211_C_TXPMGT /* tx power management */
610 | IEEE80211_C_SHSLOT /* short slot time supported */
611 | IEEE80211_C_WPA
612 | IEEE80211_C_SHPREAMBLE /* short preamble supported */
ffd7c74a
JT
613#if 0
614 | IEEE80211_C_IBSS /* ibss/adhoc mode */
615#endif
616 | IEEE80211_C_WME /* WME */
da10ea93 617 | IEEE80211_C_PMGT /* Station-side power mgmt */
ffd7c74a 618 ;
ffd7c74a
JT
619
620 /* Read MAC address, channels, etc from EEPROM. */
977fc0db 621 if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) {
ffd7c74a
JT
622 device_printf(dev, "could not read EEPROM, error %d\n",
623 error);
624 goto fail;
625 }
626
da10ea93
MD
627 /* Count the number of available chains. */
628 sc->ntxchains =
629 ((sc->txchainmask >> 2) & 1) +
630 ((sc->txchainmask >> 1) & 1) +
631 ((sc->txchainmask >> 0) & 1);
632 sc->nrxchains =
633 ((sc->rxchainmask >> 2) & 1) +
634 ((sc->rxchainmask >> 1) & 1) +
635 ((sc->rxchainmask >> 0) & 1);
636 if (bootverbose) {
977fc0db
MD
637#if defined(__DragonFly__)
638 char ethstr[ETHER_ADDRSTRLEN+1];
f92fae3f 639 device_printf(dev, "MIMO %dT%dR, %.4s, address %s\n",
da10ea93 640 sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
977fc0db
MD
641 kether_ntoa(ic->ic_macaddr, ethstr));
642#else
643 device_printf(dev, "MIMO %dT%dR, %.4s, address %6D\n",
644 sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
645 ic->ic_macaddr, ":");
646#endif
da10ea93
MD
647 }
648
649 if (sc->sc_flags & IWN_FLAG_HAS_11N) {
650 ic->ic_rxstream = sc->nrxchains;
651 ic->ic_txstream = sc->ntxchains;
ffd7c74a 652
da10ea93 653 /*
05538f72
MD
654 * Some of the 3 antenna devices (ie, the 4965) only supports
655 * 2x2 operation. So correct the number of streams if
656 * it's not a 3-stream device.
da10ea93 657 */
05538f72
MD
658 if (! iwn_is_3stream_device(sc)) {
659 if (ic->ic_rxstream > 2)
660 ic->ic_rxstream = 2;
661 if (ic->ic_txstream > 2)
662 ic->ic_txstream = 2;
663 }
da10ea93
MD
664
665 ic->ic_htcaps =
666 IEEE80211_HTCAP_SMPS_OFF /* SMPS mode disabled */
667 | IEEE80211_HTCAP_SHORTGI20 /* short GI in 20MHz */
668 | IEEE80211_HTCAP_CHWIDTH40 /* 40MHz channel width*/
669 | IEEE80211_HTCAP_SHORTGI40 /* short GI in 40MHz */
670#ifdef notyet
671 | IEEE80211_HTCAP_GREENFIELD
672#if IWN_RBUF_SIZE == 8192
673 | IEEE80211_HTCAP_MAXAMSDU_7935 /* max A-MSDU length */
674#else
675 | IEEE80211_HTCAP_MAXAMSDU_3839 /* max A-MSDU length */
676#endif
ffd7c74a 677#endif
da10ea93
MD
678 /* s/w capabilities */
679 | IEEE80211_HTC_HT /* HT operation */
680 | IEEE80211_HTC_AMPDU /* tx A-MPDU */
681#ifdef notyet
682 | IEEE80211_HTC_AMSDU /* tx A-MSDU */
683#endif
684 ;
685 }
ffd7c74a 686
977fc0db 687 ieee80211_ifattach(ic);
ffd7c74a 688 ic->ic_vap_create = iwn_vap_create;
977fc0db
MD
689 ic->ic_ioctl = iwn_ioctl;
690 ic->ic_parent = iwn_parent;
ffd7c74a 691 ic->ic_vap_delete = iwn_vap_delete;
977fc0db 692 ic->ic_transmit = iwn_transmit;
ffd7c74a
JT
693 ic->ic_raw_xmit = iwn_raw_xmit;
694 ic->ic_node_alloc = iwn_node_alloc;
da10ea93
MD
695 sc->sc_ampdu_rx_start = ic->ic_ampdu_rx_start;
696 ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
697 sc->sc_ampdu_rx_stop = ic->ic_ampdu_rx_stop;
698 ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
699 sc->sc_addba_request = ic->ic_addba_request;
700 ic->ic_addba_request = iwn_addba_request;
701 sc->sc_addba_response = ic->ic_addba_response;
702 ic->ic_addba_response = iwn_addba_response;
703 sc->sc_addba_stop = ic->ic_addba_stop;
704 ic->ic_addba_stop = iwn_ampdu_tx_stop;
ffd7c74a 705 ic->ic_newassoc = iwn_newassoc;
da10ea93 706 ic->ic_wme.wme_update = iwn_updateedca;
ffd7c74a
JT
707 ic->ic_update_mcast = iwn_update_mcast;
708 ic->ic_scan_start = iwn_scan_start;
709 ic->ic_scan_end = iwn_scan_end;
710 ic->ic_set_channel = iwn_set_channel;
711 ic->ic_scan_curchan = iwn_scan_curchan;
712 ic->ic_scan_mindwell = iwn_scan_mindwell;
977fc0db 713 ic->ic_getradiocaps = iwn_getradiocaps;
ffd7c74a 714 ic->ic_setregdomain = iwn_setregdomain;
ffd7c74a
JT
715
716 iwn_radiotap_attach(sc);
da10ea93 717
977fc0db
MD
718#if defined(__DragonFly__)
719 callout_init_lk(&sc->calib_to, &sc->sc_lk);
720 callout_init_lk(&sc->watchdog_to, &sc->sc_lk);
721#else
05538f72
MD
722 callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
723 callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
977fc0db 724#endif
05538f72
MD
725 TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc);
726 TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc);
727 TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc);
977fc0db
MD
728 TASK_INIT(&sc->sc_xmit_task, 0, iwn_xmit_task, sc);
729
730 mbufq_init(&sc->sc_xmit_queue, 1024);
fd49669c
MN
731
732 sc->sc_tq = taskqueue_create("iwn_taskq", M_WAITOK,
733 taskqueue_thread_enqueue, &sc->sc_tq);
05538f72
MD
734#if defined(__DragonFly__)
735 error = taskqueue_start_threads(&sc->sc_tq, 1, TDPRI_KERN_DAEMON,
736 -1, "iwn_taskq");
737#else
738 error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "iwn_taskq");
739#endif
fd49669c
MN
740 if (error != 0) {
741 device_printf(dev, "can't start threads, error %d\n", error);
742 goto fail;
743 }
da10ea93 744
ffd7c74a
JT
745 iwn_sysctlattach(sc);
746
747 /*
748 * Hook our interrupt after all initialization is complete.
749 */
05538f72 750#if defined(__DragonFly__)
101554a6
MD
751 error = bus_setup_intr(dev, sc->irq, INTR_MPSAFE,
752 iwn_intr, sc, &sc->sc_ih,
753 &wlan_global_serializer);
05538f72
MD
754#else
755 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
756 NULL, iwn_intr, sc, &sc->sc_ih);
757#endif
ffd7c74a 758 if (error != 0) {
da10ea93 759 device_printf(dev, "can't establish interrupt, error %d\n",
ffd7c74a
JT
760 error);
761 goto fail;
762 }
763
fd49669c
MN
764#if 0
765 device_printf(sc->sc_dev, "%s: rx_stats=%d, rx_stats_bt=%d\n",
766 __func__,
767 sizeof(struct iwn_stats),
768 sizeof(struct iwn_stats_bt));
769#endif
770
da10ea93
MD
771 if (bootverbose)
772 ieee80211_announce(ic);
773 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
977fc0db
MD
774
775 /* Add debug ioctl right at the end */
776 sc->sc_cdev = make_dev(&iwn_cdevsw, device_get_unit(dev),
777 UID_ROOT, GID_WHEEL, 0600, "%s", device_get_nameunit(dev));
778 if (sc->sc_cdev == NULL) {
779 device_printf(dev, "failed to create debug character device\n");
780 } else {
781 sc->sc_cdev->si_drv1 = sc;
782 }
ffd7c74a
JT
783 return 0;
784fail:
05538f72 785 iwn_detach(dev);
da10ea93 786 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
ffd7c74a
JT
787 return error;
788}
789
da10ea93
MD
790/*
791 * Define specific configuration based on device id and subdevice id
792 * pid : PCI device id
793 */
794static int
795iwn_config_specific(struct iwn_softc *sc, uint16_t pid)
ffd7c74a 796{
ffd7c74a 797
da10ea93
MD
798 switch (pid) {
799/* 4965 series */
800 case IWN_DID_4965_1:
801 case IWN_DID_4965_2:
802 case IWN_DID_4965_3:
803 case IWN_DID_4965_4:
804 sc->base_params = &iwn4965_base_params;
ffd7c74a
JT
805 sc->limits = &iwn4965_sensitivity_limits;
806 sc->fwname = "iwn4965fw";
da10ea93 807 /* Override chains masks, ROM is known to be broken. */
ffd7c74a
JT
808 sc->txchainmask = IWN_ANT_AB;
809 sc->rxchainmask = IWN_ANT_ABC;
da10ea93
MD
810 /* Enable normal btcoex */
811 sc->sc_flags |= IWN_FLAG_BTCOEX;
ffd7c74a 812 break;
da10ea93
MD
813/* 1000 Series */
814 case IWN_DID_1000_1:
815 case IWN_DID_1000_2:
816 switch(sc->subdevice_id) {
817 case IWN_SDID_1000_1:
818 case IWN_SDID_1000_2:
819 case IWN_SDID_1000_3:
820 case IWN_SDID_1000_4:
821 case IWN_SDID_1000_5:
822 case IWN_SDID_1000_6:
823 case IWN_SDID_1000_7:
824 case IWN_SDID_1000_8:
825 case IWN_SDID_1000_9:
826 case IWN_SDID_1000_10:
827 case IWN_SDID_1000_11:
828 case IWN_SDID_1000_12:
829 sc->limits = &iwn1000_sensitivity_limits;
830 sc->base_params = &iwn1000_base_params;
831 sc->fwname = "iwn1000fw";
832 break;
833 default:
834 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
835 "0x%04x rev %d not supported (subdevice)\n", pid,
836 sc->subdevice_id,sc->hw_type);
837 return ENOTSUP;
838 }
839 break;
840/* 6x00 Series */
841 case IWN_DID_6x00_2:
842 case IWN_DID_6x00_4:
843 case IWN_DID_6x00_1:
844 case IWN_DID_6x00_3:
845 sc->fwname = "iwn6000fw";
846 sc->limits = &iwn6000_sensitivity_limits;
847 switch(sc->subdevice_id) {
848 case IWN_SDID_6x00_1:
849 case IWN_SDID_6x00_2:
850 case IWN_SDID_6x00_8:
851 //iwl6000_3agn_cfg
852 sc->base_params = &iwn_6000_base_params;
853 break;
854 case IWN_SDID_6x00_3:
855 case IWN_SDID_6x00_6:
856 case IWN_SDID_6x00_9:
857 ////iwl6000i_2agn
858 case IWN_SDID_6x00_4:
859 case IWN_SDID_6x00_7:
860 case IWN_SDID_6x00_10:
861 //iwl6000i_2abg_cfg
862 case IWN_SDID_6x00_5:
863 //iwl6000i_2bg_cfg
864 sc->base_params = &iwn_6000i_base_params;
865 sc->sc_flags |= IWN_FLAG_INTERNAL_PA;
866 sc->txchainmask = IWN_ANT_BC;
867 sc->rxchainmask = IWN_ANT_BC;
868 break;
869 default:
870 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
871 "0x%04x rev %d not supported (subdevice)\n", pid,
872 sc->subdevice_id,sc->hw_type);
873 return ENOTSUP;
874 }
ffd7c74a 875 break;
da10ea93
MD
876/* 6x05 Series */
877 case IWN_DID_6x05_1:
878 case IWN_DID_6x05_2:
879 switch(sc->subdevice_id) {
880 case IWN_SDID_6x05_1:
881 case IWN_SDID_6x05_4:
882 case IWN_SDID_6x05_6:
883 //iwl6005_2agn_cfg
884 case IWN_SDID_6x05_2:
885 case IWN_SDID_6x05_5:
886 case IWN_SDID_6x05_7:
887 //iwl6005_2abg_cfg
888 case IWN_SDID_6x05_3:
889 //iwl6005_2bg_cfg
890 case IWN_SDID_6x05_8:
891 case IWN_SDID_6x05_9:
892 //iwl6005_2agn_sff_cfg
893 case IWN_SDID_6x05_10:
894 //iwl6005_2agn_d_cfg
895 case IWN_SDID_6x05_11:
896 //iwl6005_2agn_mow1_cfg
897 case IWN_SDID_6x05_12:
898 //iwl6005_2agn_mow2_cfg
899 sc->fwname = "iwn6000g2afw";
900 sc->limits = &iwn6000_sensitivity_limits;
901 sc->base_params = &iwn_6000g2_base_params;
902 break;
903 default:
904 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
905 "0x%04x rev %d not supported (subdevice)\n", pid,
906 sc->subdevice_id,sc->hw_type);
907 return ENOTSUP;
908 }
ffd7c74a 909 break;
da10ea93
MD
910/* 6x35 Series */
911 case IWN_DID_6035_1:
912 case IWN_DID_6035_2:
913 switch(sc->subdevice_id) {
914 case IWN_SDID_6035_1:
915 case IWN_SDID_6035_2:
916 case IWN_SDID_6035_3:
917 case IWN_SDID_6035_4:
36c2fb3e 918 case IWN_SDID_6035_5:
da10ea93 919 sc->fwname = "iwn6000g2bfw";
fd49669c
MN
920 sc->limits = &iwn6235_sensitivity_limits;
921 sc->base_params = &iwn_6235_base_params;
da10ea93
MD
922 break;
923 default:
924 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
925 "0x%04x rev %d not supported (subdevice)\n", pid,
926 sc->subdevice_id,sc->hw_type);
927 return ENOTSUP;
928 }
ffd7c74a 929 break;
da10ea93
MD
930/* 6x50 WiFi/WiMax Series */
931 case IWN_DID_6050_1:
932 case IWN_DID_6050_2:
933 switch(sc->subdevice_id) {
934 case IWN_SDID_6050_1:
935 case IWN_SDID_6050_3:
936 case IWN_SDID_6050_5:
937 //iwl6050_2agn_cfg
938 case IWN_SDID_6050_2:
939 case IWN_SDID_6050_4:
940 case IWN_SDID_6050_6:
941 //iwl6050_2abg_cfg
942 sc->fwname = "iwn6050fw";
943 sc->txchainmask = IWN_ANT_AB;
944 sc->rxchainmask = IWN_ANT_AB;
945 sc->limits = &iwn6000_sensitivity_limits;
946 sc->base_params = &iwn_6050_base_params;
947 break;
948 default:
949 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
950 "0x%04x rev %d not supported (subdevice)\n", pid,
951 sc->subdevice_id,sc->hw_type);
952 return ENOTSUP;
953 }
ffd7c74a 954 break;
da10ea93
MD
955/* 6150 WiFi/WiMax Series */
956 case IWN_DID_6150_1:
957 case IWN_DID_6150_2:
958 switch(sc->subdevice_id) {
959 case IWN_SDID_6150_1:
960 case IWN_SDID_6150_3:
961 case IWN_SDID_6150_5:
962 // iwl6150_bgn_cfg
963 case IWN_SDID_6150_2:
964 case IWN_SDID_6150_4:
965 case IWN_SDID_6150_6:
966 //iwl6150_bg_cfg
967 sc->fwname = "iwn6050fw";
968 sc->limits = &iwn6000_sensitivity_limits;
969 sc->base_params = &iwn_6150_base_params;
970 break;
971 default:
972 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
973 "0x%04x rev %d not supported (subdevice)\n", pid,
974 sc->subdevice_id,sc->hw_type);
975 return ENOTSUP;
ffd7c74a
JT
976 }
977 break;
da10ea93
MD
978/* 6030 Series and 1030 Series */
979 case IWN_DID_x030_1:
980 case IWN_DID_x030_2:
981 case IWN_DID_x030_3:
982 case IWN_DID_x030_4:
983 switch(sc->subdevice_id) {
984 case IWN_SDID_x030_1:
985 case IWN_SDID_x030_3:
986 case IWN_SDID_x030_5:
987 // iwl1030_bgn_cfg
988 case IWN_SDID_x030_2:
989 case IWN_SDID_x030_4:
990 case IWN_SDID_x030_6:
991 //iwl1030_bg_cfg
992 case IWN_SDID_x030_7:
993 case IWN_SDID_x030_10:
994 case IWN_SDID_x030_14:
995 //iwl6030_2agn_cfg
996 case IWN_SDID_x030_8:
997 case IWN_SDID_x030_11:
998 case IWN_SDID_x030_15:
999 // iwl6030_2bgn_cfg
1000 case IWN_SDID_x030_9:
1001 case IWN_SDID_x030_12:
1002 case IWN_SDID_x030_16:
1003 // iwl6030_2abg_cfg
1004 case IWN_SDID_x030_13:
1005 //iwl6030_2bg_cfg
1006 sc->fwname = "iwn6000g2bfw";
1007 sc->limits = &iwn6000_sensitivity_limits;
1008 sc->base_params = &iwn_6000g2b_base_params;
1009 break;
1010 default:
1011 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1012 "0x%04x rev %d not supported (subdevice)\n", pid,
1013 sc->subdevice_id,sc->hw_type);
1014 return ENOTSUP;
1015 }
1016 break;
1017/* 130 Series WiFi */
1018/* XXX: This series will need adjustment for rate.
1019 * see rx_with_siso_diversity in linux kernel
1020 */
1021 case IWN_DID_130_1:
1022 case IWN_DID_130_2:
1023 switch(sc->subdevice_id) {
1024 case IWN_SDID_130_1:
1025 case IWN_SDID_130_3:
1026 case IWN_SDID_130_5:
1027 //iwl130_bgn_cfg
1028 case IWN_SDID_130_2:
1029 case IWN_SDID_130_4:
1030 case IWN_SDID_130_6:
1031 //iwl130_bg_cfg
1032 sc->fwname = "iwn6000g2bfw";
1033 sc->limits = &iwn6000_sensitivity_limits;
1034 sc->base_params = &iwn_6000g2b_base_params;
1035 break;
1036 default:
1037 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1038 "0x%04x rev %d not supported (subdevice)\n", pid,
1039 sc->subdevice_id,sc->hw_type);
1040 return ENOTSUP;
1041 }
1042 break;
1043/* 100 Series WiFi */
1044 case IWN_DID_100_1:
1045 case IWN_DID_100_2:
1046 switch(sc->subdevice_id) {
1047 case IWN_SDID_100_1:
1048 case IWN_SDID_100_2:
1049 case IWN_SDID_100_3:
1050 case IWN_SDID_100_4:
1051 case IWN_SDID_100_5:
1052 case IWN_SDID_100_6:
1053 sc->limits = &iwn1000_sensitivity_limits;
1054 sc->base_params = &iwn1000_base_params;
1055 sc->fwname = "iwn100fw";
1056 break;
1057 default:
1058 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1059 "0x%04x rev %d not supported (subdevice)\n", pid,
1060 sc->subdevice_id,sc->hw_type);
1061 return ENOTSUP;
1062 }
1063 break;
1064
fd49669c
MN
1065/* 105 Series */
1066/* XXX: This series will need adjustment for rate.
1067 * see rx_with_siso_diversity in linux kernel
1068 */
1069 case IWN_DID_105_1:
1070 case IWN_DID_105_2:
1071 switch(sc->subdevice_id) {
1072 case IWN_SDID_105_1:
1073 case IWN_SDID_105_2:
1074 case IWN_SDID_105_3:
1075 //iwl105_bgn_cfg
1076 case IWN_SDID_105_4:
1077 //iwl105_bgn_d_cfg
1078 sc->limits = &iwn2030_sensitivity_limits;
1079 sc->base_params = &iwn2000_base_params;
1080 sc->fwname = "iwn105fw";
1081 break;
1082 default:
1083 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1084 "0x%04x rev %d not supported (subdevice)\n", pid,
1085 sc->subdevice_id,sc->hw_type);
1086 return ENOTSUP;
1087 }
1088 break;
1089
1090/* 135 Series */
1091/* XXX: This series will need adjustment for rate.
1092 * see rx_with_siso_diversity in linux kernel
1093 */
1094 case IWN_DID_135_1:
1095 case IWN_DID_135_2:
1096 switch(sc->subdevice_id) {
1097 case IWN_SDID_135_1:
1098 case IWN_SDID_135_2:
1099 case IWN_SDID_135_3:
1100 sc->limits = &iwn2030_sensitivity_limits;
1101 sc->base_params = &iwn2030_base_params;
1102 sc->fwname = "iwn135fw";
1103 break;
1104 default:
1105 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1106 "0x%04x rev %d not supported (subdevice)\n", pid,
1107 sc->subdevice_id,sc->hw_type);
1108 return ENOTSUP;
1109 }
1110 break;
1111
da10ea93
MD
1112/* 2x00 Series */
1113 case IWN_DID_2x00_1:
1114 case IWN_DID_2x00_2:
1115 switch(sc->subdevice_id) {
1116 case IWN_SDID_2x00_1:
1117 case IWN_SDID_2x00_2:
1118 case IWN_SDID_2x00_3:
1119 //iwl2000_2bgn_cfg
1120 case IWN_SDID_2x00_4:
1121 //iwl2000_2bgn_d_cfg
1122 sc->limits = &iwn2030_sensitivity_limits;
1123 sc->base_params = &iwn2000_base_params;
1124 sc->fwname = "iwn2000fw";
1125 break;
1126 default:
1127 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1128 "0x%04x rev %d not supported (subdevice) \n",
1129 pid, sc->subdevice_id, sc->hw_type);
1130 return ENOTSUP;
1131 }
1132 break;
1133/* 2x30 Series */
1134 case IWN_DID_2x30_1:
1135 case IWN_DID_2x30_2:
1136 switch(sc->subdevice_id) {
1137 case IWN_SDID_2x30_1:
1138 case IWN_SDID_2x30_3:
1139 case IWN_SDID_2x30_5:
1140 //iwl100_bgn_cfg
1141 case IWN_SDID_2x30_2:
1142 case IWN_SDID_2x30_4:
1143 case IWN_SDID_2x30_6:
1144 //iwl100_bg_cfg
1145 sc->limits = &iwn2030_sensitivity_limits;
1146 sc->base_params = &iwn2030_base_params;
1147 sc->fwname = "iwn2030fw";
1148 break;
1149 default:
1150 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1151 "0x%04x rev %d not supported (subdevice)\n", pid,
1152 sc->subdevice_id,sc->hw_type);
1153 return ENOTSUP;
1154 }
1155 break;
1156/* 5x00 Series */
1157 case IWN_DID_5x00_1:
1158 case IWN_DID_5x00_2:
1159 case IWN_DID_5x00_3:
1160 case IWN_DID_5x00_4:
1161 sc->limits = &iwn5000_sensitivity_limits;
1162 sc->base_params = &iwn5000_base_params;
1163 sc->fwname = "iwn5000fw";
1164 switch(sc->subdevice_id) {
1165 case IWN_SDID_5x00_1:
1166 case IWN_SDID_5x00_2:
1167 case IWN_SDID_5x00_3:
1168 case IWN_SDID_5x00_4:
1169 case IWN_SDID_5x00_9:
1170 case IWN_SDID_5x00_10:
1171 case IWN_SDID_5x00_11:
1172 case IWN_SDID_5x00_12:
1173 case IWN_SDID_5x00_17:
1174 case IWN_SDID_5x00_18:
1175 case IWN_SDID_5x00_19:
1176 case IWN_SDID_5x00_20:
1177 //iwl5100_agn_cfg
1178 sc->txchainmask = IWN_ANT_B;
1179 sc->rxchainmask = IWN_ANT_AB;
1180 break;
1181 case IWN_SDID_5x00_5:
1182 case IWN_SDID_5x00_6:
1183 case IWN_SDID_5x00_13:
1184 case IWN_SDID_5x00_14:
1185 case IWN_SDID_5x00_21:
1186 case IWN_SDID_5x00_22:
1187 //iwl5100_bgn_cfg
1188 sc->txchainmask = IWN_ANT_B;
1189 sc->rxchainmask = IWN_ANT_AB;
1190 break;
1191 case IWN_SDID_5x00_7:
1192 case IWN_SDID_5x00_8:
1193 case IWN_SDID_5x00_15:
1194 case IWN_SDID_5x00_16:
1195 case IWN_SDID_5x00_23:
1196 case IWN_SDID_5x00_24:
1197 //iwl5100_abg_cfg
1198 sc->txchainmask = IWN_ANT_B;
1199 sc->rxchainmask = IWN_ANT_AB;
1200 break;
1201 case IWN_SDID_5x00_25:
1202 case IWN_SDID_5x00_26:
1203 case IWN_SDID_5x00_27:
1204 case IWN_SDID_5x00_28:
1205 case IWN_SDID_5x00_29:
1206 case IWN_SDID_5x00_30:
1207 case IWN_SDID_5x00_31:
1208 case IWN_SDID_5x00_32:
1209 case IWN_SDID_5x00_33:
1210 case IWN_SDID_5x00_34:
1211 case IWN_SDID_5x00_35:
1212 case IWN_SDID_5x00_36:
1213 //iwl5300_agn_cfg
1214 sc->txchainmask = IWN_ANT_ABC;
1215 sc->rxchainmask = IWN_ANT_ABC;
1216 break;
1217 default:
1218 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1219 "0x%04x rev %d not supported (subdevice)\n", pid,
1220 sc->subdevice_id,sc->hw_type);
1221 return ENOTSUP;
1222 }
1223 break;
1224/* 5x50 Series */
1225 case IWN_DID_5x50_1:
1226 case IWN_DID_5x50_2:
1227 case IWN_DID_5x50_3:
1228 case IWN_DID_5x50_4:
1229 sc->limits = &iwn5000_sensitivity_limits;
1230 sc->base_params = &iwn5000_base_params;
1231 sc->fwname = "iwn5000fw";
1232 switch(sc->subdevice_id) {
1233 case IWN_SDID_5x50_1:
1234 case IWN_SDID_5x50_2:
1235 case IWN_SDID_5x50_3:
1236 //iwl5350_agn_cfg
1237 sc->limits = &iwn5000_sensitivity_limits;
1238 sc->base_params = &iwn5000_base_params;
1239 sc->fwname = "iwn5000fw";
1240 break;
1241 case IWN_SDID_5x50_4:
1242 case IWN_SDID_5x50_5:
1243 case IWN_SDID_5x50_8:
1244 case IWN_SDID_5x50_9:
1245 case IWN_SDID_5x50_10:
1246 case IWN_SDID_5x50_11:
1247 //iwl5150_agn_cfg
1248 case IWN_SDID_5x50_6:
1249 case IWN_SDID_5x50_7:
1250 case IWN_SDID_5x50_12:
1251 case IWN_SDID_5x50_13:
1252 //iwl5150_abg_cfg
1253 sc->limits = &iwn5000_sensitivity_limits;
1254 sc->fwname = "iwn5150fw";
1255 sc->base_params = &iwn_5x50_base_params;
1256 break;
1257 default:
1258 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id :"
1259 "0x%04x rev %d not supported (subdevice)\n", pid,
1260 sc->subdevice_id,sc->hw_type);
1261 return ENOTSUP;
1262 }
ffd7c74a
JT
1263 break;
1264 default:
da10ea93
MD
1265 device_printf(sc->sc_dev, "adapter type id : 0x%04x sub id : 0x%04x"
1266 "rev 0x%08x not supported (device)\n", pid, sc->subdevice_id,
1267 sc->hw_type);
1268 return ENOTSUP;
ffd7c74a 1269 }
da10ea93
MD
1270 return 0;
1271}
1272
1273static int
1274iwn4965_attach(struct iwn_softc *sc, uint16_t pid)
1275{
1276 struct iwn_ops *ops = &sc->ops;
1277
1278 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
1279 ops->load_firmware = iwn4965_load_firmware;
1280 ops->read_eeprom = iwn4965_read_eeprom;
1281 ops->post_alive = iwn4965_post_alive;
1282 ops->nic_config = iwn4965_nic_config;
1283 ops->update_sched = iwn4965_update_sched;
1284 ops->get_temperature = iwn4965_get_temperature;
1285 ops->get_rssi = iwn4965_get_rssi;
1286 ops->set_txpower = iwn4965_set_txpower;
1287 ops->init_gains = iwn4965_init_gains;
1288 ops->set_gains = iwn4965_set_gains;
1289 ops->add_node = iwn4965_add_node;
1290 ops->tx_done = iwn4965_tx_done;
1291 ops->ampdu_tx_start = iwn4965_ampdu_tx_start;
1292 ops->ampdu_tx_stop = iwn4965_ampdu_tx_stop;
1293 sc->ntxqs = IWN4965_NTXQUEUES;
1294 sc->firstaggqueue = IWN4965_FIRSTAGGQUEUE;
1295 sc->ndmachnls = IWN4965_NDMACHNLS;
1296 sc->broadcast_id = IWN4965_ID_BROADCAST;
1297 sc->rxonsz = IWN4965_RXONSZ;
1298 sc->schedsz = IWN4965_SCHEDSZ;
1299 sc->fw_text_maxsz = IWN4965_FW_TEXT_MAXSZ;
1300 sc->fw_data_maxsz = IWN4965_FW_DATA_MAXSZ;
1301 sc->fwsz = IWN4965_FWSZ;
1302 sc->sched_txfact_addr = IWN4965_SCHED_TXFACT;
1303 sc->limits = &iwn4965_sensitivity_limits;
1304 sc->fwname = "iwn4965fw";
1305 /* Override chains masks, ROM is known to be broken. */
1306 sc->txchainmask = IWN_ANT_AB;
1307 sc->rxchainmask = IWN_ANT_ABC;
1308 /* Enable normal btcoex */
1309 sc->sc_flags |= IWN_FLAG_BTCOEX;
1310
1311 DPRINTF(sc, IWN_DEBUG_TRACE, "%s: end\n",__func__);
1312
1313 return 0;
1314}
1315
1316static int
1317iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
1318{
1319 struct iwn_ops *ops = &sc->ops;
1320
1321 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
1322
1323 ops->load_firmware = iwn5000_load_firmware;
1324 ops->read_eeprom = iwn5000_read_eeprom;
1325 ops->post_alive = iwn5000_post_alive;
1326 ops->nic_config = iwn5000_nic_config;
1327 ops->update_sched = iwn5000_update_sched;
1328 ops->get_temperature = iwn5000_get_temperature;
1329 ops->get_rssi = iwn5000_get_rssi;
1330 ops->set_txpower = iwn5000_set_txpower;
1331 ops->init_gains = iwn5000_init_gains;
1332 ops->set_gains = iwn5000_set_gains;
1333 ops->add_node = iwn5000_add_node;
1334 ops->tx_done = iwn5000_tx_done;
1335 ops->ampdu_tx_start = iwn5000_ampdu_tx_start;
1336 ops->ampdu_tx_stop = iwn5000_ampdu_tx_stop;
1337 sc->ntxqs = IWN5000_NTXQUEUES;
1338 sc->firstaggqueue = IWN5000_FIRSTAGGQUEUE;
1339 sc->ndmachnls = IWN5000_NDMACHNLS;
1340 sc->broadcast_id = IWN5000_ID_BROADCAST;
1341 sc->rxonsz = IWN5000_RXONSZ;
1342 sc->schedsz = IWN5000_SCHEDSZ;
1343 sc->fw_text_maxsz = IWN5000_FW_TEXT_MAXSZ;
1344 sc->fw_data_maxsz = IWN5000_FW_DATA_MAXSZ;
1345 sc->fwsz = IWN5000_FWSZ;
1346 sc->sched_txfact_addr = IWN5000_SCHED_TXFACT;
1347 sc->reset_noise_gain = IWN5000_PHY_CALIB_RESET_NOISE_GAIN;
1348 sc->noise_gain = IWN5000_PHY_CALIB_NOISE_GAIN;
1349
1350 return 0;
ffd7c74a
JT
1351}
1352
1353/*
1354 * Attach the interface to 802.11 radiotap.
1355 */
1356static void
1357iwn_radiotap_attach(struct iwn_softc *sc)
1358{
977fc0db 1359
da10ea93 1360 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
977fc0db 1361 ieee80211_radiotap_attach(&sc->sc_ic,
ffd7c74a
JT
1362 &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
1363 IWN_TX_RADIOTAP_PRESENT,
1364 &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
1365 IWN_RX_RADIOTAP_PRESENT);
da10ea93
MD
1366 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
1367}
1368
1369static void
1370iwn_sysctlattach(struct iwn_softc *sc)
1371{
1372#ifdef IWN_DEBUG
05538f72
MD
1373 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
1374 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
da10ea93
MD
1375
1376 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1377 "debug", CTLFLAG_RW, &sc->sc_debug, sc->sc_debug,
1378 "control debugging printfs");
1379#endif
ffd7c74a
JT
1380}
1381
1382static struct ieee80211vap *
da10ea93
MD
1383iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
1384 enum ieee80211_opmode opmode, int flags,
1385 const uint8_t bssid[IEEE80211_ADDR_LEN],
1386 const uint8_t mac[IEEE80211_ADDR_LEN])
ffd7c74a 1387{
977fc0db 1388 struct iwn_softc *sc = ic->ic_softc;
ffd7c74a
JT
1389 struct iwn_vap *ivp;
1390 struct ieee80211vap *vap;
1391
1392 if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
1393 return NULL;
da10ea93 1394
977fc0db 1395 ivp = kmalloc(sizeof(struct iwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
ffd7c74a 1396 vap = &ivp->iv_vap;
977fc0db 1397 ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
da10ea93 1398 ivp->ctx = IWN_RXON_BSS_CTX;
ffd7c74a
JT
1399 vap->iv_bmissthreshold = 10; /* override default */
1400 /* Override with driver methods. */
1401 ivp->iv_newstate = vap->iv_newstate;
1402 vap->iv_newstate = iwn_newstate;
da10ea93 1403 sc->ivap[IWN_RXON_BSS_CTX] = vap;
ffd7c74a
JT
1404
1405 ieee80211_ratectl_init(vap);
1406 /* Complete setup. */
977fc0db
MD
1407 ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status,
1408 mac);
ffd7c74a
JT
1409 ic->ic_opmode = opmode;
1410 return vap;
1411}
1412
1413static void
1414iwn_vap_delete(struct ieee80211vap *vap)
1415{
1416 struct iwn_vap *ivp = IWN_VAP(vap);
1417
1418 ieee80211_ratectl_deinit(vap);
1419 ieee80211_vap_detach(vap);
101554a6 1420 kfree(ivp, M_80211_VAP);
ffd7c74a
JT
1421}
1422
977fc0db
MD
1423static void
1424iwn_xmit_queue_drain(struct iwn_softc *sc)
1425{
1426 struct mbuf *m;
1427 struct ieee80211_node *ni;
1428
1429 IWN_LOCK_ASSERT(sc);
1430 while ((m = mbufq_dequeue(&sc->sc_xmit_queue)) != NULL) {
1431 ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
1432 ieee80211_free_node(ni);
1433 m_freem(m);
1434 }
1435}
1436
1437static int
1438iwn_xmit_queue_enqueue(struct iwn_softc *sc, struct mbuf *m)
1439{
1440
1441 IWN_LOCK_ASSERT(sc);
1442 return (mbufq_enqueue(&sc->sc_xmit_queue, m));
1443}
1444
ffd7c74a 1445static int
05538f72 1446iwn_detach(device_t dev)
ffd7c74a
JT
1447{
1448 struct iwn_softc *sc = device_get_softc(dev);
da10ea93
MD
1449 int qid;
1450
1451 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a 1452
977fc0db
MD
1453 if (sc->sc_ic.ic_softc != NULL) {
1454 /* Free the mbuf queue and node references */
1455 IWN_LOCK(sc);
1456 iwn_xmit_queue_drain(sc);
1457 IWN_UNLOCK(sc);
ffd7c74a 1458
977fc0db
MD
1459 ieee80211_draintask(&sc->sc_ic, &sc->sc_radioon_task);
1460 ieee80211_draintask(&sc->sc_ic, &sc->sc_radiooff_task);
05538f72 1461 iwn_stop(sc);
fd49669c 1462
05538f72
MD
1463#if defined(__DragonFly__)
1464 /* doesn't exist for DFly, DFly drains tasks on free */
1465#else
fd49669c
MN
1466 taskqueue_drain_all(sc->sc_tq);
1467#endif
1468 taskqueue_free(sc->sc_tq);
1469
05538f72
MD
1470 callout_drain(&sc->watchdog_to);
1471 callout_drain(&sc->calib_to);
977fc0db 1472 ieee80211_ifdetach(&sc->sc_ic);
ffd7c74a
JT
1473 }
1474
da10ea93
MD
1475 /* Uninstall interrupt handler. */
1476 if (sc->irq != NULL) {
1477 bus_teardown_intr(dev, sc->irq, sc->sc_ih);
fd49669c
MN
1478 bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq),
1479 sc->irq);
1480 pci_release_msi(dev);
da10ea93 1481 }
8f7750c0 1482
ffd7c74a
JT
1483 /* Free DMA resources. */
1484 iwn_free_rx_ring(sc, &sc->rxq);
da10ea93
MD
1485 for (qid = 0; qid < sc->ntxqs; qid++)
1486 iwn_free_tx_ring(sc, &sc->txq[qid]);
ffd7c74a
JT
1487 iwn_free_sched(sc);
1488 iwn_free_kw(sc);
05538f72 1489 if (sc->ict != NULL)
ffd7c74a
JT
1490 iwn_free_ict(sc);
1491 iwn_free_fwmem(sc);
1492
05538f72 1493 if (sc->mem != NULL)
fd49669c
MN
1494 bus_release_resource(dev, SYS_RES_MEMORY,
1495 rman_get_rid(sc->mem), sc->mem);
ffd7c74a 1496
977fc0db
MD
1497 if (sc->sc_cdev) {
1498 destroy_dev(sc->sc_cdev);
1499 sc->sc_cdev = NULL;
1500 }
ffd7c74a 1501
da10ea93 1502 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n", __func__);
05538f72 1503 IWN_LOCK_DESTROY(sc);
ffd7c74a
JT
1504 return 0;
1505}
1506
1507static int
05538f72 1508iwn_shutdown(device_t dev)
ffd7c74a 1509{
da10ea93 1510 struct iwn_softc *sc = device_get_softc(dev);
458fc9cf 1511
05538f72 1512 iwn_stop(sc);
da10ea93
MD
1513 return 0;
1514}
1515
1516static int
05538f72 1517iwn_suspend(device_t dev)
da10ea93
MD
1518{
1519 struct iwn_softc *sc = device_get_softc(dev);
da10ea93 1520
977fc0db 1521 ieee80211_suspend_all(&sc->sc_ic);
da10ea93
MD
1522 return 0;
1523}
1524
1525static int
05538f72 1526iwn_resume(device_t dev)
da10ea93
MD
1527{
1528 struct iwn_softc *sc = device_get_softc(dev);
da10ea93
MD
1529
1530 /* Clear device-specific "PCI retry timeout" register (41h). */
1531 pci_write_config(dev, 0x41, 0, 1);
1532
977fc0db 1533 ieee80211_resume_all(&sc->sc_ic);
ffd7c74a
JT
1534 return 0;
1535}
1536
1537static int
1538iwn_nic_lock(struct iwn_softc *sc)
1539{
1540 int ntries;
1541
1542 /* Request exclusive access to NIC. */
1543 IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
1544
1545 /* Spin until we actually get the lock. */
1546 for (ntries = 0; ntries < 1000; ntries++) {
1547 if ((IWN_READ(sc, IWN_GP_CNTRL) &
da10ea93 1548 (IWN_GP_CNTRL_MAC_ACCESS_ENA | IWN_GP_CNTRL_SLEEP)) ==
ffd7c74a
JT
1549 IWN_GP_CNTRL_MAC_ACCESS_ENA)
1550 return 0;
1551 DELAY(10);
1552 }
1553 return ETIMEDOUT;
1554}
1555
1556static __inline void
1557iwn_nic_unlock(struct iwn_softc *sc)
1558{
1559 IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
1560}
1561
1562static __inline uint32_t
1563iwn_prph_read(struct iwn_softc *sc, uint32_t addr)
1564{
1565 IWN_WRITE(sc, IWN_PRPH_RADDR, IWN_PRPH_DWORD | addr);
1566 IWN_BARRIER_READ_WRITE(sc);
1567 return IWN_READ(sc, IWN_PRPH_RDATA);
1568}
1569
1570static __inline void
1571iwn_prph_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)
1572{
1573 IWN_WRITE(sc, IWN_PRPH_WADDR, IWN_PRPH_DWORD | addr);
1574 IWN_BARRIER_WRITE(sc);
1575 IWN_WRITE(sc, IWN_PRPH_WDATA, data);
1576}
1577
1578static __inline void
1579iwn_prph_setbits(struct iwn_softc *sc, uint32_t addr, uint32_t mask)
1580{
1581 iwn_prph_write(sc, addr, iwn_prph_read(sc, addr) | mask);
1582}
1583
1584static __inline void
1585iwn_prph_clrbits(struct iwn_softc *sc, uint32_t addr, uint32_t mask)
1586{
1587 iwn_prph_write(sc, addr, iwn_prph_read(sc, addr) & ~mask);
1588}
1589
1590static __inline void
1591iwn_prph_write_region_4(struct iwn_softc *sc, uint32_t addr,
1592 const uint32_t *data, int count)
1593{
1594 for (; count > 0; count--, data++, addr += 4)
1595 iwn_prph_write(sc, addr, *data);
1596}
1597
1598static __inline uint32_t
1599iwn_mem_read(struct iwn_softc *sc, uint32_t addr)
1600{
1601 IWN_WRITE(sc, IWN_MEM_RADDR, addr);
1602 IWN_BARRIER_READ_WRITE(sc);
1603 return IWN_READ(sc, IWN_MEM_RDATA);
1604}
1605
1606static __inline void
1607iwn_mem_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)
1608{
1609 IWN_WRITE(sc, IWN_MEM_WADDR, addr);
1610 IWN_BARRIER_WRITE(sc);
1611 IWN_WRITE(sc, IWN_MEM_WDATA, data);
1612}
1613
1614static __inline void
1615iwn_mem_write_2(struct iwn_softc *sc, uint32_t addr, uint16_t data)
1616{
1617 uint32_t tmp;
1618
1619 tmp = iwn_mem_read(sc, addr & ~3);
1620 if (addr & 3)
1621 tmp = (tmp & 0x0000ffff) | data << 16;
1622 else
1623 tmp = (tmp & 0xffff0000) | data;
1624 iwn_mem_write(sc, addr & ~3, tmp);
1625}
1626
1627static __inline void
1628iwn_mem_read_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t *data,
1629 int count)
1630{
1631 for (; count > 0; count--, addr += 4)
1632 *data++ = iwn_mem_read(sc, addr);
1633}
1634
1635static __inline void
1636iwn_mem_set_region_4(struct iwn_softc *sc, uint32_t addr, uint32_t val,
1637 int count)
1638{
1639 for (; count > 0; count--, addr += 4)
1640 iwn_mem_write(sc, addr, val);
1641}
1642
1643static int
1644iwn_eeprom_lock(struct iwn_softc *sc)
1645{
1646 int i, ntries;
1647
1648 for (i = 0; i < 100; i++) {
1649 /* Request exclusive access to EEPROM. */
1650 IWN_SETBITS(sc, IWN_HW_IF_CONFIG,
1651 IWN_HW_IF_CONFIG_EEPROM_LOCKED);
1652
1653 /* Spin until we actually get the lock. */
1654 for (ntries = 0; ntries < 100; ntries++) {
1655 if (IWN_READ(sc, IWN_HW_IF_CONFIG) &
1656 IWN_HW_IF_CONFIG_EEPROM_LOCKED)
1657 return 0;
1658 DELAY(10);
1659 }
1660 }
da10ea93 1661 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end timeout\n", __func__);
ffd7c74a
JT
1662 return ETIMEDOUT;
1663}
1664
1665static __inline void
1666iwn_eeprom_unlock(struct iwn_softc *sc)
1667{
1668 IWN_CLRBITS(sc, IWN_HW_IF_CONFIG, IWN_HW_IF_CONFIG_EEPROM_LOCKED);
1669}
1670
1671/*
1672 * Initialize access by host to One Time Programmable ROM.
1673 * NB: This kind of ROM can be found on 1000 or 6000 Series only.
1674 */
1675static int
1676iwn_init_otprom(struct iwn_softc *sc)
1677{
1678 uint16_t prev, base, next;
1679 int count, error;
1680
da10ea93
MD
1681 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
1682
ffd7c74a 1683 /* Wait for clock stabilization before accessing prph. */
da10ea93 1684 if ((error = iwn_clock_wait(sc)) != 0)
ffd7c74a
JT
1685 return error;
1686
da10ea93 1687 if ((error = iwn_nic_lock(sc)) != 0)
ffd7c74a
JT
1688 return error;
1689 iwn_prph_setbits(sc, IWN_APMG_PS, IWN_APMG_PS_RESET_REQ);
1690 DELAY(5);
1691 iwn_prph_clrbits(sc, IWN_APMG_PS, IWN_APMG_PS_RESET_REQ);
1692 iwn_nic_unlock(sc);
1693
1694 /* Set auto clock gate disable bit for HW with OTP shadow RAM. */
da10ea93 1695 if (sc->base_params->shadow_ram_support) {
ffd7c74a
JT
1696 IWN_SETBITS(sc, IWN_DBG_LINK_PWR_MGMT,
1697 IWN_RESET_LINK_PWR_MGMT_DIS);
1698 }
1699 IWN_CLRBITS(sc, IWN_EEPROM_GP, IWN_EEPROM_GP_IF_OWNER);
1700 /* Clear ECC status. */
1701 IWN_SETBITS(sc, IWN_OTP_GP,
1702 IWN_OTP_GP_ECC_CORR_STTS | IWN_OTP_GP_ECC_UNCORR_STTS);
1703
1704 /*
1705 * Find the block before last block (contains the EEPROM image)
1706 * for HW without OTP shadow RAM.
1707 */
da10ea93 1708 if (! sc->base_params->shadow_ram_support) {
ffd7c74a
JT
1709 /* Switch to absolute addressing mode. */
1710 IWN_CLRBITS(sc, IWN_OTP_GP, IWN_OTP_GP_RELATIVE_ACCESS);
1711 base = prev = 0;
da10ea93
MD
1712 for (count = 0; count < sc->base_params->max_ll_items;
1713 count++) {
ffd7c74a
JT
1714 error = iwn_read_prom_data(sc, base, &next, 2);
1715 if (error != 0)
1716 return error;
1717 if (next == 0) /* End of linked-list. */
1718 break;
1719 prev = base;
1720 base = le16toh(next);
1721 }
da10ea93 1722 if (count == 0 || count == sc->base_params->max_ll_items)
ffd7c74a
JT
1723 return EIO;
1724 /* Skip "next" word. */
1725 sc->prom_base = prev + 1;
1726 }
da10ea93
MD
1727
1728 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
1729
ffd7c74a
JT
1730 return 0;
1731}
1732
1733static int
1734iwn_read_prom_data(struct iwn_softc *sc, uint32_t addr, void *data, int count)
1735{
da10ea93 1736 uint8_t *out = data;
ffd7c74a
JT
1737 uint32_t val, tmp;
1738 int ntries;
da10ea93
MD
1739
1740 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a
JT
1741
1742 addr += sc->prom_base;
1743 for (; count > 0; count -= 2, addr++) {
1744 IWN_WRITE(sc, IWN_EEPROM, addr << 2);
1745 for (ntries = 0; ntries < 10; ntries++) {
1746 val = IWN_READ(sc, IWN_EEPROM);
1747 if (val & IWN_EEPROM_READ_VALID)
1748 break;
1749 DELAY(5);
1750 }
1751 if (ntries == 10) {
1752 device_printf(sc->sc_dev,
1753 "timeout reading ROM at 0x%x\n", addr);
1754 return ETIMEDOUT;
1755 }
1756 if (sc->sc_flags & IWN_FLAG_HAS_OTPROM) {
1757 /* OTPROM, check for ECC errors. */
1758 tmp = IWN_READ(sc, IWN_OTP_GP);
1759 if (tmp & IWN_OTP_GP_ECC_UNCORR_STTS) {
1760 device_printf(sc->sc_dev,
1761 "OTPROM ECC error at 0x%x\n", addr);
1762 return EIO;
1763 }
1764 if (tmp & IWN_OTP_GP_ECC_CORR_STTS) {
1765 /* Correctable ECC error, clear bit. */
1766 IWN_SETBITS(sc, IWN_OTP_GP,
1767 IWN_OTP_GP_ECC_CORR_STTS);
1768 }
1769 }
1770 *out++ = val >> 16;
1771 if (count > 1)
1772 *out++ = val >> 24;
1773 }
da10ea93
MD
1774
1775 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
1776
ffd7c74a
JT
1777 return 0;
1778}
1779
1780static void
1781iwn_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1782{
1783 if (error != 0)
1784 return;
1785 KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs));
1786 *(bus_addr_t *)arg = segs[0].ds_addr;
1787}
1788
1789static int
1790iwn_dma_contig_alloc(struct iwn_softc *sc, struct iwn_dma_info *dma,
da10ea93 1791 void **kvap, bus_size_t size, bus_size_t alignment)
ffd7c74a
JT
1792{
1793 int error;
1794
ffd7c74a 1795 dma->tag = NULL;
da10ea93 1796 dma->size = size;
ffd7c74a 1797
05538f72
MD
1798#if defined(__DragonFly__)
1799 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), alignment,
977fc0db
MD
1800 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
1801 1, size, 0, &dma->tag);
05538f72
MD
1802#else
1803 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), alignment,
ffd7c74a 1804 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
977fc0db 1805 1, size, 0, NULL, NULL, &dma->tag);
05538f72 1806#endif
da10ea93 1807 if (error != 0)
ffd7c74a 1808 goto fail;
da10ea93 1809
ffd7c74a 1810 error = bus_dmamem_alloc(dma->tag, (void **)&dma->vaddr,
da10ea93
MD
1811 BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, &dma->map);
1812 if (error != 0)
ffd7c74a 1813 goto fail;
da10ea93
MD
1814
1815 error = bus_dmamap_load(dma->tag, dma->map, dma->vaddr, size,
1816 iwn_dma_map_addr, &dma->paddr, BUS_DMA_NOWAIT);
1817 if (error != 0)
ffd7c74a 1818 goto fail;
da10ea93
MD
1819
1820 bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE);
ffd7c74a
JT
1821
1822 if (kvap != NULL)
1823 *kvap = dma->vaddr;
da10ea93 1824
ffd7c74a 1825 return 0;
da10ea93
MD
1826
1827fail: iwn_dma_contig_free(dma);
ffd7c74a
JT
1828 return error;
1829}
1830
1831static void
1832iwn_dma_contig_free(struct iwn_dma_info *dma)
1833{
fd49669c
MN
1834 if (dma->vaddr != NULL) {
1835 bus_dmamap_sync(dma->tag, dma->map,
1836 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1837 bus_dmamap_unload(dma->tag, dma->map);
1838 bus_dmamem_free(dma->tag, dma->vaddr, dma->map);
1839 dma->vaddr = NULL;
da10ea93
MD
1840 }
1841 if (dma->tag != NULL) {
ffd7c74a 1842 bus_dma_tag_destroy(dma->tag);
da10ea93 1843 dma->tag = NULL;
ffd7c74a
JT
1844 }
1845}
1846
1847static int
1848iwn_alloc_sched(struct iwn_softc *sc)
1849{
1850 /* TX scheduler rings must be aligned on a 1KB boundary. */
da10ea93
MD
1851 return iwn_dma_contig_alloc(sc, &sc->sched_dma, (void **)&sc->sched,
1852 sc->schedsz, 1024);
ffd7c74a
JT
1853}
1854
1855static void
1856iwn_free_sched(struct iwn_softc *sc)
1857{
1858 iwn_dma_contig_free(&sc->sched_dma);
1859}
1860
1861static int
1862iwn_alloc_kw(struct iwn_softc *sc)
1863{
1864 /* "Keep Warm" page must be aligned on a 4KB boundary. */
da10ea93 1865 return iwn_dma_contig_alloc(sc, &sc->kw_dma, NULL, 4096, 4096);
ffd7c74a
JT
1866}
1867
1868static void
1869iwn_free_kw(struct iwn_softc *sc)
1870{
1871 iwn_dma_contig_free(&sc->kw_dma);
1872}
1873
1874static int
1875iwn_alloc_ict(struct iwn_softc *sc)
1876{
1877 /* ICT table must be aligned on a 4KB boundary. */
da10ea93
MD
1878 return iwn_dma_contig_alloc(sc, &sc->ict_dma, (void **)&sc->ict,
1879 IWN_ICT_SIZE, 4096);
ffd7c74a
JT
1880}
1881
1882static void
1883iwn_free_ict(struct iwn_softc *sc)
1884{
1885 iwn_dma_contig_free(&sc->ict_dma);
1886}
1887
1888static int
1889iwn_alloc_fwmem(struct iwn_softc *sc)
1890{
1891 /* Must be aligned on a 16-byte boundary. */
da10ea93 1892 return iwn_dma_contig_alloc(sc, &sc->fw_dma, NULL, sc->fwsz, 16);
ffd7c74a
JT
1893}
1894
1895static void
1896iwn_free_fwmem(struct iwn_softc *sc)
1897{
1898 iwn_dma_contig_free(&sc->fw_dma);
1899}
1900
1901static int
1902iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
1903{
1904 bus_size_t size;
1905 int i, error;
1906
1907 ring->cur = 0;
1908
da10ea93
MD
1909 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
1910
ffd7c74a
JT
1911 /* Allocate RX descriptors (256-byte aligned). */
1912 size = IWN_RX_RING_COUNT * sizeof (uint32_t);
da10ea93
MD
1913 error = iwn_dma_contig_alloc(sc, &ring->desc_dma, (void **)&ring->desc,
1914 size, 256);
ffd7c74a
JT
1915 if (error != 0) {
1916 device_printf(sc->sc_dev,
da10ea93 1917 "%s: could not allocate RX ring DMA memory, error %d\n",
ffd7c74a
JT
1918 __func__, error);
1919 goto fail;
1920 }
1921
da10ea93
MD
1922 /* Allocate RX status area (16-byte aligned). */
1923 error = iwn_dma_contig_alloc(sc, &ring->stat_dma, (void **)&ring->stat,
1924 sizeof (struct iwn_rx_status), 16);
ffd7c74a
JT
1925 if (error != 0) {
1926 device_printf(sc->sc_dev,
da10ea93 1927 "%s: could not allocate RX status DMA memory, error %d\n",
ffd7c74a
JT
1928 __func__, error);
1929 goto fail;
1930 }
1931
da10ea93 1932 /* Create RX buffer DMA tag. */
05538f72 1933#if defined(__DragonFly__)
977fc0db
MD
1934 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
1935 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1936 IWN_RBUF_SIZE, 1, IWN_RBUF_SIZE, 0, &ring->data_dmat);
05538f72
MD
1937#else
1938 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
da10ea93 1939 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
977fc0db 1940 IWN_RBUF_SIZE, 1, IWN_RBUF_SIZE, 0, NULL, NULL, &ring->data_dmat);
05538f72 1941#endif
ffd7c74a
JT
1942 if (error != 0) {
1943 device_printf(sc->sc_dev,
da10ea93 1944 "%s: could not create RX buf DMA tag, error %d\n",
ffd7c74a
JT
1945 __func__, error);
1946 goto fail;
1947 }
1948
1949 /*
1950 * Allocate and map RX buffers.
1951 */
1952 for (i = 0; i < IWN_RX_RING_COUNT; i++) {
1953 struct iwn_rx_data *data = &ring->data[i];
1954 bus_addr_t paddr;
1955
1956 error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
1957 if (error != 0) {
1958 device_printf(sc->sc_dev,
da10ea93 1959 "%s: could not create RX buf DMA map, error %d\n",
ffd7c74a
JT
1960 __func__, error);
1961 goto fail;
1962 }
1963
b5523eac 1964 data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
977fc0db 1965 IWN_RBUF_SIZE);
ffd7c74a
JT
1966 if (data->m == NULL) {
1967 device_printf(sc->sc_dev,
da10ea93
MD
1968 "%s: could not allocate RX mbuf\n", __func__);
1969 error = ENOBUFS;
ffd7c74a
JT
1970 goto fail;
1971 }
1972
ffd7c74a 1973 error = bus_dmamap_load(ring->data_dmat, data->map,
da10ea93
MD
1974 mtod(data->m, void *), IWN_RBUF_SIZE, iwn_dma_map_addr,
1975 &paddr, BUS_DMA_NOWAIT);
ffd7c74a
JT
1976 if (error != 0 && error != EFBIG) {
1977 device_printf(sc->sc_dev,
977fc0db 1978 "%s: can't map mbuf, error %d\n", __func__,
da10ea93 1979 error);
ffd7c74a
JT
1980 goto fail;
1981 }
ffd7c74a
JT
1982
1983 /* Set physical address of RX buffer (256-byte aligned). */
1984 ring->desc[i] = htole32(paddr >> 8);
1985 }
da10ea93 1986
ffd7c74a
JT
1987 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
1988 BUS_DMASYNC_PREWRITE);
da10ea93
MD
1989
1990 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
1991
ffd7c74a 1992 return 0;
da10ea93
MD
1993
1994fail: iwn_free_rx_ring(sc, ring);
1995
1996 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
1997
ffd7c74a
JT
1998 return error;
1999}
2000
2001static void
2002iwn_reset_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
2003{
2004 int ntries;
2005
da10ea93
MD
2006 DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
2007
ffd7c74a
JT
2008 if (iwn_nic_lock(sc) == 0) {
2009 IWN_WRITE(sc, IWN_FH_RX_CONFIG, 0);
2010 for (ntries = 0; ntries < 1000; ntries++) {
2011 if (IWN_READ(sc, IWN_FH_RX_STATUS) &
2012 IWN_FH_RX_STATUS_IDLE)
2013 break;
2014 DELAY(10);
2015 }
2016 iwn_nic_unlock(sc);
ffd7c74a
JT
2017 }
2018 ring->cur = 0;
2019 sc->last_rx_valid = 0;
2020}
2021
2022static void
2023iwn_free_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
2024{
2025 int i;
2026
da10ea93
MD
2027 DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s \n", __func__);
2028
ffd7c74a
JT
2029 iwn_dma_contig_free(&ring->desc_dma);
2030 iwn_dma_contig_free(&ring->stat_dma);
2031
2032 for (i = 0; i < IWN_RX_RING_COUNT; i++) {
2033 struct iwn_rx_data *data = &ring->data[i];
2034
2035 if (data->m != NULL) {
2036 bus_dmamap_sync(ring->data_dmat, data->map,
2037 BUS_DMASYNC_POSTREAD);
2038 bus_dmamap_unload(ring->data_dmat, data->map);
2039 m_freem(data->m);
da10ea93 2040 data->m = NULL;
ffd7c74a
JT
2041 }
2042 if (data->map != NULL)
2043 bus_dmamap_destroy(ring->data_dmat, data->map);
2044 }
da10ea93
MD
2045 if (ring->data_dmat != NULL) {
2046 bus_dma_tag_destroy(ring->data_dmat);
2047 ring->data_dmat = NULL;
2048 }
ffd7c74a
JT
2049}
2050
2051static int
2052iwn_alloc_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring, int qid)
2053{
ffd7c74a 2054 bus_addr_t paddr;
da10ea93 2055 bus_size_t size;
ffd7c74a
JT
2056 int i, error;
2057
2058 ring->qid = qid;
2059 ring->queued = 0;
2060 ring->cur = 0;
2061
da10ea93
MD
2062 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
2063
2064 /* Allocate TX descriptors (256-byte aligned). */
2065 size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_desc);
2066 error = iwn_dma_contig_alloc(sc, &ring->desc_dma, (void **)&ring->desc,
2067 size, 256);
ffd7c74a
JT
2068 if (error != 0) {
2069 device_printf(sc->sc_dev,
2070 "%s: could not allocate TX ring DMA memory, error %d\n",
2071 __func__, error);
2072 goto fail;
2073 }
2074
da10ea93
MD
2075 size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_cmd);
2076 error = iwn_dma_contig_alloc(sc, &ring->cmd_dma, (void **)&ring->cmd,
2077 size, 4);
ffd7c74a
JT
2078 if (error != 0) {
2079 device_printf(sc->sc_dev,
2080 "%s: could not allocate TX cmd DMA memory, error %d\n",
2081 __func__, error);
2082 goto fail;
2083 }
2084
05538f72 2085#if defined(__DragonFly__)
977fc0db
MD
2086 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
2087 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
2088 IWN_MAX_SCATTER - 1, MCLBYTES, 0, &ring->data_dmat);
05538f72
MD
2089#else
2090 error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
da10ea93 2091 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
977fc0db 2092 IWN_MAX_SCATTER - 1, MCLBYTES, 0, NULL, NULL, &ring->data_dmat);
05538f72 2093#endif
ffd7c74a
JT
2094 if (error != 0) {
2095 device_printf(sc->sc_dev,
da10ea93 2096 "%s: could not create TX buf DMA tag, error %d\n",
ffd7c74a
JT
2097 __func__, error);
2098 goto fail;
2099 }
2100
2101 paddr = ring->cmd_dma.paddr;
2102 for (i = 0; i < IWN_TX_RING_COUNT; i++) {
2103 struct iwn_tx_data *data = &ring->data[i];
2104
2105 data->cmd_paddr = paddr;
2106 data->scratch_paddr = paddr + 12;
2107 paddr += sizeof (struct iwn_tx_cmd);
2108
2109 error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
2110 if (error != 0) {
2111 device_printf(sc->sc_dev,
da10ea93 2112 "%s: could not create TX buf DMA map, error %d\n",
ffd7c74a
JT
2113 __func__, error);
2114 goto fail;
2115 }
ffd7c74a 2116 }
da10ea93
MD
2117
2118 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
2119
ffd7c74a 2120 return 0;
da10ea93
MD
2121
2122fail: iwn_free_tx_ring(sc, ring);
2123 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
ffd7c74a
JT
2124 return error;
2125}
2126
2127static void
2128iwn_reset_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)
2129{
2130 int i;
2131
da10ea93
MD
2132 DPRINTF(sc, IWN_DEBUG_TRACE, "->doing %s \n", __func__);
2133
ffd7c74a
JT
2134 for (i = 0; i < IWN_TX_RING_COUNT; i++) {
2135 struct iwn_tx_data *data = &ring->data[i];
2136
2137 if (data->m != NULL) {
da10ea93
MD
2138 bus_dmamap_sync(ring->data_dmat, data->map,
2139 BUS_DMASYNC_POSTWRITE);
ffd7c74a
JT
2140 bus_dmamap_unload(ring->data_dmat, data->map);
2141 m_freem(data->m);
2142 data->m = NULL;
2143 }
977fc0db
MD
2144 if (data->ni != NULL) {
2145 ieee80211_free_node(data->ni);
2146 data->ni = NULL;
2147 }
ffd7c74a
JT
2148 }
2149 /* Clear TX descriptors. */
2150 memset(ring->desc, 0, ring->desc_dma.size);
2151 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
2152 BUS_DMASYNC_PREWRITE);
2153 sc->qfullmsk &= ~(1 << ring->qid);
2154 ring->queued = 0;
2155 ring->cur = 0;
2156}
2157
2158static void
2159iwn_free_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)
2160{
2161 int i;
2162
da10ea93
MD
2163 DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s \n", __func__);
2164
ffd7c74a
JT
2165 iwn_dma_contig_free(&ring->desc_dma);
2166 iwn_dma_contig_free(&ring->cmd_dma);
2167
2168 for (i = 0; i < IWN_TX_RING_COUNT; i++) {
2169 struct iwn_tx_data *data = &ring->data[i];
2170
2171 if (data->m != NULL) {
2172 bus_dmamap_sync(ring->data_dmat, data->map,
2173 BUS_DMASYNC_POSTWRITE);
2174 bus_dmamap_unload(ring->data_dmat, data->map);
2175 m_freem(data->m);
2176 }
2177 if (data->map != NULL)
2178 bus_dmamap_destroy(ring->data_dmat, data->map);
2179 }
da10ea93
MD
2180 if (ring->data_dmat != NULL) {
2181 bus_dma_tag_destroy(ring->data_dmat);
2182 ring->data_dmat = NULL;
2183 }
ffd7c74a
JT
2184}
2185
2186static void
2187iwn5000_ict_reset(struct iwn_softc *sc)
2188{
2189 /* Disable interrupts. */
2190 IWN_WRITE(sc, IWN_INT_MASK, 0);
2191
2192 /* Reset ICT table. */
2193 memset(sc->ict, 0, IWN_ICT_SIZE);
2194 sc->ict_cur = 0;
2195
da10ea93 2196 /* Set physical address of ICT table (4KB aligned). */
ffd7c74a
JT
2197 DPRINTF(sc, IWN_DEBUG_RESET, "%s: enabling ICT\n", __func__);
2198 IWN_WRITE(sc, IWN_DRAM_INT_TBL, IWN_DRAM_INT_TBL_ENABLE |
2199 IWN_DRAM_INT_TBL_WRAP_CHECK | sc->ict_dma.paddr >> 12);
2200
2201 /* Enable periodic RX interrupt. */
2202 sc->int_mask |= IWN_INT_RX_PERIODIC;
2203 /* Switch to ICT interrupt mode in driver. */
2204 sc->sc_flags |= IWN_FLAG_USE_ICT;
2205
2206 /* Re-enable interrupts. */
2207 IWN_WRITE(sc, IWN_INT, 0xffffffff);
2208 IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
2209}
2210
2211static int
2212iwn_read_eeprom(struct iwn_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
2213{
da10ea93 2214 struct iwn_ops *ops = &sc->ops;
ffd7c74a 2215 uint16_t val;
da10ea93
MD
2216 int error;
2217
2218 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a
JT
2219
2220 /* Check whether adapter has an EEPROM or an OTPROM. */
2221 if (sc->hw_type >= IWN_HW_REV_TYPE_1000 &&
2222 (IWN_READ(sc, IWN_OTP_GP) & IWN_OTP_GP_DEV_SEL_OTP))
2223 sc->sc_flags |= IWN_FLAG_HAS_OTPROM;
2224 DPRINTF(sc, IWN_DEBUG_RESET, "%s found\n",
2225 (sc->sc_flags & IWN_FLAG_HAS_OTPROM) ? "OTPROM" : "EEPROM");
2226
2227 /* Adapter has to be powered on for EEPROM access to work. */
da10ea93 2228 if ((error = iwn_apm_init(sc)) != 0) {
ffd7c74a 2229 device_printf(sc->sc_dev,
da10ea93
MD
2230 "%s: could not power ON adapter, error %d\n", __func__,
2231 error);
ffd7c74a
JT
2232 return error;
2233 }
2234
2235 if ((IWN_READ(sc, IWN_EEPROM_GP) & 0x7) == 0) {
2236 device_printf(sc->sc_dev, "%s: bad ROM signature\n", __func__);
2237 return EIO;
2238 }
da10ea93
MD
2239 if ((error = iwn_eeprom_lock(sc)) != 0) {
2240 device_printf(sc->sc_dev, "%s: could not lock ROM, error %d\n",
ffd7c74a
JT
2241 __func__, error);
2242 return error;
2243 }
ffd7c74a 2244 if (sc->sc_flags & IWN_FLAG_HAS_OTPROM) {
da10ea93 2245 if ((error = iwn_init_otprom(sc)) != 0) {
ffd7c74a
JT
2246 device_printf(sc->sc_dev,
2247 "%s: could not initialize OTPROM, error %d\n",
2248 __func__, error);
2249 return error;
2250 }
2251 }
2252
da10ea93
MD
2253 iwn_read_prom_data(sc, IWN_EEPROM_SKU_CAP, &val, 2);
2254 DPRINTF(sc, IWN_DEBUG_RESET, "SKU capabilities=0x%04x\n", le16toh(val));
2255 /* Check if HT support is bonded out. */
2256 if (val & htole16(IWN_EEPROM_SKU_CAP_11N))
2257 sc->sc_flags |= IWN_FLAG_HAS_11N;
2258
ffd7c74a
JT
2259 iwn_read_prom_data(sc, IWN_EEPROM_RFCFG, &val, 2);
2260 sc->rfcfg = le16toh(val);
2261 DPRINTF(sc, IWN_DEBUG_RESET, "radio config=0x%04x\n", sc->rfcfg);
da10ea93
MD
2262 /* Read Tx/Rx chains from ROM unless it's known to be broken. */
2263 if (sc->txchainmask == 0)
2264 sc->txchainmask = IWN_RFCFG_TXANTMSK(sc->rfcfg);
2265 if (sc->rxchainmask == 0)
2266 sc->rxchainmask = IWN_RFCFG_RXANTMSK(sc->rfcfg);
ffd7c74a
JT
2267
2268 /* Read MAC address. */
2269 iwn_read_prom_data(sc, IWN_EEPROM_MAC, macaddr, 6);
2270
2271 /* Read adapter-specific information from EEPROM. */
da10ea93 2272 ops->read_eeprom(sc);
ffd7c74a
JT
2273
2274 iwn_apm_stop(sc); /* Power OFF adapter. */
2275
2276 iwn_eeprom_unlock(sc);
da10ea93
MD
2277
2278 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
2279
ffd7c74a
JT
2280 return 0;
2281}
2282
2283static void
2284iwn4965_read_eeprom(struct iwn_softc *sc)
2285{
2286 uint32_t addr;
ffd7c74a 2287 uint16_t val;
da10ea93 2288 int i;
ffd7c74a 2289
da10ea93
MD
2290 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
2291
2292 /* Read regulatory domain (4 ASCII characters). */
ffd7c74a
JT
2293 iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4);
2294
977fc0db 2295 /* Read the list of authorized channels (20MHz & 40MHz). */
da10ea93 2296 for (i = 0; i < IWN_NBANDS - 1; i++) {
ffd7c74a
JT
2297 addr = iwn4965_regulatory_bands[i];
2298 iwn_read_eeprom_channels(sc, i, addr);
2299 }
2300
2301 /* Read maximum allowed TX power for 2GHz and 5GHz bands. */
2302 iwn_read_prom_data(sc, IWN4965_EEPROM_MAXPOW, &val, 2);
2303 sc->maxpwr2GHz = val & 0xff;
2304 sc->maxpwr5GHz = val >> 8;
2305 /* Check that EEPROM values are within valid range. */
2306 if (sc->maxpwr5GHz < 20 || sc->maxpwr5GHz > 50)
2307 sc->maxpwr5GHz = 38;
2308 if (sc->maxpwr2GHz < 20 || sc->maxpwr2GHz > 50)
2309 sc->maxpwr2GHz = 38;
2310 DPRINTF(sc, IWN_DEBUG_RESET, "maxpwr 2GHz=%d 5GHz=%d\n",
2311 sc->maxpwr2GHz, sc->maxpwr5GHz);
2312
2313 /* Read samples for each TX power group. */
2314 iwn_read_prom_data(sc, IWN4965_EEPROM_BANDS, sc->bands,
2315 sizeof sc->bands);
2316
2317 /* Read voltage at which samples were taken. */
2318 iwn_read_prom_data(sc, IWN4965_EEPROM_VOLTAGE, &val, 2);
2319 sc->eeprom_voltage = (int16_t)le16toh(val);
2320 DPRINTF(sc, IWN_DEBUG_RESET, "voltage=%d (in 0.3V)\n",
2321 sc->eeprom_voltage);
2322
2323#ifdef IWN_DEBUG
2324 /* Print samples. */
2325 if (sc->sc_debug & IWN_DEBUG_ANY) {
da10ea93 2326 for (i = 0; i < IWN_NBANDS - 1; i++)
ffd7c74a
JT
2327 iwn4965_print_power_group(sc, i);
2328 }
2329#endif
da10ea93
MD
2330
2331 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
ffd7c74a
JT
2332}
2333
2334#ifdef IWN_DEBUG
2335static void
2336iwn4965_print_power_group(struct iwn_softc *sc, int i)
2337{
2338 struct iwn4965_eeprom_band *band = &sc->bands[i];
2339 struct iwn4965_eeprom_chan_samples *chans = band->chans;
2340 int j, c;
2341
101554a6
MD
2342 kprintf("===band %d===\n", i);
2343 kprintf("chan lo=%d, chan hi=%d\n", band->lo, band->hi);
2344 kprintf("chan1 num=%d\n", chans[0].num);
ffd7c74a
JT
2345 for (c = 0; c < 2; c++) {
2346 for (j = 0; j < IWN_NSAMPLES; j++) {
101554a6 2347 kprintf("chain %d, sample %d: temp=%d gain=%d "
ffd7c74a
JT
2348 "power=%d pa_det=%d\n", c, j,
2349 chans[0].samples[c][j].temp,
2350 chans[0].samples[c][j].gain,
2351 chans[0].samples[c][j].power,
2352 chans[0].samples[c][j].pa_det);
2353 }
2354 }
101554a6 2355 kprintf("chan2 num=%d\n", chans[1].num);
ffd7c74a
JT
2356 for (c = 0; c < 2; c++) {
2357 for (j = 0; j < IWN_NSAMPLES; j++) {
101554a6 2358 kprintf("chain %d, sample %d: temp=%d gain=%d "
ffd7c74a
JT
2359 "power=%d pa_det=%d\n", c, j,
2360 chans[1].samples[c][j].temp,
2361 chans[1].samples[c][j].gain,
2362 chans[1].samples[c][j].power,
2363 chans[1].samples[c][j].pa_det);
2364 }
2365 }
2366}
2367#endif
2368
2369static void
2370iwn5000_read_eeprom(struct iwn_softc *sc)
2371{
2372 struct iwn5000_eeprom_calib_hdr hdr;
da10ea93
MD
2373 int32_t volt;
2374 uint32_t base, addr;
ffd7c74a 2375 uint16_t val;
da10ea93
MD
2376 int i;
2377
2378 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a 2379
da10ea93 2380 /* Read regulatory domain (4 ASCII characters). */
ffd7c74a
JT
2381 iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
2382 base = le16toh(val);
2383 iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN,
2384 sc->eeprom_domain, 4);
2385
977fc0db 2386 /* Read the list of authorized channels (20MHz & 40MHz). */
da10ea93
MD
2387 for (i = 0; i < IWN_NBANDS - 1; i++) {
2388 addr = base + sc->base_params->regulatory_bands[i];
ffd7c74a
JT
2389 iwn_read_eeprom_channels(sc, i, addr);
2390 }
2391
2392 /* Read enhanced TX power information for 6000 Series. */
da10ea93 2393 if (sc->base_params->enhanced_TX_power)
ffd7c74a
JT
2394 iwn_read_eeprom_enhinfo(sc);
2395
2396 iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2);
2397 base = le16toh(val);
2398 iwn_read_prom_data(sc, base, &hdr, sizeof hdr);
2399 DPRINTF(sc, IWN_DEBUG_CALIBRATE,
da10ea93
MD
2400 "%s: calib version=%u pa type=%u voltage=%u\n", __func__,
2401 hdr.version, hdr.pa_type, le16toh(hdr.volt));
2402 sc->calib_ver = hdr.version;
2403
2404 if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TEMP_OFFSETv2) {
2405 sc->eeprom_voltage = le16toh(hdr.volt);
2406 iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
2407 sc->eeprom_temp_high=le16toh(val);
2408 iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);
2409 sc->eeprom_temp = le16toh(val);
2410 }
ffd7c74a
JT
2411
2412 if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
2413 /* Compute temperature offset. */
2414 iwn_read_prom_data(sc, base + IWN5000_EEPROM_TEMP, &val, 2);
da10ea93 2415 sc->eeprom_temp = le16toh(val);
ffd7c74a
JT
2416 iwn_read_prom_data(sc, base + IWN5000_EEPROM_VOLT, &val, 2);
2417 volt = le16toh(val);
da10ea93 2418 sc->temp_off = sc->eeprom_temp - (volt / -5);
ffd7c74a 2419 DPRINTF(sc, IWN_DEBUG_CALIBRATE, "temp=%d volt=%d offset=%dK\n",
da10ea93 2420 sc->eeprom_temp, volt, sc->temp_off);
ffd7c74a
JT
2421 } else {
2422 /* Read crystal calibration. */
2423 iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL,
2424 &sc->eeprom_crystal, sizeof (uint32_t));
2425 DPRINTF(sc, IWN_DEBUG_CALIBRATE, "crystal calibration 0x%08x\n",
da10ea93 2426 le32toh(sc->eeprom_crystal));
ffd7c74a 2427 }
da10ea93
MD
2428
2429 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
2430
ffd7c74a
JT
2431}
2432
2433/*
2434 * Translate EEPROM flags to net80211.
2435 */
2436static uint32_t
2437iwn_eeprom_channel_flags(struct iwn_eeprom_chan *channel)
2438{
2439 uint32_t nflags;
2440
2441 nflags = 0;
2442 if ((channel->flags & IWN_EEPROM_CHAN_ACTIVE) == 0)
2443 nflags |= IEEE80211_CHAN_PASSIVE;
2444 if ((channel->flags & IWN_EEPROM_CHAN_IBSS) == 0)
2445 nflags |= IEEE80211_CHAN_NOADHOC;
2446 if (channel->flags & IWN_EEPROM_CHAN_RADAR) {
2447 nflags |= IEEE80211_CHAN_DFS;
2448 /* XXX apparently IBSS may still be marked */
2449 nflags |= IEEE80211_CHAN_NOADHOC;
2450 }
2451
2452 return nflags;
2453}
2454
2455static void
977fc0db
MD
2456iwn_read_eeprom_band(struct iwn_softc *sc, int n, int maxchans, int *nchans,
2457 struct ieee80211_channel chans[])
ffd7c74a 2458{
ffd7c74a
JT
2459 struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
2460 const struct iwn_chan_band *band = &iwn_bands[n];
977fc0db 2461 uint8_t bands[IEEE80211_MODE_BYTES];
da10ea93 2462 uint8_t chan;
977fc0db 2463 int i, error, nflags;
da10ea93
MD
2464
2465 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a 2466
977fc0db
MD
2467 memset(bands, 0, sizeof(bands));
2468 if (n == 0) {
2469 setbit(bands, IEEE80211_MODE_11B);
2470 setbit(bands, IEEE80211_MODE_11G);
2471 if (sc->sc_flags & IWN_FLAG_HAS_11N)
2472 setbit(bands, IEEE80211_MODE_11NG);
2473 } else {
2474 setbit(bands, IEEE80211_MODE_11A);
2475 if (sc->sc_flags & IWN_FLAG_HAS_11N)
2476 setbit(bands, IEEE80211_MODE_11NA);
2477 }
2478
ffd7c74a
JT
2479 for (i = 0; i < band->nchan; i++) {
2480 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) {
2481 DPRINTF(sc, IWN_DEBUG_RESET,
2482 "skip chan %d flags 0x%x maxpwr %d\n",
2483 band->chan[i], channels[i].flags,
2484 channels[i].maxpwr);
2485 continue;
2486 }
977fc0db 2487
ffd7c74a
JT
2488 chan = band->chan[i];
2489 nflags = iwn_eeprom_channel_flags(&channels[i]);
977fc0db
MD
2490 error = ieee80211_add_channel(chans, maxchans, nchans,
2491 chan, 0, channels[i].maxpwr, nflags, bands);
2492 if (error != 0)
2493 break;
da10ea93
MD
2494
2495 /* Save maximum allowed TX power for this channel. */
977fc0db 2496 /* XXX wrong */
da10ea93
MD
2497 sc->maxpwr[chan] = channels[i].maxpwr;
2498
2499 DPRINTF(sc, IWN_DEBUG_RESET,
2500 "add chan %d flags 0x%x maxpwr %d\n", chan,
2501 channels[i].flags, channels[i].maxpwr);
ffd7c74a 2502 }
da10ea93
MD
2503
2504 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
2505
ffd7c74a
JT
2506}
2507
ffd7c74a 2508static void
977fc0db
MD
2509iwn_read_eeprom_ht40(struct iwn_softc *sc, int n, int maxchans, int *nchans,
2510 struct ieee80211_channel chans[])
ffd7c74a 2511{
ffd7c74a
JT
2512 struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
2513 const struct iwn_chan_band *band = &iwn_bands[n];
da10ea93 2514 uint8_t chan;
977fc0db 2515 int i, error, nflags;
da10ea93
MD
2516
2517 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s start\n", __func__);
2518
2519 if (!(sc->sc_flags & IWN_FLAG_HAS_11N)) {
2520 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end no 11n\n", __func__);
2521 return;
2522 }
ffd7c74a
JT
2523
2524 for (i = 0; i < band->nchan; i++) {
da10ea93 2525 if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID)) {
ffd7c74a
JT
2526 DPRINTF(sc, IWN_DEBUG_RESET,
2527 "skip chan %d flags 0x%x maxpwr %d\n",
2528 band->chan[i], channels[i].flags,
2529 channels[i].maxpwr);
2530 continue;
2531 }
977fc0db 2532
da10ea93
MD
2533 chan = band->chan[i];
2534 nflags = iwn_eeprom_channel_flags(&channels[i]);
977fc0db
MD
2535 nflags |= (n == 5 ? IEEE80211_CHAN_G : IEEE80211_CHAN_A);
2536 error = ieee80211_add_channel_ht40(chans, maxchans, nchans,
2537 chan, channels[i].maxpwr, nflags);
2538 switch (error) {
2539 case EINVAL:
ffd7c74a 2540 device_printf(sc->sc_dev,
da10ea93 2541 "%s: no entry for channel %d\n", __func__, chan);
ffd7c74a 2542 continue;
977fc0db 2543 case ENOENT:
ffd7c74a 2544 DPRINTF(sc, IWN_DEBUG_RESET,
da10ea93
MD
2545 "%s: skip chan %d, extension channel not found\n",
2546 __func__, chan);
ffd7c74a 2547 continue;
977fc0db
MD
2548 case ENOBUFS:
2549 device_printf(sc->sc_dev,
2550 "%s: channel table is full!\n", __func__);
2551 break;
2552 case 0:
2553 DPRINTF(sc, IWN_DEBUG_RESET,
2554 "add ht40 chan %d flags 0x%x maxpwr %d\n",
2555 chan, channels[i].flags, channels[i].maxpwr);
2556 /* FALLTHROUGH */
2557 default:
2558 break;
ffd7c74a 2559 }
ffd7c74a 2560 }
da10ea93
MD
2561
2562 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
2563
ffd7c74a 2564}
ffd7c74a
JT
2565
2566static void
2567iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
2568{
977fc0db 2569 struct ieee80211com *ic = &sc->sc_ic;
ffd7c74a
JT
2570
2571 iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
2572 iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
2573
977fc0db
MD
2574 if (n < 5) {
2575 iwn_read_eeprom_band(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans,
2576 ic->ic_channels);
2577 } else {
2578 iwn_read_eeprom_ht40(sc, n, IEEE80211_CHAN_MAX, &ic->ic_nchans,
2579 ic->ic_channels);
2580 }
ffd7c74a
JT
2581 ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
2582}
2583
da10ea93
MD
2584static struct iwn_eeprom_chan *
2585iwn_find_eeprom_channel(struct iwn_softc *sc, struct ieee80211_channel *c)
2586{
2587 int band, chan, i, j;
2588
2589 if (IEEE80211_IS_CHAN_HT40(c)) {
2590 band = IEEE80211_IS_CHAN_5GHZ(c) ? 6 : 5;
2591 if (IEEE80211_IS_CHAN_HT40D(c))
2592 chan = c->ic_extieee;
2593 else
2594 chan = c->ic_ieee;
2595 for (i = 0; i < iwn_bands[band].nchan; i++) {
2596 if (iwn_bands[band].chan[i] == chan)
2597 return &sc->eeprom_channels[band][i];
2598 }
2599 } else {
2600 for (j = 0; j < 5; j++) {
2601 for (i = 0; i < iwn_bands[j].nchan; i++) {
977fc0db
MD
2602 if (iwn_bands[j].chan[i] == c->ic_ieee &&
2603 ((j == 0) ^ IEEE80211_IS_CHAN_A(c)) == 1)
da10ea93
MD
2604 return &sc->eeprom_channels[j][i];
2605 }
2606 }
2607 }
2608 return NULL;
2609}
2610
977fc0db
MD
2611static void
2612iwn_getradiocaps(struct ieee80211com *ic,
2613 int maxchans, int *nchans, struct ieee80211_channel chans[])
2614{
2615 struct iwn_softc *sc = ic->ic_softc;
2616 int i;
2617
2618 /* Parse the list of authorized channels. */
2619 for (i = 0; i < 5 && *nchans < maxchans; i++)
2620 iwn_read_eeprom_band(sc, i, maxchans, nchans, chans);
2621 for (i = 5; i < IWN_NBANDS - 1 && *nchans < maxchans; i++)
2622 iwn_read_eeprom_ht40(sc, i, maxchans, nchans, chans);
2623}
2624
da10ea93
MD
2625/*
2626 * Enforce flags read from EEPROM.
2627 */
2628static int
2629iwn_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
2630 int nchan, struct ieee80211_channel chans[])
2631{
4f1aaf2f 2632 struct iwn_softc *sc = ic->ic_softc;
da10ea93
MD
2633 int i;
2634
2635 for (i = 0; i < nchan; i++) {
2636 struct ieee80211_channel *c = &chans[i];
2637 struct iwn_eeprom_chan *channel;
2638
2639 channel = iwn_find_eeprom_channel(sc, c);
2640 if (channel == NULL) {
977fc0db 2641 ic_printf(ic, "%s: invalid channel %u freq %u/0x%x\n",
da10ea93
MD
2642 __func__, c->ic_ieee, c->ic_freq, c->ic_flags);
2643 return EINVAL;
2644 }
2645 c->ic_flags |= iwn_eeprom_channel_flags(channel);
2646 }
2647
2648 return 0;
2649}
2650
ffd7c74a
JT
2651static void
2652iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
2653{
2654 struct iwn_eeprom_enhinfo enhinfo[35];
977fc0db 2655 struct ieee80211com *ic = &sc->sc_ic;
da10ea93 2656 struct ieee80211_channel *c;
ffd7c74a
JT
2657 uint16_t val, base;
2658 int8_t maxpwr;
da10ea93
MD
2659 uint8_t flags;
2660 int i, j;
2661
2662 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a
JT
2663
2664 iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
2665 base = le16toh(val);
2666 iwn_read_prom_data(sc, base + IWN6000_EEPROM_ENHINFO,
2667 enhinfo, sizeof enhinfo);
2668
da10ea93
MD
2669 for (i = 0; i < nitems(enhinfo); i++) {
2670 flags = enhinfo[i].flags;
2671 if (!(flags & IWN_ENHINFO_VALID))
ffd7c74a
JT
2672 continue; /* Skip invalid entries. */
2673
2674 maxpwr = 0;
2675 if (sc->txchainmask & IWN_ANT_A)
2676 maxpwr = MAX(maxpwr, enhinfo[i].chain[0]);
2677 if (sc->txchainmask & IWN_ANT_B)
2678 maxpwr = MAX(maxpwr, enhinfo[i].chain[1]);
2679 if (sc->txchainmask & IWN_ANT_C)
2680 maxpwr = MAX(maxpwr, enhinfo[i].chain[2]);
2681 if (sc->ntxchains == 2)
2682 maxpwr = MAX(maxpwr, enhinfo[i].mimo2);
2683 else if (sc->ntxchains == 3)
2684 maxpwr = MAX(maxpwr, enhinfo[i].mimo3);
ffd7c74a 2685
da10ea93
MD
2686 for (j = 0; j < ic->ic_nchans; j++) {
2687 c = &ic->ic_channels[j];
2688 if ((flags & IWN_ENHINFO_5GHZ)) {
2689 if (!IEEE80211_IS_CHAN_A(c))
2690 continue;
2691 } else if ((flags & IWN_ENHINFO_OFDM)) {
2692 if (!IEEE80211_IS_CHAN_G(c))
2693 continue;
2694 } else if (!IEEE80211_IS_CHAN_B(c))
2695 continue;
2696 if ((flags & IWN_ENHINFO_HT40)) {
2697 if (!IEEE80211_IS_CHAN_HT40(c))
2698 continue;
2699 } else {
2700 if (IEEE80211_IS_CHAN_HT40(c))
2701 continue;
2702 }
2703 if (enhinfo[i].chan != 0 &&
2704 enhinfo[i].chan != c->ic_ieee)
2705 continue;
2706
2707 DPRINTF(sc, IWN_DEBUG_RESET,
2708 "channel %d(%x), maxpwr %d\n", c->ic_ieee,
2709 c->ic_flags, maxpwr / 2);
2710 c->ic_maxregpower = maxpwr / 2;
2711 c->ic_maxpower = maxpwr;
2712 }
ffd7c74a 2713 }
da10ea93
MD
2714
2715 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end\n", __func__);
2716
ffd7c74a
JT
2717}
2718
2719static struct ieee80211_node *
2720iwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
2721{
977fc0db
MD
2722 return kmalloc(sizeof (struct iwn_node), M_80211_NODE,
2723 M_INTWAIT | M_ZERO);
da10ea93
MD
2724}
2725
2726static __inline int
2727rate2plcp(int rate)
2728{
2729 switch (rate & 0xff) {
2730 case 12: return 0xd;
2731 case 18: return 0xf;
2732 case 24: return 0x5;
2733 case 36: return 0x7;
2734 case 48: return 0x9;
2735 case 72: return 0xb;
2736 case 96: return 0x1;
2737 case 108: return 0x3;
2738 case 2: return 10;
2739 case 4: return 20;
2740 case 11: return 55;
2741 case 22: return 110;
2742 }
2743 return 0;
2744}
2745
05538f72
MD
2746static int
2747iwn_get_1stream_tx_antmask(struct iwn_softc *sc)
2748{
2749
2750 return IWN_LSB(sc->txchainmask);
2751}
2752
2753static int
2754iwn_get_2stream_tx_antmask(struct iwn_softc *sc)
2755{
2756 int tx;
2757
2758 /*
2759 * The '2 stream' setup is a bit .. odd.
2760 *
2761 * For NICs that support only 1 antenna, default to IWN_ANT_AB or
2762 * the firmware panics (eg Intel 5100.)
2763 *
2764 * For NICs that support two antennas, we use ANT_AB.
2765 *
2766 * For NICs that support three antennas, we use the two that
2767 * wasn't the default one.
2768 *
2769 * XXX TODO: if bluetooth (full concurrent) is enabled, restrict
2770 * this to only one antenna.
2771 */
2772
2773 /* Default - transmit on the other antennas */
2774 tx = (sc->txchainmask & ~IWN_LSB(sc->txchainmask));
2775
2776 /* Now, if it's zero, set it to IWN_ANT_AB, so to not panic firmware */
2777 if (tx == 0)
2778 tx = IWN_ANT_AB;
2779
2780 /*
2781 * If the NIC is a two-stream TX NIC, configure the TX mask to
2782 * the default chainmask
2783 */
2784 else if (sc->ntxchains == 2)
2785 tx = sc->txchainmask;
2786
2787 return (tx);
2788}
2789
2790
2791
da10ea93
MD
2792/*
2793 * Calculate the required PLCP value from the given rate,
2794 * to the given node.
2795 *
2796 * This will take the node configuration (eg 11n, rate table
2797 * setup, etc) into consideration.
2798 */
2799static uint32_t
2800iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni,
2801 uint8_t rate)
2802{
da10ea93 2803 struct ieee80211com *ic = ni->ni_ic;
da10ea93
MD
2804 uint32_t plcp = 0;
2805 int ridx;
2806
da10ea93
MD
2807 /*
2808 * If it's an MCS rate, let's set the plcp correctly
2809 * and set the relevant flags based on the node config.
2810 */
2811 if (rate & IEEE80211_RATE_MCS) {
2812 /*
2813 * Set the initial PLCP value to be between 0->31 for
2814 * MCS 0 -> MCS 31, then set the "I'm an MCS rate!"
2815 * flag.
2816 */
977fc0db 2817 plcp = IEEE80211_RV(rate) | IWN_RFLAG_MCS;
da10ea93
MD
2818
2819 /*
2820 * XXX the following should only occur if both
2821 * the local configuration _and_ the remote node
2822 * advertise these capabilities. Thus this code
2823 * may need fixing!
2824 */
2825
2826 /*
2827 * Set the channel width and guard interval.
2828 */
2829 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
2830 plcp |= IWN_RFLAG_HT40;
2831 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
2832 plcp |= IWN_RFLAG_SGI;
2833 } else if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) {
2834 plcp |= IWN_RFLAG_SGI;
2835 }
2836
2837 /*
05538f72
MD
2838 * Ensure the selected rate matches the link quality
2839 * table entries being used.
da10ea93 2840 */
05538f72
MD
2841 if (rate > 0x8f)
2842 plcp |= IWN_RFLAG_ANT(sc->txchainmask);
2843 else if (rate > 0x87)
2844 plcp |= IWN_RFLAG_ANT(iwn_get_2stream_tx_antmask(sc));
da10ea93 2845 else
05538f72 2846 plcp |= IWN_RFLAG_ANT(iwn_get_1stream_tx_antmask(sc));
da10ea93
MD
2847 } else {
2848 /*
2849 * Set the initial PLCP - fine for both
2850 * OFDM and CCK rates.
2851 */
2852 plcp = rate2plcp(rate);
2853
2854 /* Set CCK flag if it's CCK */
2855
2856 /* XXX It would be nice to have a method
2857 * to map the ridx -> phy table entry
2858 * so we could just query that, rather than
2859 * this hack to check against IWN_RIDX_OFDM6.
2860 */
2861 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt,
2862 rate & IEEE80211_RATE_VAL);
2863 if (ridx < IWN_RIDX_OFDM6 &&
2864 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
2865 plcp |= IWN_RFLAG_CCK;
2866
2867 /* Set antenna configuration */
05538f72
MD
2868 /* XXX TODO: is this the right antenna to use for legacy? */
2869 plcp |= IWN_RFLAG_ANT(iwn_get_1stream_tx_antmask(sc));
da10ea93
MD
2870 }
2871
2872 DPRINTF(sc, IWN_DEBUG_TXRATE, "%s: rate=0x%02x, plcp=0x%08x\n",
2873 __func__,
2874 rate,
2875 plcp);
2876
2877 return (htole32(plcp));
ffd7c74a
JT
2878}
2879
2880static void
2881iwn_newassoc(struct ieee80211_node *ni, int isnew)
2882{
da10ea93 2883 /* Doesn't do anything at the moment */
ffd7c74a
JT
2884}
2885
2886static int
2887iwn_media_change(struct ifnet *ifp)
2888{
da10ea93
MD
2889 int error;
2890
2891 error = ieee80211_media_change(ifp);
ffd7c74a
JT
2892 /* NB: only the fixed rate can change and that doesn't need a reset */
2893 return (error == ENETRESET ? 0 : error);
2894}
2895
2896static int
2897iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
2898{
2899 struct iwn_vap *ivp = IWN_VAP(vap);
2900 struct ieee80211com *ic = vap->iv_ic;
4f1aaf2f 2901 struct iwn_softc *sc = ic->ic_softc;
da10ea93
MD
2902 int error = 0;
2903
2904 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ffd7c74a
JT
2905
2906 DPRINTF(sc, IWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
da10ea93 2907 ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]);
ffd7c74a 2908
05538f72
MD
2909 IEEE80211_UNLOCK(ic);
2910 IWN_LOCK(sc);
2911#if defined(__DragonFly__)
2912 callout_stop_sync(&sc->calib_to);
2913#else
da10ea93 2914 callout_stop(&sc->calib_to);
05538f72 2915#endif
da10ea93
MD
2916
2917 sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
2918
2919 switch (nstate) {
2920 case IEEE80211_S_ASSOC:
2921 if (vap->iv_state != IEEE80211_S_RUN)
2922 break;
2923 /* FALLTHROUGH */
2924 case IEEE80211_S_AUTH:
2925 if (vap->iv_state == IEEE80211_S_AUTH)
2926 break;
2927
2928 /*
2929 * !AUTH -> AUTH transition requires state reset to handle
2930 * reassociations correctly.
2931 */
2932 sc->rxon->associd = 0;
2933 sc->rxon->filter &= ~htole32(IWN_FILTER_BSS);
2934 sc->calib.state = IWN_CALIB_STATE_INIT;
2935
977fc0db
MD
2936 /* Wait until we hear a beacon before we transmit */
2937 if (IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan))
2938 sc->sc_beacon_wait = 1;
2939
da10ea93
MD
2940 if ((error = iwn_auth(sc, vap)) != 0) {
2941 device_printf(sc->sc_dev,
2942 "%s: could not move to auth state\n", __func__);
2943 }
2944 break;
2945
2946 case IEEE80211_S_RUN:
2947 /*
2948 * RUN -> RUN transition; Just restart the timers.
2949 */
2950 if (vap->iv_state == IEEE80211_S_RUN) {
2951 sc->calib_cnt = 0;
2952 break;
2953 }
ffd7c74a 2954
977fc0db
MD
2955 /* Wait until we hear a beacon before we transmit */
2956 if (IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan))
2957 sc->sc_beacon_wait = 1;
2958
ffd7c74a
JT
2959 /*
2960 * !RUN -> RUN requires setting the association id
2961 * which is done with a firmware cmd. We also defer
2962 * starting the timers until that work is done.
2963 */
da10ea93
MD
2964 if ((error = iwn_run(sc, vap)) != 0) {
2965 device_printf(sc->sc_dev,
2966 "%s: could not move to run state\n", __func__);
2967 }
2968 break;
2969
2970 case IEEE80211_S_INIT:
2971 sc->calib.state = IWN_CALIB_STATE_INIT;
977fc0db
MD
2972 /*
2973 * Purge the xmit queue so we don't have old frames
2974 * during a new association attempt.
2975 */
2976 sc->sc_beacon_wait = 0;
2977 iwn_xmit_queue_drain(sc);
da10ea93
MD
2978 break;
2979
2980 default:
2981 break;
ffd7c74a 2982 }
05538f72
MD
2983 IWN_UNLOCK(sc);
2984 IEEE80211_LOCK(ic);
da10ea93
MD
2985 if (error != 0){
2986 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s end in error\n", __func__);
2987 return error;
ffd7c74a 2988 }
da10ea93
MD
2989
2990 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
2991
ffd7c74a
JT
2992 return ivp->iv_newstate(vap, nstate, arg);
2993}
2994
da10ea93
MD
2995static void
2996iwn_calib_timeout(void *arg)
2997{
2998 struct iwn_softc *sc = arg;
2999
05538f72 3000 IWN_LOCK_ASSERT(sc);
da10ea93
MD
3001
3002 /* Force automatic TX power calibration every 60 secs. */
3003 if (++sc->calib_cnt >= 120) {
3004 uint32_t flags = 0;
3005
3006 DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s\n",
3007 "sending request for statistics");
3008 (void)iwn_cmd(sc, IWN_CMD_GET_STATISTICS, &flags,
3009 sizeof flags, 1);
3010 sc->calib_cnt = 0;
3011 }
3012 callout_reset(&sc->calib_to, msecs_to_ticks(500), iwn_calib_timeout,
3013 sc);
3014}
3015
ffd7c74a
JT
3016/*
3017 * Process an RX_PHY firmware notification. This is usually immediately
3018 * followed by an MPDU_RX_DONE notification.
3019 */
3020static void
3021iwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *desc,
3022 struct iwn_rx_data *data)
3023{
3024 struct iwn_rx_stat *stat = (struct iwn_rx_stat *)(desc + 1);
3025
3026 DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: received PHY stats\n", __func__);
3027 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
3028
3029 /* Save RX statistics, they will be used on MPDU_RX_DONE. */
3030 memcpy(&sc->last_rx_stat, stat, sizeof (*stat));
3031 sc->last_rx_valid = 1;
3032}
3033
ffd7c74a
JT
3034/*
3035 * Process an RX_DONE (4965AGN only) or MPDU_RX_DONE firmware notification.
3036 * Each MPDU_RX_DONE notification must be preceded by an RX_PHY one.
3037 */
3038static void
3039iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
3040 struct iwn_rx_data *data)
3041{
da10ea93 3042 struct iwn_ops *ops = &sc->ops;
977fc0db 3043 struct ieee80211com *ic = &sc->sc_ic;
ffd7c74a
JT
3044 struct iwn_rx_ring *ring = &sc->rxq;
3045 struct ieee80211_frame *wh;
3046 struct ieee80211_node *ni;
3047 struct mbuf *m, *m1;
3048 struct iwn_rx_stat *stat;
3049 caddr_t head;
3050 bus_addr_t paddr;
3051 uint32_t flags;
3052 int error, len, rssi, nf;
3053
da10ea93
MD
3054 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
3055
ffd7c74a
JT
3056 if (desc->type == IWN_MPDU_RX_DONE) {
3057 /* Check for prior RX_PHY notification. */
3058 if (!sc->last_rx_valid) {
3059 DPRINTF(sc, IWN_DEBUG_ANY,
3060 "%s: missing RX_PHY\n", __func__);
ffd7c74a
JT
3061 return;
3062 }
ffd7c74a
JT
3063 stat = &sc->last_rx_stat;
3064 } else
3065 stat = (struct iwn_rx_stat *)(desc + 1);
3066
3067 bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
3068
3069 if (stat->cfg_phy_len > IWN_STAT_MAXLEN) {
3070 device_printf(sc->sc_dev,
da10ea93
MD
3071 "%s: invalid RX statistic header, len %d\n", __func__,
3072 stat->cfg_phy_len);
ffd7c74a
JT
3073 return;
3074 }
3075 if (desc->type == IWN_MPDU_RX_DONE) {
3076 struct iwn_rx_mpdu *mpdu = (struct iwn_rx_mpdu *)(desc + 1);
3077 head = (caddr_t)(mpdu + 1);
3078 len = le16toh(mpdu->len);
3079 } else {
3080 head = (caddr_t)(stat + 1) + stat->cfg_phy_len;
3081 len = le16toh(stat->len);
3082 }
3083
3084 flags = le32toh(*(uint32_t *)(head + len));
3085
3086 /* Discard frames with a bad FCS early. */
3087 if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) {
da10ea93 3088 DPRINTF(sc, IWN_DEBUG_RECV, "%s: RX flags error %x\n",
ffd7c74a 3089 __func__, flags);
05538f72 3090#if defined(__DragonFly__)
977fc0db 3091 ++ic->ic_ierrors;
05538f72 3092#else
977fc0db 3093 counter_u64_add(ic->ic_ierrors, 1);
05538f72 3094#endif
ffd7c74a
JT
3095 return;
3096 }
3097 /* Discard frames that are too short. */
977fc0db 3098 if (len < sizeof (struct ieee80211_frame_ack)) {
ffd7c74a
JT
3099 DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too short: %d\n",
3100 __func__, len);
05538f72 3101#if defined(__DragonFly__)
977fc0db 3102 ++ic->ic_ierrors;
05538f72 3103#else
977fc0db 3104 counter_u64_add(ic->ic_ierrors, 1);
05538f72 3105#endif
ffd7c74a
JT
3106 return;
3107 }
3108
b5523eac 3109 m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, IWN_RBUF_SIZE);
ffd7c74a
JT
3110 if (m1 == NULL) {
3111 DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n",
3112 __func__);
05538f72 3113#if defined(__DragonFly__)
977fc0db 3114 ++ic->ic_ierrors;
05538f72 3115#else
977fc0db 3116 counter_u64_add(ic->ic_ierrors, 1);
05538f72 3117#endif
ffd7c74a
JT
3118 return;
3119 }
3120 bus_dmamap_unload(ring->data_dmat, data->map);
3121
da10ea93
MD
3122 error = bus_dmamap_load(ring->data_dmat, data->map, mtod(m1, void *),
3123 IWN_RBUF_SIZE, iwn_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
ffd7c74a
JT
3124 if (error != 0 && error != EFBIG) {
3125 device_printf(sc->sc_dev,
3126 "%s: bus_dmamap_load failed, error %d\n", __func__, error);
3127 m_freem(m1);
da10ea93
MD
3128
3129 /* Try to reload the old mbuf. */
3130 error = bus_dmamap_load(ring->data_dmat, data->map,
3131 mtod(data->m, void *), IWN_RBUF_SIZE, iwn_dma_map_addr,
3132 &paddr, BUS_DMA_NOWAIT);
3133 if (error != 0 && error != EFBIG) {
3134 panic("%s: could not load old RX mbuf", __func__);
3135 }
3136 /* Physical address may have changed. */
3137 ring->desc[ring->cur] = htole32(paddr >> 8);
3138 bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map,
3139 BUS_DMASYNC_PREWRITE);
05538f72 3140#if defined(__DragonFly__)
977fc0db 3141 ++ic->ic_ierrors;
05538f72 3142#else
977fc0db 3143 counter_u64_add(ic->ic_ierrors, 1);
05538f72 3144#endif
ffd7c74a
JT
3145 return;
3146 }
3147
3148 m = data->m;
3149 data->m = m1;
3150 /* Update RX descriptor. */
3151 ring->desc[ring->cur] = htole32(paddr >> 8);
3152 bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
3153 BUS_DMASYNC_PREWRITE);
3154
3155 /* Finalize mbuf. */
ffd7c74a
JT
3156 m->m_data = head;
3157 m->m_pkthdr.len = m->m_len = len;
3158
ffd7c74a
JT
3159 /* Grab a reference to the source node. */
3160 wh = mtod(m, struct ieee80211_frame *);
977fc0db
MD
3161 if (len >= sizeof(struct ieee80211_frame_min))
3162 ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
3163 else
3164 ni = NULL;
ffd7c74a
JT
3165 nf = (ni != NULL && ni->ni_vap->iv_state == IEEE80211_S_RUN &&
3166 (ic->ic_flags & IEEE80211_F_SCAN) == 0) ? sc->noise : -95;
3167
da10ea93
MD
3168 rssi = ops->get_rssi(sc, stat);
3169
ffd7c74a
JT
3170 if (ieee80211_radiotap_active(ic)) {
3171 struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;
3172
ffd7c74a
JT
3173 tap->wr_flags = 0;
3174 if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE))
3175 tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
da10ea93
MD
3176 tap->wr_dbm_antsignal = (int8_t)rssi;
3177 tap->wr_dbm_antnoise = (int8_t)nf;
3178 tap->wr_tsft = stat->tstamp;
ffd7c74a
JT
3179 switch (stat->rate) {
3180 /* CCK rates. */
3181 case 10: tap->wr_rate = 2; break;
3182 case 20: tap->wr_rate = 4; break;
3183 case 55: tap->wr_rate = 11; break;
3184 case 110: tap->wr_rate = 22; break;
3185 /* OFDM rates. */
3186 case 0xd: tap->wr_rate = 12; break;
3187 case 0xf: tap->wr_rate = 18; break;
3188 case 0x5: tap->wr_rate = 24; break;
3189 case 0x7: tap->wr_rate = 36; break;
3190 case 0x9: tap->wr_rate = 48; break;
3191 case 0xb: tap->wr_rate = 72; break;
3192 case 0x1: tap->wr_rate = 96; break;
3193 case 0x3: tap->wr_rate = 108; break;
3194 /* Unknown rate: should not happen. */
3195 default: tap->wr_rate = 0;
3196 }
ffd7c74a
JT
3197 }
3198
977fc0db
MD
3199 /*
3200 * If it's a beacon and we're waiting, then do the
3201 * wakeup. This should unblock raw_xmit/start.
3202 */
3203 if (sc->sc_beacon_wait) {
3204 uint8_t type, subtype;
3205 /* NB: Re-assign wh */
3206 wh = mtod(m, struct ieee80211_frame *);
3207 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
3208 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
3209 /*
3210 * This assumes at this point we've received our own
3211 * beacon.
3212 */
3213 DPRINTF(sc, IWN_DEBUG_TRACE,
3214 "%s: beacon_wait, type=%d, subtype=%d\n",
3215 __func__, type, subtype);
3216 if (type == IEEE80211_FC0_TYPE_MGT &&
3217 subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
3218 DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT,
3219 "%s: waking things up\n", __func__);
3220 /* queue taskqueue to transmit! */
3221 taskqueue_enqueue(sc->sc_tq, &sc->sc_xmit_task);
3222 }
3223 }
3224
05538f72
MD
3225 IWN_UNLOCK(sc);
3226
da10ea93
MD
3227 /* Send the frame to the 802.11 layer. */
3228 if (ni != NULL) {
3229 if (ni->ni_flags & IEEE80211_NODE_HT)
3230 m->m_flags |= M_AMPDU;
3231 (void)ieee80211_input(ni, m, rssi - nf, nf);
3232 /* Node is no longer needed. */
3233 ieee80211_free_node(ni);
05538f72 3234 } else
da10ea93 3235 (void)ieee80211_input_all(ic, m, rssi - nf, nf);
05538f72
MD
3236
3237 IWN_LOCK(sc);
da10ea93
MD
3238
3239 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
3240
3241}
3242
3243/* Process an incoming Compressed BlockAck. */
3244static void
3245iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
3246 struct iwn_rx_data *data)
3247{
3248 struct iwn_ops *ops = &sc->ops;
da10ea93
MD
3249 struct iwn_node *wn;
3250 struct ieee80211_node *ni;
3251 struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1);
3252 struct iwn_tx_ring *txq;
3253 struct iwn_tx_data *txdata;
3254 struct ieee80211_tx_ampdu *tap;
3255 struct mbuf *m;
3256 uint64_t bitmap;
3257 uint16_t ssn;
3258 uint8_t tid;
3259 int ackfailcnt = 0, i, lastidx, qid, *res, shift;
05538f72 3260 int tx_ok = 0, tx_err = 0;
da10ea93 3261
05538f72 3262 DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__);
da10ea93
MD
3263
3264 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
3265
3266 qid = le16toh(ba->qid);
3267 txq = &sc->txq[ba->qid];
3268 tap = sc->qid2tap[ba->qid];
085ff963 3269 tid = tap->txa_tid;
da10ea93
MD
3270 wn = (void *)tap->txa_ni;
3271
3272 res = NULL;
3273 ssn = 0;
3274 if (!IEEE80211_AMPDU_RUNNING(tap)) {
3275 res = tap->txa_private;
3276 ssn = tap->txa_start & 0xfff;
3277 }
3278
3279 for (lastidx = le16toh(ba->ssn) & 0xff; txq->read != lastidx;) {
3280 txdata = &txq->data[txq->read];
3281
3282 /* Unmap and free mbuf. */
3283 bus_dmamap_sync(txq->data_dmat, txdata->map,
3284 BUS_DMASYNC_POSTWRITE);
3285 bus_dmamap_unload(txq->data_dmat, txdata->map);
3286 m = txdata->m, txdata->m = NULL;
3287 ni = txdata->ni, txdata->ni = NULL;
3288
3289 KASSERT(ni != NULL, ("no node"));
3290 KASSERT(m != NULL, ("no mbuf"));
3291
05538f72 3292 DPRINTF(sc, IWN_DEBUG_XMIT, "%s: freeing m=%p\n", __func__, m);
da10ea93
MD
3293 ieee80211_tx_complete(ni, m, 1);
3294
3295 txq->queued--;
3296 txq->read = (txq->read + 1) % IWN_TX_RING_COUNT;
3297 }
3298
3299 if (txq->queued == 0 && res != NULL) {
3300 iwn_nic_lock(sc);
3301 ops->ampdu_tx_stop(sc, qid, tid, ssn);
3302 iwn_nic_unlock(sc);
3303 sc->qid2tap[qid] = NULL;
101554a6 3304 kfree(res, M_DEVBUF);
da10ea93
MD
3305 return;
3306 }
3307
3308 if (wn->agg[tid].bitmap == 0)
3309 return;
3310
3311 shift = wn->agg[tid].startidx - ((le16toh(ba->seq) >> 4) & 0xff);
3312 if (shift < 0)
3313 shift += 0x100;
3314
3315 if (wn->agg[tid].nframes > (64 - shift))
3316 return;
3317
05538f72
MD
3318 /*
3319 * Walk the bitmap and calculate how many successful and failed
3320 * attempts are made.
3321 *
3322 * Yes, the rate control code doesn't know these are A-MPDU
3323 * subframes and that it's okay to fail some of these.
3324 */
da10ea93
MD
3325 ni = tap->txa_ni;
3326 bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
3327 for (i = 0; bitmap; i++) {
3328 if ((bitmap & 1) == 0) {
05538f72 3329 tx_err ++;
da10ea93
MD
3330 ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
3331 IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
3332 } else {
05538f72 3333 tx_ok ++;
da10ea93
MD
3334 ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
3335 IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
3336 }
3337 bitmap >>= 1;
458fc9cf 3338 }
ffd7c74a 3339
05538f72
MD
3340 DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT,
3341 "->%s: end; %d ok; %d err\n",__func__, tx_ok, tx_err);
ffd7c74a 3342
ffd7c74a 3343}
ffd7c74a
JT
3344
3345/*
3346 * Process a CALIBRATION_RESULT notification sent by the initialization
da10ea93 3347 * firmware on response to a CMD_CALIB_CONFIG command (5000 only).
ffd7c74a
JT
3348 */
3349static void
3350iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc,
3351 struct iwn_rx_data *data)
3352{
3353 struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1);
3354 int len, idx = -1;
3355
da10ea93
MD
3356 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
3357
ffd7c74a 3358 /* Runtime firmware should not send such a notification. */
da10ea93
MD
3359 if (sc->sc_flags & IWN_FLAG_CALIB_DONE){
3360 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s received after clib done\n",
3361 __func__);
ffd7c74a 3362 return;
da10ea93 3363 }
ffd7c74a 3364 len = (le32toh(desc->len) & 0x3fff) - 4;
da10ea93 3365 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
ffd7c74a
JT
3366
3367 switch (calib->code) {
3368 case IWN5000_PHY_CALIB_DC:
da10ea93 3369 if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_DC)
ffd7c74a
JT
3370 idx = 0;
3371 break;
3372 case IWN5000_PHY_CALIB_LO:
da10ea93
MD
3373 if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_LO)
3374 idx = 1;
ffd7c74a
JT
3375 break;
3376 case IWN5000_PHY_CALIB_TX_IQ:
da10ea93
MD
3377 if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ)
3378 idx = 2;
ffd7c74a
JT
3379 break;
3380 case IWN5000_PHY_CALIB_TX_IQ_PERIODIC:
da10ea93 3381 if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_TX_IQ_PERIODIC)
ffd7c74a
JT
3382 idx = 3;
3383 break;
3384 case IWN5000_PHY_CALIB_BASE_BAND:
da10ea93
MD
3385 if (sc->base_params->calib_need & IWN_FLG_NEED_PHY_CALIB_BASE_BAND)
3386 idx = 4;
ffd7c74a
JT
3387 break;
3388 }
3389 if (idx == -1) /* Ignore other results. */
3390 return;
3391
3392 /* Save calibration result. */
3393 if (sc->calibcmd[idx].buf != NULL)
101554a6
MD
3394 kfree(sc->calibcmd[idx].buf, M_DEVBUF);
3395 sc->calibcmd[idx].buf = kmalloc(len, M_DEVBUF, M_INTWAIT);
05538f72
MD
3396 if (sc->calibcmd[idx].buf == NULL) {
3397 DPRINTF(sc, IWN_DEBUG_CALIBRATE,
3398 "not enough memory for calibration result %d\n",
3399 calib->code);
3400 return;
3401 }
ffd7c74a 3402 DPRINTF(sc, IWN_DEBUG_CALIBRATE,
da10ea93 3403 "saving calibration result idx=%d, code=%d len=%d\n", idx, calib->code, len);
ffd7c74a
JT
3404 sc->calibcmd[idx].len = len;
3405 memcpy(sc->calibcmd[idx].buf, calib, len);
3406}
3407
fd49669c
MN
3408static void
3409iwn_stats_update(struct iwn_softc *sc, struct iwn_calib_state *calib,
3410 struct iwn_stats *stats, int len)
3411{
3412 struct iwn_stats_bt *stats_bt;
3413 struct iwn_stats *lstats;
3414
3415 /*
3416 * First - check whether the length is the bluetooth or normal.
3417 *
3418 * If it's normal - just copy it and bump out.
3419 * Otherwise we have to convert things.
3420 */
3421
3422 if (len == sizeof(struct iwn_stats) + 4) {
3423 memcpy(&sc->last_stat, stats, sizeof(struct iwn_stats));
3424 sc->last_stat_valid = 1;
3425 return;
3426 }
3427
3428 /*
3429 * If it's not the bluetooth size - log, then just copy.
3430 */
3431 if (len != sizeof(struct iwn_stats_bt) + 4) {
3432 DPRINTF(sc, IWN_DEBUG_STATS,
3433 "%s: size of rx statistics (%d) not an expected size!\n",
3434 __func__,
3435 len);
3436 memcpy(&sc->last_stat, stats, sizeof(struct iwn_stats));
3437 sc->last_stat_valid = 1;
3438 return;
3439 }
3440
3441 /*
3442 * Ok. Time to copy.
3443 */
3444 stats_bt = (struct iwn_stats_bt *) stats;
3445 lstats = &sc->last_stat;
3446
3447 /* flags */
3448 lstats->flags = stats_bt->flags;
3449 /* rx_bt */
3450 memcpy(&lstats->rx.ofdm, &stats_bt->rx_bt.ofdm,
3451 sizeof(struct iwn_rx_phy_stats));
3452 memcpy(&lstats->rx.cck, &stats_bt->rx_bt.cck,
3453 sizeof(struct iwn_rx_phy_stats));
3454 memcpy(&lstats->rx.general, &stats_bt->rx_bt.general_bt.common,
3455 sizeof(struct iwn_rx_general_stats));
3456 memcpy(&lstats->rx.ht, &stats_bt->rx_bt.ht,
3457 sizeof(struct iwn_rx_ht_phy_stats));
3458 /* tx */
3459 memcpy(&lstats->tx, &stats_bt->tx,
3460 sizeof(struct iwn_tx_stats));
3461 /* general */
3462 memcpy(&lstats->general, &stats_bt->general,
3463 sizeof(struct iwn_general_stats));
3464
3465 /* XXX TODO: Squirrel away the extra bluetooth stats somewhere */
3466 sc->last_stat_valid = 1;
3467}
3468
ffd7c74a
JT
3469/*
3470 * Process an RX_STATISTICS or BEACON_STATISTICS firmware notification.
3471 * The latter is sent by the firmware after each received beacon.
3472 */
3473static void
3474iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
3475 struct iwn_rx_data *data)
3476{
da10ea93 3477 struct iwn_ops *ops = &sc->ops;
977fc0db 3478 struct ieee80211com *ic = &sc->sc_ic;
ffd7c74a
JT
3479 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
3480 struct iwn_calib_state *calib = &sc->calib;
3481 struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
fd49669c 3482 struct iwn_stats *lstats;
ffd7c74a
JT
3483 int temp;
3484
da10ea93
MD
3485 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
3486
3487 /* Ignore statistics received during a scan. */
ffd7c74a 3488 if (vap->iv_state != IEEE80211_S_RUN ||
da10ea93
MD
3489 (ic->ic_flags & IEEE80211_F_SCAN)){
3490 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s received during calib\n",
3491 __func__);
ffd7c74a 3492 return;
da10ea93 3493 }
ffd7c74a
JT
3494
3495 bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
da10ea93 3496
fd49669c
MN
3497 DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_STATS,
3498 "%s: received statistics, cmd %d, len %d\n",
3499 __func__, desc->type, le16toh(desc->len));
da10ea93 3500 sc->calib_cnt = 0; /* Reset TX power calibration timeout. */
ffd7c74a 3501
fd49669c
MN
3502 /*
3503 * Collect/track general statistics for reporting.
3504 *
3505 * This takes care of ensuring that the bluetooth sized message
3506 * will be correctly converted to the legacy sized message.
3507 */
3508 iwn_stats_update(sc, calib, stats, le16toh(desc->len));
3509
3510 /*
3511 * And now, let's take a reference of it to use!
3512 */
3513 lstats = &sc->last_stat;
3514
ffd7c74a 3515 /* Test if temperature has changed. */
fd49669c 3516 if (lstats->general.temp != sc->rawtemp) {
ffd7c74a
JT
3517 /* Convert "raw" temperature to degC. */
3518 sc->rawtemp = stats->general.temp;
da10ea93 3519 temp = ops->get_temperature(sc);
ffd7c74a
JT
3520 DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: temperature %d\n",
3521 __func__, temp);
3522
da10ea93 3523 /* Update TX power if need be (4965AGN only). */
ffd7c74a
JT
3524 if (sc->hw_type == IWN_HW_REV_TYPE_4965)
3525 iwn4965_power_calibration(sc, temp);
3526 }
3527
3528 if (desc->type != IWN_BEACON_STATISTICS)
3529 return; /* Reply to a statistics request. */
3530
fd49669c 3531 sc->noise = iwn_get_noise(&lstats->rx.general);
ffd7c74a
JT
3532 DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: noise %d\n", __func__, sc->noise);
3533
3534 /* Test that RSSI and noise are present in stats report. */
fd49669c 3535 if (le32toh(lstats->rx.general.flags) != 1) {
ffd7c74a
JT
3536 DPRINTF(sc, IWN_DEBUG_ANY, "%s\n",
3537 "received statistics without RSSI");
3538 return;
3539 }
3540
3541 if (calib->state == IWN_CALIB_STATE_ASSOC)
fd49669c
MN
3542 iwn_collect_noise(sc, &lstats->rx.general);
3543 else if (calib->state == IWN_CALIB_STATE_RUN) {
3544 iwn_tune_sensitivity(sc, &lstats->rx);
3545 /*
3546 * XXX TODO: Only run the RX recovery if we're associated!
3547 */
3548 iwn_check_rx_recovery(sc, lstats);
3549 iwn_save_stats_counters(sc, lstats);
3550 }
da10ea93
MD
3551
3552 DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
ffd7c74a
JT
3553}
3554
fd49669c
MN
3555/*
3556 * Save the relevant statistic counters for the next calibration
3557 * pass.
3558 */
3559static void
3560iwn_save_stats_counters(struct iwn_softc *sc, const struct iwn_stats *rs)
3561{
3562 struct iwn_calib_state *calib = &sc->calib;
3563
3564 /* Save counters values for next call. */
3565 calib->bad_plcp_cck = le32toh(rs->rx.cck.bad_plcp);
3566 calib->fa_cck = le32toh(rs->rx.cck.fa);
3567 calib->bad_plcp_ht = le32toh(rs->rx.ht.bad_plcp);
3568 calib->bad_plcp_ofdm = le32toh(rs->rx.ofdm.bad_plcp);
3569 calib->fa_ofdm = le32toh(rs->rx.ofdm.fa);
3570
3571 /* Last time we received these tick values */
3572 sc->last_calib_ticks = ticks;
3573}
3574
ffd7c74a
JT
3575/*
3576 * Process a TX_DONE firmware notification. Unfortunately, the 4965AGN
3577 * and 5000 adapters have different incompatible TX status formats.
3578 */
3579static void
3580iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
3581 struct iwn_rx_data *data)
3582{
3583 struct iwn4965_tx_stat *stat = (struct iwn4965_tx_stat *)(desc + 1);
da10ea93
MD
3584 struct iwn_tx_ring *ring;
3585 int qid;
3586
3587 qid = desc->qid & 0xf;
3588 ring = &sc->txq[qid];
ffd7c74a
JT
3589
3590 DPRINTF(sc, IWN_DEBUG_XMIT, "%s: "
05538f72
MD
3591 "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n",
3592 __func__, desc->qid, desc->idx,
3593 stat->rtsfailcnt,
3594 stat->ackfailcnt,
3595 stat->btkillcnt,
3596 stat->rate, le16toh(stat->duration),