if_wpi.c revision 289126
1173362Sbenjsc/*-
2173362Sbenjsc * Copyright (c) 2006,2007
3173362Sbenjsc *	Damien Bergamini <damien.bergamini@free.fr>
4173362Sbenjsc *	Benjamin Close <Benjamin.Close@clearchain.com>
5173362Sbenjsc *
6173362Sbenjsc * Permission to use, copy, modify, and distribute this software for any
7173362Sbenjsc * purpose with or without fee is hereby granted, provided that the above
8173362Sbenjsc * copyright notice and this permission notice appear in all copies.
9173362Sbenjsc *
10173362Sbenjsc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11173362Sbenjsc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12173362Sbenjsc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13173362Sbenjsc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14173362Sbenjsc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15173362Sbenjsc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16173362Sbenjsc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17173362Sbenjsc */
18173362Sbenjsc
19173362Sbenjsc#include <sys/cdefs.h>
20173362Sbenjsc__FBSDID("$FreeBSD: head/sys/dev/wpi/if_wpi.c 289126 2015-10-11 01:53:51Z adrian $");
21173362Sbenjsc
22173362Sbenjsc/*
23173362Sbenjsc * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
24173362Sbenjsc *
25173362Sbenjsc * The 3945ABG network adapter doesn't use traditional hardware as
26173362Sbenjsc * many other adaptors do. Instead at run time the eeprom is set into a known
27173362Sbenjsc * state and told to load boot firmware. The boot firmware loads an init and a
28173362Sbenjsc * main  binary firmware image into SRAM on the card via DMA.
29173362Sbenjsc * Once the firmware is loaded, the driver/hw then
30218909Sbrucec * communicate by way of circular dma rings via the SRAM to the firmware.
31173362Sbenjsc *
32173362Sbenjsc * There is 6 memory rings. 1 command ring, 1 rx data ring & 4 tx data rings.
33173362Sbenjsc * The 4 tx data rings allow for prioritization QoS.
34173362Sbenjsc *
35173362Sbenjsc * The rx data ring consists of 32 dma buffers. Two registers are used to
36173362Sbenjsc * indicate where in the ring the driver and the firmware are up to. The
37173362Sbenjsc * driver sets the initial read index (reg1) and the initial write index (reg2),
38173362Sbenjsc * the firmware updates the read index (reg1) on rx of a packet and fires an
39173362Sbenjsc * interrupt. The driver then processes the buffers starting at reg1 indicating
40173362Sbenjsc * to the firmware which buffers have been accessed by updating reg2. At the
41173362Sbenjsc * same time allocating new memory for the processed buffer.
42173362Sbenjsc *
43173362Sbenjsc * A similar thing happens with the tx rings. The difference is the firmware
44173362Sbenjsc * stop processing buffers once the queue is full and until confirmation
45278764Sadrian * of a successful transmition (tx_done) has occurred.
46173362Sbenjsc *
47173362Sbenjsc * The command ring operates in the same manner as the tx queues.
48173362Sbenjsc *
49173362Sbenjsc * All communication direct to the card (ie eeprom) is classed as Stage1
50173362Sbenjsc * communication
51173362Sbenjsc *
52173362Sbenjsc * All communication via the firmware to the card is classed as State2.
53173362Sbenjsc * The firmware consists of 2 parts. A bootstrap firmware and a runtime
54173362Sbenjsc * firmware. The bootstrap firmware and runtime firmware are loaded
55173362Sbenjsc * from host memory via dma to the card then told to execute. From this point
56173362Sbenjsc * on the majority of communications between the driver and the card goes
57173362Sbenjsc * via the firmware.
58173362Sbenjsc */
59173362Sbenjsc
60236381Sadrian#include "opt_wlan.h"
61278366Sadrian#include "opt_wpi.h"
62236381Sadrian
63173362Sbenjsc#include <sys/param.h>
64173362Sbenjsc#include <sys/sysctl.h>
65173362Sbenjsc#include <sys/sockio.h>
66173362Sbenjsc#include <sys/mbuf.h>
67173362Sbenjsc#include <sys/kernel.h>
68173362Sbenjsc#include <sys/socket.h>
69173362Sbenjsc#include <sys/systm.h>
70173362Sbenjsc#include <sys/malloc.h>
71173362Sbenjsc#include <sys/queue.h>
72173362Sbenjsc#include <sys/taskqueue.h>
73173362Sbenjsc#include <sys/module.h>
74173362Sbenjsc#include <sys/bus.h>
75173362Sbenjsc#include <sys/endian.h>
76173362Sbenjsc#include <sys/linker.h>
77173362Sbenjsc#include <sys/firmware.h>
78173362Sbenjsc
79173362Sbenjsc#include <machine/bus.h>
80173362Sbenjsc#include <machine/resource.h>
81173362Sbenjsc#include <sys/rman.h>
82173362Sbenjsc
83173362Sbenjsc#include <dev/pci/pcireg.h>
84173362Sbenjsc#include <dev/pci/pcivar.h>
85173362Sbenjsc
86173362Sbenjsc#include <net/bpf.h>
87173362Sbenjsc#include <net/if.h>
88257176Sglebius#include <net/if_var.h>
89173362Sbenjsc#include <net/if_arp.h>
90173362Sbenjsc#include <net/ethernet.h>
91173362Sbenjsc#include <net/if_dl.h>
92173362Sbenjsc#include <net/if_media.h>
93173362Sbenjsc#include <net/if_types.h>
94173362Sbenjsc
95278366Sadrian#include <netinet/in.h>
96278366Sadrian#include <netinet/in_systm.h>
97278366Sadrian#include <netinet/in_var.h>
98278366Sadrian#include <netinet/if_ether.h>
99278366Sadrian#include <netinet/ip.h>
100278366Sadrian
101173362Sbenjsc#include <net80211/ieee80211_var.h>
102173362Sbenjsc#include <net80211/ieee80211_radiotap.h>
103173362Sbenjsc#include <net80211/ieee80211_regdomain.h>
104206358Srpaulo#include <net80211/ieee80211_ratectl.h>
105173362Sbenjsc
106173362Sbenjsc#include <dev/wpi/if_wpireg.h>
107173362Sbenjsc#include <dev/wpi/if_wpivar.h>
108278366Sadrian#include <dev/wpi/if_wpi_debug.h>
109173362Sbenjsc
110173362Sbenjscstruct wpi_ident {
111173362Sbenjsc	uint16_t	vendor;
112173362Sbenjsc	uint16_t	device;
113173362Sbenjsc	uint16_t	subdevice;
114173362Sbenjsc	const char	*name;
115173362Sbenjsc};
116173362Sbenjsc
117173362Sbenjscstatic const struct wpi_ident wpi_ident_table[] = {
118173362Sbenjsc	/* The below entries support ABG regardless of the subid */
119173362Sbenjsc	{ 0x8086, 0x4222,    0x0, "Intel(R) PRO/Wireless 3945ABG" },
120173362Sbenjsc	{ 0x8086, 0x4227,    0x0, "Intel(R) PRO/Wireless 3945ABG" },
121173362Sbenjsc	/* The below entries only support BG */
122182127Sbenjsc	{ 0x8086, 0x4222, 0x1005, "Intel(R) PRO/Wireless 3945BG"  },
123182127Sbenjsc	{ 0x8086, 0x4222, 0x1034, "Intel(R) PRO/Wireless 3945BG"  },
124182127Sbenjsc	{ 0x8086, 0x4227, 0x1014, "Intel(R) PRO/Wireless 3945BG"  },
125182127Sbenjsc	{ 0x8086, 0x4222, 0x1044, "Intel(R) PRO/Wireless 3945BG"  },
126173362Sbenjsc	{ 0, 0, 0, NULL }
127173362Sbenjsc};
128173362Sbenjsc
129278366Sadrianstatic int	wpi_probe(device_t);
130278366Sadrianstatic int	wpi_attach(device_t);
131278366Sadrianstatic void	wpi_radiotap_attach(struct wpi_softc *);
132278366Sadrianstatic void	wpi_sysctlattach(struct wpi_softc *);
133280083Sadrianstatic void	wpi_init_beacon(struct wpi_vap *);
134178354Ssamstatic struct ieee80211vap *wpi_vap_create(struct ieee80211com *,
135228621Sbschmidt		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
136228621Sbschmidt		    const uint8_t [IEEE80211_ADDR_LEN],
137228621Sbschmidt		    const uint8_t [IEEE80211_ADDR_LEN]);
138178354Ssamstatic void	wpi_vap_delete(struct ieee80211vap *);
139278366Sadrianstatic int	wpi_detach(device_t);
140278366Sadrianstatic int	wpi_shutdown(device_t);
141278366Sadrianstatic int	wpi_suspend(device_t);
142278366Sadrianstatic int	wpi_resume(device_t);
143278366Sadrianstatic int	wpi_nic_lock(struct wpi_softc *);
144278366Sadrianstatic int	wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
145278366Sadrianstatic void	wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
146173362Sbenjscstatic int	wpi_dma_contig_alloc(struct wpi_softc *, struct wpi_dma_info *,
147278366Sadrian		    void **, bus_size_t, bus_size_t);
148173362Sbenjscstatic void	wpi_dma_contig_free(struct wpi_dma_info *);
149173362Sbenjscstatic int	wpi_alloc_shared(struct wpi_softc *);
150173362Sbenjscstatic void	wpi_free_shared(struct wpi_softc *);
151278366Sadrianstatic int	wpi_alloc_fwmem(struct wpi_softc *);
152278366Sadrianstatic void	wpi_free_fwmem(struct wpi_softc *);
153278366Sadrianstatic int	wpi_alloc_rx_ring(struct wpi_softc *);
154278366Sadrianstatic void	wpi_update_rx_ring(struct wpi_softc *);
155282400Sadrianstatic void	wpi_update_rx_ring_ps(struct wpi_softc *);
156278366Sadrianstatic void	wpi_reset_rx_ring(struct wpi_softc *);
157278366Sadrianstatic void	wpi_free_rx_ring(struct wpi_softc *);
158173362Sbenjscstatic int	wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
159289124Sadrian		    uint8_t);
160278366Sadrianstatic void	wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
161282400Sadrianstatic void	wpi_update_tx_ring_ps(struct wpi_softc *,
162282400Sadrian		    struct wpi_tx_ring *);
163173362Sbenjscstatic void	wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
164173362Sbenjscstatic void	wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
165278366Sadrianstatic int	wpi_read_eeprom(struct wpi_softc *,
166278366Sadrian		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
167278366Sadrianstatic uint32_t	wpi_eeprom_channel_flags(struct wpi_eeprom_chan *);
168289124Sadrianstatic void	wpi_read_eeprom_band(struct wpi_softc *, uint8_t);
169289124Sadrianstatic int	wpi_read_eeprom_channels(struct wpi_softc *, uint8_t);
170278366Sadrianstatic struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
171278366Sadrian		    struct ieee80211_channel *);
172278366Sadrianstatic int	wpi_setregdomain(struct ieee80211com *,
173278366Sadrian		    struct ieee80211_regdomain *, int,
174278366Sadrian		    struct ieee80211_channel[]);
175289124Sadrianstatic int	wpi_read_eeprom_group(struct wpi_softc *, uint8_t);
176278366Sadrianstatic struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *,
177278366Sadrian		    const uint8_t mac[IEEE80211_ADDR_LEN]);
178282401Sadrianstatic void	wpi_node_free(struct ieee80211_node *);
179289125Sadrianstatic void	wpi_ibss_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
180283536Sadrian		    const struct ieee80211_rx_stats *,
181283536Sadrian		    int, int);
182282401Sadrianstatic void	wpi_restore_node(void *, struct ieee80211_node *);
183282401Sadrianstatic void	wpi_restore_node_table(struct wpi_softc *, struct wpi_vap *);
184178354Ssamstatic int	wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
185278366Sadrianstatic void	wpi_calib_timeout(void *);
186278366Sadrianstatic void	wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
187173362Sbenjsc		    struct wpi_rx_data *);
188278366Sadrianstatic void	wpi_rx_statistics(struct wpi_softc *, struct wpi_rx_desc *,
189278366Sadrian		    struct wpi_rx_data *);
190278366Sadrianstatic void	wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *);
191278366Sadrianstatic void	wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *);
192173362Sbenjscstatic void	wpi_notif_intr(struct wpi_softc *);
193278366Sadrianstatic void	wpi_wakeup_intr(struct wpi_softc *);
194280093Sadrian#ifdef WPI_DEBUG
195280093Sadrianstatic void	wpi_debug_registers(struct wpi_softc *);
196280093Sadrian#endif
197278366Sadrianstatic void	wpi_fatal_intr(struct wpi_softc *);
198173362Sbenjscstatic void	wpi_intr(void *);
199278366Sadrianstatic int	wpi_cmd2(struct wpi_softc *, struct wpi_buf *);
200173362Sbenjscstatic int	wpi_tx_data(struct wpi_softc *, struct mbuf *,
201278366Sadrian		    struct ieee80211_node *);
202278366Sadrianstatic int	wpi_tx_data_raw(struct wpi_softc *, struct mbuf *,
203278366Sadrian		    struct ieee80211_node *,
204278366Sadrian		    const struct ieee80211_bpf_params *);
205278366Sadrianstatic int	wpi_raw_xmit(struct ieee80211_node *, struct mbuf *,
206278366Sadrian		    const struct ieee80211_bpf_params *);
207287197Sglebiusstatic int	wpi_transmit(struct ieee80211com *, struct mbuf *);
208278366Sadrianstatic void	wpi_watchdog_rfkill(void *);
209280106Sadrianstatic void	wpi_scan_timeout(void *);
210280109Sadrianstatic void	wpi_tx_timeout(void *);
211287197Sglebiusstatic void	wpi_parent(struct ieee80211com *);
212289124Sadrianstatic int	wpi_cmd(struct wpi_softc *, uint8_t, const void *, uint16_t,
213289124Sadrian		    int);
214173362Sbenjscstatic int	wpi_mrr_setup(struct wpi_softc *);
215278366Sadrianstatic int	wpi_add_node(struct wpi_softc *, struct ieee80211_node *);
216278366Sadrianstatic int	wpi_add_broadcast_node(struct wpi_softc *, int);
217278366Sadrianstatic int	wpi_add_ibss_node(struct wpi_softc *, struct ieee80211_node *);
218278366Sadrianstatic void	wpi_del_node(struct wpi_softc *, struct ieee80211_node *);
219278366Sadrianstatic int	wpi_updateedca(struct ieee80211com *);
220278366Sadrianstatic void	wpi_set_promisc(struct wpi_softc *);
221283540Sglebiusstatic void	wpi_update_promisc(struct ieee80211com *);
222283540Sglebiusstatic void	wpi_update_mcast(struct ieee80211com *);
223173362Sbenjscstatic void	wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
224278366Sadrianstatic int	wpi_set_timing(struct wpi_softc *, struct ieee80211_node *);
225278366Sadrianstatic void	wpi_power_calibration(struct wpi_softc *);
226278366Sadrianstatic int	wpi_set_txpower(struct wpi_softc *, int);
227278366Sadrianstatic int	wpi_get_power_index(struct wpi_softc *,
228281287Sadrian		    struct wpi_power_group *, uint8_t, int, int);
229278366Sadrianstatic int	wpi_set_pslevel(struct wpi_softc *, uint8_t, int, int);
230278366Sadrianstatic int	wpi_send_btcoex(struct wpi_softc *);
231278366Sadrianstatic int	wpi_send_rxon(struct wpi_softc *, int, int);
232278366Sadrianstatic int	wpi_config(struct wpi_softc *);
233278366Sadrianstatic uint16_t	wpi_get_active_dwell_time(struct wpi_softc *,
234278366Sadrian		    struct ieee80211_channel *, uint8_t);
235278366Sadrianstatic uint16_t	wpi_limit_dwell(struct wpi_softc *, uint16_t);
236278366Sadrianstatic uint16_t	wpi_get_passive_dwell_time(struct wpi_softc *,
237278366Sadrian		    struct ieee80211_channel *);
238282383Sadrianstatic uint32_t	wpi_get_scan_pause_time(uint32_t, uint16_t);
239278366Sadrianstatic int	wpi_scan(struct wpi_softc *, struct ieee80211_channel *);
240278366Sadrianstatic int	wpi_auth(struct wpi_softc *, struct ieee80211vap *);
241280084Sadrianstatic int	wpi_config_beacon(struct wpi_vap *);
242280084Sadrianstatic int	wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
243278366Sadrianstatic void	wpi_update_beacon(struct ieee80211vap *, int);
244280079Sadrianstatic void	wpi_newassoc(struct ieee80211_node *, int);
245178354Ssamstatic int	wpi_run(struct wpi_softc *, struct ieee80211vap *);
246280088Sadrianstatic int	wpi_load_key(struct ieee80211_node *,
247280088Sadrian		    const struct ieee80211_key *);
248280088Sadrianstatic void	wpi_load_key_cb(void *, struct ieee80211_node *);
249280088Sadrianstatic int	wpi_set_global_keys(struct ieee80211_node *);
250280088Sadrianstatic int	wpi_del_key(struct ieee80211_node *,
251280088Sadrian		    const struct ieee80211_key *);
252280088Sadrianstatic void	wpi_del_key_cb(void *, struct ieee80211_node *);
253280088Sadrianstatic int	wpi_process_key(struct ieee80211vap *,
254280088Sadrian		    const struct ieee80211_key *, int);
255278366Sadrianstatic int	wpi_key_set(struct ieee80211vap *,
256288635Sadrian		    const struct ieee80211_key *);
257278366Sadrianstatic int	wpi_key_delete(struct ieee80211vap *,
258278366Sadrian		    const struct ieee80211_key *);
259278366Sadrianstatic int	wpi_post_alive(struct wpi_softc *);
260289124Sadrianstatic int	wpi_load_bootcode(struct wpi_softc *, const uint8_t *,
261289124Sadrian		    uint32_t);
262278366Sadrianstatic int	wpi_load_firmware(struct wpi_softc *);
263278366Sadrianstatic int	wpi_read_firmware(struct wpi_softc *);
264278366Sadrianstatic void	wpi_unload_firmware(struct wpi_softc *);
265278366Sadrianstatic int	wpi_clock_wait(struct wpi_softc *);
266278366Sadrianstatic int	wpi_apm_init(struct wpi_softc *);
267278366Sadrianstatic void	wpi_apm_stop_master(struct wpi_softc *);
268278366Sadrianstatic void	wpi_apm_stop(struct wpi_softc *);
269278366Sadrianstatic void	wpi_nic_config(struct wpi_softc *);
270278366Sadrianstatic int	wpi_hw_init(struct wpi_softc *);
271278366Sadrianstatic void	wpi_hw_stop(struct wpi_softc *);
272278366Sadrianstatic void	wpi_radio_on(void *, int);
273278366Sadrianstatic void	wpi_radio_off(void *, int);
274287197Sglebiusstatic int	wpi_init(struct wpi_softc *);
275278366Sadrianstatic void	wpi_stop_locked(struct wpi_softc *);
276173362Sbenjscstatic void	wpi_stop(struct wpi_softc *);
277278366Sadrianstatic void	wpi_scan_start(struct ieee80211com *);
278278366Sadrianstatic void	wpi_scan_end(struct ieee80211com *);
279278366Sadrianstatic void	wpi_set_channel(struct ieee80211com *);
280278366Sadrianstatic void	wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
281278366Sadrianstatic void	wpi_scan_mindwell(struct ieee80211_scan_state *);
282278366Sadrianstatic void	wpi_hw_reset(void *, int);
283173362Sbenjsc
284173362Sbenjscstatic device_method_t wpi_methods[] = {
285173362Sbenjsc	/* Device interface */
286173362Sbenjsc	DEVMETHOD(device_probe,		wpi_probe),
287173362Sbenjsc	DEVMETHOD(device_attach,	wpi_attach),
288173362Sbenjsc	DEVMETHOD(device_detach,	wpi_detach),
289173362Sbenjsc	DEVMETHOD(device_shutdown,	wpi_shutdown),
290173362Sbenjsc	DEVMETHOD(device_suspend,	wpi_suspend),
291173362Sbenjsc	DEVMETHOD(device_resume,	wpi_resume),
292173362Sbenjsc
293260064Smarius	DEVMETHOD_END
294173362Sbenjsc};
295173362Sbenjsc
296173362Sbenjscstatic driver_t wpi_driver = {
297173362Sbenjsc	"wpi",
298173362Sbenjsc	wpi_methods,
299173362Sbenjsc	sizeof (struct wpi_softc)
300173362Sbenjsc};
301173362Sbenjscstatic devclass_t wpi_devclass;
302173362Sbenjsc
303260064SmariusDRIVER_MODULE(wpi, pci, wpi_driver, wpi_devclass, NULL, NULL);
304173362Sbenjsc
305222543SbschmidtMODULE_VERSION(wpi, 1);
306222543Sbschmidt
307278366SadrianMODULE_DEPEND(wpi, pci,  1, 1, 1);
308278366SadrianMODULE_DEPEND(wpi, wlan, 1, 1, 1);
309278366SadrianMODULE_DEPEND(wpi, firmware, 1, 1, 1);
310260064Smarius
311173362Sbenjscstatic int
312173362Sbenjscwpi_probe(device_t dev)
313173362Sbenjsc{
314173362Sbenjsc	const struct wpi_ident *ident;
315173362Sbenjsc
316173362Sbenjsc	for (ident = wpi_ident_table; ident->name != NULL; ident++) {
317173362Sbenjsc		if (pci_get_vendor(dev) == ident->vendor &&
318173362Sbenjsc		    pci_get_device(dev) == ident->device) {
319173362Sbenjsc			device_set_desc(dev, ident->name);
320260064Smarius			return (BUS_PROBE_DEFAULT);
321173362Sbenjsc		}
322173362Sbenjsc	}
323173362Sbenjsc	return ENXIO;
324173362Sbenjsc}
325173362Sbenjsc
326173362Sbenjscstatic int
327173362Sbenjscwpi_attach(device_t dev)
328173362Sbenjsc{
329278366Sadrian	struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev);
330278366Sadrian	struct ieee80211com *ic;
331289124Sadrian	uint8_t i;
332289124Sadrian	int error, rid;
333280061Sadrian#ifdef WPI_DEBUG
334280061Sadrian	int supportsa = 1;
335173362Sbenjsc	const struct wpi_ident *ident;
336280061Sadrian#endif
337173362Sbenjsc
338173362Sbenjsc	sc->sc_dev = dev;
339173362Sbenjsc
340280059Sadrian#ifdef WPI_DEBUG
341278366Sadrian	error = resource_int_value(device_get_name(sc->sc_dev),
342278366Sadrian	    device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug));
343278366Sadrian	if (error != 0)
344278366Sadrian		sc->sc_debug = 0;
345278366Sadrian#else
346278366Sadrian	sc->sc_debug = 0;
347278366Sadrian#endif
348173362Sbenjsc
349278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
350278366Sadrian
351173362Sbenjsc	/*
352278366Sadrian	 * Get the offset of the PCI Express Capability Structure in PCI
353278366Sadrian	 * Configuration Space.
354278366Sadrian	 */
355278366Sadrian	error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
356278366Sadrian	if (error != 0) {
357278366Sadrian		device_printf(dev, "PCIe capability structure not found!\n");
358278366Sadrian		return error;
359278366Sadrian	}
360278366Sadrian
361278366Sadrian	/*
362173362Sbenjsc	 * Some card's only support 802.11b/g not a, check to see if
363173362Sbenjsc	 * this is one such card. A 0x0 in the subdevice table indicates
364173362Sbenjsc	 * the entire subdevice range is to be ignored.
365173362Sbenjsc	 */
366280061Sadrian#ifdef WPI_DEBUG
367173362Sbenjsc	for (ident = wpi_ident_table; ident->name != NULL; ident++) {
368173362Sbenjsc		if (ident->subdevice &&
369173362Sbenjsc		    pci_get_subdevice(dev) == ident->subdevice) {
370173362Sbenjsc		    supportsa = 0;
371173362Sbenjsc		    break;
372173362Sbenjsc		}
373173362Sbenjsc	}
374280061Sadrian#endif
375173362Sbenjsc
376278366Sadrian	/* Clear device-specific "PCI retry timeout" register (41h). */
377173362Sbenjsc	pci_write_config(dev, 0x41, 0, 1);
378173362Sbenjsc
379278366Sadrian	/* Enable bus-mastering. */
380173362Sbenjsc	pci_enable_busmaster(dev);
381173362Sbenjsc
382260064Smarius	rid = PCIR_BAR(0);
383260064Smarius	sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
384173362Sbenjsc	    RF_ACTIVE);
385173362Sbenjsc	if (sc->mem == NULL) {
386278366Sadrian		device_printf(dev, "can't map mem space\n");
387280091Sadrian		return ENOMEM;
388173362Sbenjsc	}
389173362Sbenjsc	sc->sc_st = rman_get_bustag(sc->mem);
390173362Sbenjsc	sc->sc_sh = rman_get_bushandle(sc->mem);
391173362Sbenjsc
392289124Sadrian	rid = 1;
393289124Sadrian	if (pci_alloc_msi(dev, &rid) == 0)
394278366Sadrian		rid = 1;
395289124Sadrian	else
396289124Sadrian		rid = 0;
397278366Sadrian	/* Install interrupt handler. */
398278366Sadrian	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
399278366Sadrian	    (rid != 0 ? 0 : RF_SHAREABLE));
400173362Sbenjsc	if (sc->irq == NULL) {
401278366Sadrian		device_printf(dev, "can't map interrupt\n");
402173362Sbenjsc		error = ENOMEM;
403173362Sbenjsc		goto fail;
404173362Sbenjsc	}
405173362Sbenjsc
406278366Sadrian	WPI_LOCK_INIT(sc);
407280113Sadrian	WPI_TX_LOCK_INIT(sc);
408280108Sadrian	WPI_RXON_LOCK_INIT(sc);
409280077Sadrian	WPI_NT_LOCK_INIT(sc);
410280071Sadrian	WPI_TXQ_LOCK_INIT(sc);
411280112Sadrian	WPI_TXQ_STATE_LOCK_INIT(sc);
412278366Sadrian
413278366Sadrian	/* Allocate DMA memory for firmware transfers. */
414173362Sbenjsc	if ((error = wpi_alloc_fwmem(sc)) != 0) {
415278366Sadrian		device_printf(dev,
416278366Sadrian		    "could not allocate memory for firmware, error %d\n",
417278366Sadrian		    error);
418173362Sbenjsc		goto fail;
419173362Sbenjsc	}
420173362Sbenjsc
421278366Sadrian	/* Allocate shared page. */
422173362Sbenjsc	if ((error = wpi_alloc_shared(sc)) != 0) {
423173362Sbenjsc		device_printf(dev, "could not allocate shared page\n");
424173362Sbenjsc		goto fail;
425173362Sbenjsc	}
426173362Sbenjsc
427278366Sadrian	/* Allocate TX rings - 4 for QoS purposes, 1 for commands. */
428289126Sadrian	for (i = 0; i < WPI_DRV_NTXQUEUES; i++) {
429278366Sadrian		if ((error = wpi_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
430278366Sadrian			device_printf(dev,
431278366Sadrian			    "could not allocate TX ring %d, error %d\n", i,
432278366Sadrian			    error);
433278366Sadrian			goto fail;
434173362Sbenjsc		}
435173362Sbenjsc	}
436173362Sbenjsc
437278366Sadrian	/* Allocate RX ring. */
438278366Sadrian	if ((error = wpi_alloc_rx_ring(sc)) != 0) {
439278366Sadrian		device_printf(dev, "could not allocate RX ring, error %d\n",
440278366Sadrian		    error);
441173362Sbenjsc		goto fail;
442173362Sbenjsc	}
443173362Sbenjsc
444278366Sadrian	/* Clear pending interrupts. */
445278366Sadrian	WPI_WRITE(sc, WPI_INT, 0xffffffff);
446173362Sbenjsc
447287197Sglebius	ic = &sc->sc_ic;
448283537Sglebius	ic->ic_softc = sc;
449283527Sglebius	ic->ic_name = device_get_nameunit(dev);
450178354Ssam	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
451178354Ssam	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
452173362Sbenjsc
453278366Sadrian	/* Set device capabilities. */
454173362Sbenjsc	ic->ic_caps =
455178957Ssam		  IEEE80211_C_STA		/* station mode supported */
456278366Sadrian		| IEEE80211_C_IBSS		/* IBSS mode supported */
457280105Sadrian		| IEEE80211_C_HOSTAP		/* Host access point mode */
458178957Ssam		| IEEE80211_C_MONITOR		/* monitor mode supported */
459278366Sadrian		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
460278366Sadrian		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
461173362Sbenjsc		| IEEE80211_C_TXPMGT		/* tx power management */
462173362Sbenjsc		| IEEE80211_C_SHSLOT		/* short slot time supported */
463278366Sadrian		| IEEE80211_C_WPA		/* 802.11i */
464173362Sbenjsc		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
465278366Sadrian		| IEEE80211_C_WME		/* 802.11e */
466278366Sadrian		| IEEE80211_C_PMGT		/* Station-side power mgmt */
467173362Sbenjsc		;
468173362Sbenjsc
469278366Sadrian	ic->ic_cryptocaps =
470278366Sadrian		  IEEE80211_CRYPTO_AES_CCM;
471278366Sadrian
472173362Sbenjsc	/*
473173362Sbenjsc	 * Read in the eeprom and also setup the channels for
474173362Sbenjsc	 * net80211. We don't set the rates as net80211 does this for us
475173362Sbenjsc	 */
476287197Sglebius	if ((error = wpi_read_eeprom(sc, ic->ic_macaddr)) != 0) {
477278366Sadrian		device_printf(dev, "could not read EEPROM, error %d\n",
478278366Sadrian		    error);
479278366Sadrian		goto fail;
480280059Sadrian	}
481173362Sbenjsc
482280059Sadrian#ifdef WPI_DEBUG
483278366Sadrian	if (bootverbose) {
484280059Sadrian		device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n",
485280059Sadrian		    sc->domain);
486280059Sadrian		device_printf(sc->sc_dev, "Hardware Type: %c\n",
487280059Sadrian		    sc->type > 1 ? 'B': '?');
488280059Sadrian		device_printf(sc->sc_dev, "Hardware Revision: %c\n",
489280076Sadrian		    ((sc->rev & 0xf0) == 0xd0) ? 'D': '?');
490280059Sadrian		device_printf(sc->sc_dev, "SKU %s support 802.11a\n",
491280059Sadrian		    supportsa ? "does" : "does not");
492173362Sbenjsc
493280059Sadrian		/* XXX hw_config uses the PCIDEV for the Hardware rev. Must
494280059Sadrian		   check what sc->rev really represents - benjsc 20070615 */
495173362Sbenjsc	}
496278366Sadrian#endif
497173362Sbenjsc
498287197Sglebius	ieee80211_ifattach(ic);
499278366Sadrian	ic->ic_vap_create = wpi_vap_create;
500278366Sadrian	ic->ic_vap_delete = wpi_vap_delete;
501287197Sglebius	ic->ic_parent = wpi_parent;
502178354Ssam	ic->ic_raw_xmit = wpi_raw_xmit;
503287197Sglebius	ic->ic_transmit = wpi_transmit;
504278366Sadrian	ic->ic_node_alloc = wpi_node_alloc;
505278366Sadrian	sc->sc_node_free = ic->ic_node_free;
506278366Sadrian	ic->ic_node_free = wpi_node_free;
507278366Sadrian	ic->ic_wme.wme_update = wpi_updateedca;
508278366Sadrian	ic->ic_update_promisc = wpi_update_promisc;
509278366Sadrian	ic->ic_update_mcast = wpi_update_mcast;
510280079Sadrian	ic->ic_newassoc = wpi_newassoc;
511173362Sbenjsc	ic->ic_scan_start = wpi_scan_start;
512173362Sbenjsc	ic->ic_scan_end = wpi_scan_end;
513173362Sbenjsc	ic->ic_set_channel = wpi_set_channel;
514173362Sbenjsc	ic->ic_scan_curchan = wpi_scan_curchan;
515173362Sbenjsc	ic->ic_scan_mindwell = wpi_scan_mindwell;
516278366Sadrian	ic->ic_setregdomain = wpi_setregdomain;
517173362Sbenjsc
518282400Sadrian	sc->sc_update_rx_ring = wpi_update_rx_ring;
519282400Sadrian	sc->sc_update_tx_ring = wpi_update_tx_ring;
520282400Sadrian
521278366Sadrian	wpi_radiotap_attach(sc);
522173362Sbenjsc
523280108Sadrian	callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0);
524280108Sadrian	callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0);
525280112Sadrian	callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0);
526278366Sadrian	callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0);
527278366Sadrian	TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc);
528278366Sadrian	TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
529278366Sadrian	TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc);
530173362Sbenjsc
531280120Sadrian	sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK,
532280120Sadrian	    taskqueue_thread_enqueue, &sc->sc_tq);
533280120Sadrian	error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "wpi_taskq");
534280120Sadrian	if (error != 0) {
535280120Sadrian		device_printf(dev, "can't start threads, error %d\n", error);
536280120Sadrian		goto fail;
537280120Sadrian	}
538280120Sadrian
539278366Sadrian	wpi_sysctlattach(sc);
540278366Sadrian
541173362Sbenjsc	/*
542173362Sbenjsc	 * Hook our interrupt after all initialization is complete.
543173362Sbenjsc	 */
544278366Sadrian	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
545177043Sthompsa	    NULL, wpi_intr, sc, &sc->sc_ih);
546173362Sbenjsc	if (error != 0) {
547278366Sadrian		device_printf(dev, "can't establish interrupt, error %d\n",
548278366Sadrian		    error);
549173362Sbenjsc		goto fail;
550173362Sbenjsc	}
551173362Sbenjsc
552177043Sthompsa	if (bootverbose)
553177043Sthompsa		ieee80211_announce(ic);
554278366Sadrian
555278366Sadrian#ifdef WPI_DEBUG
556278366Sadrian	if (sc->sc_debug & WPI_DEBUG_HW)
557278366Sadrian		ieee80211_announce_channels(ic);
558173362Sbenjsc#endif
559278366Sadrian
560278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
561173362Sbenjsc	return 0;
562173362Sbenjsc
563173362Sbenjscfail:	wpi_detach(dev);
564278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
565278366Sadrian	return error;
566173362Sbenjsc}
567173362Sbenjsc
568278366Sadrian/*
569278366Sadrian * Attach the interface to 802.11 radiotap.
570278366Sadrian */
571278366Sadrianstatic void
572278366Sadrianwpi_radiotap_attach(struct wpi_softc *sc)
573278366Sadrian{
574287197Sglebius	struct wpi_rx_radiotap_header *rxtap = &sc->sc_rxtap;
575287197Sglebius	struct wpi_tx_radiotap_header *txtap = &sc->sc_txtap;
576287197Sglebius
577278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
578287197Sglebius	ieee80211_radiotap_attach(&sc->sc_ic,
579287197Sglebius	    &txtap->wt_ihdr, sizeof(*txtap), WPI_TX_RADIOTAP_PRESENT,
580287197Sglebius	    &rxtap->wr_ihdr, sizeof(*rxtap), WPI_RX_RADIOTAP_PRESENT);
581278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
582278366Sadrian}
583278366Sadrian
584278366Sadrianstatic void
585278366Sadrianwpi_sysctlattach(struct wpi_softc *sc)
586278366Sadrian{
587280059Sadrian#ifdef WPI_DEBUG
588278366Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
589278366S