summaryrefslogtreecommitdiffstats
path: root/sys/dev/iwi/if_iwivar.h
blob: b38bbd91d2c0fb2d5615a3eb49d741f15d19efe4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*	$FreeBSD$	*/

/*-
 * Copyright (c) 2004, 2005
 *      Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

struct iwi_rx_radiotap_header {
	struct ieee80211_radiotap_header wr_ihdr;
	uint8_t		wr_flags;
	uint8_t		wr_rate;
	uint16_t	wr_chan_freq;
	uint16_t	wr_chan_flags;
	int8_t		wr_antsignal;
	int8_t		wr_antnoise;
	uint8_t		wr_antenna;
};

#define IWI_RX_RADIOTAP_PRESENT						\
	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
	 (1 << IEEE80211_RADIOTAP_RATE) |				\
	 (1 << IEEE80211_RADIOTAP_CHANNEL) |				\
	 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |			\
	 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |			\
	 (1 << IEEE80211_RADIOTAP_ANTENNA))

struct iwi_tx_radiotap_header {
	struct ieee80211_radiotap_header wt_ihdr;
	uint8_t		wt_flags;
	uint16_t	wt_chan_freq;
	uint16_t	wt_chan_flags;
};

#define IWI_TX_RADIOTAP_PRESENT						\
	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
	 (1 << IEEE80211_RADIOTAP_CHANNEL))

struct iwi_cmd_ring {
	bus_dma_tag_t		desc_dmat;
	bus_dmamap_t		desc_map;
	bus_addr_t		physaddr;
	struct iwi_cmd_desc	*desc;
	int			count;
	int			queued;
	int			cur;
	int			next;
};

struct iwi_tx_data {
	bus_dmamap_t		map;
	struct mbuf		*m;
	struct ieee80211_node	*ni;
};

struct iwi_tx_ring {
	bus_dma_tag_t		desc_dmat;
	bus_dma_tag_t		data_dmat;
	bus_dmamap_t		desc_map;
	bus_addr_t		physaddr;
	bus_addr_t		csr_ridx;
	bus_addr_t		csr_widx;
	struct iwi_tx_desc	*desc;
	struct iwi_tx_data	*data;
	int			count;
	int			queued;
	int			cur;
	int			next;
};

struct iwi_rx_data {
	bus_dmamap_t	map;
	bus_addr_t	physaddr;
	uint32_t	reg;
	struct mbuf	*m;
};

struct iwi_rx_ring {
	bus_dma_tag_t		data_dmat;
	struct iwi_rx_data	*data;
	int			count;
	int			cur;
};

struct iwi_node {
	struct ieee80211_node	in_node;
	int			in_station;
#define IWI_MAX_IBSSNODE	32
};

struct iwi_fw {
	const struct firmware	*fp;		/* image handle */
	const char		*data;		/* firmware image data */
	size_t			size;		/* firmware image size */
	const char		*name;		/* associated image name */
};

struct iwi_vap {
	struct ieee80211vap	iwi_vap;

	int			(*iwi_newstate)(struct ieee80211vap *,
				    enum ieee80211_state, int);
};
#define	IWI_VAP(vap)	((struct iwi_vap *)(vap))

struct iwi_softc {
	struct ifnet		*sc_ifp;
	void			(*sc_node_free)(struct ieee80211_node *);
	device_t		sc_dev;

	struct mtx		sc_mtx;
	uint8_t			sc_mcast[IEEE80211_ADDR_LEN];
	struct unrhdr		*sc_unr;

	uint32_t		flags;
#define IWI_FLAG_FW_INITED	(1 << 0)
#define	IWI_FLAG_BUSY		(1 << 3)	/* busy sending a command */
#define	IWI_FLAG_ASSOCIATED	(1 << 4)	/* currently associated  */
#define IWI_FLAG_CHANNEL_SCAN	(1 << 5)
	uint32_t		fw_state;
#define IWI_FW_IDLE		0
#define IWI_FW_LOADING		1
#define IWI_FW_ASSOCIATING	2
#define IWI_FW_DISASSOCIATING	3
#define IWI_FW_SCANNING		4
	struct iwi_cmd_ring	cmdq;
	struct iwi_tx_ring	txq[WME_NUM_AC];
	struct iwi_rx_ring	rxq;

	struct resource		*irq;
	struct resource		*mem;
	bus_space_tag_t		sc_st;
	bus_space_handle_t	sc_sh;
	void 			*sc_ih;

	/*
	 * The card needs external firmware images to work, which is made of a
	 * bootloader, microcode and firmware proper. In version 3.00 and
	 * above, all pieces are contained in a single image, preceded by a
	 * struct iwi_firmware_hdr indicating the size of the 3 pieces.
	 * Old firmware < 3.0 has separate boot and ucode, so we need to
	 * load all of them explicitly.
	 * To avoid issues related to fragmentation, we keep the block of
	 * dma-ble memory around until detach time, and reallocate it when
	 * it becomes too small. fw_dma_size is the size currently allocated.
	 */
	int			fw_dma_size;
	uint32_t		fw_flags;	/* allocation status */
#define	IWI_FW_HAVE_DMAT	0x01
#define	IWI_FW_HAVE_MAP		0x02
#define	IWI_FW_HAVE_PHY		0x04
	bus_dma_tag_t		fw_dmat;
	bus_dmamap_t		fw_map;
	bus_addr_t		fw_physaddr;
	void			*fw_virtaddr;
	enum ieee80211_opmode	fw_mode;	/* mode of current firmware */
	struct iwi_fw		fw_boot;	/* boot firmware */
	struct iwi_fw		fw_uc;		/* microcode */
	struct iwi_fw		fw_fw;		/* operating mode support */

	int			curchan;	/* current h/w channel # */
	int			antenna;
	int			bluetooth;
	struct iwi_associate	assoc;
	struct iwi_wme_params	wme[3];
	u_int			sc_scangen;

	struct task		sc_radiontask;	/* radio on processing */
	struct task		sc_radiofftask;	/* radio off processing */
	struct task		sc_restarttask;	/* restart adapter processing */
	struct task		sc_disassoctask;
	struct task		sc_wmetask;	/* set wme parameters */
	struct task		sc_monitortask;

	unsigned int		sc_softled : 1,	/* enable LED gpio status */
				sc_ledstate: 1,	/* LED on/off state */
				sc_blinking: 1;	/* LED blink operation active */
	u_int			sc_nictype;	/* NIC type from EEPROM */
	u_int			sc_ledpin;	/* mask for activity LED */
	u_int			sc_ledidle;	/* idle polling interval */
	int			sc_ledevent;	/* time of last LED event */
	u_int8_t		sc_rxrate;	/* current rx rate for LED */
	u_int8_t		sc_rxrix;
	u_int8_t		sc_txrate;	/* current tx rate for LED */
	u_int8_t		sc_txrix;
	u_int16_t		sc_ledoff;	/* off time for current blink */
	struct callout		sc_ledtimer;	/* led off timer */
	struct callout		sc_wdtimer;	/* watchdog timer */
	struct callout		sc_rftimer;	/* rfkill timer */

	int			sc_tx_timer;
	int			sc_state_timer;	/* firmware state timer */
	int			sc_busy_timer;	/* firmware cmd timer */

	struct iwi_rx_radiotap_header sc_rxtap;
	struct iwi_tx_radiotap_header sc_txtap;

	struct iwi_notif_link_quality sc_linkqual;
	int			sc_linkqual_valid;
};

#define	IWI_STATE_BEGIN(_sc, _state)	do {			\
	KASSERT(_sc->fw_state == IWI_FW_IDLE,			\
	    ("iwi firmware not idle, state %s", iwi_fw_states[_sc->fw_state]));\
	_sc->fw_state = _state;					\
	_sc->sc_state_timer = 5;				\
	DPRINTF(("enter %s state\n", iwi_fw_states[_state]));	\
} while (0)

#define	IWI_STATE_END(_sc, _state)	do {			\
	if (_sc->fw_state == _state)				\
		DPRINTF(("exit %s state\n", iwi_fw_states[_state])); \
	 else							\
		DPRINTF(("expected %s state, got %s\n",	\
		    iwi_fw_states[_state], iwi_fw_states[_sc->fw_state])); \
	_sc->fw_state = IWI_FW_IDLE;				\
	wakeup(_sc);						\
	_sc->sc_state_timer = 0;				\
} while (0)
/*
 * NB.: This models the only instance of async locking in iwi_init_locked
 *	and must be kept in sync.
 */
#define	IWI_LOCK_INIT(sc) \
	mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
	    MTX_NETWORK_LOCK, MTX_DEF)
#define	IWI_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->sc_mtx)
#define	IWI_LOCK_DECL	int	__waslocked = 0
#define IWI_LOCK_ASSERT(sc)	mtx_assert(&(sc)->sc_mtx, MA_OWNED)
#define IWI_LOCK(sc)	do {				\
	if (!(__waslocked = mtx_owned(&(sc)->sc_mtx)))	\
		mtx_lock(&(sc)->sc_mtx);		\
} while (0)
#define IWI_UNLOCK(sc)	do {			\
	if (!__waslocked)			\
		mtx_unlock(&(sc)->sc_mtx);	\
} while (0)
OpenPOWER on IntegriCloud