1173362Sbenjsc/*-
2173362Sbenjsc * Copyright (c) 2006,2007
3173362Sbenjsc *	Damien Bergamini <damien.bergamini@free.fr>
4173362Sbenjsc *	Benjamin Close <Benjamin.Close@clearchain.com>
5292176Savos * Copyright (c) 2015 Andriy Voskoboinyk <avos@FreeBSD.org>
6173362Sbenjsc *
7173362Sbenjsc * Permission to use, copy, modify, and distribute this software for any
8173362Sbenjsc * purpose with or without fee is hereby granted, provided that the above
9173362Sbenjsc * copyright notice and this permission notice appear in all copies.
10173362Sbenjsc *
11173362Sbenjsc * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12173362Sbenjsc * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13173362Sbenjsc * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14173362Sbenjsc * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15173362Sbenjsc * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16173362Sbenjsc * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17173362Sbenjsc * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18173362Sbenjsc */
19173362Sbenjsc
20173362Sbenjsc#include <sys/cdefs.h>
21173362Sbenjsc__FBSDID("$FreeBSD$");
22173362Sbenjsc
23173362Sbenjsc/*
24173362Sbenjsc * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
25173362Sbenjsc *
26173362Sbenjsc * The 3945ABG network adapter doesn't use traditional hardware as
27173362Sbenjsc * many other adaptors do. Instead at run time the eeprom is set into a known
28173362Sbenjsc * state and told to load boot firmware. The boot firmware loads an init and a
29173362Sbenjsc * main  binary firmware image into SRAM on the card via DMA.
30173362Sbenjsc * Once the firmware is loaded, the driver/hw then
31218909Sbrucec * communicate by way of circular dma rings via the SRAM to the firmware.
32173362Sbenjsc *
33173362Sbenjsc * There is 6 memory rings. 1 command ring, 1 rx data ring & 4 tx data rings.
34173362Sbenjsc * The 4 tx data rings allow for prioritization QoS.
35173362Sbenjsc *
36173362Sbenjsc * The rx data ring consists of 32 dma buffers. Two registers are used to
37173362Sbenjsc * indicate where in the ring the driver and the firmware are up to. The
38173362Sbenjsc * driver sets the initial read index (reg1) and the initial write index (reg2),
39173362Sbenjsc * the firmware updates the read index (reg1) on rx of a packet and fires an
40173362Sbenjsc * interrupt. The driver then processes the buffers starting at reg1 indicating
41173362Sbenjsc * to the firmware which buffers have been accessed by updating reg2. At the
42173362Sbenjsc * same time allocating new memory for the processed buffer.
43173362Sbenjsc *
44173362Sbenjsc * A similar thing happens with the tx rings. The difference is the firmware
45173362Sbenjsc * stop processing buffers once the queue is full and until confirmation
46278764Sadrian * of a successful transmition (tx_done) has occurred.
47173362Sbenjsc *
48173362Sbenjsc * The command ring operates in the same manner as the tx queues.
49173362Sbenjsc *
50173362Sbenjsc * All communication direct to the card (ie eeprom) is classed as Stage1
51173362Sbenjsc * communication
52173362Sbenjsc *
53173362Sbenjsc * All communication via the firmware to the card is classed as State2.
54173362Sbenjsc * The firmware consists of 2 parts. A bootstrap firmware and a runtime
55173362Sbenjsc * firmware. The bootstrap firmware and runtime firmware are loaded
56173362Sbenjsc * from host memory via dma to the card then told to execute. From this point
57173362Sbenjsc * on the majority of communications between the driver and the card goes
58173362Sbenjsc * via the firmware.
59173362Sbenjsc */
60173362Sbenjsc
61236381Sadrian#include "opt_wlan.h"
62278366Sadrian#include "opt_wpi.h"
63236381Sadrian
64173362Sbenjsc#include <sys/param.h>
65173362Sbenjsc#include <sys/sysctl.h>
66173362Sbenjsc#include <sys/sockio.h>
67173362Sbenjsc#include <sys/mbuf.h>
68173362Sbenjsc#include <sys/kernel.h>
69173362Sbenjsc#include <sys/socket.h>
70173362Sbenjsc#include <sys/systm.h>
71173362Sbenjsc#include <sys/malloc.h>
72173362Sbenjsc#include <sys/queue.h>
73173362Sbenjsc#include <sys/taskqueue.h>
74173362Sbenjsc#include <sys/module.h>
75173362Sbenjsc#include <sys/bus.h>
76173362Sbenjsc#include <sys/endian.h>
77173362Sbenjsc#include <sys/linker.h>
78173362Sbenjsc#include <sys/firmware.h>
79173362Sbenjsc
80173362Sbenjsc#include <machine/bus.h>
81173362Sbenjsc#include <machine/resource.h>
82173362Sbenjsc#include <sys/rman.h>
83173362Sbenjsc
84173362Sbenjsc#include <dev/pci/pcireg.h>
85173362Sbenjsc#include <dev/pci/pcivar.h>
86173362Sbenjsc
87173362Sbenjsc#include <net/bpf.h>
88173362Sbenjsc#include <net/if.h>
89257176Sglebius#include <net/if_var.h>
90173362Sbenjsc#include <net/if_arp.h>
91173362Sbenjsc#include <net/ethernet.h>
92173362Sbenjsc#include <net/if_dl.h>
93173362Sbenjsc#include <net/if_media.h>
94173362Sbenjsc#include <net/if_types.h>
95173362Sbenjsc
96278366Sadrian#include <netinet/in.h>
97278366Sadrian#include <netinet/in_systm.h>
98278366Sadrian#include <netinet/in_var.h>
99278366Sadrian#include <netinet/if_ether.h>
100278366Sadrian#include <netinet/ip.h>
101278366Sadrian
102173362Sbenjsc#include <net80211/ieee80211_var.h>
103173362Sbenjsc#include <net80211/ieee80211_radiotap.h>
104173362Sbenjsc#include <net80211/ieee80211_regdomain.h>
105206358Srpaulo#include <net80211/ieee80211_ratectl.h>
106173362Sbenjsc
107173362Sbenjsc#include <dev/wpi/if_wpireg.h>
108173362Sbenjsc#include <dev/wpi/if_wpivar.h>
109278366Sadrian#include <dev/wpi/if_wpi_debug.h>
110173362Sbenjsc
111173362Sbenjscstruct wpi_ident {
112173362Sbenjsc	uint16_t	vendor;
113173362Sbenjsc	uint16_t	device;
114173362Sbenjsc	uint16_t	subdevice;
115173362Sbenjsc	const char	*name;
116173362Sbenjsc};
117173362Sbenjsc
118173362Sbenjscstatic const struct wpi_ident wpi_ident_table[] = {
119173362Sbenjsc	/* The below entries support ABG regardless of the subid */
120173362Sbenjsc	{ 0x8086, 0x4222,    0x0, "Intel(R) PRO/Wireless 3945ABG" },
121173362Sbenjsc	{ 0x8086, 0x4227,    0x0, "Intel(R) PRO/Wireless 3945ABG" },
122173362Sbenjsc	/* The below entries only support BG */
123182127Sbenjsc	{ 0x8086, 0x4222, 0x1005, "Intel(R) PRO/Wireless 3945BG"  },
124182127Sbenjsc	{ 0x8086, 0x4222, 0x1034, "Intel(R) PRO/Wireless 3945BG"  },
125182127Sbenjsc	{ 0x8086, 0x4227, 0x1014, "Intel(R) PRO/Wireless 3945BG"  },
126182127Sbenjsc	{ 0x8086, 0x4222, 0x1044, "Intel(R) PRO/Wireless 3945BG"  },
127173362Sbenjsc	{ 0, 0, 0, NULL }
128173362Sbenjsc};
129173362Sbenjsc
130278366Sadrianstatic int	wpi_probe(device_t);
131278366Sadrianstatic int	wpi_attach(device_t);
132278366Sadrianstatic void	wpi_radiotap_attach(struct wpi_softc *);
133278366Sadrianstatic void	wpi_sysctlattach(struct wpi_softc *);
134280083Sadrianstatic void	wpi_init_beacon(struct wpi_vap *);
135178354Ssamstatic struct ieee80211vap *wpi_vap_create(struct ieee80211com *,
136228621Sbschmidt		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
137228621Sbschmidt		    const uint8_t [IEEE80211_ADDR_LEN],
138228621Sbschmidt		    const uint8_t [IEEE80211_ADDR_LEN]);
139178354Ssamstatic void	wpi_vap_delete(struct ieee80211vap *);
140278366Sadrianstatic int	wpi_detach(device_t);
141278366Sadrianstatic int	wpi_shutdown(device_t);
142278366Sadrianstatic int	wpi_suspend(device_t);
143278366Sadrianstatic int	wpi_resume(device_t);
144278366Sadrianstatic int	wpi_nic_lock(struct wpi_softc *);
145278366Sadrianstatic int	wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
146278366Sadrianstatic void	wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
147173362Sbenjscstatic int	wpi_dma_contig_alloc(struct wpi_softc *, struct wpi_dma_info *,
148278366Sadrian		    void **, bus_size_t, bus_size_t);
149173362Sbenjscstatic void	wpi_dma_contig_free(struct wpi_dma_info *);
150173362Sbenjscstatic int	wpi_alloc_shared(struct wpi_softc *);
151173362Sbenjscstatic void	wpi_free_shared(struct wpi_softc *);
152278366Sadrianstatic int	wpi_alloc_fwmem(struct wpi_softc *);
153278366Sadrianstatic void	wpi_free_fwmem(struct wpi_softc *);
154278366Sadrianstatic int	wpi_alloc_rx_ring(struct wpi_softc *);
155278366Sadrianstatic void	wpi_update_rx_ring(struct wpi_softc *);
156282400Sadrianstatic void	wpi_update_rx_ring_ps(struct wpi_softc *);
157278366Sadrianstatic void	wpi_reset_rx_ring(struct wpi_softc *);
158278366Sadrianstatic void	wpi_free_rx_ring(struct wpi_softc *);
159173362Sbenjscstatic int	wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
160289124Sadrian		    uint8_t);
161278366Sadrianstatic void	wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
162282400Sadrianstatic void	wpi_update_tx_ring_ps(struct wpi_softc *,
163282400Sadrian		    struct wpi_tx_ring *);
164173362Sbenjscstatic void	wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
165173362Sbenjscstatic void	wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
166278366Sadrianstatic int	wpi_read_eeprom(struct wpi_softc *,
167278366Sadrian		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
168278366Sadrianstatic uint32_t	wpi_eeprom_channel_flags(struct wpi_eeprom_chan *);
169293716Savosstatic void	wpi_read_eeprom_band(struct wpi_softc *, uint8_t, int, int *,
170293716Savos		    struct ieee80211_channel[]);
171289124Sadrianstatic int	wpi_read_eeprom_channels(struct wpi_softc *, uint8_t);
172278366Sadrianstatic struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
173278366Sadrian		    struct ieee80211_channel *);
174293716Savosstatic void	wpi_getradiocaps(struct ieee80211com *, int, int *,
175293716Savos		    struct ieee80211_channel[]);
176278366Sadrianstatic int	wpi_setregdomain(struct ieee80211com *,
177278366Sadrian		    struct ieee80211_regdomain *, int,
178278366Sadrian		    struct ieee80211_channel[]);
179289124Sadrianstatic int	wpi_read_eeprom_group(struct wpi_softc *, uint8_t);
180278366Sadrianstatic struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *,
181278366Sadrian		    const uint8_t mac[IEEE80211_ADDR_LEN]);
182282401Sadrianstatic void	wpi_node_free(struct ieee80211_node *);
183289125Sadrianstatic void	wpi_ibss_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
184283536Sadrian		    const struct ieee80211_rx_stats *,
185283536Sadrian		    int, int);
186282401Sadrianstatic void	wpi_restore_node(void *, struct ieee80211_node *);
187282401Sadrianstatic void	wpi_restore_node_table(struct wpi_softc *, struct wpi_vap *);
188178354Ssamstatic int	wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
189278366Sadrianstatic void	wpi_calib_timeout(void *);
190278366Sadrianstatic void	wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
191173362Sbenjsc		    struct wpi_rx_data *);
192278366Sadrianstatic void	wpi_rx_statistics(struct wpi_softc *, struct wpi_rx_desc *,
193278366Sadrian		    struct wpi_rx_data *);
194278366Sadrianstatic void	wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *);
195278366Sadrianstatic void	wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *);
196173362Sbenjscstatic void	wpi_notif_intr(struct wpi_softc *);
197278366Sadrianstatic void	wpi_wakeup_intr(struct wpi_softc *);
198280093Sadrian#ifdef WPI_DEBUG
199280093Sadrianstatic void	wpi_debug_registers(struct wpi_softc *);
200280093Sadrian#endif
201278366Sadrianstatic void	wpi_fatal_intr(struct wpi_softc *);
202173362Sbenjscstatic void	wpi_intr(void *);
203289163Sadrianstatic void	wpi_free_txfrags(struct wpi_softc *, uint16_t);
204278366Sadrianstatic int	wpi_cmd2(struct wpi_softc *, struct wpi_buf *);
205173362Sbenjscstatic int	wpi_tx_data(struct wpi_softc *, struct mbuf *,
206278366Sadrian		    struct ieee80211_node *);
207278366Sadrianstatic int	wpi_tx_data_raw(struct wpi_softc *, struct mbuf *,
208278366Sadrian		    struct ieee80211_node *,
209278366Sadrian		    const struct ieee80211_bpf_params *);
210278366Sadrianstatic int	wpi_raw_xmit(struct ieee80211_node *, struct mbuf *,
211278366Sadrian		    const struct ieee80211_bpf_params *);
212287197Sglebiusstatic int	wpi_transmit(struct ieee80211com *, struct mbuf *);
213278366Sadrianstatic void	wpi_watchdog_rfkill(void *);
214280106Sadrianstatic void	wpi_scan_timeout(void *);
215280109Sadrianstatic void	wpi_tx_timeout(void *);
216287197Sglebiusstatic void	wpi_parent(struct ieee80211com *);
217289124Sadrianstatic int	wpi_cmd(struct wpi_softc *, uint8_t, const void *, uint16_t,
218289124Sadrian		    int);
219173362Sbenjscstatic int	wpi_mrr_setup(struct wpi_softc *);
220278366Sadrianstatic int	wpi_add_node(struct wpi_softc *, struct ieee80211_node *);
221278366Sadrianstatic int	wpi_add_broadcast_node(struct wpi_softc *, int);
222278366Sadrianstatic int	wpi_add_ibss_node(struct wpi_softc *, struct ieee80211_node *);
223278366Sadrianstatic void	wpi_del_node(struct wpi_softc *, struct ieee80211_node *);
224278366Sadrianstatic int	wpi_updateedca(struct ieee80211com *);
225278366Sadrianstatic void	wpi_set_promisc(struct wpi_softc *);
226283540Sglebiusstatic void	wpi_update_promisc(struct ieee80211com *);
227283540Sglebiusstatic void	wpi_update_mcast(struct ieee80211com *);
228173362Sbenjscstatic void	wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
229278366Sadrianstatic int	wpi_set_timing(struct wpi_softc *, struct ieee80211_node *);
230278366Sadrianstatic void	wpi_power_calibration(struct wpi_softc *);
231278366Sadrianstatic int	wpi_set_txpower(struct wpi_softc *, int);
232278366Sadrianstatic int	wpi_get_power_index(struct wpi_softc *,
233281287Sadrian		    struct wpi_power_group *, uint8_t, int, int);
234278366Sadrianstatic int	wpi_set_pslevel(struct wpi_softc *, uint8_t, int, int);
235278366Sadrianstatic int	wpi_send_btcoex(struct wpi_softc *);
236278366Sadrianstatic int	wpi_send_rxon(struct wpi_softc *, int, int);
237278366Sadrianstatic int	wpi_config(struct wpi_softc *);
238278366Sadrianstatic uint16_t	wpi_get_active_dwell_time(struct wpi_softc *,
239278366Sadrian		    struct ieee80211_channel *, uint8_t);
240278366Sadrianstatic uint16_t	wpi_limit_dwell(struct wpi_softc *, uint16_t);
241278366Sadrianstatic uint16_t	wpi_get_passive_dwell_time(struct wpi_softc *,
242278366Sadrian		    struct ieee80211_channel *);
243282383Sadrianstatic uint32_t	wpi_get_scan_pause_time(uint32_t, uint16_t);
244278366Sadrianstatic int	wpi_scan(struct wpi_softc *, struct ieee80211_channel *);
245278366Sadrianstatic int	wpi_auth(struct wpi_softc *, struct ieee80211vap *);
246280084Sadrianstatic int	wpi_config_beacon(struct wpi_vap *);
247280084Sadrianstatic int	wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
248278366Sadrianstatic void	wpi_update_beacon(struct ieee80211vap *, int);
249280079Sadrianstatic void	wpi_newassoc(struct ieee80211_node *, int);
250178354Ssamstatic int	wpi_run(struct wpi_softc *, struct ieee80211vap *);
251280088Sadrianstatic int	wpi_load_key(struct ieee80211_node *,
252280088Sadrian		    const struct ieee80211_key *);
253280088Sadrianstatic void	wpi_load_key_cb(void *, struct ieee80211_node *);
254280088Sadrianstatic int	wpi_set_global_keys(struct ieee80211_node *);
255280088Sadrianstatic int	wpi_del_key(struct ieee80211_node *,
256280088Sadrian		    const struct ieee80211_key *);
257280088Sadrianstatic void	wpi_del_key_cb(void *, struct ieee80211_node *);
258280088Sadrianstatic int	wpi_process_key(struct ieee80211vap *,
259280088Sadrian		    const struct ieee80211_key *, int);
260278366Sadrianstatic int	wpi_key_set(struct ieee80211vap *,
261288635Sadrian		    const struct ieee80211_key *);
262278366Sadrianstatic int	wpi_key_delete(struct ieee80211vap *,
263278366Sadrian		    const struct ieee80211_key *);
264278366Sadrianstatic int	wpi_post_alive(struct wpi_softc *);
265289124Sadrianstatic int	wpi_load_bootcode(struct wpi_softc *, const uint8_t *,
266289124Sadrian		    uint32_t);
267278366Sadrianstatic int	wpi_load_firmware(struct wpi_softc *);
268278366Sadrianstatic int	wpi_read_firmware(struct wpi_softc *);
269278366Sadrianstatic void	wpi_unload_firmware(struct wpi_softc *);
270278366Sadrianstatic int	wpi_clock_wait(struct wpi_softc *);
271278366Sadrianstatic int	wpi_apm_init(struct wpi_softc *);
272278366Sadrianstatic void	wpi_apm_stop_master(struct wpi_softc *);
273278366Sadrianstatic void	wpi_apm_stop(struct wpi_softc *);
274278366Sadrianstatic void	wpi_nic_config(struct wpi_softc *);
275278366Sadrianstatic int	wpi_hw_init(struct wpi_softc *);
276278366Sadrianstatic void	wpi_hw_stop(struct wpi_softc *);
277278366Sadrianstatic void	wpi_radio_on(void *, int);
278278366Sadrianstatic void	wpi_radio_off(void *, int);
279287197Sglebiusstatic int	wpi_init(struct wpi_softc *);
280278366Sadrianstatic void	wpi_stop_locked(struct wpi_softc *);
281173362Sbenjscstatic void	wpi_stop(struct wpi_softc *);
282278366Sadrianstatic void	wpi_scan_start(struct ieee80211com *);
283278366Sadrianstatic void	wpi_scan_end(struct ieee80211com *);
284278366Sadrianstatic void	wpi_set_channel(struct ieee80211com *);
285278366Sadrianstatic void	wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
286278366Sadrianstatic void	wpi_scan_mindwell(struct ieee80211_scan_state *);
287173362Sbenjsc
288173362Sbenjscstatic device_method_t wpi_methods[] = {
289173362Sbenjsc	/* Device interface */
290173362Sbenjsc	DEVMETHOD(device_probe,		wpi_probe),
291173362Sbenjsc	DEVMETHOD(device_attach,	wpi_attach),
292173362Sbenjsc	DEVMETHOD(device_detach,	wpi_detach),
293173362Sbenjsc	DEVMETHOD(device_shutdown,	wpi_shutdown),
294173362Sbenjsc	DEVMETHOD(device_suspend,	wpi_suspend),
295173362Sbenjsc	DEVMETHOD(device_resume,	wpi_resume),
296173362Sbenjsc
297260064Smarius	DEVMETHOD_END
298173362Sbenjsc};
299173362Sbenjsc
300173362Sbenjscstatic driver_t wpi_driver = {
301173362Sbenjsc	"wpi",
302173362Sbenjsc	wpi_methods,
303173362Sbenjsc	sizeof (struct wpi_softc)
304173362Sbenjsc};
305173362Sbenjscstatic devclass_t wpi_devclass;
306173362Sbenjsc
307260064SmariusDRIVER_MODULE(wpi, pci, wpi_driver, wpi_devclass, NULL, NULL);
308173362Sbenjsc
309222543SbschmidtMODULE_VERSION(wpi, 1);
310222543Sbschmidt
311278366SadrianMODULE_DEPEND(wpi, pci,  1, 1, 1);
312278366SadrianMODULE_DEPEND(wpi, wlan, 1, 1, 1);
313278366SadrianMODULE_DEPEND(wpi, firmware, 1, 1, 1);
314260064Smarius
315173362Sbenjscstatic int
316173362Sbenjscwpi_probe(device_t dev)
317173362Sbenjsc{
318173362Sbenjsc	const struct wpi_ident *ident;
319173362Sbenjsc
320173362Sbenjsc	for (ident = wpi_ident_table; ident->name != NULL; ident++) {
321173362Sbenjsc		if (pci_get_vendor(dev) == ident->vendor &&
322173362Sbenjsc		    pci_get_device(dev) == ident->device) {
323173362Sbenjsc			device_set_desc(dev, ident->name);
324260064Smarius			return (BUS_PROBE_DEFAULT);
325173362Sbenjsc		}
326173362Sbenjsc	}
327173362Sbenjsc	return ENXIO;
328173362Sbenjsc}
329173362Sbenjsc
330173362Sbenjscstatic int
331173362Sbenjscwpi_attach(device_t dev)
332173362Sbenjsc{
333278366Sadrian	struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev);
334278366Sadrian	struct ieee80211com *ic;
335289124Sadrian	uint8_t i;
336289124Sadrian	int error, rid;
337280061Sadrian#ifdef WPI_DEBUG
338280061Sadrian	int supportsa = 1;
339173362Sbenjsc	const struct wpi_ident *ident;
340280061Sadrian#endif
341173362Sbenjsc
342173362Sbenjsc	sc->sc_dev = dev;
343173362Sbenjsc
344280059Sadrian#ifdef WPI_DEBUG
345278366Sadrian	error = resource_int_value(device_get_name(sc->sc_dev),
346278366Sadrian	    device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug));
347278366Sadrian	if (error != 0)
348278366Sadrian		sc->sc_debug = 0;
349278366Sadrian#else
350278366Sadrian	sc->sc_debug = 0;
351278366Sadrian#endif
352173362Sbenjsc
353278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
354278366Sadrian
355173362Sbenjsc	/*
356278366Sadrian	 * Get the offset of the PCI Express Capability Structure in PCI
357278366Sadrian	 * Configuration Space.
358278366Sadrian	 */
359278366Sadrian	error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
360278366Sadrian	if (error != 0) {
361278366Sadrian		device_printf(dev, "PCIe capability structure not found!\n");
362278366Sadrian		return error;
363278366Sadrian	}
364278366Sadrian
365278366Sadrian	/*
366173362Sbenjsc	 * Some card's only support 802.11b/g not a, check to see if
367173362Sbenjsc	 * this is one such card. A 0x0 in the subdevice table indicates
368173362Sbenjsc	 * the entire subdevice range is to be ignored.
369173362Sbenjsc	 */
370280061Sadrian#ifdef WPI_DEBUG
371173362Sbenjsc	for (ident = wpi_ident_table; ident->name != NULL; ident++) {
372173362Sbenjsc		if (ident->subdevice &&
373173362Sbenjsc		    pci_get_subdevice(dev) == ident->subdevice) {
374173362Sbenjsc		    supportsa = 0;
375173362Sbenjsc		    break;
376173362Sbenjsc		}
377173362Sbenjsc	}
378280061Sadrian#endif
379173362Sbenjsc
380278366Sadrian	/* Clear device-specific "PCI retry timeout" register (41h). */
381173362Sbenjsc	pci_write_config(dev, 0x41, 0, 1);
382173362Sbenjsc
383278366Sadrian	/* Enable bus-mastering. */
384173362Sbenjsc	pci_enable_busmaster(dev);
385173362Sbenjsc
386260064Smarius	rid = PCIR_BAR(0);
387260064Smarius	sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
388173362Sbenjsc	    RF_ACTIVE);
389173362Sbenjsc	if (sc->mem == NULL) {
390278366Sadrian		device_printf(dev, "can't map mem space\n");
391280091Sadrian		return ENOMEM;
392173362Sbenjsc	}
393173362Sbenjsc	sc->sc_st = rman_get_bustag(sc->mem);
394173362Sbenjsc	sc->sc_sh = rman_get_bushandle(sc->mem);
395173362Sbenjsc
396289124Sadrian	rid = 1;
397289124Sadrian	if (pci_alloc_msi(dev, &rid) == 0)
398278366Sadrian		rid = 1;
399289124Sadrian	else
400289124Sadrian		rid = 0;
401278366Sadrian	/* Install interrupt handler. */
402278366Sadrian	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
403278366Sadrian	    (rid != 0 ? 0 : RF_SHAREABLE));
404173362Sbenjsc	if (sc->irq == NULL) {
405278366Sadrian		device_printf(dev, "can't map interrupt\n");
406173362Sbenjsc		error = ENOMEM;
407173362Sbenjsc		goto fail;
408173362Sbenjsc	}
409173362Sbenjsc
410278366Sadrian	WPI_LOCK_INIT(sc);
411280113Sadrian	WPI_TX_LOCK_INIT(sc);
412280108Sadrian	WPI_RXON_LOCK_INIT(sc);
413280077Sadrian	WPI_NT_LOCK_INIT(sc);
414280071Sadrian	WPI_TXQ_LOCK_INIT(sc);
415280112Sadrian	WPI_TXQ_STATE_LOCK_INIT(sc);
416278366Sadrian
417278366Sadrian	/* Allocate DMA memory for firmware transfers. */
418173362Sbenjsc	if ((error = wpi_alloc_fwmem(sc)) != 0) {
419278366Sadrian		device_printf(dev,
420278366Sadrian		    "could not allocate memory for firmware, error %d\n",
421278366Sadrian		    error);
422173362Sbenjsc		goto fail;
423173362Sbenjsc	}
424173362Sbenjsc
425278366Sadrian	/* Allocate shared page. */
426173362Sbenjsc	if ((error = wpi_alloc_shared(sc)) != 0) {
427173362Sbenjsc		device_printf(dev, "could not allocate shared page\n");
428173362Sbenjsc		goto fail;
429173362Sbenjsc	}
430173362Sbenjsc
431278366Sadrian	/* Allocate TX rings - 4 for QoS purposes, 1 for commands. */
432289126Sadrian	for (i = 0; i < WPI_DRV_NTXQUEUES; i++) {
433278366Sadrian		if ((error = wpi_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
434278366Sadrian			device_printf(dev,
435278366Sadrian			    "could not allocate TX ring %d, error %d\n", i,
436278366Sadrian			    error);
437278366Sadrian			goto fail;
438173362Sbenjsc		}
439173362Sbenjsc	}
440173362Sbenjsc
441278366Sadrian	/* Allocate RX ring. */
442278366Sadrian	if ((error = wpi_alloc_rx_ring(sc)) != 0) {
443278366Sadrian		device_printf(dev, "could not allocate RX ring, error %d\n",
444278366Sadrian		    error);
445173362Sbenjsc		goto fail;
446173362Sbenjsc	}
447173362Sbenjsc
448278366Sadrian	/* Clear pending interrupts. */
449278366Sadrian	WPI_WRITE(sc, WPI_INT, 0xffffffff);
450173362Sbenjsc
451287197Sglebius	ic = &sc->sc_ic;
452283537Sglebius	ic->ic_softc = sc;
453283527Sglebius	ic->ic_name = device_get_nameunit(dev);
454178354Ssam	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
455178354Ssam	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
456173362Sbenjsc
457278366Sadrian	/* Set device capabilities. */
458173362Sbenjsc	ic->ic_caps =
459178957Ssam		  IEEE80211_C_STA		/* station mode supported */
460278366Sadrian		| IEEE80211_C_IBSS		/* IBSS mode supported */
461280105Sadrian		| IEEE80211_C_HOSTAP		/* Host access point mode */
462178957Ssam		| IEEE80211_C_MONITOR		/* monitor mode supported */
463278366Sadrian		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
464278366Sadrian		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
465289163Sadrian		| IEEE80211_C_TXFRAG		/* handle tx frags */
466173362Sbenjsc		| IEEE80211_C_TXPMGT		/* tx power management */
467173362Sbenjsc		| IEEE80211_C_SHSLOT		/* short slot time supported */
468278366Sadrian		| IEEE80211_C_WPA		/* 802.11i */
469173362Sbenjsc		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
470278366Sadrian		| IEEE80211_C_WME		/* 802.11e */
471278366Sadrian		| IEEE80211_C_PMGT		/* Station-side power mgmt */
472173362Sbenjsc		;
473173362Sbenjsc
474278366Sadrian	ic->ic_cryptocaps =
475278366Sadrian		  IEEE80211_CRYPTO_AES_CCM;
476278366Sadrian
477173362Sbenjsc	/*
478173362Sbenjsc	 * Read in the eeprom and also setup the channels for
479173362Sbenjsc	 * net80211. We don't set the rates as net80211 does this for us
480173362Sbenjsc	 */
481287197Sglebius	if ((error = wpi_read_eeprom(sc, ic->ic_macaddr)) != 0) {
482278366Sadrian		device_printf(dev, "could not read EEPROM, error %d\n",
483278366Sadrian		    error);
484278366Sadrian		goto fail;
485280059Sadrian	}
486173362Sbenjsc
487280059Sadrian#ifdef WPI_DEBUG
488278366Sadrian	if (bootverbose) {
489280059Sadrian		device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n",
490280059Sadrian		    sc->domain);
491280059Sadrian		device_printf(sc->sc_dev, "Hardware Type: %c\n",
492280059Sadrian		    sc->type > 1 ? 'B': '?');
493280059Sadrian		device_printf(sc->sc_dev, "Hardware Revision: %c\n",
494280076Sadrian		    ((sc->rev & 0xf0) == 0xd0) ? 'D': '?');
495280059Sadrian		device_printf(sc->sc_dev, "SKU %s support 802.11a\n",
496280059Sadrian		    supportsa ? "does" : "does not");
497173362Sbenjsc
498280059Sadrian		/* XXX hw_config uses the PCIDEV for the Hardware rev. Must
499280059Sadrian		   check what sc->rev really represents - benjsc 20070615 */
500173362Sbenjsc	}
501278366Sadrian#endif
502173362Sbenjsc
503287197Sglebius	ieee80211_ifattach(ic);
504278366Sadrian	ic->ic_vap_create = wpi_vap_create;
505278366Sadrian	ic->ic_vap_delete = wpi_vap_delete;
506287197Sglebius	ic->ic_parent = wpi_parent;
507178354Ssam	ic->ic_raw_xmit = wpi_raw_xmit;
508287197Sglebius	ic->ic_transmit = wpi_transmit;
509278366Sadrian	ic->ic_node_alloc = wpi_node_alloc;
510278366Sadrian	sc->sc_node_free = ic->ic_node_free;
511278366Sadrian	ic->ic_node_free = wpi_node_free;
512278366Sadrian	ic->ic_wme.wme_update = wpi_updateedca;
513278366Sadrian	ic->ic_update_promisc = wpi_update_promisc;
514278366Sadrian	ic->ic_update_mcast = wpi_update_mcast;
515280079Sadrian	ic->ic_newassoc = wpi_newassoc;
516173362Sbenjsc	ic->ic_scan_start = wpi_scan_start;
517173362Sbenjsc	ic->ic_scan_end = wpi_scan_end;
518173362Sbenjsc	ic->ic_set_channel = wpi_set_channel;
519173362Sbenjsc	ic->ic_scan_curchan = wpi_scan_curchan;
520173362Sbenjsc	ic->ic_scan_mindwell = wpi_scan_mindwell;
521293716Savos	ic->ic_getradiocaps = wpi_getradiocaps;
522278366Sadrian	ic->ic_setregdomain = wpi_setregdomain;
523173362Sbenjsc
524282400Sadrian	sc->sc_update_rx_ring = wpi_update_rx_ring;
525282400Sadrian	sc->sc_update_tx_ring = wpi_update_tx_ring;
526282400Sadrian
527278366Sadrian	wpi_radiotap_attach(sc);
528173362Sbenjsc
529280108Sadrian	callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0);
530280108Sadrian	callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0);
531280112Sadrian	callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0);
532278366Sadrian	callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0);
533278366Sadrian	TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
534278366Sadrian	TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc);
535173362Sbenjsc
536278366Sadrian	wpi_sysctlattach(sc);
537278366Sadrian
538173362Sbenjsc	/*
539173362Sbenjsc	 * Hook our interrupt after all initialization is complete.
540173362Sbenjsc	 */
541278366Sadrian	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
542177043Sthompsa	    NULL, wpi_intr, sc, &sc->sc_ih);
543173362Sbenjsc	if (error != 0) {
544278366Sadrian		device_printf(dev, "can't establish interrupt, error %d\n",
545278366Sadrian		    error);
546173362Sbenjsc		goto fail;
547173362Sbenjsc	}
548173362Sbenjsc
549177043Sthompsa	if (bootverbose)
550177043Sthompsa		ieee80211_announce(ic);
551278366Sadrian
552278366Sadrian#ifdef WPI_DEBUG
553278366Sadrian	if (sc->sc_debug & WPI_DEBUG_HW)
554278366Sadrian		ieee80211_announce_channels(ic);
555173362Sbenjsc#endif
556278366Sadrian
557278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
558173362Sbenjsc	return 0;
559173362Sbenjsc
560173362Sbenjscfail:	wpi_detach(dev);
561278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
562278366Sadrian	return error;
563173362Sbenjsc}
564173362Sbenjsc
565278366Sadrian/*
566278366Sadrian * Attach the interface to 802.11 radiotap.
567278366Sadrian */
568278366Sadrianstatic void
569278366Sadrianwpi_radiotap_attach(struct wpi_softc *sc)
570278366Sadrian{
571287197Sglebius	struct wpi_rx_radiotap_header *rxtap = &sc->sc_rxtap;
572287197Sglebius	struct wpi_tx_radiotap_header *txtap = &sc->sc_txtap;
573287197Sglebius
574278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
575287197Sglebius	ieee80211_radiotap_attach(&sc->sc_ic,
576287197Sglebius	    &txtap->wt_ihdr, sizeof(*txtap), WPI_TX_RADIOTAP_PRESENT,
577287197Sglebius	    &rxtap->wr_ihdr, sizeof(*rxtap), WPI_RX_RADIOTAP_PRESENT);
578278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
579278366Sadrian}
580278366Sadrian
581278366Sadrianstatic void
582278366Sadrianwpi_sysctlattach(struct wpi_softc *sc)
583278366Sadrian{
584280059Sadrian#ifdef WPI_DEBUG
585278366Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
586278366Sadrian	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
587278366Sadrian
588278366Sadrian	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
589278366Sadrian	    "debug", CTLFLAG_RW, &sc->sc_debug, sc->sc_debug,
590278366Sadrian		"control debugging printfs");
591