if_wpi.c revision 280084
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 280084 2015-03-15 20:51:56Z 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 *);
155278366Sadrianstatic void	wpi_reset_rx_ring(struct wpi_softc *);
156278366Sadrianstatic void	wpi_free_rx_ring(struct wpi_softc *);
157173362Sbenjscstatic int	wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
158278366Sadrian		    int);
159278366Sadrianstatic void	wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
160173362Sbenjscstatic void	wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
161173362Sbenjscstatic void	wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
162278366Sadrianstatic int	wpi_read_eeprom(struct wpi_softc *,
163278366Sadrian		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
164278366Sadrianstatic uint32_t	wpi_eeprom_channel_flags(struct wpi_eeprom_chan *);
165278366Sadrianstatic void	wpi_read_eeprom_band(struct wpi_softc *, int);
166278366Sadrianstatic int	wpi_read_eeprom_channels(struct wpi_softc *, int);
167278366Sadrianstatic struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
168278366Sadrian		    struct ieee80211_channel *);
169278366Sadrianstatic int	wpi_setregdomain(struct ieee80211com *,
170278366Sadrian		    struct ieee80211_regdomain *, int,
171278366Sadrian		    struct ieee80211_channel[]);
172278366Sadrianstatic int	wpi_read_eeprom_group(struct wpi_softc *, int);
173280069Sadrianstatic int	wpi_add_node_entry_adhoc(struct wpi_softc *);
174278366Sadrianstatic void	wpi_node_free(struct ieee80211_node *);
175278366Sadrianstatic struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *,
176278366Sadrian		    const uint8_t mac[IEEE80211_ADDR_LEN]);
177178354Ssamstatic int	wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
178278366Sadrianstatic void	wpi_calib_timeout(void *);
179278366Sadrianstatic void	wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
180173362Sbenjsc		    struct wpi_rx_data *);
181278366Sadrianstatic void	wpi_rx_statistics(struct wpi_softc *, struct wpi_rx_desc *,
182278366Sadrian		    struct wpi_rx_data *);
183278366Sadrianstatic void	wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *);
184278366Sadrianstatic void	wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *);
185173362Sbenjscstatic void	wpi_notif_intr(struct wpi_softc *);
186278366Sadrianstatic void	wpi_wakeup_intr(struct wpi_softc *);
187278366Sadrianstatic void	wpi_fatal_intr(struct wpi_softc *);
188173362Sbenjscstatic void	wpi_intr(void *);
189278366Sadrianstatic int	wpi_cmd2(struct wpi_softc *, struct wpi_buf *);
190173362Sbenjscstatic int	wpi_tx_data(struct wpi_softc *, struct mbuf *,
191278366Sadrian		    struct ieee80211_node *);
192278366Sadrianstatic int	wpi_tx_data_raw(struct wpi_softc *, struct mbuf *,
193278366Sadrian		    struct ieee80211_node *,
194278366Sadrian		    const struct ieee80211_bpf_params *);
195278366Sadrianstatic int	wpi_raw_xmit(struct ieee80211_node *, struct mbuf *,
196278366Sadrian		    const struct ieee80211_bpf_params *);
197173362Sbenjscstatic void	wpi_start(struct ifnet *);
198178354Ssamstatic void	wpi_start_locked(struct ifnet *);
199280078Sadrianstatic void	wpi_start_task(void *, int);
200278366Sadrianstatic void	wpi_watchdog_rfkill(void *);
201278366Sadrianstatic void	wpi_watchdog(void *);
202173362Sbenjscstatic int	wpi_ioctl(struct ifnet *, u_long, caddr_t);
203278366Sadrianstatic int	wpi_cmd(struct wpi_softc *, int, const void *, size_t, int);
204173362Sbenjscstatic int	wpi_mrr_setup(struct wpi_softc *);
205278366Sadrianstatic int	wpi_add_node(struct wpi_softc *, struct ieee80211_node *);
206278366Sadrianstatic int	wpi_add_broadcast_node(struct wpi_softc *, int);
207278366Sadrianstatic int	wpi_add_ibss_node(struct wpi_softc *, struct ieee80211_node *);
208278366Sadrianstatic void	wpi_del_node(struct wpi_softc *, struct ieee80211_node *);
209278366Sadrianstatic int	wpi_updateedca(struct ieee80211com *);
210278366Sadrianstatic void	wpi_set_promisc(struct wpi_softc *);
211278366Sadrianstatic void	wpi_update_promisc(struct ifnet *);
212278366Sadrianstatic void	wpi_update_mcast(struct ifnet *);
213173362Sbenjscstatic void	wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
214278366Sadrianstatic int	wpi_set_timing(struct wpi_softc *, struct ieee80211_node *);
215278366Sadrianstatic void	wpi_power_calibration(struct wpi_softc *);
216278366Sadrianstatic int	wpi_set_txpower(struct wpi_softc *, int);
217278366Sadrianstatic int	wpi_get_power_index(struct wpi_softc *,
218278366Sadrian		    struct wpi_power_group *, struct ieee80211_channel *, int);
219278366Sadrianstatic int	wpi_set_pslevel(struct wpi_softc *, uint8_t, int, int);
220278366Sadrianstatic int	wpi_send_btcoex(struct wpi_softc *);
221278366Sadrianstatic int	wpi_send_rxon(struct wpi_softc *, int, int);
222278366Sadrianstatic int	wpi_config(struct wpi_softc *);
223278366Sadrianstatic uint16_t	wpi_get_active_dwell_time(struct wpi_softc *,
224278366Sadrian		    struct ieee80211_channel *, uint8_t);
225278366Sadrianstatic uint16_t	wpi_limit_dwell(struct wpi_softc *, uint16_t);
226278366Sadrianstatic uint16_t	wpi_get_passive_dwell_time(struct wpi_softc *,
227278366Sadrian		    struct ieee80211_channel *);
228278366Sadrianstatic int	wpi_scan(struct wpi_softc *, struct ieee80211_channel *);
229278366Sadrianstatic int	wpi_auth(struct wpi_softc *, struct ieee80211vap *);
230280084Sadrianstatic int	wpi_config_beacon(struct wpi_vap *);
231280084Sadrianstatic int	wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
232278366Sadrianstatic void	wpi_update_beacon(struct ieee80211vap *, int);
233280079Sadrianstatic void	wpi_newassoc(struct ieee80211_node *, int);
234178354Ssamstatic int	wpi_run(struct wpi_softc *, struct ieee80211vap *);
235278366Sadrianstatic int	wpi_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
236278366Sadrian		    ieee80211_keyix *, ieee80211_keyix *);
237278366Sadrianstatic int	wpi_key_set(struct ieee80211vap *,
238278366Sadrian		    const struct ieee80211_key *,
239278366Sadrian		    const uint8_t mac[IEEE80211_ADDR_LEN]);
240278366Sadrianstatic int	wpi_key_delete(struct ieee80211vap *,
241278366Sadrian		    const struct ieee80211_key *);
242278366Sadrianstatic int	wpi_post_alive(struct wpi_softc *);
243278366Sadrianstatic int	wpi_load_bootcode(struct wpi_softc *, const uint8_t *, int);
244278366Sadrianstatic int	wpi_load_firmware(struct wpi_softc *);
245278366Sadrianstatic int	wpi_read_firmware(struct wpi_softc *);
246278366Sadrianstatic void	wpi_unload_firmware(struct wpi_softc *);
247278366Sadrianstatic int	wpi_clock_wait(struct wpi_softc *);
248278366Sadrianstatic int	wpi_apm_init(struct wpi_softc *);
249278366Sadrianstatic void	wpi_apm_stop_master(struct wpi_softc *);
250278366Sadrianstatic void	wpi_apm_stop(struct wpi_softc *);
251278366Sadrianstatic void	wpi_nic_config(struct wpi_softc *);
252278366Sadrianstatic int	wpi_hw_init(struct wpi_softc *);
253278366Sadrianstatic void	wpi_hw_stop(struct wpi_softc *);
254278366Sadrianstatic void	wpi_radio_on(void *, int);
255278366Sadrianstatic void	wpi_radio_off(void *, int);
256278366Sadrianstatic void	wpi_init_locked(struct wpi_softc *);
257173362Sbenjscstatic void	wpi_init(void *);
258278366Sadrianstatic void	wpi_stop_locked(struct wpi_softc *);
259173362Sbenjscstatic void	wpi_stop(struct wpi_softc *);
260278366Sadrianstatic void	wpi_scan_start(struct ieee80211com *);
261278366Sadrianstatic void	wpi_scan_end(struct ieee80211com *);
262278366Sadrianstatic void	wpi_set_channel(struct ieee80211com *);
263278366Sadrianstatic void	wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
264278366Sadrianstatic void	wpi_scan_mindwell(struct ieee80211_scan_state *);
265278366Sadrianstatic void	wpi_hw_reset(void *, int);
266173362Sbenjsc
267173362Sbenjscstatic device_method_t wpi_methods[] = {
268173362Sbenjsc	/* Device interface */
269173362Sbenjsc	DEVMETHOD(device_probe,		wpi_probe),
270173362Sbenjsc	DEVMETHOD(device_attach,	wpi_attach),
271173362Sbenjsc	DEVMETHOD(device_detach,	wpi_detach),
272173362Sbenjsc	DEVMETHOD(device_shutdown,	wpi_shutdown),
273173362Sbenjsc	DEVMETHOD(device_suspend,	wpi_suspend),
274173362Sbenjsc	DEVMETHOD(device_resume,	wpi_resume),
275173362Sbenjsc
276260064Smarius	DEVMETHOD_END
277173362Sbenjsc};
278173362Sbenjsc
279173362Sbenjscstatic driver_t wpi_driver = {
280173362Sbenjsc	"wpi",
281173362Sbenjsc	wpi_methods,
282173362Sbenjsc	sizeof (struct wpi_softc)
283173362Sbenjsc};
284173362Sbenjscstatic devclass_t wpi_devclass;
285173362Sbenjsc
286260064SmariusDRIVER_MODULE(wpi, pci, wpi_driver, wpi_devclass, NULL, NULL);
287173362Sbenjsc
288222543SbschmidtMODULE_VERSION(wpi, 1);
289222543Sbschmidt
290278366SadrianMODULE_DEPEND(wpi, pci,  1, 1, 1);
291278366SadrianMODULE_DEPEND(wpi, wlan, 1, 1, 1);
292278366SadrianMODULE_DEPEND(wpi, firmware, 1, 1, 1);
293260064Smarius
294173362Sbenjscstatic int
295173362Sbenjscwpi_probe(device_t dev)
296173362Sbenjsc{
297173362Sbenjsc	const struct wpi_ident *ident;
298173362Sbenjsc
299173362Sbenjsc	for (ident = wpi_ident_table; ident->name != NULL; ident++) {
300173362Sbenjsc		if (pci_get_vendor(dev) == ident->vendor &&
301173362Sbenjsc		    pci_get_device(dev) == ident->device) {
302173362Sbenjsc			device_set_desc(dev, ident->name);
303260064Smarius			return (BUS_PROBE_DEFAULT);
304173362Sbenjsc		}
305173362Sbenjsc	}
306173362Sbenjsc	return ENXIO;
307173362Sbenjsc}
308173362Sbenjsc
309173362Sbenjscstatic int
310173362Sbenjscwpi_attach(device_t dev)
311173362Sbenjsc{
312278366Sadrian	struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev);
313278366Sadrian	struct ieee80211com *ic;
314173362Sbenjsc	struct ifnet *ifp;
315280061Sadrian	int i, error, rid;
316280061Sadrian#ifdef WPI_DEBUG
317280061Sadrian	int supportsa = 1;
318173362Sbenjsc	const struct wpi_ident *ident;
319280061Sadrian#endif
320190526Ssam	uint8_t macaddr[IEEE80211_ADDR_LEN];
321173362Sbenjsc
322173362Sbenjsc	sc->sc_dev = dev;
323173362Sbenjsc
324280059Sadrian#ifdef WPI_DEBUG
325278366Sadrian	error = resource_int_value(device_get_name(sc->sc_dev),
326278366Sadrian	    device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug));
327278366Sadrian	if (error != 0)
328278366Sadrian		sc->sc_debug = 0;
329278366Sadrian#else
330278366Sadrian	sc->sc_debug = 0;
331278366Sadrian#endif
332173362Sbenjsc
333278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
334278366Sadrian
335173362Sbenjsc	/*
336278366Sadrian	 * Get the offset of the PCI Express Capability Structure in PCI
337278366Sadrian	 * Configuration Space.
338278366Sadrian	 */
339278366Sadrian	error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
340278366Sadrian	if (error != 0) {
341278366Sadrian		device_printf(dev, "PCIe capability structure not found!\n");
342278366Sadrian		return error;
343278366Sadrian	}
344278366Sadrian
345278366Sadrian	/*
346173362Sbenjsc	 * Some card's only support 802.11b/g not a, check to see if
347173362Sbenjsc	 * this is one such card. A 0x0 in the subdevice table indicates
348173362Sbenjsc	 * the entire subdevice range is to be ignored.
349173362Sbenjsc	 */
350280061Sadrian#ifdef WPI_DEBUG
351173362Sbenjsc	for (ident = wpi_ident_table; ident->name != NULL; ident++) {
352173362Sbenjsc		if (ident->subdevice &&
353173362Sbenjsc		    pci_get_subdevice(dev) == ident->subdevice) {
354173362Sbenjsc		    supportsa = 0;
355173362Sbenjsc		    break;
356173362Sbenjsc		}
357173362Sbenjsc	}
358280061Sadrian#endif
359173362Sbenjsc
360278366Sadrian	/* Clear device-specific "PCI retry timeout" register (41h). */
361173362Sbenjsc	pci_write_config(dev, 0x41, 0, 1);
362173362Sbenjsc
363278366Sadrian	/* Enable bus-mastering. */
364173362Sbenjsc	pci_enable_busmaster(dev);
365173362Sbenjsc
366260064Smarius	rid = PCIR_BAR(0);
367260064Smarius	sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
368173362Sbenjsc	    RF_ACTIVE);
369173362Sbenjsc	if (sc->mem == NULL) {
370278366Sadrian		device_printf(dev, "can't map mem space\n");
371173362Sbenjsc		error = ENOMEM;
372278366Sadrian		return error;
373173362Sbenjsc	}
374173362Sbenjsc	sc->sc_st = rman_get_bustag(sc->mem);
375173362Sbenjsc	sc->sc_sh = rman_get_bushandle(sc->mem);
376173362Sbenjsc
377278366Sadrian	i = 1;
378260064Smarius	rid = 0;
379278366Sadrian	if (pci_alloc_msi(dev, &i) == 0)
380278366Sadrian		rid = 1;
381278366Sadrian	/* Install interrupt handler. */
382278366Sadrian	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
383278366Sadrian	    (rid != 0 ? 0 : RF_SHAREABLE));
384173362Sbenjsc	if (sc->irq == NULL) {
385278366Sadrian		device_printf(dev, "can't map interrupt\n");
386173362Sbenjsc		error = ENOMEM;
387173362Sbenjsc		goto fail;
388173362Sbenjsc	}
389173362Sbenjsc
390278366Sadrian	WPI_LOCK_INIT(sc);
391280077Sadrian	WPI_NT_LOCK_INIT(sc);
392280071Sadrian	WPI_TXQ_LOCK_INIT(sc);
393278366Sadrian
394278366Sadrian	/* Allocate DMA memory for firmware transfers. */
395173362Sbenjsc	if ((error = wpi_alloc_fwmem(sc)) != 0) {
396278366Sadrian		device_printf(dev,
397278366Sadrian		    "could not allocate memory for firmware, error %d\n",
398278366Sadrian		    error);
399173362Sbenjsc		goto fail;
400173362Sbenjsc	}
401173362Sbenjsc
402278366Sadrian	/* Allocate shared page. */
403173362Sbenjsc	if ((error = wpi_alloc_shared(sc)) != 0) {
404173362Sbenjsc		device_printf(dev, "could not allocate shared page\n");
405173362Sbenjsc		goto fail;
406173362Sbenjsc	}
407173362Sbenjsc
408278366Sadrian	/* Allocate TX rings - 4 for QoS purposes, 1 for commands. */
409278366Sadrian	for (i = 0; i < WPI_NTXQUEUES; i++) {
410278366Sadrian		if ((error = wpi_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
411278366Sadrian			device_printf(dev,
412278366Sadrian			    "could not allocate TX ring %d, error %d\n", i,
413278366Sadrian			    error);
414278366Sadrian			goto fail;
415173362Sbenjsc		}
416173362Sbenjsc	}
417173362Sbenjsc
418278366Sadrian	/* Allocate RX ring. */
419278366Sadrian	if ((error = wpi_alloc_rx_ring(sc)) != 0) {
420278366Sadrian		device_printf(dev, "could not allocate RX ring, error %d\n",
421278366Sadrian		    error);
422173362Sbenjsc		goto fail;
423173362Sbenjsc	}
424173362Sbenjsc
425278366Sadrian	/* Clear pending interrupts. */
426278366Sadrian	WPI_WRITE(sc, WPI_INT, 0xffffffff);
427173362Sbenjsc
428178354Ssam	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
429173362Sbenjsc	if (ifp == NULL) {
430278366Sadrian		device_printf(dev, "can not allocate ifnet structure\n");
431173362Sbenjsc		goto fail;
432173362Sbenjsc	}
433278366Sadrian
434178354Ssam	ic = ifp->if_l2com;
435173362Sbenjsc	ic->ic_ifp = ifp;
436178354Ssam	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
437178354Ssam	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
438173362Sbenjsc
439278366Sadrian	/* Set device capabilities. */
440173362Sbenjsc	ic->ic_caps =
441178957Ssam		  IEEE80211_C_STA		/* station mode supported */
442278366Sadrian		| IEEE80211_C_IBSS		/* IBSS mode supported */
443178957Ssam		| IEEE80211_C_MONITOR		/* monitor mode supported */
444278366Sadrian		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
445278366Sadrian		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
446173362Sbenjsc		| IEEE80211_C_TXPMGT		/* tx power management */
447173362Sbenjsc		| IEEE80211_C_SHSLOT		/* short slot time supported */
448278366Sadrian		| IEEE80211_C_WPA		/* 802.11i */
449173362Sbenjsc		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
450173362Sbenjsc#if 0
451173362Sbenjsc		| IEEE80211_C_HOSTAP		/* Host access point mode */
452173362Sbenjsc#endif
453278366Sadrian		| IEEE80211_C_WME		/* 802.11e */
454278366Sadrian		| IEEE80211_C_PMGT		/* Station-side power mgmt */
455173362Sbenjsc		;
456173362Sbenjsc
457278366Sadrian	ic->ic_cryptocaps =
458278366Sadrian		  IEEE80211_CRYPTO_AES_CCM;
459278366Sadrian
460173362Sbenjsc	/*
461173362Sbenjsc	 * Read in the eeprom and also setup the channels for
462173362Sbenjsc	 * net80211. We don't set the rates as net80211 does this for us
463173362Sbenjsc	 */
464278366Sadrian	if ((error = wpi_read_eeprom(sc, macaddr)) != 0) {
465278366Sadrian		device_printf(dev, "could not read EEPROM, error %d\n",
466278366Sadrian		    error);
467278366Sadrian		goto fail;
468280059Sadrian	}
469173362Sbenjsc
470280059Sadrian#ifdef WPI_DEBUG
471278366Sadrian	if (bootverbose) {
472280059Sadrian		device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n",
473280059Sadrian		    sc->domain);
474280059Sadrian		device_printf(sc->sc_dev, "Hardware Type: %c\n",
475280059Sadrian		    sc->type > 1 ? 'B': '?');
476280059Sadrian		device_printf(sc->sc_dev, "Hardware Revision: %c\n",
477280076Sadrian		    ((sc->rev & 0xf0) == 0xd0) ? 'D': '?');
478280059Sadrian		device_printf(sc->sc_dev, "SKU %s support 802.11a\n",
479280059Sadrian		    supportsa ? "does" : "does not");
480173362Sbenjsc
481280059Sadrian		/* XXX hw_config uses the PCIDEV for the Hardware rev. Must
482280059Sadrian		   check what sc->rev really represents - benjsc 20070615 */
483173362Sbenjsc	}
484278366Sadrian#endif
485173362Sbenjsc
486173362Sbenjsc	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
487173362Sbenjsc	ifp->if_softc = sc;
488173362Sbenjsc	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
489173362Sbenjsc	ifp->if_init = wpi_init;
490173362Sbenjsc	ifp->if_ioctl = wpi_ioctl;
491173362Sbenjsc	ifp->if_start = wpi_start;
492207554Ssobomax	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
493207554Ssobomax	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
494173362Sbenjsc	IFQ_SET_READY(&ifp->if_snd);
495178354Ssam
496190526Ssam	ieee80211_ifattach(ic, macaddr);
497278366Sadrian	ic->ic_vap_create = wpi_vap_create;
498278366Sadrian	ic->ic_vap_delete = wpi_vap_delete;
499178354Ssam	ic->ic_raw_xmit = wpi_raw_xmit;
500278366Sadrian	ic->ic_node_alloc = wpi_node_alloc;
501278366Sadrian	sc->sc_node_free = ic->ic_node_free;
502278366Sadrian	ic->ic_node_free = wpi_node_free;
503278366Sadrian	ic->ic_wme.wme_update = wpi_updateedca;
504278366Sadrian	ic->ic_update_promisc = wpi_update_promisc;
505278366Sadrian	ic->ic_update_mcast = wpi_update_mcast;
506280079Sadrian	ic->ic_newassoc = wpi_newassoc;
507173362Sbenjsc	ic->ic_scan_start = wpi_scan_start;
508173362Sbenjsc	ic->ic_scan_end = wpi_scan_end;
509173362Sbenjsc	ic->ic_set_channel = wpi_set_channel;
510278366Sadrian	sc->sc_scan_curchan = ic->ic_scan_curchan;
511173362Sbenjsc	ic->ic_scan_curchan = wpi_scan_curchan;
512173362Sbenjsc	ic->ic_scan_mindwell = wpi_scan_mindwell;
513278366Sadrian	ic->ic_setregdomain = wpi_setregdomain;
514173362Sbenjsc
515278366Sadrian	wpi_radiotap_attach(sc);
516173362Sbenjsc
517278366Sadrian	callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
518278366Sadrian	callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
519278366Sadrian	callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0);
520278366Sadrian	TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc);
521278366Sadrian	TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
522278366Sadrian	TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc);
523280078Sadrian	TASK_INIT(&sc->sc_start_task, 0, wpi_start_task, sc);
524173362Sbenjsc
525278366Sadrian	wpi_sysctlattach(sc);
526278366Sadrian
527173362Sbenjsc	/*
528173362Sbenjsc	 * Hook our interrupt after all initialization is complete.
529173362Sbenjsc	 */
530278366Sadrian	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
531177043Sthompsa	    NULL, wpi_intr, sc, &sc->sc_ih);
532173362Sbenjsc	if (error != 0) {
533278366Sadrian		device_printf(dev, "can't establish interrupt, error %d\n",
534278366Sadrian		    error);
535173362Sbenjsc		goto fail;
536173362Sbenjsc	}
537173362Sbenjsc
538177043Sthompsa	if (bootverbose)
539177043Sthompsa		ieee80211_announce(ic);
540278366Sadrian
541278366Sadrian#ifdef WPI_DEBUG
542278366Sadrian	if (sc->sc_debug & WPI_DEBUG_HW)
543278366Sadrian		ieee80211_announce_channels(ic);
544173362Sbenjsc#endif
545278366Sadrian
546278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
547173362Sbenjsc	return 0;
548173362Sbenjsc
549173362Sbenjscfail:	wpi_detach(dev);
550278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
551278366Sadrian	return error;
552173362Sbenjsc}
553173362Sbenjsc
554278366Sadrian/*
555278366Sadrian * Attach the interface to 802.11 radiotap.
556278366Sadrian */
557278366Sadrianstatic void
558278366Sadrianwpi_radiotap_attach(struct wpi_softc *sc)
559278366Sadrian{
560278366Sadrian	struct ifnet *ifp = sc->sc_ifp;
561278366Sadrian	struct ieee80211com *ic = ifp->if_l2com;
562278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
563278366Sadrian	ieee80211_radiotap_attach(ic,
564278366Sadrian	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
565278366Sadrian		WPI_TX_RADIOTAP_PRESENT,
566278366Sadrian	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
567278366Sadrian		WPI_RX_RADIOTAP_PRESENT);
568278366Sadrian	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
569278366Sadrian}
570278366Sadrian
571278366Sadrianstatic void
572278366Sadrianwpi_sysctlattach(struct wpi_softc *sc)
573278366Sadrian{
574280059Sadrian#ifdef WPI_DEBUG
575278366Sadrian	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
576278366Sadrian	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
577278366Sadrian
578278366Sadrian	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
579278366Sadrian	    "debug", CTLFLAG_RW, &sc->sc_debug, sc->sc_debug,
580278366Sadrian		"control debugging printfs");
581278366Sadrian#endif
582