if_iwi.c revision 1.37.2.3 1 1.37.2.3 yamt /* $NetBSD: if_iwi.c,v 1.37.2.3 2005/11/29 21:23:14 yamt Exp $ */
2 1.37.2.2 yamt
3 1.37.2.2 yamt /*-
4 1.37.2.2 yamt * Copyright (c) 2004, 2005
5 1.37.2.2 yamt * Damien Bergamini <damien.bergamini (at) free.fr>. All rights reserved.
6 1.37.2.2 yamt *
7 1.37.2.2 yamt * Redistribution and use in source and binary forms, with or without
8 1.37.2.2 yamt * modification, are permitted provided that the following conditions
9 1.37.2.2 yamt * are met:
10 1.37.2.2 yamt * 1. Redistributions of source code must retain the above copyright
11 1.37.2.2 yamt * notice unmodified, this list of conditions, and the following
12 1.37.2.2 yamt * disclaimer.
13 1.37.2.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
14 1.37.2.2 yamt * notice, this list of conditions and the following disclaimer in the
15 1.37.2.2 yamt * documentation and/or other materials provided with the distribution.
16 1.37.2.2 yamt *
17 1.37.2.2 yamt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 1.37.2.2 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.37.2.2 yamt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.37.2.2 yamt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 1.37.2.2 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.37.2.2 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.37.2.2 yamt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.37.2.2 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.37.2.2 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.37.2.2 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.37.2.2 yamt * SUCH DAMAGE.
28 1.37.2.2 yamt */
29 1.37.2.2 yamt
30 1.37.2.2 yamt #include <sys/cdefs.h>
31 1.37.2.3 yamt __KERNEL_RCSID(0, "$NetBSD: if_iwi.c,v 1.37.2.3 2005/11/29 21:23:14 yamt Exp $");
32 1.37.2.2 yamt
33 1.37.2.2 yamt /*-
34 1.37.2.2 yamt * Intel(R) PRO/Wireless 2200BG/2225BG/2915ABG driver
35 1.37.2.2 yamt * http://www.intel.com/network/connectivity/products/wireless/prowireless_mobile.htm
36 1.37.2.2 yamt */
37 1.37.2.2 yamt
38 1.37.2.2 yamt #include "bpfilter.h"
39 1.37.2.2 yamt
40 1.37.2.2 yamt #include <sys/param.h>
41 1.37.2.2 yamt #include <sys/sockio.h>
42 1.37.2.2 yamt #include <sys/sysctl.h>
43 1.37.2.2 yamt #include <sys/mbuf.h>
44 1.37.2.2 yamt #include <sys/kernel.h>
45 1.37.2.2 yamt #include <sys/socket.h>
46 1.37.2.2 yamt #include <sys/systm.h>
47 1.37.2.2 yamt #include <sys/malloc.h>
48 1.37.2.2 yamt #include <sys/conf.h>
49 1.37.2.2 yamt
50 1.37.2.2 yamt #include <machine/bus.h>
51 1.37.2.2 yamt #include <machine/endian.h>
52 1.37.2.2 yamt #include <machine/intr.h>
53 1.37.2.2 yamt
54 1.37.2.2 yamt #include <dev/pci/pcireg.h>
55 1.37.2.2 yamt #include <dev/pci/pcivar.h>
56 1.37.2.2 yamt #include <dev/pci/pcidevs.h>
57 1.37.2.2 yamt
58 1.37.2.2 yamt #if NBPFILTER > 0
59 1.37.2.2 yamt #include <net/bpf.h>
60 1.37.2.2 yamt #endif
61 1.37.2.2 yamt #include <net/if.h>
62 1.37.2.2 yamt #include <net/if_arp.h>
63 1.37.2.2 yamt #include <net/if_dl.h>
64 1.37.2.2 yamt #include <net/if_ether.h>
65 1.37.2.2 yamt #include <net/if_media.h>
66 1.37.2.2 yamt #include <net/if_types.h>
67 1.37.2.2 yamt
68 1.37.2.2 yamt #include <net80211/ieee80211_var.h>
69 1.37.2.2 yamt #include <net80211/ieee80211_radiotap.h>
70 1.37.2.2 yamt
71 1.37.2.2 yamt #include <netinet/in.h>
72 1.37.2.2 yamt #include <netinet/in_systm.h>
73 1.37.2.2 yamt #include <netinet/in_var.h>
74 1.37.2.2 yamt #include <netinet/ip.h>
75 1.37.2.2 yamt
76 1.37.2.2 yamt #include <crypto/arc4/arc4.h>
77 1.37.2.2 yamt
78 1.37.2.2 yamt #include <dev/pci/if_iwireg.h>
79 1.37.2.2 yamt #include <dev/pci/if_iwivar.h>
80 1.37.2.2 yamt
81 1.37.2.2 yamt #ifdef IWI_DEBUG
82 1.37.2.2 yamt #define DPRINTF(x) if (iwi_debug > 0) printf x
83 1.37.2.2 yamt #define DPRINTFN(n, x) if (iwi_debug >= (n)) printf x
84 1.37.2.2 yamt int iwi_debug = 4;
85 1.37.2.2 yamt #else
86 1.37.2.2 yamt #define DPRINTF(x)
87 1.37.2.2 yamt #define DPRINTFN(n, x)
88 1.37.2.2 yamt #endif
89 1.37.2.2 yamt
90 1.37.2.2 yamt static int iwi_match(struct device *, struct cfdata *, void *);
91 1.37.2.2 yamt static void iwi_attach(struct device *, struct device *, void *);
92 1.37.2.2 yamt static int iwi_detach(struct device *, int);
93 1.37.2.2 yamt
94 1.37.2.2 yamt static void iwi_shutdown(void *);
95 1.37.2.2 yamt static int iwi_suspend(struct iwi_softc *);
96 1.37.2.2 yamt static int iwi_resume(struct iwi_softc *);
97 1.37.2.2 yamt static void iwi_powerhook(int, void *);
98 1.37.2.2 yamt
99 1.37.2.2 yamt static int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *,
100 1.37.2.2 yamt int);
101 1.37.2.2 yamt static void iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
102 1.37.2.2 yamt static void iwi_free_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *);
103 1.37.2.2 yamt static int iwi_alloc_tx_ring(struct iwi_softc *, struct iwi_tx_ring *,
104 1.37.2.2 yamt int, bus_addr_t, bus_addr_t);
105 1.37.2.2 yamt static void iwi_reset_tx_ring(struct iwi_softc *, struct iwi_tx_ring *);
106 1.37.2.2 yamt static void iwi_free_tx_ring(struct iwi_softc *, struct iwi_tx_ring *);
107 1.37.2.2 yamt static struct mbuf *
108 1.37.2.2 yamt iwi_alloc_rx_buf(struct iwi_softc *sc);
109 1.37.2.2 yamt static int iwi_alloc_rx_ring(struct iwi_softc *, struct iwi_rx_ring *,
110 1.37.2.2 yamt int);
111 1.37.2.2 yamt static void iwi_reset_rx_ring(struct iwi_softc *, struct iwi_rx_ring *);
112 1.37.2.2 yamt static void iwi_free_rx_ring(struct iwi_softc *, struct iwi_rx_ring *);
113 1.37.2.2 yamt
114 1.37.2.2 yamt static struct ieee80211_node *iwi_node_alloc(struct ieee80211_node_table *);
115 1.37.2.2 yamt static void iwi_node_free(struct ieee80211_node *);
116 1.37.2.2 yamt
117 1.37.2.2 yamt static int iwi_media_change(struct ifnet *);
118 1.37.2.2 yamt static void iwi_media_status(struct ifnet *, struct ifmediareq *);
119 1.37.2.2 yamt static int iwi_wme_update(struct ieee80211com *);
120 1.37.2.2 yamt static uint16_t iwi_read_prom_word(struct iwi_softc *, uint8_t);
121 1.37.2.2 yamt static int iwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
122 1.37.2.2 yamt static void iwi_fix_channel(struct ieee80211com *, struct mbuf *);
123 1.37.2.2 yamt static void iwi_frame_intr(struct iwi_softc *, struct iwi_rx_data *, int,
124 1.37.2.2 yamt struct iwi_frame *);
125 1.37.2.2 yamt static void iwi_notification_intr(struct iwi_softc *, struct iwi_notif *);
126 1.37.2.3 yamt static void iwi_cmd_intr(struct iwi_softc *);
127 1.37.2.2 yamt static void iwi_rx_intr(struct iwi_softc *);
128 1.37.2.2 yamt static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
129 1.37.2.2 yamt static int iwi_intr(void *);
130 1.37.2.2 yamt static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t, int);
131 1.37.2.2 yamt static void iwi_write_ibssnode(struct iwi_softc *, const struct iwi_node *);
132 1.37.2.2 yamt static int iwi_tx_start(struct ifnet *, struct mbuf *, struct ieee80211_node *,
133 1.37.2.2 yamt int);
134 1.37.2.2 yamt static void iwi_start(struct ifnet *);
135 1.37.2.2 yamt static void iwi_watchdog(struct ifnet *);
136 1.37.2.2 yamt
137 1.37.2.2 yamt static int iwi_alloc_unr(struct iwi_softc *);
138 1.37.2.2 yamt static void iwi_free_unr(struct iwi_softc *, int);
139 1.37.2.2 yamt
140 1.37.2.2 yamt static int iwi_get_table0(struct iwi_softc *, uint32_t *);
141 1.37.2.2 yamt static int iwi_get_radio(struct iwi_softc *, int *);
142 1.37.2.2 yamt
143 1.37.2.2 yamt static int iwi_ioctl(struct ifnet *, u_long, caddr_t);
144 1.37.2.2 yamt static void iwi_stop_master(struct iwi_softc *);
145 1.37.2.2 yamt static int iwi_reset(struct iwi_softc *);
146 1.37.2.2 yamt static int iwi_load_ucode(struct iwi_softc *, void *, int);
147 1.37.2.2 yamt static int iwi_load_firmware(struct iwi_softc *, void *, int);
148 1.37.2.2 yamt static int iwi_cache_firmware(struct iwi_softc *, void *);
149 1.37.2.2 yamt static void iwi_free_firmware(struct iwi_softc *);
150 1.37.2.2 yamt static int iwi_config(struct iwi_softc *);
151 1.37.2.2 yamt static int iwi_set_chan(struct iwi_softc *, struct ieee80211_channel *);
152 1.37.2.2 yamt static int iwi_scan(struct iwi_softc *);
153 1.37.2.2 yamt static int iwi_auth_and_assoc(struct iwi_softc *);
154 1.37.2.2 yamt static int iwi_init(struct ifnet *);
155 1.37.2.2 yamt static void iwi_stop(struct ifnet *, int);
156 1.37.2.3 yamt static void iwi_led_set(struct iwi_softc *, uint32_t, int);
157 1.37.2.2 yamt static void iwi_error_log(struct iwi_softc *);
158 1.37.2.2 yamt
159 1.37.2.2 yamt /*
160 1.37.2.2 yamt * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
161 1.37.2.2 yamt */
162 1.37.2.2 yamt static const struct ieee80211_rateset iwi_rateset_11a =
163 1.37.2.2 yamt { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
164 1.37.2.2 yamt
165 1.37.2.2 yamt static const struct ieee80211_rateset iwi_rateset_11b =
166 1.37.2.2 yamt { 4, { 2, 4, 11, 22 } };
167 1.37.2.2 yamt
168 1.37.2.2 yamt static const struct ieee80211_rateset iwi_rateset_11g =
169 1.37.2.2 yamt { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
170 1.37.2.2 yamt
171 1.37.2.2 yamt static __inline uint8_t
172 1.37.2.2 yamt MEM_READ_1(struct iwi_softc *sc, uint32_t addr)
173 1.37.2.2 yamt {
174 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_INDIRECT_ADDR, addr);
175 1.37.2.2 yamt return CSR_READ_1(sc, IWI_CSR_INDIRECT_DATA);
176 1.37.2.2 yamt }
177 1.37.2.2 yamt
178 1.37.2.2 yamt static __inline uint32_t
179 1.37.2.2 yamt MEM_READ_4(struct iwi_softc *sc, uint32_t addr)
180 1.37.2.2 yamt {
181 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_INDIRECT_ADDR, addr);
182 1.37.2.2 yamt return CSR_READ_4(sc, IWI_CSR_INDIRECT_DATA);
183 1.37.2.2 yamt }
184 1.37.2.2 yamt
185 1.37.2.2 yamt static void
186 1.37.2.2 yamt MEM_CPY(struct iwi_softc *sc, void *dst, uint32_t base, size_t sz)
187 1.37.2.2 yamt {
188 1.37.2.2 yamt KASSERT(sz % 4 == 0);
189 1.37.2.2 yamt int j;
190 1.37.2.2 yamt
191 1.37.2.2 yamt uint32_t *p = dst;
192 1.37.2.2 yamt
193 1.37.2.2 yamt for (j = 0; j < sz / 4; j++)
194 1.37.2.2 yamt p[j] = MEM_READ_4(sc, base + j * sizeof(uint32_t));
195 1.37.2.2 yamt }
196 1.37.2.2 yamt
197 1.37.2.2 yamt CFATTACH_DECL(iwi, sizeof (struct iwi_softc), iwi_match, iwi_attach,
198 1.37.2.2 yamt iwi_detach, NULL);
199 1.37.2.2 yamt
200 1.37.2.2 yamt static int
201 1.37.2.2 yamt iwi_match(struct device *parent, struct cfdata *match, void *aux)
202 1.37.2.2 yamt {
203 1.37.2.2 yamt struct pci_attach_args *pa = aux;
204 1.37.2.2 yamt
205 1.37.2.2 yamt if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)
206 1.37.2.2 yamt return 0;
207 1.37.2.2 yamt
208 1.37.2.2 yamt if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_2200BG ||
209 1.37.2.2 yamt PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_2225BG ||
210 1.37.2.2 yamt PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_2915ABG_1 ||
211 1.37.2.2 yamt PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_2915ABG_2)
212 1.37.2.2 yamt return 1;
213 1.37.2.2 yamt
214 1.37.2.2 yamt return 0;
215 1.37.2.2 yamt }
216 1.37.2.2 yamt
217 1.37.2.2 yamt /* Base Address Register */
218 1.37.2.2 yamt #define IWI_PCI_BAR0 0x10
219 1.37.2.2 yamt
220 1.37.2.2 yamt static void
221 1.37.2.2 yamt iwi_attach(struct device *parent, struct device *self, void *aux)
222 1.37.2.2 yamt {
223 1.37.2.2 yamt struct iwi_softc *sc = (struct iwi_softc *)self;
224 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
225 1.37.2.2 yamt struct ifnet *ifp = &sc->sc_if;
226 1.37.2.2 yamt struct pci_attach_args *pa = aux;
227 1.37.2.2 yamt const char *intrstr;
228 1.37.2.2 yamt char devinfo[256];
229 1.37.2.2 yamt bus_space_tag_t memt;
230 1.37.2.2 yamt bus_space_handle_t memh;
231 1.37.2.2 yamt bus_addr_t base;
232 1.37.2.2 yamt pci_intr_handle_t ih;
233 1.37.2.2 yamt pcireg_t data;
234 1.37.2.2 yamt uint16_t val;
235 1.37.2.2 yamt int error, revision, i;
236 1.37.2.2 yamt
237 1.37.2.2 yamt sc->sc_pct = pa->pa_pc;
238 1.37.2.2 yamt sc->sc_pcitag = pa->pa_tag;
239 1.37.2.2 yamt
240 1.37.2.2 yamt pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof devinfo);
241 1.37.2.2 yamt revision = PCI_REVISION(pa->pa_class);
242 1.37.2.2 yamt aprint_normal(": %s (rev. 0x%02x)\n", devinfo, revision);
243 1.37.2.2 yamt
244 1.37.2.2 yamt /* clear device specific PCI configuration register 0x41 */
245 1.37.2.2 yamt data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
246 1.37.2.2 yamt data &= ~0x0000ff00;
247 1.37.2.2 yamt pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
248 1.37.2.2 yamt
249 1.37.2.2 yamt /* clear unit numbers allocated to IBSS */
250 1.37.2.2 yamt sc->sc_unr = 0;
251 1.37.2.2 yamt
252 1.37.2.2 yamt /* enable bus-mastering */
253 1.37.2.2 yamt data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
254 1.37.2.2 yamt data |= PCI_COMMAND_MASTER_ENABLE;
255 1.37.2.2 yamt pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, data);
256 1.37.2.2 yamt
257 1.37.2.2 yamt /* map the register window */
258 1.37.2.2 yamt error = pci_mapreg_map(pa, IWI_PCI_BAR0, PCI_MAPREG_TYPE_MEM |
259 1.37.2.2 yamt PCI_MAPREG_MEM_TYPE_32BIT, 0, &memt, &memh, &base, &sc->sc_sz);
260 1.37.2.2 yamt if (error != 0) {
261 1.37.2.2 yamt aprint_error("%s: could not map memory space\n",
262 1.37.2.2 yamt sc->sc_dev.dv_xname);
263 1.37.2.2 yamt return;
264 1.37.2.2 yamt }
265 1.37.2.2 yamt
266 1.37.2.2 yamt sc->sc_st = memt;
267 1.37.2.2 yamt sc->sc_sh = memh;
268 1.37.2.2 yamt sc->sc_dmat = pa->pa_dmat;
269 1.37.2.2 yamt
270 1.37.2.2 yamt /* disable interrupts */
271 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
272 1.37.2.2 yamt
273 1.37.2.2 yamt if (pci_intr_map(pa, &ih) != 0) {
274 1.37.2.2 yamt aprint_error("%s: could not map interrupt\n",
275 1.37.2.2 yamt sc->sc_dev.dv_xname);
276 1.37.2.2 yamt return;
277 1.37.2.2 yamt }
278 1.37.2.2 yamt
279 1.37.2.2 yamt intrstr = pci_intr_string(sc->sc_pct, ih);
280 1.37.2.2 yamt sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwi_intr, sc);
281 1.37.2.2 yamt if (sc->sc_ih == NULL) {
282 1.37.2.2 yamt aprint_error("%s: could not establish interrupt",
283 1.37.2.2 yamt sc->sc_dev.dv_xname);
284 1.37.2.2 yamt if (intrstr != NULL)
285 1.37.2.2 yamt aprint_error(" at %s", intrstr);
286 1.37.2.2 yamt aprint_error("\n");
287 1.37.2.2 yamt return;
288 1.37.2.2 yamt }
289 1.37.2.2 yamt aprint_normal("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
290 1.37.2.2 yamt
291 1.37.2.2 yamt if (iwi_reset(sc) != 0) {
292 1.37.2.2 yamt aprint_error("%s: could not reset adapter\n",
293 1.37.2.2 yamt sc->sc_dev.dv_xname);
294 1.37.2.2 yamt return;
295 1.37.2.2 yamt }
296 1.37.2.2 yamt
297 1.37.2.2 yamt /*
298 1.37.2.2 yamt * Allocate rings.
299 1.37.2.2 yamt */
300 1.37.2.2 yamt if (iwi_alloc_cmd_ring(sc, &sc->cmdq, IWI_CMD_RING_COUNT) != 0) {
301 1.37.2.2 yamt aprint_error("%s: could not allocate command ring\n",
302 1.37.2.2 yamt sc->sc_dev.dv_xname);
303 1.37.2.2 yamt goto fail;
304 1.37.2.2 yamt }
305 1.37.2.2 yamt
306 1.37.2.2 yamt error = iwi_alloc_tx_ring(sc, &sc->txq[0], IWI_TX_RING_COUNT,
307 1.37.2.2 yamt IWI_CSR_TX1_RIDX, IWI_CSR_TX1_WIDX);
308 1.37.2.2 yamt if (error != 0) {
309 1.37.2.2 yamt aprint_error("%s: could not allocate Tx ring 1\n",
310 1.37.2.2 yamt sc->sc_dev.dv_xname);
311 1.37.2.2 yamt goto fail;
312 1.37.2.2 yamt }
313 1.37.2.2 yamt
314 1.37.2.2 yamt error = iwi_alloc_tx_ring(sc, &sc->txq[1], IWI_TX_RING_COUNT,
315 1.37.2.2 yamt IWI_CSR_TX2_RIDX, IWI_CSR_TX2_WIDX);
316 1.37.2.2 yamt if (error != 0) {
317 1.37.2.2 yamt aprint_error("%s: could not allocate Tx ring 2\n",
318 1.37.2.2 yamt sc->sc_dev.dv_xname);
319 1.37.2.2 yamt goto fail;
320 1.37.2.2 yamt }
321 1.37.2.2 yamt
322 1.37.2.2 yamt error = iwi_alloc_tx_ring(sc, &sc->txq[2], IWI_TX_RING_COUNT,
323 1.37.2.2 yamt IWI_CSR_TX3_RIDX, IWI_CSR_TX3_WIDX);
324 1.37.2.2 yamt if (error != 0) {
325 1.37.2.2 yamt aprint_error("%s: could not allocate Tx ring 3\n",
326 1.37.2.2 yamt sc->sc_dev.dv_xname);
327 1.37.2.2 yamt goto fail;
328 1.37.2.2 yamt }
329 1.37.2.2 yamt
330 1.37.2.2 yamt error = iwi_alloc_tx_ring(sc, &sc->txq[3], IWI_TX_RING_COUNT,
331 1.37.2.2 yamt IWI_CSR_TX4_RIDX, IWI_CSR_TX4_WIDX);
332 1.37.2.2 yamt if (error != 0) {
333 1.37.2.2 yamt aprint_error("%s: could not allocate Tx ring 4\n",
334 1.37.2.2 yamt sc->sc_dev.dv_xname);
335 1.37.2.2 yamt goto fail;
336 1.37.2.2 yamt }
337 1.37.2.2 yamt
338 1.37.2.2 yamt if (iwi_alloc_rx_ring(sc, &sc->rxq, IWI_RX_RING_COUNT) != 0) {
339 1.37.2.2 yamt aprint_error("%s: could not allocate Rx ring\n",
340 1.37.2.2 yamt sc->sc_dev.dv_xname);
341 1.37.2.2 yamt goto fail;
342 1.37.2.2 yamt }
343 1.37.2.2 yamt
344 1.37.2.2 yamt ic->ic_ifp = ifp;
345 1.37.2.2 yamt ic->ic_wme.wme_update = iwi_wme_update;
346 1.37.2.2 yamt ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
347 1.37.2.2 yamt ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
348 1.37.2.2 yamt ic->ic_state = IEEE80211_S_INIT;
349 1.37.2.2 yamt
350 1.37.2.2 yamt /* set device capabilities */
351 1.37.2.2 yamt ic->ic_caps =
352 1.37.2.2 yamt IEEE80211_C_IBSS | /* IBSS mode supported */
353 1.37.2.2 yamt IEEE80211_C_MONITOR | /* monitor mode supported */
354 1.37.2.2 yamt IEEE80211_C_TXPMGT | /* tx power management */
355 1.37.2.2 yamt IEEE80211_C_SHPREAMBLE | /* short preamble supported */
356 1.37.2.2 yamt IEEE80211_C_WPA | /* 802.11i */
357 1.37.2.2 yamt IEEE80211_C_WME; /* 802.11e */
358 1.37.2.2 yamt
359 1.37.2.2 yamt /* read MAC address from EEPROM */
360 1.37.2.2 yamt val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
361 1.37.2.2 yamt ic->ic_myaddr[0] = val & 0xff;
362 1.37.2.2 yamt ic->ic_myaddr[1] = val >> 8;
363 1.37.2.2 yamt val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
364 1.37.2.2 yamt ic->ic_myaddr[2] = val & 0xff;
365 1.37.2.2 yamt ic->ic_myaddr[3] = val >> 8;
366 1.37.2.2 yamt val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
367 1.37.2.2 yamt ic->ic_myaddr[4] = val & 0xff;
368 1.37.2.2 yamt ic->ic_myaddr[5] = val >> 8;
369 1.37.2.2 yamt
370 1.37.2.2 yamt aprint_normal("%s: 802.11 address %s\n", sc->sc_dev.dv_xname,
371 1.37.2.2 yamt ether_sprintf(ic->ic_myaddr));
372 1.37.2.2 yamt
373 1.37.2.3 yamt /* read the NIC type from EEPROM */
374 1.37.2.3 yamt val = iwi_read_prom_word(sc, IWI_EEPROM_NIC_TYPE);
375 1.37.2.3 yamt sc->nictype = val & 0xff;
376 1.37.2.3 yamt
377 1.37.2.3 yamt DPRINTF(("%s: NIC type %d\n", sc->sc_dev.dv_xname, sc->nictype));
378 1.37.2.2 yamt
379 1.37.2.2 yamt if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_2915ABG_1 ||
380 1.37.2.2 yamt PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_2915ABG_2) {
381 1.37.2.2 yamt /* set supported .11a rates (2915ABG only) */
382 1.37.2.2 yamt ic->ic_sup_rates[IEEE80211_MODE_11A] = iwi_rateset_11a;
383 1.37.2.2 yamt
384 1.37.2.2 yamt /* set supported .11a channels */
385 1.37.2.2 yamt for (i = 36; i <= 64; i += 4) {
386 1.37.2.2 yamt ic->ic_channels[i].ic_freq =
387 1.37.2.2 yamt ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
388 1.37.2.2 yamt ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
389 1.37.2.2 yamt }
390 1.37.2.2 yamt for (i = 149; i <= 165; i += 4) {
391 1.37.2.2 yamt ic->ic_channels[i].ic_freq =
392 1.37.2.2 yamt ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
393 1.37.2.2 yamt ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
394 1.37.2.2 yamt }
395 1.37.2.2 yamt }
396 1.37.2.2 yamt
397 1.37.2.2 yamt /* set supported .11b and .11g rates */
398 1.37.2.2 yamt ic->ic_sup_rates[IEEE80211_MODE_11B] = iwi_rateset_11b;
399 1.37.2.2 yamt ic->ic_sup_rates[IEEE80211_MODE_11G] = iwi_rateset_11g;
400 1.37.2.2 yamt
401 1.37.2.2 yamt /* set supported .11b and .11g channels (1 through 14) */
402 1.37.2.2 yamt for (i = 1; i <= 14; i++) {
403 1.37.2.2 yamt ic->ic_channels[i].ic_freq =
404 1.37.2.2 yamt ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
405 1.37.2.2 yamt ic->ic_channels[i].ic_flags =
406 1.37.2.2 yamt IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
407 1.37.2.2 yamt IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
408 1.37.2.2 yamt }
409 1.37.2.2 yamt
410 1.37.2.2 yamt ifp->if_softc = sc;
411 1.37.2.2 yamt ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
412 1.37.2.2 yamt ifp->if_init = iwi_init;
413 1.37.2.2 yamt ifp->if_stop = iwi_stop;
414 1.37.2.2 yamt ifp->if_ioctl = iwi_ioctl;
415 1.37.2.2 yamt ifp->if_start = iwi_start;
416 1.37.2.2 yamt ifp->if_watchdog = iwi_watchdog;
417 1.37.2.2 yamt IFQ_SET_READY(&ifp->if_snd);
418 1.37.2.2 yamt memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
419 1.37.2.2 yamt
420 1.37.2.2 yamt if_attach(ifp);
421 1.37.2.2 yamt ieee80211_ifattach(ic);
422 1.37.2.2 yamt /* override default methods */
423 1.37.2.2 yamt ic->ic_node_alloc = iwi_node_alloc;
424 1.37.2.2 yamt sc->sc_node_free = ic->ic_node_free;
425 1.37.2.2 yamt ic->ic_node_free = iwi_node_free;
426 1.37.2.2 yamt /* override state transition machine */
427 1.37.2.2 yamt sc->sc_newstate = ic->ic_newstate;
428 1.37.2.2 yamt ic->ic_newstate = iwi_newstate;
429 1.37.2.2 yamt ieee80211_media_init(ic, iwi_media_change, iwi_media_status);
430 1.37.2.2 yamt
431 1.37.2.2 yamt #if NBPFILTER > 0
432 1.37.2.2 yamt bpfattach2(ifp, DLT_IEEE802_11_RADIO,
433 1.37.2.2 yamt sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf);
434 1.37.2.2 yamt
435 1.37.2.2 yamt sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
436 1.37.2.2 yamt sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
437 1.37.2.2 yamt sc->sc_rxtap.wr_ihdr.it_present = htole32(IWI_RX_RADIOTAP_PRESENT);
438 1.37.2.2 yamt
439 1.37.2.2 yamt sc->sc_txtap_len = sizeof sc->sc_txtapu;
440 1.37.2.2 yamt sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
441 1.37.2.2 yamt sc->sc_txtap.wt_ihdr.it_present = htole32(IWI_TX_RADIOTAP_PRESENT);
442 1.37.2.2 yamt #endif
443 1.37.2.2 yamt
444 1.37.2.2 yamt /*
445 1.37.2.2 yamt * Make sure the interface is shutdown during reboot.
446 1.37.2.2 yamt */
447 1.37.2.2 yamt sc->sc_sdhook = shutdownhook_establish(iwi_shutdown, sc);
448 1.37.2.2 yamt if (sc->sc_sdhook == NULL)
449 1.37.2.2 yamt aprint_error("%s: WARNING: unable to establish shutdown hook\n",
450 1.37.2.2 yamt sc->sc_dev.dv_xname);
451 1.37.2.2 yamt sc->sc_powerhook = powerhook_establish(iwi_powerhook, sc);
452 1.37.2.2 yamt if (sc->sc_powerhook == NULL)
453 1.37.2.2 yamt printf("%s: WARNING: unable to establish power hook\n",
454 1.37.2.2 yamt sc->sc_dev.dv_xname);
455 1.37.2.2 yamt
456 1.37.2.2 yamt ieee80211_announce(ic);
457 1.37.2.2 yamt /*
458 1.37.2.2 yamt * Add a few sysctl knobs.
459 1.37.2.2 yamt * XXX: Not yet.
460 1.37.2.2 yamt */
461 1.37.2.2 yamt sc->dwelltime = 100;
462 1.37.2.2 yamt sc->bluetooth = 1;
463 1.37.2.2 yamt sc->antenna = 0;
464 1.37.2.2 yamt
465 1.37.2.2 yamt return;
466 1.37.2.2 yamt
467 1.37.2.2 yamt fail: iwi_detach(self, 0);
468 1.37.2.2 yamt }
469 1.37.2.2 yamt
470 1.37.2.2 yamt static int
471 1.37.2.2 yamt iwi_detach(struct device* self, int flags)
472 1.37.2.2 yamt {
473 1.37.2.2 yamt struct iwi_softc *sc = (struct iwi_softc *)self;
474 1.37.2.2 yamt struct ifnet *ifp = &sc->sc_if;
475 1.37.2.2 yamt
476 1.37.2.2 yamt iwi_stop(ifp, 1);
477 1.37.2.2 yamt iwi_free_firmware(sc);
478 1.37.2.2 yamt
479 1.37.2.2 yamt #if NBPFILTER > 0
480 1.37.2.2 yamt if (ifp != NULL)
481 1.37.2.2 yamt bpfdetach(ifp);
482 1.37.2.2 yamt #endif
483 1.37.2.2 yamt ieee80211_ifdetach(&sc->sc_ic);
484 1.37.2.2 yamt if (ifp != NULL)
485 1.37.2.2 yamt if_detach(ifp);
486 1.37.2.2 yamt
487 1.37.2.2 yamt iwi_free_cmd_ring(sc, &sc->cmdq);
488 1.37.2.2 yamt iwi_free_tx_ring(sc, &sc->txq[0]);
489 1.37.2.2 yamt iwi_free_tx_ring(sc, &sc->txq[1]);
490 1.37.2.2 yamt iwi_free_tx_ring(sc, &sc->txq[2]);
491 1.37.2.2 yamt iwi_free_tx_ring(sc, &sc->txq[3]);
492 1.37.2.2 yamt iwi_free_rx_ring(sc, &sc->rxq);
493 1.37.2.2 yamt
494 1.37.2.2 yamt if (sc->sc_ih != NULL) {
495 1.37.2.2 yamt pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
496 1.37.2.2 yamt sc->sc_ih = NULL;
497 1.37.2.2 yamt }
498 1.37.2.2 yamt
499 1.37.2.2 yamt bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
500 1.37.2.2 yamt
501 1.37.2.2 yamt powerhook_disestablish(sc->sc_powerhook);
502 1.37.2.2 yamt shutdownhook_disestablish(sc->sc_sdhook);
503 1.37.2.2 yamt
504 1.37.2.2 yamt return 0;
505 1.37.2.2 yamt }
506 1.37.2.2 yamt
507 1.37.2.2 yamt static int
508 1.37.2.2 yamt iwi_alloc_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring,
509 1.37.2.2 yamt int count)
510 1.37.2.2 yamt {
511 1.37.2.2 yamt int error, nsegs;
512 1.37.2.2 yamt
513 1.37.2.2 yamt ring->count = count;
514 1.37.2.2 yamt ring->queued = 0;
515 1.37.2.2 yamt ring->cur = ring->next = 0;
516 1.37.2.2 yamt
517 1.37.2.2 yamt /*
518 1.37.2.2 yamt * Allocate and map command ring
519 1.37.2.2 yamt */
520 1.37.2.2 yamt error = bus_dmamap_create(sc->sc_dmat,
521 1.37.2.2 yamt IWI_CMD_DESC_SIZE * count, 1,
522 1.37.2.2 yamt IWI_CMD_DESC_SIZE * count, 0,
523 1.37.2.2 yamt BUS_DMA_NOWAIT, &ring->desc_map);
524 1.37.2.2 yamt if (error != 0) {
525 1.37.2.2 yamt aprint_error("%s: could not create command ring DMA map\n",
526 1.37.2.2 yamt sc->sc_dev.dv_xname);
527 1.37.2.2 yamt goto fail;
528 1.37.2.2 yamt }
529 1.37.2.2 yamt
530 1.37.2.2 yamt error = bus_dmamem_alloc(sc->sc_dmat,
531 1.37.2.2 yamt IWI_CMD_DESC_SIZE * count, PAGE_SIZE, 0,
532 1.37.2.2 yamt &sc->cmdq.desc_seg, 1, &nsegs, BUS_DMA_NOWAIT);
533 1.37.2.2 yamt if (error != 0) {
534 1.37.2.2 yamt aprint_error("%s: could not allocate command ring DMA memory\n",
535 1.37.2.2 yamt sc->sc_dev.dv_xname);
536 1.37.2.2 yamt goto fail;
537 1.37.2.2 yamt }
538 1.37.2.2 yamt
539 1.37.2.2 yamt error = bus_dmamem_map(sc->sc_dmat, &sc->cmdq.desc_seg, nsegs,
540 1.37.2.2 yamt IWI_CMD_DESC_SIZE * count,
541 1.37.2.2 yamt (caddr_t *)&sc->cmdq.desc, BUS_DMA_NOWAIT);
542 1.37.2.2 yamt if (error != 0) {
543 1.37.2.2 yamt aprint_error("%s: could not map command ring DMA memory\n",
544 1.37.2.2 yamt sc->sc_dev.dv_xname);
545 1.37.2.2 yamt goto fail;
546 1.37.2.2 yamt }
547 1.37.2.2 yamt
548 1.37.2.2 yamt error = bus_dmamap_load(sc->sc_dmat, sc->cmdq.desc_map, sc->cmdq.desc,
549 1.37.2.2 yamt IWI_CMD_DESC_SIZE * count, NULL,
550 1.37.2.2 yamt BUS_DMA_NOWAIT);
551 1.37.2.2 yamt if (error != 0) {
552 1.37.2.2 yamt aprint_error("%s: could not load command ring DMA map\n",
553 1.37.2.2 yamt sc->sc_dev.dv_xname);
554 1.37.2.2 yamt goto fail;
555 1.37.2.2 yamt }
556 1.37.2.2 yamt
557 1.37.2.2 yamt memset(sc->cmdq.desc, 0,
558 1.37.2.2 yamt IWI_CMD_DESC_SIZE * count);
559 1.37.2.2 yamt
560 1.37.2.2 yamt return 0;
561 1.37.2.2 yamt
562 1.37.2.2 yamt fail: iwi_free_cmd_ring(sc, ring);
563 1.37.2.2 yamt return error;
564 1.37.2.2 yamt }
565 1.37.2.2 yamt
566 1.37.2.2 yamt static void
567 1.37.2.2 yamt iwi_reset_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring)
568 1.37.2.2 yamt {
569 1.37.2.3 yamt int i;
570 1.37.2.3 yamt
571 1.37.2.3 yamt for (i = ring->next; i != ring->cur;) {
572 1.37.2.3 yamt bus_dmamap_sync(sc->sc_dmat, sc->cmdq.desc_map,
573 1.37.2.3 yamt i * IWI_CMD_DESC_SIZE, IWI_CMD_DESC_SIZE,
574 1.37.2.3 yamt BUS_DMASYNC_POSTWRITE);
575 1.37.2.3 yamt
576 1.37.2.3 yamt wakeup(&ring->desc[i]);
577 1.37.2.3 yamt i = (i + 1) % ring->count;
578 1.37.2.3 yamt }
579 1.37.2.3 yamt
580 1.37.2.2 yamt ring->queued = 0;
581 1.37.2.2 yamt ring->cur = ring->next = 0;
582 1.37.2.2 yamt }
583 1.37.2.2 yamt
584 1.37.2.2 yamt static void
585 1.37.2.2 yamt iwi_free_cmd_ring(struct iwi_softc *sc, struct iwi_cmd_ring *ring)
586 1.37.2.2 yamt {
587 1.37.2.2 yamt if (ring->desc_map != NULL) {
588 1.37.2.2 yamt if (ring->desc != NULL) {
589 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, ring->desc_map);
590 1.37.2.2 yamt bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
591 1.37.2.2 yamt IWI_CMD_DESC_SIZE * ring->count);
592 1.37.2.2 yamt bus_dmamem_free(sc->sc_dmat, &ring->desc_seg, 1);
593 1.37.2.2 yamt }
594 1.37.2.2 yamt bus_dmamap_destroy(sc->sc_dmat, ring->desc_map);
595 1.37.2.2 yamt }
596 1.37.2.2 yamt }
597 1.37.2.2 yamt
598 1.37.2.2 yamt static int
599 1.37.2.2 yamt iwi_alloc_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring,
600 1.37.2.2 yamt int count, bus_addr_t csr_ridx, bus_addr_t csr_widx)
601 1.37.2.2 yamt {
602 1.37.2.2 yamt int i, error, nsegs;
603 1.37.2.2 yamt
604 1.37.2.2 yamt ring->count = count;
605 1.37.2.2 yamt ring->queued = 0;
606 1.37.2.2 yamt ring->cur = ring->next = 0;
607 1.37.2.2 yamt ring->csr_ridx = csr_ridx;
608 1.37.2.2 yamt ring->csr_widx = csr_widx;
609 1.37.2.2 yamt
610 1.37.2.2 yamt /*
611 1.37.2.2 yamt * Allocate and map Tx ring
612 1.37.2.2 yamt */
613 1.37.2.2 yamt error = bus_dmamap_create(sc->sc_dmat,
614 1.37.2.2 yamt IWI_TX_DESC_SIZE * count, 1,
615 1.37.2.2 yamt IWI_TX_DESC_SIZE * count, 0, BUS_DMA_NOWAIT,
616 1.37.2.2 yamt &ring->desc_map);
617 1.37.2.2 yamt if (error != 0) {
618 1.37.2.2 yamt aprint_error("%s: could not create tx ring DMA map\n",
619 1.37.2.2 yamt sc->sc_dev.dv_xname);
620 1.37.2.2 yamt goto fail;
621 1.37.2.2 yamt }
622 1.37.2.2 yamt
623 1.37.2.2 yamt error = bus_dmamem_alloc(sc->sc_dmat,
624 1.37.2.2 yamt IWI_TX_DESC_SIZE * count, PAGE_SIZE, 0,
625 1.37.2.2 yamt &ring->desc_seg, 1, &nsegs, BUS_DMA_NOWAIT);
626 1.37.2.2 yamt if (error != 0) {
627 1.37.2.2 yamt aprint_error("%s: could not allocate tx ring DMA memory\n",
628 1.37.2.2 yamt sc->sc_dev.dv_xname);
629 1.37.2.2 yamt goto fail;
630 1.37.2.2 yamt }
631 1.37.2.2 yamt
632 1.37.2.2 yamt error = bus_dmamem_map(sc->sc_dmat, &ring->desc_seg, nsegs,
633 1.37.2.2 yamt IWI_TX_DESC_SIZE * count,
634 1.37.2.2 yamt (caddr_t *)&ring->desc, BUS_DMA_NOWAIT);
635 1.37.2.2 yamt if (error != 0) {
636 1.37.2.2 yamt aprint_error("%s: could not map tx ring DMA memory\n",
637 1.37.2.2 yamt sc->sc_dev.dv_xname);
638 1.37.2.2 yamt goto fail;
639 1.37.2.2 yamt }
640 1.37.2.2 yamt
641 1.37.2.2 yamt error = bus_dmamap_load(sc->sc_dmat, ring->desc_map, ring->desc,
642 1.37.2.2 yamt IWI_TX_DESC_SIZE * count, NULL,
643 1.37.2.2 yamt BUS_DMA_NOWAIT);
644 1.37.2.2 yamt if (error != 0) {
645 1.37.2.2 yamt aprint_error("%s: could not load tx ring DMA map\n",
646 1.37.2.2 yamt sc->sc_dev.dv_xname);
647 1.37.2.2 yamt goto fail;
648 1.37.2.2 yamt }
649 1.37.2.2 yamt
650 1.37.2.2 yamt memset(ring->desc, 0, IWI_TX_DESC_SIZE * count);
651 1.37.2.2 yamt
652 1.37.2.2 yamt ring->data = malloc(count * sizeof (struct iwi_tx_data), M_DEVBUF,
653 1.37.2.2 yamt M_NOWAIT | M_ZERO);
654 1.37.2.2 yamt if (ring->data == NULL) {
655 1.37.2.2 yamt aprint_error("%s: could not allocate soft data\n",
656 1.37.2.2 yamt sc->sc_dev.dv_xname);
657 1.37.2.2 yamt error = ENOMEM;
658 1.37.2.2 yamt goto fail;
659 1.37.2.2 yamt }
660 1.37.2.2 yamt
661 1.37.2.2 yamt /*
662 1.37.2.2 yamt * Allocate Tx buffers DMA maps
663 1.37.2.2 yamt */
664 1.37.2.2 yamt for (i = 0; i < count; i++) {
665 1.37.2.2 yamt error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, IWI_MAX_NSEG,
666 1.37.2.2 yamt MCLBYTES, 0, BUS_DMA_NOWAIT, &ring->data[i].map);
667 1.37.2.2 yamt if (error != 0) {
668 1.37.2.2 yamt aprint_error("%s: could not create tx buf DMA map",
669 1.37.2.2 yamt sc->sc_dev.dv_xname);
670 1.37.2.2 yamt goto fail;
671 1.37.2.2 yamt }
672 1.37.2.2 yamt }
673 1.37.2.2 yamt return 0;
674 1.37.2.2 yamt
675 1.37.2.2 yamt fail: iwi_free_tx_ring(sc, ring);
676 1.37.2.2 yamt return error;
677 1.37.2.2 yamt }
678 1.37.2.2 yamt
679 1.37.2.2 yamt static void
680 1.37.2.2 yamt iwi_reset_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring)
681 1.37.2.2 yamt {
682 1.37.2.2 yamt struct iwi_tx_data *data;
683 1.37.2.2 yamt int i;
684 1.37.2.2 yamt
685 1.37.2.2 yamt for (i = 0; i < ring->count; i++) {
686 1.37.2.2 yamt data = &ring->data[i];
687 1.37.2.2 yamt
688 1.37.2.2 yamt if (data->m != NULL) {
689 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, data->map, 0,
690 1.37.2.2 yamt data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
691 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, data->map);
692 1.37.2.2 yamt m_freem(data->m);
693 1.37.2.2 yamt data->m = NULL;
694 1.37.2.2 yamt }
695 1.37.2.2 yamt
696 1.37.2.2 yamt if (data->ni != NULL) {
697 1.37.2.2 yamt ieee80211_free_node(data->ni);
698 1.37.2.2 yamt data->ni = NULL;
699 1.37.2.2 yamt }
700 1.37.2.2 yamt }
701 1.37.2.2 yamt
702 1.37.2.2 yamt ring->queued = 0;
703 1.37.2.2 yamt ring->cur = ring->next = 0;
704 1.37.2.2 yamt }
705 1.37.2.2 yamt
706 1.37.2.2 yamt static void
707 1.37.2.2 yamt iwi_free_tx_ring(struct iwi_softc *sc, struct iwi_tx_ring *ring)
708 1.37.2.2 yamt {
709 1.37.2.2 yamt int i;
710 1.37.2.2 yamt
711 1.37.2.2 yamt if (ring->desc_map != NULL) {
712 1.37.2.2 yamt if (ring->desc != NULL) {
713 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, ring->desc_map);
714 1.37.2.2 yamt bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
715 1.37.2.2 yamt IWI_TX_DESC_SIZE * ring->count);
716 1.37.2.2 yamt bus_dmamem_free(sc->sc_dmat, &ring->desc_seg, 1);
717 1.37.2.2 yamt }
718 1.37.2.2 yamt bus_dmamap_destroy(sc->sc_dmat, ring->desc_map);
719 1.37.2.2 yamt }
720 1.37.2.2 yamt
721 1.37.2.2 yamt for (i = 0; i < ring->count; i++) {
722 1.37.2.2 yamt if (ring->data[i].m != NULL) {
723 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, ring->data[i].map);
724 1.37.2.2 yamt m_freem(ring->data[i].m);
725 1.37.2.2 yamt }
726 1.37.2.2 yamt bus_dmamap_destroy(sc->sc_dmat, ring->data[i].map);
727 1.37.2.2 yamt }
728 1.37.2.2 yamt }
729 1.37.2.2 yamt
730 1.37.2.2 yamt static int
731 1.37.2.2 yamt iwi_alloc_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring,
732 1.37.2.2 yamt int count)
733 1.37.2.2 yamt {
734 1.37.2.2 yamt int i, error;
735 1.37.2.2 yamt
736 1.37.2.2 yamt ring->count = count;
737 1.37.2.2 yamt ring->cur = 0;
738 1.37.2.2 yamt
739 1.37.2.2 yamt ring->data = malloc(count * sizeof (struct iwi_rx_data), M_DEVBUF,
740 1.37.2.2 yamt M_NOWAIT | M_ZERO);
741 1.37.2.2 yamt if (ring->data == NULL) {
742 1.37.2.2 yamt aprint_error("%s: could not allocate soft data\n",
743 1.37.2.2 yamt sc->sc_dev.dv_xname);
744 1.37.2.2 yamt error = ENOMEM;
745 1.37.2.2 yamt goto fail;
746 1.37.2.2 yamt }
747 1.37.2.2 yamt
748 1.37.2.2 yamt /*
749 1.37.2.2 yamt * Allocate and map Rx buffers
750 1.37.2.2 yamt */
751 1.37.2.2 yamt for (i = 0; i < count; i++) {
752 1.37.2.2 yamt
753 1.37.2.2 yamt error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
754 1.37.2.2 yamt 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ring->data[i].map);
755 1.37.2.2 yamt if (error != 0) {
756 1.37.2.2 yamt aprint_error("%s: could not create rx buf DMA map",
757 1.37.2.2 yamt sc->sc_dev.dv_xname);
758 1.37.2.2 yamt goto fail;
759 1.37.2.2 yamt }
760 1.37.2.2 yamt
761 1.37.2.2 yamt if ((ring->data[i].m = iwi_alloc_rx_buf(sc)) == NULL) {
762 1.37.2.2 yamt error = ENOMEM;
763 1.37.2.2 yamt goto fail;
764 1.37.2.2 yamt }
765 1.37.2.2 yamt
766 1.37.2.2 yamt error = bus_dmamap_load_mbuf(sc->sc_dmat, ring->data[i].map,
767 1.37.2.2 yamt ring->data[i].m, BUS_DMA_READ | BUS_DMA_NOWAIT);
768 1.37.2.2 yamt if (error != 0) {
769 1.37.2.2 yamt aprint_error("%s: could not load rx buffer DMA map\n",
770 1.37.2.2 yamt sc->sc_dev.dv_xname);
771 1.37.2.2 yamt goto fail;
772 1.37.2.2 yamt }
773 1.37.2.3 yamt
774 1.37.2.3 yamt bus_dmamap_sync(sc->sc_dmat, ring->data[i].map, 0,
775 1.37.2.3 yamt ring->data[i].map->dm_mapsize, BUS_DMASYNC_PREREAD);
776 1.37.2.2 yamt }
777 1.37.2.2 yamt
778 1.37.2.2 yamt return 0;
779 1.37.2.2 yamt
780 1.37.2.2 yamt fail: iwi_free_rx_ring(sc, ring);
781 1.37.2.2 yamt return error;
782 1.37.2.2 yamt }
783 1.37.2.2 yamt
784 1.37.2.2 yamt static void
785 1.37.2.2 yamt iwi_reset_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring)
786 1.37.2.2 yamt {
787 1.37.2.2 yamt ring->cur = 0;
788 1.37.2.2 yamt }
789 1.37.2.2 yamt
790 1.37.2.2 yamt static void
791 1.37.2.2 yamt iwi_free_rx_ring(struct iwi_softc *sc, struct iwi_rx_ring *ring)
792 1.37.2.2 yamt {
793 1.37.2.2 yamt int i;
794 1.37.2.2 yamt
795 1.37.2.2 yamt for (i = 0; i < ring->count; i++) {
796 1.37.2.2 yamt if (ring->data[i].m != NULL) {
797 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, ring->data[i].map);
798 1.37.2.2 yamt m_freem(ring->data[i].m);
799 1.37.2.2 yamt }
800 1.37.2.2 yamt bus_dmamap_destroy(sc->sc_dmat, ring->data[i].map);
801 1.37.2.2 yamt }
802 1.37.2.2 yamt }
803 1.37.2.2 yamt
804 1.37.2.2 yamt static void
805 1.37.2.2 yamt iwi_shutdown(void *arg)
806 1.37.2.2 yamt {
807 1.37.2.2 yamt struct iwi_softc *sc = (struct iwi_softc *)arg;
808 1.37.2.2 yamt struct ifnet *ifp = sc->sc_ic.ic_ifp;
809 1.37.2.2 yamt
810 1.37.2.2 yamt iwi_stop(ifp, 1);
811 1.37.2.2 yamt }
812 1.37.2.2 yamt
813 1.37.2.2 yamt static int
814 1.37.2.2 yamt iwi_suspend(struct iwi_softc *sc)
815 1.37.2.2 yamt {
816 1.37.2.2 yamt struct ifnet *ifp = sc->sc_ic.ic_ifp;
817 1.37.2.2 yamt
818 1.37.2.2 yamt iwi_stop(ifp, 1);
819 1.37.2.2 yamt
820 1.37.2.2 yamt return 0;
821 1.37.2.2 yamt }
822 1.37.2.2 yamt
823 1.37.2.2 yamt static int
824 1.37.2.2 yamt iwi_resume(struct iwi_softc *sc)
825 1.37.2.2 yamt {
826 1.37.2.2 yamt struct ifnet *ifp = sc->sc_ic.ic_ifp;
827 1.37.2.2 yamt pcireg_t data;
828 1.37.2.2 yamt
829 1.37.2.2 yamt /* clear device specific PCI configuration register 0x41 */
830 1.37.2.2 yamt data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
831 1.37.2.2 yamt data &= ~0x0000ff00;
832 1.37.2.2 yamt pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
833 1.37.2.2 yamt
834 1.37.2.2 yamt if (ifp->if_flags & IFF_UP) {
835 1.37.2.2 yamt iwi_init(ifp);
836 1.37.2.2 yamt if (ifp->if_flags & IFF_RUNNING)
837 1.37.2.2 yamt iwi_start(ifp);
838 1.37.2.2 yamt }
839 1.37.2.2 yamt
840 1.37.2.2 yamt return 0;
841 1.37.2.2 yamt }
842 1.37.2.2 yamt
843 1.37.2.2 yamt static void
844 1.37.2.2 yamt iwi_powerhook(int why, void *arg)
845 1.37.2.2 yamt {
846 1.37.2.2 yamt struct iwi_softc *sc = arg;
847 1.37.2.2 yamt int s;
848 1.37.2.2 yamt
849 1.37.2.2 yamt s = splnet();
850 1.37.2.2 yamt switch (why) {
851 1.37.2.2 yamt case PWR_SUSPEND:
852 1.37.2.2 yamt case PWR_STANDBY:
853 1.37.2.2 yamt iwi_suspend(sc);
854 1.37.2.2 yamt break;
855 1.37.2.2 yamt case PWR_RESUME:
856 1.37.2.2 yamt iwi_resume(sc);
857 1.37.2.2 yamt break;
858 1.37.2.2 yamt case PWR_SOFTSUSPEND:
859 1.37.2.2 yamt case PWR_SOFTSTANDBY:
860 1.37.2.2 yamt case PWR_SOFTRESUME:
861 1.37.2.2 yamt break;
862 1.37.2.2 yamt }
863 1.37.2.2 yamt splx(s);
864 1.37.2.2 yamt }
865 1.37.2.2 yamt
866 1.37.2.2 yamt static struct ieee80211_node *
867 1.37.2.2 yamt iwi_node_alloc(struct ieee80211_node_table *nt)
868 1.37.2.2 yamt {
869 1.37.2.2 yamt struct iwi_node *in;
870 1.37.2.2 yamt
871 1.37.2.2 yamt in = malloc(sizeof (struct iwi_node), M_80211_NODE, M_NOWAIT | M_ZERO);
872 1.37.2.2 yamt if (in == NULL)
873 1.37.2.2 yamt return NULL;
874 1.37.2.2 yamt
875 1.37.2.2 yamt in->in_station = -1;
876 1.37.2.2 yamt
877 1.37.2.2 yamt return &in->in_node;
878 1.37.2.2 yamt }
879 1.37.2.2 yamt
880 1.37.2.2 yamt static int
881 1.37.2.2 yamt iwi_alloc_unr(struct iwi_softc *sc)
882 1.37.2.2 yamt {
883 1.37.2.2 yamt int i;
884 1.37.2.2 yamt
885 1.37.2.2 yamt for (i = 0; i < IWI_MAX_IBSSNODE - 1; i++)
886 1.37.2.2 yamt if ((sc->sc_unr & (1 << i)) == 0) {
887 1.37.2.2 yamt sc->sc_unr |= 1 << i;
888 1.37.2.2 yamt return i;
889 1.37.2.2 yamt }
890 1.37.2.2 yamt
891 1.37.2.2 yamt return -1;
892 1.37.2.2 yamt }
893 1.37.2.2 yamt
894 1.37.2.2 yamt static void
895 1.37.2.2 yamt iwi_free_unr(struct iwi_softc *sc, int r)
896 1.37.2.2 yamt {
897 1.37.2.2 yamt
898 1.37.2.2 yamt sc->sc_unr &= 1 << r;
899 1.37.2.2 yamt }
900 1.37.2.2 yamt
901 1.37.2.2 yamt static void
902 1.37.2.2 yamt iwi_node_free(struct ieee80211_node *ni)
903 1.37.2.2 yamt {
904 1.37.2.2 yamt struct ieee80211com *ic = ni->ni_ic;
905 1.37.2.2 yamt struct iwi_softc *sc = ic->ic_ifp->if_softc;
906 1.37.2.2 yamt struct iwi_node *in = (struct iwi_node *)ni;
907 1.37.2.2 yamt
908 1.37.2.2 yamt if (in->in_station != -1)
909 1.37.2.2 yamt iwi_free_unr(sc, in->in_station);
910 1.37.2.2 yamt
911 1.37.2.2 yamt sc->sc_node_free(ni);
912 1.37.2.2 yamt }
913 1.37.2.2 yamt
914 1.37.2.2 yamt static int
915 1.37.2.2 yamt iwi_media_change(struct ifnet *ifp)
916 1.37.2.2 yamt {
917 1.37.2.2 yamt int error;
918 1.37.2.2 yamt
919 1.37.2.2 yamt error = ieee80211_media_change(ifp);
920 1.37.2.2 yamt if (error != ENETRESET)
921 1.37.2.2 yamt return error;
922 1.37.2.2 yamt
923 1.37.2.2 yamt if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
924 1.37.2.2 yamt iwi_init(ifp);
925 1.37.2.2 yamt
926 1.37.2.2 yamt return 0;
927 1.37.2.2 yamt }
928 1.37.2.2 yamt
929 1.37.2.2 yamt /*
930 1.37.2.2 yamt * The firmware automatically adapts the transmit speed. We report its current
931 1.37.2.2 yamt * value here.
932 1.37.2.2 yamt */
933 1.37.2.2 yamt static void
934 1.37.2.2 yamt iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
935 1.37.2.2 yamt {
936 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
937 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
938 1.37.2.2 yamt #define N(a) (sizeof (a) / sizeof (a[0]))
939 1.37.2.2 yamt static const struct {
940 1.37.2.2 yamt uint32_t val;
941 1.37.2.2 yamt int rate;
942 1.37.2.2 yamt } rates[] = {
943 1.37.2.2 yamt { IWI_RATE_DS1, 2 },
944 1.37.2.2 yamt { IWI_RATE_DS2, 4 },
945 1.37.2.2 yamt { IWI_RATE_DS5, 11 },
946 1.37.2.2 yamt { IWI_RATE_DS11, 22 },
947 1.37.2.2 yamt { IWI_RATE_OFDM6, 12 },
948 1.37.2.2 yamt { IWI_RATE_OFDM9, 18 },
949 1.37.2.2 yamt { IWI_RATE_OFDM12, 24 },
950 1.37.2.2 yamt { IWI_RATE_OFDM18, 36 },
951 1.37.2.2 yamt { IWI_RATE_OFDM24, 48 },
952 1.37.2.2 yamt { IWI_RATE_OFDM36, 72 },
953 1.37.2.2 yamt { IWI_RATE_OFDM48, 96 },
954 1.37.2.2 yamt { IWI_RATE_OFDM54, 108 },
955 1.37.2.2 yamt };
956 1.37.2.2 yamt uint32_t val;
957 1.37.2.2 yamt int rate, i;
958 1.37.2.2 yamt
959 1.37.2.2 yamt imr->ifm_status = IFM_AVALID;
960 1.37.2.2 yamt imr->ifm_active = IFM_IEEE80211;
961 1.37.2.2 yamt if (ic->ic_state == IEEE80211_S_RUN)
962 1.37.2.2 yamt imr->ifm_status |= IFM_ACTIVE;
963 1.37.2.2 yamt
964 1.37.2.2 yamt /* read current transmission rate from adapter */
965 1.37.2.2 yamt val = CSR_READ_4(sc, IWI_CSR_CURRENT_TX_RATE);
966 1.37.2.2 yamt
967 1.37.2.2 yamt /* convert rate to 802.11 rate */
968 1.37.2.2 yamt for (i = 0; i < N(rates) && rates[i].val != val; i++);
969 1.37.2.2 yamt rate = (i < N(rates)) ? rates[i].rate : 0;
970 1.37.2.2 yamt
971 1.37.2.2 yamt imr->ifm_active |= ieee80211_rate2media(ic, rate, ic->ic_curmode);
972 1.37.2.2 yamt switch (ic->ic_opmode) {
973 1.37.2.2 yamt case IEEE80211_M_STA:
974 1.37.2.2 yamt break;
975 1.37.2.2 yamt
976 1.37.2.2 yamt case IEEE80211_M_IBSS:
977 1.37.2.2 yamt imr->ifm_active |= IFM_IEEE80211_ADHOC;
978 1.37.2.2 yamt break;
979 1.37.2.2 yamt
980 1.37.2.2 yamt case IEEE80211_M_MONITOR:
981 1.37.2.2 yamt imr->ifm_active |= IFM_IEEE80211_MONITOR;
982 1.37.2.2 yamt break;
983 1.37.2.2 yamt
984 1.37.2.2 yamt case IEEE80211_M_AHDEMO:
985 1.37.2.2 yamt case IEEE80211_M_HOSTAP:
986 1.37.2.2 yamt /* should not get there */
987 1.37.2.2 yamt break;
988 1.37.2.2 yamt }
989 1.37.2.2 yamt #undef N
990 1.37.2.2 yamt }
991 1.37.2.2 yamt
992 1.37.2.2 yamt static int
993 1.37.2.2 yamt iwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
994 1.37.2.2 yamt {
995 1.37.2.2 yamt struct iwi_softc *sc = ic->ic_ifp->if_softc;
996 1.37.2.2 yamt
997 1.37.2.2 yamt switch (nstate) {
998 1.37.2.2 yamt case IEEE80211_S_SCAN:
999 1.37.2.2 yamt if (sc->flags & IWI_FLAG_SCANNING)
1000 1.37.2.2 yamt break;
1001 1.37.2.2 yamt
1002 1.37.2.2 yamt ieee80211_node_table_reset(&ic->ic_scan);
1003 1.37.2.2 yamt ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN;
1004 1.37.2.2 yamt sc->flags |= IWI_FLAG_SCANNING;
1005 1.37.2.3 yamt /* blink the led while scanning */
1006 1.37.2.3 yamt iwi_led_set(sc, IWI_LED_ASSOCIATED, 1);
1007 1.37.2.2 yamt iwi_scan(sc);
1008 1.37.2.2 yamt break;
1009 1.37.2.2 yamt
1010 1.37.2.2 yamt case IEEE80211_S_AUTH:
1011 1.37.2.2 yamt iwi_auth_and_assoc(sc);
1012 1.37.2.2 yamt break;
1013 1.37.2.2 yamt
1014 1.37.2.2 yamt case IEEE80211_S_RUN:
1015 1.37.2.2 yamt if (ic->ic_opmode == IEEE80211_M_IBSS)
1016 1.37.2.2 yamt ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
1017 1.37.2.2 yamt else if (ic->ic_opmode == IEEE80211_M_MONITOR)
1018 1.37.2.2 yamt iwi_set_chan(sc, ic->ic_ibss_chan);
1019 1.37.2.2 yamt
1020 1.37.2.2 yamt return (*sc->sc_newstate)(ic, nstate,
1021 1.37.2.2 yamt IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
1022 1.37.2.2 yamt
1023 1.37.2.2 yamt case IEEE80211_S_ASSOC:
1024 1.37.2.3 yamt iwi_led_set(sc, IWI_LED_ASSOCIATED, 0);
1025 1.37.2.2 yamt break;
1026 1.37.2.2 yamt
1027 1.37.2.2 yamt case IEEE80211_S_INIT:
1028 1.37.2.2 yamt sc->flags &= ~IWI_FLAG_SCANNING;
1029 1.37.2.2 yamt return (*sc->sc_newstate)(ic, nstate, arg);
1030 1.37.2.2 yamt }
1031 1.37.2.2 yamt
1032 1.37.2.2 yamt ic->ic_state = nstate;
1033 1.37.2.2 yamt return 0;
1034 1.37.2.2 yamt }
1035 1.37.2.2 yamt
1036 1.37.2.2 yamt /*
1037 1.37.2.2 yamt * WME parameters coming from IEEE 802.11e specification. These values are
1038 1.37.2.2 yamt * already declared in ieee80211_proto.c, but they are static so they can't
1039 1.37.2.2 yamt * be reused here.
1040 1.37.2.2 yamt */
1041 1.37.2.2 yamt static const struct wmeParams iwi_wme_cck_params[WME_NUM_AC] = {
1042 1.37.2.2 yamt { 0, 3, 5, 7, 0 }, /* WME_AC_BE */
1043 1.37.2.2 yamt { 0, 3, 5, 10, 0 }, /* WME_AC_BK */
1044 1.37.2.2 yamt { 0, 2, 4, 5, 188 }, /* WME_AC_VI */
1045 1.37.2.2 yamt { 0, 2, 3, 4, 102 } /* WME_AC_VO */
1046 1.37.2.2 yamt };
1047 1.37.2.2 yamt
1048 1.37.2.2 yamt static const struct wmeParams iwi_wme_ofdm_params[WME_NUM_AC] = {
1049 1.37.2.2 yamt { 0, 3, 4, 6, 0 }, /* WME_AC_BE */
1050 1.37.2.2 yamt { 0, 3, 4, 10, 0 }, /* WME_AC_BK */
1051 1.37.2.2 yamt { 0, 2, 3, 4, 94 }, /* WME_AC_VI */
1052 1.37.2.2 yamt { 0, 2, 2, 3, 47 } /* WME_AC_VO */
1053 1.37.2.2 yamt };
1054 1.37.2.2 yamt
1055 1.37.2.2 yamt static int
1056 1.37.2.2 yamt iwi_wme_update(struct ieee80211com *ic)
1057 1.37.2.2 yamt {
1058 1.37.2.2 yamt #define IWI_EXP2(v) htole16((1 << (v)) - 1)
1059 1.37.2.2 yamt #define IWI_USEC(v) htole16(IEEE80211_TXOP_TO_US(v))
1060 1.37.2.2 yamt struct iwi_softc *sc = ic->ic_ifp->if_softc;
1061 1.37.2.2 yamt struct iwi_wme_params wme[3];
1062 1.37.2.2 yamt const struct wmeParams *wmep;
1063 1.37.2.2 yamt int ac;
1064 1.37.2.2 yamt
1065 1.37.2.2 yamt /*
1066 1.37.2.2 yamt * We shall not override firmware default WME values if WME is not
1067 1.37.2.2 yamt * actually enabled.
1068 1.37.2.2 yamt */
1069 1.37.2.2 yamt if (!(ic->ic_flags & IEEE80211_F_WME))
1070 1.37.2.2 yamt return 0;
1071 1.37.2.2 yamt
1072 1.37.2.2 yamt for (ac = 0; ac < WME_NUM_AC; ac++) {
1073 1.37.2.2 yamt /* set WME values for current operating mode */
1074 1.37.2.2 yamt wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
1075 1.37.2.2 yamt wme[0].aifsn[ac] = wmep->wmep_aifsn;
1076 1.37.2.2 yamt wme[0].cwmin[ac] = IWI_EXP2(wmep->wmep_logcwmin);
1077 1.37.2.2 yamt wme[0].cwmax[ac] = IWI_EXP2(wmep->wmep_logcwmax);
1078 1.37.2.2 yamt wme[0].burst[ac] = IWI_USEC(wmep->wmep_txopLimit);
1079 1.37.2.2 yamt wme[0].acm[ac] = wmep->wmep_acm;
1080 1.37.2.2 yamt
1081 1.37.2.2 yamt /* set WME values for CCK modulation */
1082 1.37.2.2 yamt wmep = &iwi_wme_cck_params[ac];
1083 1.37.2.2 yamt wme[1].aifsn[ac] = wmep->wmep_aifsn;
1084 1.37.2.2 yamt wme[1].cwmin[ac] = IWI_EXP2(wmep->wmep_logcwmin);
1085 1.37.2.2 yamt wme[1].cwmax[ac] = IWI_EXP2(wmep->wmep_logcwmax);
1086 1.37.2.2 yamt wme[1].burst[ac] = IWI_USEC(wmep->wmep_txopLimit);
1087 1.37.2.2 yamt wme[1].acm[ac] = wmep->wmep_acm;
1088 1.37.2.2 yamt
1089 1.37.2.2 yamt /* set WME values for OFDM modulation */
1090 1.37.2.2 yamt wmep = &iwi_wme_ofdm_params[ac];
1091 1.37.2.2 yamt wme[2].aifsn[ac] = wmep->wmep_aifsn;
1092 1.37.2.2 yamt wme[2].cwmin[ac] = IWI_EXP2(wmep->wmep_logcwmin);
1093 1.37.2.2 yamt wme[2].cwmax[ac] = IWI_EXP2(wmep->wmep_logcwmax);
1094 1.37.2.2 yamt wme[2].burst[ac] = IWI_USEC(wmep->wmep_txopLimit);
1095 1.37.2.2 yamt wme[2].acm[ac] = wmep->wmep_acm;
1096 1.37.2.2 yamt }
1097 1.37.2.2 yamt
1098 1.37.2.2 yamt DPRINTF(("Setting WME parameters\n"));
1099 1.37.2.2 yamt return iwi_cmd(sc, IWI_CMD_SET_WME_PARAMS, wme, sizeof wme, 1);
1100 1.37.2.2 yamt #undef IWI_USEC
1101 1.37.2.2 yamt #undef IWI_EXP2
1102 1.37.2.2 yamt }
1103 1.37.2.2 yamt
1104 1.37.2.2 yamt /*
1105 1.37.2.2 yamt * Read 16 bits at address 'addr' from the serial EEPROM.
1106 1.37.2.2 yamt */
1107 1.37.2.2 yamt static uint16_t
1108 1.37.2.2 yamt iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr)
1109 1.37.2.2 yamt {
1110 1.37.2.2 yamt uint32_t tmp;
1111 1.37.2.2 yamt uint16_t val;
1112 1.37.2.2 yamt int n;
1113 1.37.2.2 yamt
1114 1.37.2.2 yamt /* Clock C once before the first command */
1115 1.37.2.2 yamt IWI_EEPROM_CTL(sc, 0);
1116 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
1117 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_C);
1118 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
1119 1.37.2.2 yamt
1120 1.37.2.2 yamt /* Write start bit (1) */
1121 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D);
1122 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D | IWI_EEPROM_C);
1123 1.37.2.2 yamt
1124 1.37.2.2 yamt /* Write READ opcode (10) */
1125 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D);
1126 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_D | IWI_EEPROM_C);
1127 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
1128 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_C);
1129 1.37.2.2 yamt
1130 1.37.2.2 yamt /* Write address A7-A0 */
1131 1.37.2.2 yamt for (n = 7; n >= 0; n--) {
1132 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S |
1133 1.37.2.2 yamt (((addr >> n) & 1) << IWI_EEPROM_SHIFT_D));
1134 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S |
1135 1.37.2.2 yamt (((addr >> n) & 1) << IWI_EEPROM_SHIFT_D) | IWI_EEPROM_C);
1136 1.37.2.2 yamt }
1137 1.37.2.2 yamt
1138 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
1139 1.37.2.2 yamt
1140 1.37.2.2 yamt /* Read data Q15-Q0 */
1141 1.37.2.2 yamt val = 0;
1142 1.37.2.2 yamt for (n = 15; n >= 0; n--) {
1143 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S | IWI_EEPROM_C);
1144 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
1145 1.37.2.2 yamt tmp = MEM_READ_4(sc, IWI_MEM_EEPROM_CTL);
1146 1.37.2.2 yamt val |= ((tmp & IWI_EEPROM_Q) >> IWI_EEPROM_SHIFT_Q) << n;
1147 1.37.2.2 yamt }
1148 1.37.2.2 yamt
1149 1.37.2.2 yamt IWI_EEPROM_CTL(sc, 0);
1150 1.37.2.2 yamt
1151 1.37.2.2 yamt /* Clear Chip Select and clock C */
1152 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_S);
1153 1.37.2.2 yamt IWI_EEPROM_CTL(sc, 0);
1154 1.37.2.2 yamt IWI_EEPROM_CTL(sc, IWI_EEPROM_C);
1155 1.37.2.2 yamt
1156 1.37.2.2 yamt return val;
1157 1.37.2.2 yamt }
1158 1.37.2.2 yamt
1159 1.37.2.2 yamt /*
1160 1.37.2.2 yamt * XXX: Hack to set the current channel to the value advertised in beacons or
1161 1.37.2.2 yamt * probe responses. Only used during AP detection.
1162 1.37.2.2 yamt */
1163 1.37.2.2 yamt static void
1164 1.37.2.2 yamt iwi_fix_channel(struct ieee80211com *ic, struct mbuf *m)
1165 1.37.2.2 yamt {
1166 1.37.2.2 yamt struct ieee80211_frame *wh;
1167 1.37.2.2 yamt uint8_t subtype;
1168 1.37.2.2 yamt uint8_t *frm, *efrm;
1169 1.37.2.2 yamt
1170 1.37.2.2 yamt wh = mtod(m, struct ieee80211_frame *);
1171 1.37.2.2 yamt
1172 1.37.2.2 yamt if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
1173 1.37.2.2 yamt return;
1174 1.37.2.2 yamt
1175 1.37.2.2 yamt subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1176 1.37.2.2 yamt
1177 1.37.2.2 yamt if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
1178 1.37.2.2 yamt subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
1179 1.37.2.2 yamt return;
1180 1.37.2.2 yamt
1181 1.37.2.2 yamt frm = (uint8_t *)(wh + 1);
1182 1.37.2.2 yamt efrm = mtod(m, uint8_t *) + m->m_len;
1183 1.37.2.2 yamt
1184 1.37.2.2 yamt frm += 12; /* skip tstamp, bintval and capinfo fields */
1185 1.37.2.2 yamt while (frm < efrm) {
1186 1.37.2.2 yamt if (*frm == IEEE80211_ELEMID_DSPARMS)
1187 1.37.2.2 yamt #if IEEE80211_CHAN_MAX < 255
1188 1.37.2.2 yamt if (frm[2] <= IEEE80211_CHAN_MAX)
1189 1.37.2.2 yamt #endif
1190 1.37.2.2 yamt ic->ic_curchan = &ic->ic_channels[frm[2]];
1191 1.37.2.2 yamt
1192 1.37.2.2 yamt frm += frm[1] + 2;
1193 1.37.2.2 yamt }
1194 1.37.2.2 yamt }
1195 1.37.2.2 yamt
1196 1.37.2.2 yamt static struct mbuf *
1197 1.37.2.2 yamt iwi_alloc_rx_buf(struct iwi_softc *sc)
1198 1.37.2.2 yamt {
1199 1.37.2.2 yamt struct mbuf *m;
1200 1.37.2.2 yamt
1201 1.37.2.2 yamt MGETHDR(m, M_DONTWAIT, MT_DATA);
1202 1.37.2.2 yamt if (m == NULL) {
1203 1.37.2.2 yamt aprint_error("%s: could not allocate rx mbuf\n",
1204 1.37.2.2 yamt sc->sc_dev.dv_xname);
1205 1.37.2.2 yamt return NULL;
1206 1.37.2.2 yamt }
1207 1.37.2.2 yamt
1208 1.37.2.2 yamt MCLGET(m, M_DONTWAIT);
1209 1.37.2.2 yamt if (!(m->m_flags & M_EXT)) {
1210 1.37.2.2 yamt aprint_error("%s: could not allocate rx mbuf cluster\n",
1211 1.37.2.2 yamt sc->sc_dev.dv_xname);
1212 1.37.2.2 yamt m_freem(m);
1213 1.37.2.2 yamt return NULL;
1214 1.37.2.2 yamt }
1215 1.37.2.2 yamt
1216 1.37.2.2 yamt m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
1217 1.37.2.2 yamt return m;
1218 1.37.2.2 yamt }
1219 1.37.2.2 yamt
1220 1.37.2.2 yamt static void
1221 1.37.2.2 yamt iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
1222 1.37.2.2 yamt struct iwi_frame *frame)
1223 1.37.2.2 yamt {
1224 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
1225 1.37.2.2 yamt struct ifnet *ifp = ic->ic_ifp;
1226 1.37.2.2 yamt struct mbuf *m, *m_new;
1227 1.37.2.2 yamt struct ieee80211_frame *wh;
1228 1.37.2.2 yamt struct ieee80211_node *ni;
1229 1.37.2.2 yamt int error;
1230 1.37.2.2 yamt
1231 1.37.2.2 yamt DPRINTFN(5, ("received frame len=%u chan=%u rssi=%u\n",
1232 1.37.2.2 yamt le16toh(frame->len), frame->chan, frame->rssi_dbm));
1233 1.37.2.2 yamt
1234 1.37.2.2 yamt if (le16toh(frame->len) < sizeof (struct ieee80211_frame) ||
1235 1.37.2.2 yamt le16toh(frame->len) > MCLBYTES) {
1236 1.37.2.2 yamt DPRINTF(("%s: bad frame length\n", sc->sc_dev.dv_xname));
1237 1.37.2.2 yamt ifp->if_ierrors++;
1238 1.37.2.2 yamt return;
1239 1.37.2.2 yamt }
1240 1.37.2.2 yamt
1241 1.37.2.2 yamt /*
1242 1.37.2.2 yamt * Try to allocate a new mbuf for this ring element and
1243 1.37.2.2 yamt * load it before processing the current mbuf. If the ring
1244 1.37.2.2 yamt * element cannot be reloaded, drop the received packet
1245 1.37.2.2 yamt * and reuse the old mbuf. In the unlikely case that
1246 1.37.2.2 yamt * the old mbuf can't be reloaded either, explicitly panic.
1247 1.37.2.2 yamt *
1248 1.37.2.2 yamt * XXX Reorganize buffer by moving elements from the logical
1249 1.37.2.2 yamt * end of the ring to the front instead of dropping.
1250 1.37.2.2 yamt */
1251 1.37.2.2 yamt if ((m_new = iwi_alloc_rx_buf(sc)) == NULL) {
1252 1.37.2.2 yamt ifp->if_ierrors++;
1253 1.37.2.2 yamt return;
1254 1.37.2.2 yamt }
1255 1.37.2.2 yamt
1256 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, data->map);
1257 1.37.2.2 yamt
1258 1.37.2.2 yamt error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m_new,
1259 1.37.2.2 yamt BUS_DMA_READ | BUS_DMA_NOWAIT);
1260 1.37.2.2 yamt if (error != 0) {
1261 1.37.2.2 yamt aprint_error("%s: could not load rx buf DMA map\n",
1262 1.37.2.2 yamt sc->sc_dev.dv_xname);
1263 1.37.2.2 yamt m_freem(m_new);
1264 1.37.2.2 yamt ifp->if_ierrors++;
1265 1.37.2.2 yamt error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map,
1266 1.37.2.2 yamt data->m, BUS_DMA_READ | BUS_DMA_NOWAIT);
1267 1.37.2.2 yamt if (error)
1268 1.37.2.2 yamt panic("%s: unable to remap rx buf",
1269 1.37.2.2 yamt sc->sc_dev.dv_xname);
1270 1.37.2.2 yamt return;
1271 1.37.2.2 yamt }
1272 1.37.2.2 yamt
1273 1.37.2.2 yamt /*
1274 1.37.2.2 yamt * New mbuf successfully loaded, update RX ring and continue
1275 1.37.2.2 yamt * processing.
1276 1.37.2.2 yamt */
1277 1.37.2.2 yamt m = data->m;
1278 1.37.2.2 yamt data->m = m_new;
1279 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RX_BASE + i * 4, data->map->dm_segs[0].ds_addr);
1280 1.37.2.2 yamt
1281 1.37.2.2 yamt /* Finalize mbuf */
1282 1.37.2.2 yamt m->m_pkthdr.rcvif = ifp;
1283 1.37.2.2 yamt m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) +
1284 1.37.2.2 yamt sizeof (struct iwi_frame) + le16toh(frame->len);
1285 1.37.2.2 yamt
1286 1.37.2.2 yamt m_adj(m, sizeof (struct iwi_hdr) + sizeof (struct iwi_frame));
1287 1.37.2.2 yamt
1288 1.37.2.2 yamt if (ic->ic_state == IEEE80211_S_SCAN)
1289 1.37.2.2 yamt iwi_fix_channel(ic, m);
1290 1.37.2.2 yamt
1291 1.37.2.2 yamt #if NBPFILTER > 0
1292 1.37.2.2 yamt if (sc->sc_drvbpf != NULL) {
1293 1.37.2.2 yamt struct iwi_rx_radiotap_header *tap = &sc->sc_rxtap;
1294 1.37.2.2 yamt
1295 1.37.2.2 yamt tap->wr_flags = 0;
1296 1.37.2.2 yamt tap->wr_rate = frame->rate;
1297 1.37.2.2 yamt tap->wr_chan_freq =
1298 1.37.2.2 yamt htole16(ic->ic_channels[frame->chan].ic_freq);
1299 1.37.2.2 yamt tap->wr_chan_flags =
1300 1.37.2.2 yamt htole16(ic->ic_channels[frame->chan].ic_flags);
1301 1.37.2.2 yamt tap->wr_antsignal = frame->signal;
1302 1.37.2.2 yamt tap->wr_antenna = frame->antenna;
1303 1.37.2.2 yamt
1304 1.37.2.2 yamt bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
1305 1.37.2.2 yamt }
1306 1.37.2.2 yamt #endif
1307 1.37.2.2 yamt
1308 1.37.2.2 yamt wh = mtod(m, struct ieee80211_frame *);
1309 1.37.2.2 yamt ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
1310 1.37.2.2 yamt
1311 1.37.2.2 yamt /* Send the frame to the upper layer */
1312 1.37.2.2 yamt ieee80211_input(ic, m, ni, frame->rssi_dbm, 0);
1313 1.37.2.2 yamt
1314 1.37.2.2 yamt /* node is no longer needed */
1315 1.37.2.2 yamt ieee80211_free_node(ni);
1316 1.37.2.2 yamt }
1317 1.37.2.2 yamt
1318 1.37.2.2 yamt static void
1319 1.37.2.2 yamt iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
1320 1.37.2.2 yamt {
1321 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
1322 1.37.2.2 yamt struct iwi_notif_scan_channel *chan;
1323 1.37.2.2 yamt struct iwi_notif_scan_complete *scan;
1324 1.37.2.2 yamt struct iwi_notif_authentication *auth;
1325 1.37.2.2 yamt struct iwi_notif_association *assoc;
1326 1.37.2.2 yamt
1327 1.37.2.2 yamt switch (notif->type) {
1328 1.37.2.2 yamt case IWI_NOTIF_TYPE_SCAN_CHANNEL:
1329 1.37.2.2 yamt chan = (struct iwi_notif_scan_channel *)(notif + 1);
1330 1.37.2.2 yamt
1331 1.37.2.2 yamt DPRINTFN(2, ("Finished scanning channel (%u)\n", chan->nchan));
1332 1.37.2.2 yamt break;
1333 1.37.2.2 yamt
1334 1.37.2.2 yamt case IWI_NOTIF_TYPE_SCAN_COMPLETE:
1335 1.37.2.2 yamt scan = (struct iwi_notif_scan_complete *)(notif + 1);
1336 1.37.2.2 yamt
1337 1.37.2.2 yamt DPRINTFN(2, ("Scan completed (%u, %u)\n", scan->nchan,
1338 1.37.2.2 yamt scan->status));
1339 1.37.2.2 yamt
1340 1.37.2.2 yamt /* monitor mode uses scan to set the channel ... */
1341 1.37.2.2 yamt if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1342 1.37.2.2 yamt sc->flags &= ~IWI_FLAG_SCANNING;
1343 1.37.2.2 yamt ieee80211_end_scan(ic);
1344 1.37.2.2 yamt } else
1345 1.37.2.2 yamt iwi_set_chan(sc, ic->ic_ibss_chan);
1346 1.37.2.2 yamt break;
1347 1.37.2.2 yamt
1348 1.37.2.2 yamt case IWI_NOTIF_TYPE_AUTHENTICATION:
1349 1.37.2.2 yamt auth = (struct iwi_notif_authentication *)(notif + 1);
1350 1.37.2.2 yamt
1351 1.37.2.2 yamt DPRINTFN(2, ("Authentication (%u)\n", auth->state));
1352 1.37.2.2 yamt
1353 1.37.2.2 yamt switch (auth->state) {
1354 1.37.2.2 yamt case IWI_AUTHENTICATED:
1355 1.37.2.2 yamt ieee80211_node_authorize(ic->ic_bss);
1356 1.37.2.2 yamt ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1);
1357 1.37.2.2 yamt break;
1358 1.37.2.2 yamt
1359 1.37.2.2 yamt case IWI_DEAUTHENTICATED:
1360 1.37.2.2 yamt break;
1361 1.37.2.2 yamt
1362 1.37.2.2 yamt default:
1363 1.37.2.2 yamt aprint_error("%s: unknown authentication state %u\n",
1364 1.37.2.2 yamt sc->sc_dev.dv_xname, auth->state);
1365 1.37.2.2 yamt }
1366 1.37.2.2 yamt break;
1367 1.37.2.2 yamt
1368 1.37.2.2 yamt case IWI_NOTIF_TYPE_ASSOCIATION:
1369 1.37.2.2 yamt assoc = (struct iwi_notif_association *)(notif + 1);
1370 1.37.2.2 yamt
1371 1.37.2.2 yamt DPRINTFN(2, ("Association (%u, %u)\n", assoc->state,
1372 1.37.2.2 yamt assoc->status));
1373 1.37.2.2 yamt
1374 1.37.2.2 yamt switch (assoc->state) {
1375 1.37.2.2 yamt case IWI_AUTHENTICATED:
1376 1.37.2.2 yamt /* re-association, do nothing */
1377 1.37.2.2 yamt break;
1378 1.37.2.2 yamt
1379 1.37.2.2 yamt case IWI_ASSOCIATED:
1380 1.37.2.2 yamt ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1381 1.37.2.2 yamt break;
1382 1.37.2.2 yamt
1383 1.37.2.2 yamt case IWI_DEASSOCIATED:
1384 1.37.2.2 yamt ieee80211_begin_scan(ic, 1);
1385 1.37.2.2 yamt break;
1386 1.37.2.2 yamt
1387 1.37.2.2 yamt default:
1388 1.37.2.2 yamt aprint_error("%s: unknown association state %u\n",
1389 1.37.2.2 yamt sc->sc_dev.dv_xname, assoc->state);
1390 1.37.2.2 yamt }
1391 1.37.2.2 yamt break;
1392 1.37.2.2 yamt
1393 1.37.2.2 yamt case IWI_NOTIF_TYPE_CALIBRATION:
1394 1.37.2.2 yamt case IWI_NOTIF_TYPE_BEACON:
1395 1.37.2.2 yamt case IWI_NOTIF_TYPE_NOISE:
1396 1.37.2.2 yamt DPRINTFN(5, ("Notification (%u)\n", notif->type));
1397 1.37.2.2 yamt break;
1398 1.37.2.2 yamt
1399 1.37.2.2 yamt default:
1400 1.37.2.2 yamt aprint_error("%s: unknown notification type %u\n",
1401 1.37.2.2 yamt sc->sc_dev.dv_xname, notif->type);
1402 1.37.2.2 yamt }
1403 1.37.2.2 yamt }
1404 1.37.2.2 yamt
1405 1.37.2.2 yamt static void
1406 1.37.2.3 yamt iwi_cmd_intr(struct iwi_softc *sc)
1407 1.37.2.3 yamt {
1408 1.37.2.3 yamt uint32_t hw;
1409 1.37.2.3 yamt
1410 1.37.2.3 yamt hw = CSR_READ_4(sc, IWI_CSR_CMD_RIDX);
1411 1.37.2.3 yamt
1412 1.37.2.3 yamt for (; sc->cmdq.next != hw;) {
1413 1.37.2.3 yamt bus_dmamap_sync(sc->sc_dmat, sc->cmdq.desc_map,
1414 1.37.2.3 yamt sc->cmdq.next * IWI_CMD_DESC_SIZE, IWI_CMD_DESC_SIZE,
1415 1.37.2.3 yamt BUS_DMASYNC_POSTWRITE);
1416 1.37.2.3 yamt
1417 1.37.2.3 yamt wakeup(&sc->cmdq.desc[sc->cmdq.next]);
1418 1.37.2.3 yamt sc->cmdq.next = (sc->cmdq.next + 1) % sc->cmdq.count;
1419 1.37.2.3 yamt }
1420 1.37.2.3 yamt }
1421 1.37.2.3 yamt
1422 1.37.2.3 yamt static void
1423 1.37.2.2 yamt iwi_rx_intr(struct iwi_softc *sc)
1424 1.37.2.2 yamt {
1425 1.37.2.2 yamt struct iwi_rx_data *data;
1426 1.37.2.2 yamt struct iwi_hdr *hdr;
1427 1.37.2.2 yamt uint32_t hw;
1428 1.37.2.2 yamt
1429 1.37.2.2 yamt hw = CSR_READ_4(sc, IWI_CSR_RX_RIDX);
1430 1.37.2.2 yamt
1431 1.37.2.2 yamt for (; sc->rxq.cur != hw;) {
1432 1.37.2.2 yamt data = &sc->rxq.data[sc->rxq.cur];
1433 1.37.2.2 yamt
1434 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1435 1.37.2.2 yamt data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1436 1.37.2.2 yamt
1437 1.37.2.2 yamt hdr = mtod(data->m, struct iwi_hdr *);
1438 1.37.2.2 yamt
1439 1.37.2.2 yamt switch (hdr->type) {
1440 1.37.2.2 yamt case IWI_HDR_TYPE_FRAME:
1441 1.37.2.2 yamt iwi_frame_intr(sc, data, sc->rxq.cur,
1442 1.37.2.2 yamt (struct iwi_frame *)(hdr + 1));
1443 1.37.2.2 yamt break;
1444 1.37.2.2 yamt
1445 1.37.2.2 yamt case IWI_HDR_TYPE_NOTIF:
1446 1.37.2.2 yamt iwi_notification_intr(sc,
1447 1.37.2.2 yamt (struct iwi_notif *)(hdr + 1));
1448 1.37.2.2 yamt break;
1449 1.37.2.2 yamt
1450 1.37.2.2 yamt default:
1451 1.37.2.2 yamt aprint_error("%s: unknown hdr type %u\n",
1452 1.37.2.2 yamt sc->sc_dev.dv_xname, hdr->type);
1453 1.37.2.2 yamt }
1454 1.37.2.2 yamt
1455 1.37.2.3 yamt bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1456 1.37.2.3 yamt data->map->dm_mapsize, BUS_DMASYNC_PREREAD);
1457 1.37.2.3 yamt
1458 1.37.2.2 yamt DPRINTFN(15, ("rx done idx=%u\n", sc->rxq.cur));
1459 1.37.2.2 yamt
1460 1.37.2.2 yamt sc->rxq.cur = (sc->rxq.cur + 1) % sc->rxq.count;
1461 1.37.2.2 yamt }
1462 1.37.2.2 yamt
1463 1.37.2.2 yamt
1464 1.37.2.2 yamt /* Tell the firmware what we have processed */
1465 1.37.2.2 yamt hw = (hw == 0) ? sc->rxq.count - 1 : hw - 1;
1466 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RX_WIDX, hw);
1467 1.37.2.2 yamt }
1468 1.37.2.2 yamt
1469 1.37.2.2 yamt static void
1470 1.37.2.2 yamt iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
1471 1.37.2.2 yamt {
1472 1.37.2.2 yamt struct ifnet *ifp = &sc->sc_if;
1473 1.37.2.2 yamt struct iwi_tx_data *data;
1474 1.37.2.2 yamt uint32_t hw;
1475 1.37.2.2 yamt
1476 1.37.2.2 yamt hw = CSR_READ_4(sc, txq->csr_ridx);
1477 1.37.2.2 yamt
1478 1.37.2.2 yamt for (; txq->next != hw;) {
1479 1.37.2.2 yamt data = &txq->data[txq->next];
1480 1.37.2.2 yamt
1481 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, data->map, 0,
1482 1.37.2.2 yamt data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1483 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, data->map);
1484 1.37.2.2 yamt m_freem(data->m);
1485 1.37.2.2 yamt data->m = NULL;
1486 1.37.2.2 yamt ieee80211_free_node(data->ni);
1487 1.37.2.2 yamt data->ni = NULL;
1488 1.37.2.2 yamt
1489 1.37.2.2 yamt DPRINTFN(15, ("tx done idx=%u\n", txq->next));
1490 1.37.2.2 yamt
1491 1.37.2.2 yamt ifp->if_opackets++;
1492 1.37.2.2 yamt
1493 1.37.2.2 yamt txq->queued--;
1494 1.37.2.2 yamt txq->next = (txq->next + 1) % txq->count;
1495 1.37.2.2 yamt }
1496 1.37.2.2 yamt
1497 1.37.2.2 yamt sc->sc_tx_timer = 0;
1498 1.37.2.2 yamt ifp->if_flags &= ~IFF_OACTIVE;
1499 1.37.2.2 yamt
1500 1.37.2.2 yamt /* Call start() since some buffer descriptors have been released */
1501 1.37.2.2 yamt (*ifp->if_start)(ifp);
1502 1.37.2.2 yamt }
1503 1.37.2.2 yamt
1504 1.37.2.2 yamt static int
1505 1.37.2.2 yamt iwi_intr(void *arg)
1506 1.37.2.2 yamt {
1507 1.37.2.2 yamt struct iwi_softc *sc = arg;
1508 1.37.2.2 yamt uint32_t r;
1509 1.37.2.2 yamt
1510 1.37.2.2 yamt if ((r = CSR_READ_4(sc, IWI_CSR_INTR)) == 0 || r == 0xffffffff)
1511 1.37.2.2 yamt return 0;
1512 1.37.2.2 yamt
1513 1.37.2.2 yamt /* Acknowledge interrupts */
1514 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_INTR, r);
1515 1.37.2.2 yamt
1516 1.37.2.2 yamt if (r & (IWI_INTR_FATAL_ERROR | IWI_INTR_PARITY_ERROR)) {
1517 1.37.2.2 yamt aprint_error("%s: fatal error\n", sc->sc_dev.dv_xname);
1518 1.37.2.2 yamt if (r & IWI_INTR_FATAL_ERROR)
1519 1.37.2.2 yamt iwi_error_log(sc);
1520 1.37.2.2 yamt sc->sc_ic.ic_ifp->if_flags &= ~IFF_UP;
1521 1.37.2.2 yamt iwi_stop(&sc->sc_if, 1);
1522 1.37.2.3 yamt return (1);
1523 1.37.2.2 yamt }
1524 1.37.2.2 yamt
1525 1.37.2.2 yamt if (r & IWI_INTR_FW_INITED) {
1526 1.37.2.2 yamt if (!(r & (IWI_INTR_FATAL_ERROR | IWI_INTR_PARITY_ERROR)))
1527 1.37.2.2 yamt wakeup(sc);
1528 1.37.2.2 yamt }
1529 1.37.2.2 yamt
1530 1.37.2.2 yamt if (r & IWI_INTR_RADIO_OFF) {
1531 1.37.2.2 yamt DPRINTF(("radio transmitter off\n"));
1532 1.37.2.2 yamt sc->sc_ic.ic_ifp->if_flags &= ~IFF_UP;
1533 1.37.2.2 yamt iwi_stop(&sc->sc_if, 1);
1534 1.37.2.3 yamt return (1);
1535 1.37.2.2 yamt }
1536 1.37.2.2 yamt
1537 1.37.2.2 yamt if (r & IWI_INTR_CMD_DONE)
1538 1.37.2.3 yamt iwi_cmd_intr(sc);
1539 1.37.2.2 yamt
1540 1.37.2.2 yamt if (r & IWI_INTR_TX1_DONE)
1541 1.37.2.2 yamt iwi_tx_intr(sc, &sc->txq[0]);
1542 1.37.2.2 yamt
1543 1.37.2.2 yamt if (r & IWI_INTR_TX2_DONE)
1544 1.37.2.2 yamt iwi_tx_intr(sc, &sc->txq[1]);
1545 1.37.2.2 yamt
1546 1.37.2.2 yamt if (r & IWI_INTR_TX3_DONE)
1547 1.37.2.2 yamt iwi_tx_intr(sc, &sc->txq[2]);
1548 1.37.2.2 yamt
1549 1.37.2.2 yamt if (r & IWI_INTR_TX4_DONE)
1550 1.37.2.2 yamt iwi_tx_intr(sc, &sc->txq[3]);
1551 1.37.2.2 yamt
1552 1.37.2.2 yamt if (r & IWI_INTR_RX_DONE)
1553 1.37.2.2 yamt iwi_rx_intr(sc);
1554 1.37.2.2 yamt
1555 1.37.2.2 yamt return 1;
1556 1.37.2.2 yamt }
1557 1.37.2.2 yamt
1558 1.37.2.2 yamt static int
1559 1.37.2.2 yamt iwi_cmd(struct iwi_softc *sc, uint8_t type, void *data, uint8_t len,
1560 1.37.2.2 yamt int async)
1561 1.37.2.2 yamt {
1562 1.37.2.2 yamt struct iwi_cmd_desc *desc;
1563 1.37.2.2 yamt
1564 1.37.2.2 yamt desc = &sc->cmdq.desc[sc->cmdq.cur];
1565 1.37.2.2 yamt
1566 1.37.2.2 yamt desc->hdr.type = IWI_HDR_TYPE_COMMAND;
1567 1.37.2.2 yamt desc->hdr.flags = IWI_HDR_FLAG_IRQ;
1568 1.37.2.2 yamt desc->type = type;
1569 1.37.2.2 yamt desc->len = len;
1570 1.37.2.2 yamt memcpy(desc->data, data, len);
1571 1.37.2.2 yamt
1572 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, sc->cmdq.desc_map,
1573 1.37.2.2 yamt sc->cmdq.cur * IWI_CMD_DESC_SIZE,
1574 1.37.2.2 yamt IWI_CMD_DESC_SIZE, BUS_DMASYNC_PREWRITE);
1575 1.37.2.2 yamt
1576 1.37.2.2 yamt DPRINTFN(2, ("sending command idx=%u type=%u len=%u\n", sc->cmdq.cur,
1577 1.37.2.2 yamt type, len));
1578 1.37.2.2 yamt
1579 1.37.2.2 yamt sc->cmdq.cur = (sc->cmdq.cur + 1) % sc->cmdq.count;
1580 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.cur);
1581 1.37.2.2 yamt
1582 1.37.2.3 yamt return async ? 0 : tsleep(desc, 0, "iwicmd", hz);
1583 1.37.2.2 yamt }
1584 1.37.2.2 yamt
1585 1.37.2.2 yamt static void
1586 1.37.2.2 yamt iwi_write_ibssnode(struct iwi_softc *sc, const struct iwi_node *in)
1587 1.37.2.2 yamt {
1588 1.37.2.2 yamt struct iwi_ibssnode node;
1589 1.37.2.2 yamt
1590 1.37.2.2 yamt /* write node information into NIC memory */
1591 1.37.2.2 yamt memset(&node, 0, sizeof node);
1592 1.37.2.2 yamt IEEE80211_ADDR_COPY(node.bssid, in->in_node.ni_macaddr);
1593 1.37.2.2 yamt
1594 1.37.2.2 yamt CSR_WRITE_REGION_1(sc,
1595 1.37.2.2 yamt IWI_CSR_NODE_BASE + in->in_station * sizeof node,
1596 1.37.2.2 yamt (uint8_t *)&node, sizeof node);
1597 1.37.2.2 yamt }
1598 1.37.2.2 yamt
1599 1.37.2.2 yamt static int
1600 1.37.2.2 yamt iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
1601 1.37.2.2 yamt int ac)
1602 1.37.2.2 yamt {
1603 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
1604 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
1605 1.37.2.2 yamt struct iwi_node *in = (struct iwi_node *)ni;
1606 1.37.2.2 yamt struct ieee80211_frame *wh;
1607 1.37.2.2 yamt struct ieee80211_key *k;
1608 1.37.2.2 yamt const struct chanAccParams *cap;
1609 1.37.2.2 yamt struct iwi_tx_ring *txq = &sc->txq[ac];
1610 1.37.2.2 yamt struct iwi_tx_data *data;
1611 1.37.2.2 yamt struct iwi_tx_desc *desc;
1612 1.37.2.2 yamt struct mbuf *mnew;
1613 1.37.2.2 yamt int error, hdrlen, i, noack = 0;
1614 1.37.2.2 yamt
1615 1.37.2.2 yamt wh = mtod(m0, struct ieee80211_frame *);
1616 1.37.2.2 yamt
1617 1.37.2.2 yamt if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
1618 1.37.2.2 yamt hdrlen = sizeof (struct ieee80211_qosframe);
1619 1.37.2.2 yamt cap = &ic->ic_wme.wme_chanParams;
1620 1.37.2.2 yamt noack = cap->cap_wmeParams[ac].wmep_noackPolicy;
1621 1.37.2.2 yamt } else
1622 1.37.2.2 yamt hdrlen = sizeof (struct ieee80211_frame);
1623 1.37.2.2 yamt
1624 1.37.2.2 yamt /*
1625 1.37.2.2 yamt * This is only used in IBSS mode where the firmware expect an index
1626 1.37.2.2 yamt * in a h/w table instead of a destination address.
1627 1.37.2.2 yamt */
1628 1.37.2.2 yamt if (ic->ic_opmode == IEEE80211_M_IBSS && in->in_station == -1) {
1629 1.37.2.2 yamt in->in_station = iwi_alloc_unr(sc);
1630 1.37.2.2 yamt
1631 1.37.2.2 yamt if (in->in_station == -1) { /* h/w table is full */
1632 1.37.2.2 yamt m_freem(m0);
1633 1.37.2.2 yamt ieee80211_free_node(ni);
1634 1.37.2.2 yamt ifp->if_oerrors++;
1635 1.37.2.2 yamt return 0;
1636 1.37.2.2 yamt }
1637 1.37.2.2 yamt iwi_write_ibssnode(sc, in);
1638 1.37.2.2 yamt }
1639 1.37.2.2 yamt
1640 1.37.2.2 yamt if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1641 1.37.2.2 yamt k = ieee80211_crypto_encap(ic, ni, m0);
1642 1.37.2.2 yamt if (k == NULL) {
1643 1.37.2.2 yamt m_freem(m0);
1644 1.37.2.2 yamt return ENOBUFS;
1645 1.37.2.2 yamt }
1646 1.37.2.2 yamt
1647 1.37.2.2 yamt /* packet header may have moved, reset our local pointer */
1648 1.37.2.2 yamt wh = mtod(m0, struct ieee80211_frame *);
1649 1.37.2.2 yamt }
1650 1.37.2.2 yamt
1651 1.37.2.2 yamt #if NBPFILTER > 0
1652 1.37.2.2 yamt if (sc->sc_drvbpf != NULL) {
1653 1.37.2.2 yamt struct iwi_tx_radiotap_header *tap = &sc->sc_txtap;
1654 1.37.2.2 yamt
1655 1.37.2.2 yamt tap->wt_flags = 0;
1656 1.37.2.2 yamt tap->wt_chan_freq = htole16(ic->ic_ibss_chan->ic_freq);
1657 1.37.2.2 yamt tap->wt_chan_flags = htole16(ic->ic_ibss_chan->ic_flags);
1658 1.37.2.2 yamt
1659 1.37.2.2 yamt bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
1660 1.37.2.2 yamt }
1661 1.37.2.2 yamt #endif
1662 1.37.2.2 yamt
1663 1.37.2.2 yamt data = &txq->data[txq->cur];
1664 1.37.2.2 yamt desc = &txq->desc[txq->cur];
1665 1.37.2.2 yamt
1666 1.37.2.2 yamt /* save and trim IEEE802.11 header */
1667 1.37.2.2 yamt m_copydata(m0, 0, hdrlen, (caddr_t)&desc->wh);
1668 1.37.2.2 yamt m_adj(m0, hdrlen);
1669 1.37.2.2 yamt
1670 1.37.2.2 yamt error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
1671 1.37.2.2 yamt BUS_DMA_WRITE | BUS_DMA_NOWAIT);
1672 1.37.2.2 yamt if (error != 0 && error != EFBIG) {
1673 1.37.2.2 yamt aprint_error("%s: could not map mbuf (error %d)\n",
1674 1.37.2.2 yamt sc->sc_dev.dv_xname, error);
1675 1.37.2.2 yamt m_freem(m0);
1676 1.37.2.2 yamt return error;
1677 1.37.2.2 yamt }
1678 1.37.2.2 yamt if (error != 0) {
1679 1.37.2.2 yamt /* too many fragments, linearize */
1680 1.37.2.2 yamt
1681 1.37.2.2 yamt MGETHDR(mnew, M_DONTWAIT, MT_DATA);
1682 1.37.2.2 yamt if (mnew == NULL) {
1683 1.37.2.2 yamt m_freem(m0);
1684 1.37.2.2 yamt return ENOMEM;
1685 1.37.2.2 yamt }
1686 1.37.2.2 yamt
1687 1.37.2.2 yamt M_COPY_PKTHDR(mnew, m0);
1688 1.37.2.2 yamt
1689 1.37.2.2 yamt /* If the data won't fit in the header, get a cluster */
1690 1.37.2.2 yamt if (m0->m_pkthdr.len > MHLEN) {
1691 1.37.2.2 yamt MCLGET(mnew, M_DONTWAIT);
1692 1.37.2.2 yamt if (!(mnew->m_flags & M_EXT)) {
1693 1.37.2.2 yamt m_freem(m0);
1694 1.37.2.2 yamt m_freem(mnew);
1695 1.37.2.2 yamt return ENOMEM;
1696 1.37.2.2 yamt }
1697 1.37.2.2 yamt }
1698 1.37.2.2 yamt m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mnew, caddr_t));
1699 1.37.2.2 yamt m_freem(m0);
1700 1.37.2.2 yamt mnew->m_len = mnew->m_pkthdr.len;
1701 1.37.2.2 yamt m0 = mnew;
1702 1.37.2.2 yamt
1703 1.37.2.2 yamt error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
1704 1.37.2.2 yamt BUS_DMA_WRITE | BUS_DMA_NOWAIT);
1705 1.37.2.2 yamt if (error != 0) {
1706 1.37.2.2 yamt aprint_error("%s: could not map mbuf (error %d)\n",
1707 1.37.2.2 yamt sc->sc_dev.dv_xname, error);
1708 1.37.2.2 yamt m_freem(m0);
1709 1.37.2.2 yamt return error;
1710 1.37.2.2 yamt }
1711 1.37.2.2 yamt }
1712 1.37.2.2 yamt
1713 1.37.2.2 yamt data->m = m0;
1714 1.37.2.2 yamt data->ni = ni;
1715 1.37.2.2 yamt
1716 1.37.2.2 yamt desc->hdr.type = IWI_HDR_TYPE_DATA;
1717 1.37.2.2 yamt desc->hdr.flags = IWI_HDR_FLAG_IRQ;
1718 1.37.2.2 yamt desc->station =
1719 1.37.2.2 yamt (ic->ic_opmode == IEEE80211_M_IBSS) ? in->in_station : 0;
1720 1.37.2.2 yamt desc->cmd = IWI_DATA_CMD_TX;
1721 1.37.2.2 yamt desc->len = htole16(m0->m_pkthdr.len);
1722 1.37.2.2 yamt desc->flags = 0;
1723 1.37.2.2 yamt desc->xflags = 0;
1724 1.37.2.2 yamt
1725 1.37.2.2 yamt if (!noack && !IEEE80211_IS_MULTICAST(desc->wh.i_addr1))
1726 1.37.2.2 yamt desc->flags |= IWI_DATA_FLAG_NEED_ACK;
1727 1.37.2.2 yamt
1728 1.37.2.2 yamt #if 0
1729 1.37.2.2 yamt if (ic->ic_flags & IEEE80211_F_PRIVACY) {
1730 1.37.2.2 yamt desc->wh.i_fc[1] |= IEEE80211_FC1_WEP;
1731 1.37.2.2 yamt desc->wep_txkey = ic->ic_crypto.cs_def_txkey;
1732 1.37.2.2 yamt } else
1733 1.37.2.2 yamt #endif
1734 1.37.2.2 yamt desc->flags |= IWI_DATA_FLAG_NO_WEP;
1735 1.37.2.2 yamt
1736 1.37.2.2 yamt if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
1737 1.37.2.2 yamt desc->flags |= IWI_DATA_FLAG_SHPREAMBLE;
1738 1.37.2.2 yamt
1739 1.37.2.2 yamt if (desc->wh.i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS)
1740 1.37.2.2 yamt desc->xflags |= IWI_DATA_XFLAG_QOS;
1741 1.37.2.2 yamt
1742 1.37.2.2 yamt desc->nseg = htole32(data->map->dm_nsegs);
1743 1.37.2.2 yamt for (i = 0; i < data->map->dm_nsegs; i++) {
1744 1.37.2.2 yamt desc->seg_addr[i] = htole32(data->map->dm_segs[i].ds_addr);
1745 1.37.2.2 yamt desc->seg_len[i] = htole16(data->map->dm_segs[i].ds_len);
1746 1.37.2.2 yamt }
1747 1.37.2.2 yamt
1748 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, txq->desc_map,
1749 1.37.2.2 yamt txq->cur * IWI_TX_DESC_SIZE,
1750 1.37.2.2 yamt IWI_TX_DESC_SIZE, BUS_DMASYNC_PREWRITE);
1751 1.37.2.2 yamt
1752 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
1753 1.37.2.2 yamt BUS_DMASYNC_PREWRITE);
1754 1.37.2.2 yamt
1755 1.37.2.2 yamt DPRINTFN(5, ("sending data frame txq=%u idx=%u len=%u nseg=%u\n",
1756 1.37.2.2 yamt ac, txq->cur, le16toh(desc->len), le32toh(desc->nseg)));
1757 1.37.2.2 yamt
1758 1.37.2.2 yamt /* Inform firmware about this new packet */
1759 1.37.2.2 yamt txq->queued++;
1760 1.37.2.2 yamt txq->cur = (txq->cur + 1) % txq->count;
1761 1.37.2.2 yamt CSR_WRITE_4(sc, txq->csr_widx, txq->cur);
1762 1.37.2.2 yamt
1763 1.37.2.2 yamt return 0;
1764 1.37.2.2 yamt }
1765 1.37.2.2 yamt
1766 1.37.2.2 yamt static void
1767 1.37.2.2 yamt iwi_start(struct ifnet *ifp)
1768 1.37.2.2 yamt {
1769 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
1770 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
1771 1.37.2.2 yamt struct mbuf *m0;
1772 1.37.2.2 yamt struct ether_header *eh;
1773 1.37.2.2 yamt struct ieee80211_node *ni;
1774 1.37.2.2 yamt int ac;
1775 1.37.2.2 yamt
1776 1.37.2.2 yamt if (ic->ic_state != IEEE80211_S_RUN)
1777 1.37.2.2 yamt return;
1778 1.37.2.2 yamt
1779 1.37.2.2 yamt for (;;) {
1780 1.37.2.2 yamt IF_DEQUEUE(&ifp->if_snd, m0);
1781 1.37.2.2 yamt if (m0 == NULL)
1782 1.37.2.2 yamt break;
1783 1.37.2.2 yamt
1784 1.37.2.2 yamt if (m0->m_len < sizeof (struct ether_header) &&
1785 1.37.2.2 yamt (m0 = m_pullup(m0, sizeof (struct ether_header))) == NULL) {
1786 1.37.2.2 yamt ifp->if_oerrors++;
1787 1.37.2.2 yamt continue;
1788 1.37.2.2 yamt }
1789 1.37.2.2 yamt
1790 1.37.2.2 yamt eh = mtod(m0, struct ether_header *);
1791 1.37.2.2 yamt ni = ieee80211_find_txnode(ic, eh->ether_dhost);
1792 1.37.2.2 yamt if (ni == NULL) {
1793 1.37.2.2 yamt m_freem(m0);
1794 1.37.2.2 yamt ifp->if_oerrors++;
1795 1.37.2.2 yamt continue;
1796 1.37.2.2 yamt }
1797 1.37.2.2 yamt
1798 1.37.2.2 yamt /* classify mbuf so we can find which tx ring to use */
1799 1.37.2.2 yamt if (ieee80211_classify(ic, m0, ni) != 0) {
1800 1.37.2.2 yamt m_freem(m0);
1801 1.37.2.2 yamt ieee80211_free_node(ni);
1802 1.37.2.2 yamt ifp->if_oerrors++;
1803 1.37.2.2 yamt continue;
1804 1.37.2.2 yamt }
1805 1.37.2.2 yamt
1806 1.37.2.2 yamt /* no QoS encapsulation for EAPOL frames */
1807 1.37.2.2 yamt ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
1808 1.37.2.2 yamt M_WME_GETAC(m0) : WME_AC_BE;
1809 1.37.2.2 yamt
1810 1.37.2.2 yamt if (sc->txq[ac].queued > sc->txq[ac].count - 8) {
1811 1.37.2.2 yamt /* there is no place left in this ring */
1812 1.37.2.2 yamt IF_PREPEND(&ifp->if_snd, m0);
1813 1.37.2.2 yamt ifp->if_flags |= IFF_OACTIVE;
1814 1.37.2.2 yamt break;
1815 1.37.2.2 yamt }
1816 1.37.2.3 yamt
1817 1.37.2.3 yamt #if NBPFILTER > 0
1818 1.37.2.3 yamt if (ifp->if_bpf != NULL)
1819 1.37.2.3 yamt bpf_mtap(ifp->if_bpf, m0);
1820 1.37.2.2 yamt #endif
1821 1.37.2.3 yamt
1822 1.37.2.2 yamt m0 = ieee80211_encap(ic, m0, ni);
1823 1.37.2.2 yamt if (m0 == NULL) {
1824 1.37.2.2 yamt ieee80211_free_node(ni);
1825 1.37.2.2 yamt ifp->if_oerrors++;
1826 1.37.2.2 yamt continue;
1827 1.37.2.2 yamt }
1828 1.37.2.2 yamt
1829 1.37.2.2 yamt #if NBPFILTER > 0
1830 1.37.2.2 yamt if (ic->ic_rawbpf != NULL)
1831 1.37.2.2 yamt bpf_mtap(ic->ic_rawbpf, m0);
1832 1.37.2.2 yamt #endif
1833 1.37.2.2 yamt
1834 1.37.2.2 yamt if (iwi_tx_start(ifp, m0, ni, ac) != 0) {
1835 1.37.2.2 yamt ieee80211_free_node(ni);
1836 1.37.2.2 yamt ifp->if_oerrors++;
1837 1.37.2.2 yamt break;
1838 1.37.2.2 yamt }
1839 1.37.2.2 yamt
1840 1.37.2.2 yamt /* start watchdog timer */
1841 1.37.2.2 yamt sc->sc_tx_timer = 5;
1842 1.37.2.2 yamt ifp->if_timer = 1;
1843 1.37.2.2 yamt }
1844 1.37.2.2 yamt }
1845 1.37.2.2 yamt
1846 1.37.2.2 yamt static void
1847 1.37.2.2 yamt iwi_watchdog(struct ifnet *ifp)
1848 1.37.2.2 yamt {
1849 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
1850 1.37.2.2 yamt
1851 1.37.2.2 yamt ifp->if_timer = 0;
1852 1.37.2.2 yamt
1853 1.37.2.2 yamt if (sc->sc_tx_timer > 0) {
1854 1.37.2.2 yamt if (--sc->sc_tx_timer == 0) {
1855 1.37.2.2 yamt aprint_error("%s: device timeout\n",
1856 1.37.2.2 yamt sc->sc_dev.dv_xname);
1857 1.37.2.2 yamt ifp->if_oerrors++;
1858 1.37.2.2 yamt ifp->if_flags &= ~IFF_UP;
1859 1.37.2.2 yamt iwi_stop(ifp, 1);
1860 1.37.2.2 yamt return;
1861 1.37.2.2 yamt }
1862 1.37.2.2 yamt ifp->if_timer = 1;
1863 1.37.2.2 yamt }
1864 1.37.2.2 yamt
1865 1.37.2.2 yamt ieee80211_watchdog(&sc->sc_ic);
1866 1.37.2.2 yamt }
1867 1.37.2.2 yamt
1868 1.37.2.2 yamt static int
1869 1.37.2.2 yamt iwi_get_table0(struct iwi_softc *sc, uint32_t *tbl)
1870 1.37.2.2 yamt {
1871 1.37.2.2 yamt uint32_t size, buf[128];
1872 1.37.2.2 yamt
1873 1.37.2.2 yamt if (!(sc->flags & IWI_FLAG_FW_INITED)) {
1874 1.37.2.2 yamt memset(buf, 0, sizeof buf);
1875 1.37.2.2 yamt return copyout(buf, tbl, sizeof buf);
1876 1.37.2.2 yamt }
1877 1.37.2.2 yamt
1878 1.37.2.2 yamt size = min(CSR_READ_4(sc, IWI_CSR_TABLE0_SIZE), 128 - 1);
1879 1.37.2.2 yamt CSR_READ_REGION_4(sc, IWI_CSR_TABLE0_BASE, &buf[1], size);
1880 1.37.2.2 yamt
1881 1.37.2.2 yamt return copyout(buf, tbl, sizeof buf);
1882 1.37.2.2 yamt }
1883 1.37.2.2 yamt
1884 1.37.2.2 yamt static int
1885 1.37.2.2 yamt iwi_get_radio(struct iwi_softc *sc, int *ret)
1886 1.37.2.2 yamt {
1887 1.37.2.2 yamt int val;
1888 1.37.2.2 yamt
1889 1.37.2.2 yamt val = (CSR_READ_4(sc, IWI_CSR_IO) & IWI_IO_RADIO_ENABLED) ? 1 : 0;
1890 1.37.2.2 yamt return copyout(&val, ret, sizeof val);
1891 1.37.2.2 yamt }
1892 1.37.2.2 yamt
1893 1.37.2.2 yamt static int
1894 1.37.2.2 yamt iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1895 1.37.2.2 yamt {
1896 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
1897 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
1898 1.37.2.2 yamt struct ifreq *ifr;
1899 1.37.2.2 yamt int s, error = 0;
1900 1.37.2.2 yamt
1901 1.37.2.2 yamt s = splnet();
1902 1.37.2.2 yamt
1903 1.37.2.2 yamt switch (cmd) {
1904 1.37.2.2 yamt case SIOCSIFFLAGS:
1905 1.37.2.2 yamt if (ifp->if_flags & IFF_UP) {
1906 1.37.2.2 yamt if (!(ifp->if_flags & IFF_RUNNING))
1907 1.37.2.2 yamt iwi_init(ifp);
1908 1.37.2.2 yamt } else {
1909 1.37.2.2 yamt if (ifp->if_flags & IFF_RUNNING)
1910 1.37.2.2 yamt iwi_stop(ifp, 1);
1911 1.37.2.2 yamt }
1912 1.37.2.2 yamt break;
1913 1.37.2.2 yamt
1914 1.37.2.2 yamt case SIOCGTABLE0:
1915 1.37.2.2 yamt ifr = (struct ifreq *)data;
1916 1.37.2.2 yamt error = iwi_get_table0(sc, (uint32_t *)ifr->ifr_data);
1917 1.37.2.2 yamt break;
1918 1.37.2.2 yamt
1919 1.37.2.2 yamt case SIOCGRADIO:
1920 1.37.2.2 yamt ifr = (struct ifreq *)data;
1921 1.37.2.2 yamt error = iwi_get_radio(sc, (int *)ifr->ifr_data);
1922 1.37.2.2 yamt break;
1923 1.37.2.2 yamt
1924 1.37.2.2 yamt case SIOCSLOADFW:
1925 1.37.2.2 yamt /* only super-user can do that! */
1926 1.37.2.2 yamt if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
1927 1.37.2.2 yamt break;
1928 1.37.2.2 yamt
1929 1.37.2.2 yamt ifr = (struct ifreq *)data;
1930 1.37.2.2 yamt error = iwi_cache_firmware(sc, ifr->ifr_data);
1931 1.37.2.2 yamt break;
1932 1.37.2.2 yamt
1933 1.37.2.2 yamt case SIOCSKILLFW:
1934 1.37.2.2 yamt /* only super-user can do that! */
1935 1.37.2.2 yamt if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
1936 1.37.2.2 yamt break;
1937 1.37.2.2 yamt
1938 1.37.2.2 yamt ifp->if_flags &= ~IFF_UP;
1939 1.37.2.2 yamt iwi_stop(ifp, 1);
1940 1.37.2.2 yamt iwi_free_firmware(sc);
1941 1.37.2.2 yamt break;
1942 1.37.2.2 yamt
1943 1.37.2.2 yamt default:
1944 1.37.2.2 yamt error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
1945 1.37.2.2 yamt }
1946 1.37.2.2 yamt
1947 1.37.2.3 yamt if (error == ENETRESET) {
1948 1.37.2.2 yamt if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1949 1.37.2.2 yamt (IFF_UP | IFF_RUNNING) &&
1950 1.37.2.2 yamt (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
1951 1.37.2.2 yamt iwi_init(ifp);
1952 1.37.2.2 yamt error = 0;
1953 1.37.2.2 yamt }
1954 1.37.2.2 yamt
1955 1.37.2.2 yamt splx(s);
1956 1.37.2.2 yamt return error;
1957 1.37.2.2 yamt }
1958 1.37.2.2 yamt
1959 1.37.2.2 yamt static void
1960 1.37.2.2 yamt iwi_stop_master(struct iwi_softc *sc)
1961 1.37.2.2 yamt {
1962 1.37.2.2 yamt int ntries;
1963 1.37.2.2 yamt
1964 1.37.2.2 yamt /* Disable interrupts */
1965 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
1966 1.37.2.2 yamt
1967 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, IWI_RST_STOP_MASTER);
1968 1.37.2.2 yamt for (ntries = 0; ntries < 5; ntries++) {
1969 1.37.2.2 yamt if (CSR_READ_4(sc, IWI_CSR_RST) & IWI_RST_MASTER_DISABLED)
1970 1.37.2.2 yamt break;
1971 1.37.2.2 yamt DELAY(10);
1972 1.37.2.2 yamt }
1973 1.37.2.2 yamt if (ntries == 5)
1974 1.37.2.2 yamt aprint_error("%s: timeout waiting for master\n",
1975 1.37.2.2 yamt sc->sc_dev.dv_xname);
1976 1.37.2.2 yamt
1977 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
1978 1.37.2.2 yamt IWI_RST_PRINCETON_RESET);
1979 1.37.2.2 yamt
1980 1.37.2.2 yamt sc->flags &= ~IWI_FLAG_FW_INITED;
1981 1.37.2.2 yamt }
1982 1.37.2.2 yamt
1983 1.37.2.2 yamt static int
1984 1.37.2.2 yamt iwi_reset(struct iwi_softc *sc)
1985 1.37.2.2 yamt {
1986 1.37.2.2 yamt int i, ntries;
1987 1.37.2.2 yamt
1988 1.37.2.2 yamt iwi_stop_master(sc);
1989 1.37.2.2 yamt
1990 1.37.2.2 yamt /* Move adapter to D0 state */
1991 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CTL, CSR_READ_4(sc, IWI_CSR_CTL) |
1992 1.37.2.2 yamt IWI_CTL_INIT);
1993 1.37.2.2 yamt
1994 1.37.2.2 yamt /* Initialize Phase-Locked Level (PLL) */
1995 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_READ_INT, IWI_READ_INT_INIT_HOST);
1996 1.37.2.2 yamt
1997 1.37.2.2 yamt /* Wait for clock stabilization */
1998 1.37.2.2 yamt for (ntries = 0; ntries < 1000; ntries++) {
1999 1.37.2.2 yamt if (CSR_READ_4(sc, IWI_CSR_CTL) & IWI_CTL_CLOCK_READY)
2000 1.37.2.2 yamt break;
2001 1.37.2.2 yamt DELAY(200);
2002 1.37.2.2 yamt }
2003 1.37.2.2 yamt if (ntries == 1000) {
2004 1.37.2.2 yamt aprint_error("%s: timeout waiting for clock stabilization\n",
2005 1.37.2.2 yamt sc->sc_dev.dv_xname);
2006 1.37.2.2 yamt return EIO;
2007 1.37.2.2 yamt }
2008 1.37.2.2 yamt
2009 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
2010 1.37.2.2 yamt IWI_RST_SW_RESET);
2011 1.37.2.2 yamt
2012 1.37.2.2 yamt DELAY(10);
2013 1.37.2.2 yamt
2014 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CTL, CSR_READ_4(sc, IWI_CSR_CTL) |
2015 1.37.2.2 yamt IWI_CTL_INIT);
2016 1.37.2.2 yamt
2017 1.37.2.2 yamt /* Clear NIC memory */
2018 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_ADDR, 0);
2019 1.37.2.2 yamt for (i = 0; i < 0xc000; i++)
2020 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, 0);
2021 1.37.2.2 yamt
2022 1.37.2.2 yamt return 0;
2023 1.37.2.2 yamt }
2024 1.37.2.2 yamt
2025 1.37.2.2 yamt static int
2026 1.37.2.2 yamt iwi_load_ucode(struct iwi_softc *sc, void *uc, int size)
2027 1.37.2.2 yamt {
2028 1.37.2.2 yamt uint16_t *w;
2029 1.37.2.2 yamt int ntries, i;
2030 1.37.2.2 yamt
2031 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) |
2032 1.37.2.2 yamt IWI_RST_STOP_MASTER);
2033 1.37.2.2 yamt for (ntries = 0; ntries < 5; ntries++) {
2034 1.37.2.2 yamt if (CSR_READ_4(sc, IWI_CSR_RST) & IWI_RST_MASTER_DISABLED)
2035 1.37.2.2 yamt break;
2036 1.37.2.2 yamt DELAY(10);
2037 1.37.2.2 yamt }
2038 1.37.2.2 yamt if (ntries == 5) {
2039 1.37.2.2 yamt aprint_error("%s: timeout waiting for master\n",
2040 1.37.2.2 yamt sc->sc_dev.dv_xname);
2041 1.37.2.2 yamt return EIO;
2042 1.37.2.2 yamt }
2043 1.37.2.2 yamt
2044 1.37.2.2 yamt MEM_WRITE_4(sc, 0x3000e0, 0x80000000);
2045 1.37.2.2 yamt DELAY(5000);
2046 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) &
2047 1.37.2.2 yamt ~IWI_RST_PRINCETON_RESET);
2048 1.37.2.2 yamt DELAY(5000);
2049 1.37.2.2 yamt MEM_WRITE_4(sc, 0x3000e0, 0);
2050 1.37.2.2 yamt DELAY(1000);
2051 1.37.2.2 yamt MEM_WRITE_4(sc, 0x300004, 1);
2052 1.37.2.2 yamt DELAY(1000);
2053 1.37.2.2 yamt MEM_WRITE_4(sc, 0x300004, 0);
2054 1.37.2.2 yamt DELAY(1000);
2055 1.37.2.2 yamt MEM_WRITE_1(sc, 0x200000, 0x00);
2056 1.37.2.2 yamt MEM_WRITE_1(sc, 0x200000, 0x40);
2057 1.37.2.2 yamt DELAY(1000);
2058 1.37.2.2 yamt
2059 1.37.2.2 yamt /* Adapter is buggy, we must set the address for each word */
2060 1.37.2.2 yamt for (w = uc; size > 0; w++, size -= 2)
2061 1.37.2.2 yamt MEM_WRITE_2(sc, 0x200010, htole16(*w));
2062 1.37.2.2 yamt
2063 1.37.2.2 yamt MEM_WRITE_1(sc, 0x200000, 0x00);
2064 1.37.2.2 yamt MEM_WRITE_1(sc, 0x200000, 0x80);
2065 1.37.2.2 yamt
2066 1.37.2.2 yamt /* Wait until we get a response in the uc queue */
2067 1.37.2.2 yamt for (ntries = 0; ntries < 100; ntries++) {
2068 1.37.2.2 yamt if (MEM_READ_1(sc, 0x200000) & 1)
2069 1.37.2.2 yamt break;
2070 1.37.2.2 yamt DELAY(100);
2071 1.37.2.2 yamt }
2072 1.37.2.2 yamt if (ntries == 100) {
2073 1.37.2.2 yamt aprint_error("%s: timeout waiting for ucode to initialize\n",
2074 1.37.2.2 yamt sc->sc_dev.dv_xname);
2075 1.37.2.2 yamt return EIO;
2076 1.37.2.2 yamt }
2077 1.37.2.2 yamt
2078 1.37.2.2 yamt /* Empty the uc queue or the firmware will not initialize properly */
2079 1.37.2.2 yamt for (i = 0; i < 7; i++)
2080 1.37.2.2 yamt MEM_READ_4(sc, 0x200004);
2081 1.37.2.2 yamt
2082 1.37.2.2 yamt MEM_WRITE_1(sc, 0x200000, 0x00);
2083 1.37.2.2 yamt
2084 1.37.2.2 yamt return 0;
2085 1.37.2.2 yamt }
2086 1.37.2.2 yamt
2087 1.37.2.2 yamt /* macro to handle unaligned little endian data in firmware image */
2088 1.37.2.2 yamt #define GETLE32(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24)
2089 1.37.2.2 yamt static int
2090 1.37.2.2 yamt iwi_load_firmware(struct iwi_softc *sc, void *fw, int size)
2091 1.37.2.2 yamt {
2092 1.37.2.2 yamt bus_dmamap_t map;
2093 1.37.2.2 yamt u_char *p, *end;
2094 1.37.2.2 yamt uint32_t sentinel, ctl, sum;
2095 1.37.2.2 yamt uint32_t cs, sl, cd, cl;
2096 1.37.2.2 yamt int ntries, nsegs, error;
2097 1.37.2.2 yamt int sn;
2098 1.37.2.2 yamt
2099 1.37.2.2 yamt nsegs = (size + PAGE_SIZE - 1) / PAGE_SIZE;
2100 1.37.2.2 yamt
2101 1.37.2.2 yamt /* Create a DMA map for the firmware image */
2102 1.37.2.2 yamt error = bus_dmamap_create(sc->sc_dmat, size, nsegs, size, 0,
2103 1.37.2.2 yamt BUS_DMA_NOWAIT, &map);
2104 1.37.2.2 yamt if (error != 0) {
2105 1.37.2.2 yamt aprint_error("%s: could not create firmware DMA map\n",
2106 1.37.2.2 yamt sc->sc_dev.dv_xname);
2107 1.37.2.2 yamt goto fail1;
2108 1.37.2.2 yamt }
2109 1.37.2.2 yamt
2110 1.37.2.2 yamt error = bus_dmamap_load(sc->sc_dmat, map, fw, size, NULL,
2111 1.37.2.2 yamt BUS_DMA_NOWAIT | BUS_DMA_WRITE);
2112 1.37.2.2 yamt if (error != 0) {
2113 1.37.2.2 yamt aprint_error("%s: could not load fw dma map(%d)\n",
2114 1.37.2.2 yamt sc->sc_dev.dv_xname, error);
2115 1.37.2.2 yamt goto fail2;
2116 1.37.2.2 yamt }
2117 1.37.2.2 yamt
2118 1.37.2.2 yamt /* Make sure the adapter will get up-to-date values */
2119 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_PREWRITE);
2120 1.37.2.2 yamt
2121 1.37.2.2 yamt /* Tell the adapter where the command blocks are stored */
2122 1.37.2.2 yamt MEM_WRITE_4(sc, 0x3000a0, 0x27000);
2123 1.37.2.2 yamt
2124 1.37.2.2 yamt /*
2125 1.37.2.2 yamt * Store command blocks into adapter's internal memory using register
2126 1.37.2.2 yamt * indirections. The adapter will read the firmware image through DMA
2127 1.37.2.2 yamt * using information stored in command blocks.
2128 1.37.2.2 yamt */
2129 1.37.2.2 yamt p = fw;
2130 1.37.2.2 yamt end = p + size;
2131 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_ADDR, 0x27000);
2132 1.37.2.2 yamt
2133 1.37.2.2 yamt sn = 0;
2134 1.37.2.2 yamt sl = cl = 0;
2135 1.37.2.2 yamt cs = cd = 0;
2136 1.37.2.2 yamt while (p < end) {
2137 1.37.2.2 yamt if (sl == 0) {
2138 1.37.2.2 yamt cs = map->dm_segs[sn].ds_addr;
2139 1.37.2.2 yamt sl = map->dm_segs[sn].ds_len;
2140 1.37.2.2 yamt sn++;
2141 1.37.2.2 yamt }
2142 1.37.2.2 yamt if (cl == 0) {
2143 1.37.2.2 yamt cd = GETLE32(p); p += 4; cs += 4; sl -= 4;
2144 1.37.2.2 yamt cl = GETLE32(p); p += 4; cs += 4; sl -= 4;
2145 1.37.2.2 yamt }
2146 1.37.2.2 yamt while (sl > 0 && cl > 0) {
2147 1.37.2.2 yamt int len = min(cl, sl);
2148 1.37.2.2 yamt
2149 1.37.2.2 yamt sl -= len;
2150 1.37.2.2 yamt cl -= len;
2151 1.37.2.2 yamt p += len;
2152 1.37.2.2 yamt
2153 1.37.2.2 yamt while (len > 0) {
2154 1.37.2.2 yamt int mlen = min(len, IWI_CB_MAXDATALEN);
2155 1.37.2.2 yamt
2156 1.37.2.2 yamt ctl = IWI_CB_DEFAULT_CTL | mlen;
2157 1.37.2.2 yamt sum = ctl ^ cs ^ cd;
2158 1.37.2.2 yamt
2159 1.37.2.2 yamt /* Write a command block */
2160 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, ctl);
2161 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, cs);
2162 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, cd);
2163 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, sum);
2164 1.37.2.2 yamt
2165 1.37.2.2 yamt cs += mlen;
2166 1.37.2.2 yamt cd += mlen;
2167 1.37.2.2 yamt len -= mlen;
2168 1.37.2.2 yamt }
2169 1.37.2.2 yamt }
2170 1.37.2.2 yamt }
2171 1.37.2.2 yamt
2172 1.37.2.2 yamt /* Write a fictive final command block (sentinel) */
2173 1.37.2.2 yamt sentinel = CSR_READ_4(sc, IWI_CSR_AUTOINC_ADDR);
2174 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_AUTOINC_DATA, 0);
2175 1.37.2.2 yamt
2176 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, CSR_READ_4(sc, IWI_CSR_RST) &
2177 1.37.2.2 yamt ~(IWI_RST_MASTER_DISABLED | IWI_RST_STOP_MASTER));
2178 1.37.2.2 yamt
2179 1.37.2.2 yamt /* Tell the adapter to start processing command blocks */
2180 1.37.2.2 yamt MEM_WRITE_4(sc, 0x3000a4, 0x540100);
2181 1.37.2.2 yamt
2182 1.37.2.2 yamt /* Wait until the adapter has processed all command blocks */
2183 1.37.2.2 yamt for (ntries = 0; ntries < 400; ntries++) {
2184 1.37.2.2 yamt if (MEM_READ_4(sc, 0x3000d0) >= sentinel)
2185 1.37.2.2 yamt break;
2186 1.37.2.2 yamt DELAY(100);
2187 1.37.2.2 yamt }
2188 1.37.2.2 yamt if (ntries == 400) {
2189 1.37.2.2 yamt aprint_error("%s: timeout processing cb\n",
2190 1.37.2.2 yamt sc->sc_dev.dv_xname);
2191 1.37.2.2 yamt error = EIO;
2192 1.37.2.3 yamt goto fail3;
2193 1.37.2.2 yamt }
2194 1.37.2.2 yamt
2195 1.37.2.2 yamt /* We're done with command blocks processing */
2196 1.37.2.2 yamt MEM_WRITE_4(sc, 0x3000a4, 0x540c00);
2197 1.37.2.2 yamt
2198 1.37.2.2 yamt /* Allow interrupts so we know when the firmware is inited */
2199 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK);
2200 1.37.2.2 yamt
2201 1.37.2.2 yamt /* Tell the adapter to initialize the firmware */
2202 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, 0);
2203 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CTL, CSR_READ_4(sc, IWI_CSR_CTL) |
2204 1.37.2.2 yamt IWI_CTL_ALLOW_STANDBY);
2205 1.37.2.2 yamt
2206 1.37.2.2 yamt /* Wait at most one second for firmware initialization to complete */
2207 1.37.2.2 yamt if ((error = tsleep(sc, 0, "iwiinit", hz)) != 0) {
2208 1.37.2.2 yamt aprint_error("%s: timeout waiting for firmware initialization "
2209 1.37.2.2 yamt "to complete\n", sc->sc_dev.dv_xname);
2210 1.37.2.2 yamt goto fail3;
2211 1.37.2.2 yamt }
2212 1.37.2.2 yamt
2213 1.37.2.2 yamt fail3:
2214 1.37.2.2 yamt bus_dmamap_sync(sc->sc_dmat, map, 0, size, BUS_DMASYNC_POSTWRITE);
2215 1.37.2.2 yamt bus_dmamap_unload(sc->sc_dmat, map);
2216 1.37.2.2 yamt fail2:
2217 1.37.2.2 yamt bus_dmamap_destroy(sc->sc_dmat, map);
2218 1.37.2.2 yamt
2219 1.37.2.2 yamt fail1:
2220 1.37.2.2 yamt return error;
2221 1.37.2.2 yamt }
2222 1.37.2.2 yamt
2223 1.37.2.2 yamt /*
2224 1.37.2.2 yamt * Store firmware into kernel memory so we can download it when we need to,
2225 1.37.2.2 yamt * e.g when the adapter wakes up from suspend mode.
2226 1.37.2.2 yamt */
2227 1.37.2.2 yamt static int
2228 1.37.2.2 yamt iwi_cache_firmware(struct iwi_softc *sc, void *data)
2229 1.37.2.2 yamt {
2230 1.37.2.2 yamt struct iwi_firmware *kfw = &sc->fw;
2231 1.37.2.2 yamt struct iwi_firmware ufw;
2232 1.37.2.2 yamt int error;
2233 1.37.2.2 yamt
2234 1.37.2.2 yamt iwi_free_firmware(sc);
2235 1.37.2.2 yamt
2236 1.37.2.2 yamt if ((error = copyin(data, &ufw, sizeof ufw)) != 0)
2237 1.37.2.2 yamt goto fail1;
2238 1.37.2.2 yamt
2239 1.37.2.2 yamt kfw->boot_size = ufw.boot_size;
2240 1.37.2.2 yamt kfw->ucode_size = ufw.ucode_size;
2241 1.37.2.2 yamt kfw->main_size = ufw.main_size;
2242 1.37.2.2 yamt
2243 1.37.2.2 yamt kfw->boot = malloc(kfw->boot_size, M_DEVBUF, M_NOWAIT);
2244 1.37.2.2 yamt if (kfw->boot == NULL) {
2245 1.37.2.2 yamt error = ENOMEM;
2246 1.37.2.2 yamt goto fail1;
2247 1.37.2.2 yamt }
2248 1.37.2.2 yamt
2249 1.37.2.2 yamt kfw->ucode = malloc(kfw->ucode_size, M_DEVBUF, M_NOWAIT);
2250 1.37.2.2 yamt if (kfw->ucode == NULL) {
2251 1.37.2.2 yamt error = ENOMEM;
2252 1.37.2.2 yamt goto fail2;
2253 1.37.2.2 yamt }
2254 1.37.2.2 yamt
2255 1.37.2.2 yamt kfw->main = malloc(kfw->main_size, M_DEVBUF, M_NOWAIT);
2256 1.37.2.2 yamt if (kfw->main == NULL) {
2257 1.37.2.2 yamt error = ENOMEM;
2258 1.37.2.2 yamt goto fail3;
2259 1.37.2.2 yamt }
2260 1.37.2.2 yamt
2261 1.37.2.2 yamt if ((error = copyin(ufw.boot, kfw->boot, kfw->boot_size)) != 0)
2262 1.37.2.2 yamt goto fail4;
2263 1.37.2.2 yamt
2264 1.37.2.2 yamt if ((error = copyin(ufw.ucode, kfw->ucode, kfw->ucode_size)) != 0)
2265 1.37.2.2 yamt goto fail4;
2266 1.37.2.2 yamt
2267 1.37.2.2 yamt if ((error = copyin(ufw.main, kfw->main, kfw->main_size)) != 0)
2268 1.37.2.2 yamt goto fail4;
2269 1.37.2.2 yamt
2270 1.37.2.2 yamt DPRINTF(("Firmware cached: boot %u, ucode %u, main %u\n",
2271 1.37.2.2 yamt kfw->boot_size, kfw->ucode_size, kfw->main_size));
2272 1.37.2.2 yamt
2273 1.37.2.2 yamt sc->flags |= IWI_FLAG_FW_CACHED;
2274 1.37.2.2 yamt
2275 1.37.2.2 yamt return 0;
2276 1.37.2.2 yamt
2277 1.37.2.2 yamt fail4: free(kfw->boot, M_DEVBUF);
2278 1.37.2.2 yamt fail3: free(kfw->ucode, M_DEVBUF);
2279 1.37.2.2 yamt fail2: free(kfw->main, M_DEVBUF);
2280 1.37.2.2 yamt fail1:
2281 1.37.2.2 yamt return error;
2282 1.37.2.2 yamt }
2283 1.37.2.2 yamt
2284 1.37.2.2 yamt static void
2285 1.37.2.2 yamt iwi_free_firmware(struct iwi_softc *sc)
2286 1.37.2.2 yamt {
2287 1.37.2.2 yamt if (!(sc->flags & IWI_FLAG_FW_CACHED))
2288 1.37.2.2 yamt return;
2289 1.37.2.2 yamt
2290 1.37.2.2 yamt free(sc->fw.boot, M_DEVBUF);
2291 1.37.2.2 yamt free(sc->fw.ucode, M_DEVBUF);
2292 1.37.2.2 yamt free(sc->fw.main, M_DEVBUF);
2293 1.37.2.2 yamt
2294 1.37.2.2 yamt sc->flags &= ~IWI_FLAG_FW_CACHED;
2295 1.37.2.2 yamt }
2296 1.37.2.2 yamt
2297 1.37.2.2 yamt static int
2298 1.37.2.2 yamt iwi_config(struct iwi_softc *sc)
2299 1.37.2.2 yamt {
2300 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
2301 1.37.2.2 yamt struct ifnet *ifp = &sc->sc_if;
2302 1.37.2.2 yamt struct iwi_configuration config;
2303 1.37.2.2 yamt struct iwi_rateset rs;
2304 1.37.2.2 yamt struct iwi_txpower power;
2305 1.37.2.2 yamt struct ieee80211_key *wk;
2306 1.37.2.2 yamt struct iwi_wep_key wepkey;
2307 1.37.2.2 yamt uint32_t data;
2308 1.37.2.2 yamt int error, i;
2309 1.37.2.2 yamt
2310 1.37.2.2 yamt IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
2311 1.37.2.2 yamt DPRINTF(("Setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
2312 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_myaddr,
2313 1.37.2.2 yamt IEEE80211_ADDR_LEN, 0);
2314 1.37.2.2 yamt if (error != 0)
2315 1.37.2.2 yamt return error;
2316 1.37.2.2 yamt
2317 1.37.2.2 yamt memset(&config, 0, sizeof config);
2318 1.37.2.2 yamt config.bluetooth_coexistence = sc->bluetooth;
2319 1.37.2.2 yamt config.antenna = sc->antenna;
2320 1.37.2.2 yamt config.multicast_enabled = 1;
2321 1.37.2.2 yamt config.answer_pbreq = (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0;
2322 1.37.2.2 yamt config.disable_unicast_decryption = 1;
2323 1.37.2.2 yamt config.disable_multicast_decryption = 1;
2324 1.37.2.2 yamt DPRINTF(("Configuring adapter\n"));
2325 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_CONFIGURATION, &config, sizeof config,
2326 1.37.2.2 yamt 0);
2327 1.37.2.2 yamt if (error != 0)
2328 1.37.2.2 yamt return error;
2329 1.37.2.2 yamt
2330 1.37.2.2 yamt data = htole32(IWI_POWER_MODE_CAM);
2331 1.37.2.2 yamt DPRINTF(("Setting power mode to %u\n", le32toh(data)));
2332 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_POWER_MODE, &data, sizeof data, 0);
2333 1.37.2.2 yamt if (error != 0)
2334 1.37.2.2 yamt return error;
2335 1.37.2.2 yamt
2336 1.37.2.2 yamt data = htole32(ic->ic_rtsthreshold);
2337 1.37.2.2 yamt DPRINTF(("Setting RTS threshold to %u\n", le32toh(data)));
2338 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_RTS_THRESHOLD, &data, sizeof data, 0);
2339 1.37.2.2 yamt if (error != 0)
2340 1.37.2.2 yamt return error;
2341 1.37.2.2 yamt
2342 1.37.2.2 yamt data = htole32(ic->ic_fragthreshold);
2343 1.37.2.2 yamt DPRINTF(("Setting fragmentation threshold to %u\n", le32toh(data)));
2344 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_FRAG_THRESHOLD, &data, sizeof data, 0);
2345 1.37.2.2 yamt if (error != 0)
2346 1.37.2.2 yamt return error;
2347 1.37.2.2 yamt
2348 1.37.2.2 yamt if (ic->ic_opmode == IEEE80211_M_IBSS) {
2349 1.37.2.2 yamt power.mode = IWI_MODE_11B;
2350 1.37.2.2 yamt power.nchan = 11;
2351 1.37.2.2 yamt for (i = 0; i < 11; i++) {
2352 1.37.2.2 yamt power.chan[i].chan = i + 1;
2353 1.37.2.2 yamt power.chan[i].power = IWI_TXPOWER_MAX;
2354 1.37.2.2 yamt }
2355 1.37.2.2 yamt DPRINTF(("Setting .11b channels tx power\n"));
2356 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_TX_POWER, &power, sizeof power,
2357 1.37.2.2 yamt 0);
2358 1.37.2.2 yamt if (error != 0)
2359 1.37.2.2 yamt return error;
2360 1.37.2.2 yamt
2361 1.37.2.2 yamt power.mode = IWI_MODE_11G;
2362 1.37.2.2 yamt DPRINTF(("Setting .11g channels tx power\n"));
2363 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_TX_POWER, &power, sizeof power,
2364 1.37.2.2 yamt 0);
2365 1.37.2.2 yamt if (error != 0)
2366 1.37.2.2 yamt return error;
2367 1.37.2.2 yamt }
2368 1.37.2.2 yamt
2369 1.37.2.2 yamt rs.mode = IWI_MODE_11G;
2370 1.37.2.2 yamt rs.type = IWI_RATESET_TYPE_SUPPORTED;
2371 1.37.2.2 yamt rs.nrates = ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates;
2372 1.37.2.2 yamt memcpy(rs.rates, ic->ic_sup_rates[IEEE80211_MODE_11G].rs_rates,
2373 1.37.2.2 yamt rs.nrates);
2374 1.37.2.2 yamt DPRINTF(("Setting .11bg supported rates (%u)\n", rs.nrates));
2375 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs, 0);
2376 1.37.2.2 yamt if (error != 0)
2377 1.37.2.2 yamt return error;
2378 1.37.2.2 yamt
2379 1.37.2.2 yamt rs.mode = IWI_MODE_11A;
2380 1.37.2.2 yamt rs.type = IWI_RATESET_TYPE_SUPPORTED;
2381 1.37.2.2 yamt rs.nrates = ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates;
2382 1.37.2.2 yamt memcpy(rs.rates, ic->ic_sup_rates[IEEE80211_MODE_11A].rs_rates,
2383 1.37.2.2 yamt rs.nrates);
2384 1.37.2.2 yamt DPRINTF(("Setting .11a supported rates (%u)\n", rs.nrates));
2385 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs, 0);
2386 1.37.2.2 yamt if (error != 0)
2387 1.37.2.2 yamt return error;
2388 1.37.2.2 yamt
2389 1.37.2.2 yamt /* if we have a desired ESSID, set it now */
2390 1.37.2.2 yamt if (ic->ic_des_esslen != 0) {
2391 1.37.2.2 yamt #ifdef IWI_DEBUG
2392 1.37.2.2 yamt if (iwi_debug > 0) {
2393 1.37.2.2 yamt printf("Setting desired ESSID to ");
2394 1.37.2.2 yamt ieee80211_print_essid(ic->ic_des_essid,
2395 1.37.2.2 yamt ic->ic_des_esslen);
2396 1.37.2.2 yamt printf("\n");
2397 1.37.2.2 yamt }
2398 1.37.2.2 yamt #endif
2399 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ic->ic_des_essid,
2400 1.37.2.2 yamt ic->ic_des_esslen, 0);
2401 1.37.2.2 yamt if (error != 0)
2402 1.37.2.2 yamt return error;
2403 1.37.2.2 yamt }
2404 1.37.2.2 yamt
2405 1.37.2.2 yamt data = htole32(arc4random());
2406 1.37.2.2 yamt DPRINTF(("Setting initialization vector to %u\n", le32toh(data)));
2407 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_IV, &data, sizeof data, 0);
2408 1.37.2.2 yamt if (error != 0)
2409 1.37.2.2 yamt return error;
2410 1.37.2.2 yamt
2411 1.37.2.2 yamt for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2412 1.37.2.2 yamt wk = &ic->ic_crypto.cs_nw_keys[i];
2413 1.37.2.2 yamt
2414 1.37.2.2 yamt wepkey.cmd = IWI_WEP_KEY_CMD_SETKEY;
2415 1.37.2.2 yamt wepkey.idx = i;
2416 1.37.2.2 yamt wepkey.len = wk->wk_keylen;
2417 1.37.2.2 yamt memset(wepkey.key, 0, sizeof wepkey.key);
2418 1.37.2.2 yamt memcpy(wepkey.key, wk->wk_key, wk->wk_keylen);
2419 1.37.2.2 yamt DPRINTF(("Setting wep key index %u len %u\n",
2420 1.37.2.2 yamt wepkey.idx, wepkey.len));
2421 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_WEP_KEY, &wepkey,
2422 1.37.2.2 yamt sizeof wepkey, 0);
2423 1.37.2.2 yamt if (error != 0)
2424 1.37.2.2 yamt return error;
2425 1.37.2.2 yamt }
2426 1.37.2.2 yamt
2427 1.37.2.2 yamt /* Enable adapter */
2428 1.37.2.2 yamt DPRINTF(("Enabling adapter\n"));
2429 1.37.2.2 yamt return iwi_cmd(sc, IWI_CMD_ENABLE, NULL, 0, 0);
2430 1.37.2.2 yamt }
2431 1.37.2.2 yamt
2432 1.37.2.2 yamt static int
2433 1.37.2.2 yamt iwi_set_chan(struct iwi_softc *sc, struct ieee80211_channel *chan)
2434 1.37.2.2 yamt {
2435 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
2436 1.37.2.2 yamt struct iwi_scan_v2 scan;
2437 1.37.2.2 yamt
2438 1.37.2.2 yamt (void)memset(&scan, 0, sizeof scan);
2439 1.37.2.2 yamt
2440 1.37.2.2 yamt scan.dwelltime[IWI_SCAN_TYPE_PASSIVE] = htole16(2000);
2441 1.37.2.2 yamt scan.channels[0] = 1 |
2442 1.37.2.2 yamt (IEEE80211_IS_CHAN_5GHZ(chan) ? IWI_CHAN_5GHZ : IWI_CHAN_2GHZ);
2443 1.37.2.2 yamt scan.channels[1] = ieee80211_chan2ieee(ic, chan);
2444 1.37.2.2 yamt iwi_scan_type_set(scan, 1, IWI_SCAN_TYPE_PASSIVE);
2445 1.37.2.2 yamt
2446 1.37.2.2 yamt DPRINTF(("Setting channel to %u\n", ieee80211_chan2ieee(ic, chan)));
2447 1.37.2.2 yamt return iwi_cmd(sc, IWI_CMD_SCAN_V2, &scan, sizeof scan, 1);
2448 1.37.2.2 yamt }
2449 1.37.2.2 yamt
2450 1.37.2.2 yamt static int
2451 1.37.2.2 yamt iwi_scan(struct iwi_softc *sc)
2452 1.37.2.2 yamt {
2453 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
2454 1.37.2.2 yamt struct iwi_scan_v2 scan;
2455 1.37.2.2 yamt uint32_t type;
2456 1.37.2.2 yamt uint8_t *p;
2457 1.37.2.2 yamt int i, count, idx;
2458 1.37.2.2 yamt
2459 1.37.2.2 yamt (void)memset(&scan, 0, sizeof scan);
2460 1.37.2.2 yamt scan.dwelltime[IWI_SCAN_TYPE_ACTIVE_BROADCAST] =
2461 1.37.2.2 yamt htole16(sc->dwelltime);
2462 1.37.2.2 yamt scan.dwelltime[IWI_SCAN_TYPE_ACTIVE_BDIRECT] =
2463 1.37.2.2 yamt htole16(sc->dwelltime);
2464 1.37.2.2 yamt
2465 1.37.2.2 yamt /* tell the firmware about the desired essid */
2466 1.37.2.2 yamt if (ic->ic_des_esslen) {
2467 1.37.2.2 yamt int error;
2468 1.37.2.2 yamt
2469 1.37.2.2 yamt DPRINTF(("%s: Setting adapter desired ESSID to %s\n",
2470 1.37.2.2 yamt __func__, ic->ic_des_essid));
2471 1.37.2.2 yamt
2472 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_ESSID,
2473 1.37.2.2 yamt ic->ic_des_essid, ic->ic_des_esslen, 1);
2474 1.37.2.2 yamt if (error)
2475 1.37.2.2 yamt return error;
2476 1.37.2.2 yamt
2477 1.37.2.2 yamt type = IWI_SCAN_TYPE_ACTIVE_BDIRECT;
2478 1.37.2.2 yamt } else {
2479 1.37.2.2 yamt type = IWI_SCAN_TYPE_ACTIVE_BROADCAST;
2480 1.37.2.2 yamt }
2481 1.37.2.2 yamt
2482 1.37.2.2 yamt p = &scan.channels[0];
2483 1.37.2.2 yamt count = idx = 0;
2484 1.37.2.2 yamt for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
2485 1.37.2.2 yamt if (IEEE80211_IS_CHAN_5GHZ(&ic->ic_channels[i]) &&
2486 1.37.2.2 yamt isset(ic->ic_chan_active, i)) {
2487 1.37.2.2 yamt *++p = i;
2488 1.37.2.2 yamt count++;
2489 1.37.2.2 yamt idx++;
2490 1.37.2.2 yamt iwi_scan_type_set(scan, idx, type);
2491 1.37.2.2 yamt }
2492 1.37.2.2 yamt }
2493 1.37.2.2 yamt if (count) {
2494 1.37.2.2 yamt *(p - count) = IWI_CHAN_5GHZ | count;
2495 1.37.2.2 yamt p++;
2496 1.37.2.2 yamt }
2497 1.37.2.2 yamt
2498 1.37.2.2 yamt count = 0;
2499 1.37.2.2 yamt for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
2500 1.37.2.2 yamt if (IEEE80211_IS_CHAN_2GHZ(&ic->ic_channels[i]) &&
2501 1.37.2.2 yamt isset(ic->ic_chan_active, i)) {
2502 1.37.2.2 yamt *++p = i;
2503 1.37.2.2 yamt count++;
2504 1.37.2.2 yamt idx++;
2505 1.37.2.2 yamt iwi_scan_type_set(scan, idx, type);
2506 1.37.2.2 yamt }
2507 1.37.2.2 yamt }
2508 1.37.2.2 yamt *(p - count) = IWI_CHAN_2GHZ | count;
2509 1.37.2.2 yamt
2510 1.37.2.2 yamt DPRINTF(("Start scanning\n"));
2511 1.37.2.2 yamt return iwi_cmd(sc, IWI_CMD_SCAN_V2, &scan, sizeof scan, 1);
2512 1.37.2.2 yamt }
2513 1.37.2.2 yamt
2514 1.37.2.2 yamt static int
2515 1.37.2.2 yamt iwi_auth_and_assoc(struct iwi_softc *sc)
2516 1.37.2.2 yamt {
2517 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
2518 1.37.2.2 yamt struct ieee80211_node *ni = ic->ic_bss;
2519 1.37.2.2 yamt struct ifnet *ifp = &sc->sc_if;
2520 1.37.2.2 yamt struct ieee80211_wme_info wme;
2521 1.37.2.2 yamt struct iwi_configuration config;
2522 1.37.2.2 yamt struct iwi_associate assoc;
2523 1.37.2.2 yamt struct iwi_rateset rs;
2524 1.37.2.2 yamt uint16_t capinfo;
2525 1.37.2.2 yamt uint32_t data;
2526 1.37.2.2 yamt int error;
2527 1.37.2.2 yamt
2528 1.37.2.2 yamt if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
2529 1.37.2.2 yamt memset(&config, 0, sizeof config);
2530 1.37.2.2 yamt config.bluetooth_coexistence = sc->bluetooth;
2531 1.37.2.2 yamt config.antenna = sc->antenna;
2532 1.37.2.2 yamt config.multicast_enabled = 1;
2533 1.37.2.2 yamt config.use_protection = 1;
2534 1.37.2.2 yamt config.answer_pbreq =
2535 1.37.2.2 yamt (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0;
2536 1.37.2.2 yamt config.disable_unicast_decryption = 1;
2537 1.37.2.2 yamt config.disable_multicast_decryption = 1;
2538 1.37.2.2 yamt DPRINTF(("Configuring adapter\n"));
2539 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_CONFIGURATION, &config,
2540 1.37.2.2 yamt sizeof config, 1);
2541 1.37.2.2 yamt if (error != 0)
2542 1.37.2.2 yamt return error;
2543 1.37.2.2 yamt }
2544 1.37.2.2 yamt
2545 1.37.2.2 yamt #ifdef IWI_DEBUG
2546 1.37.2.2 yamt if (iwi_debug > 0) {
2547 1.37.2.2 yamt printf("Setting ESSID to ");
2548 1.37.2.2 yamt ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
2549 1.37.2.2 yamt printf("\n");
2550 1.37.2.2 yamt }
2551 1.37.2.2 yamt #endif
2552 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_ESSID, ni->ni_essid, ni->ni_esslen, 1);
2553 1.37.2.2 yamt if (error != 0)
2554 1.37.2.2 yamt return error;
2555 1.37.2.2 yamt
2556 1.37.2.2 yamt /* the rate set has already been "negotiated" */
2557 1.37.2.2 yamt rs.mode = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? IWI_MODE_11A :
2558 1.37.2.2 yamt IWI_MODE_11G;
2559 1.37.2.2 yamt rs.type = IWI_RATESET_TYPE_NEGOTIATED;
2560 1.37.2.2 yamt rs.nrates = ni->ni_rates.rs_nrates;
2561 1.37.2.2 yamt memcpy(rs.rates, ni->ni_rates.rs_rates, rs.nrates);
2562 1.37.2.2 yamt DPRINTF(("Setting negotiated rates (%u)\n", rs.nrates));
2563 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_RATES, &rs, sizeof rs, 1);
2564 1.37.2.2 yamt if (error != 0)
2565 1.37.2.2 yamt return error;
2566 1.37.2.2 yamt
2567 1.37.2.2 yamt if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL) {
2568 1.37.2.2 yamt wme.wme_id = IEEE80211_ELEMID_VENDOR;
2569 1.37.2.2 yamt wme.wme_len = sizeof (struct ieee80211_wme_info) - 2;
2570 1.37.2.2 yamt wme.wme_oui[0] = 0x00;
2571 1.37.2.2 yamt wme.wme_oui[1] = 0x50;
2572 1.37.2.2 yamt wme.wme_oui[2] = 0xf2;
2573 1.37.2.2 yamt wme.wme_type = WME_OUI_TYPE;
2574 1.37.2.2 yamt wme.wme_subtype = WME_INFO_OUI_SUBTYPE;
2575 1.37.2.2 yamt wme.wme_version = WME_VERSION;
2576 1.37.2.2 yamt wme.wme_info = 0;
2577 1.37.2.2 yamt
2578 1.37.2.2 yamt DPRINTF(("Setting WME IE (len=%u)\n", wme.wme_len));
2579 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_WMEIE, &wme, sizeof wme, 1);
2580 1.37.2.2 yamt if (error != 0)
2581 1.37.2.2 yamt return error;
2582 1.37.2.2 yamt }
2583 1.37.2.2 yamt
2584 1.37.2.2 yamt if (ic->ic_opt_ie != NULL) {
2585 1.37.2.2 yamt DPRINTF(("Setting optional IE (len=%u)\n", ic->ic_opt_ie_len));
2586 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_OPTIE, ic->ic_opt_ie,
2587 1.37.2.2 yamt ic->ic_opt_ie_len, 1);
2588 1.37.2.2 yamt if (error != 0)
2589 1.37.2.2 yamt return error;
2590 1.37.2.2 yamt }
2591 1.37.2.2 yamt data = htole32(ni->ni_rssi);
2592 1.37.2.2 yamt DPRINTF(("Setting sensitivity to %d\n", (int8_t)ni->ni_rssi));
2593 1.37.2.2 yamt error = iwi_cmd(sc, IWI_CMD_SET_SENSITIVITY, &data, sizeof data, 1);
2594 1.37.2.2 yamt if (error != 0)
2595 1.37.2.2 yamt return error;
2596 1.37.2.2 yamt
2597 1.37.2.2 yamt memset(&assoc, 0, sizeof assoc);
2598 1.37.2.2 yamt assoc.mode = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? IWI_MODE_11A :
2599 1.37.2.2 yamt IWI_MODE_11G;
2600 1.37.2.2 yamt assoc.chan = ieee80211_chan2ieee(ic, ni->ni_chan);
2601 1.37.2.2 yamt if (ni->ni_authmode == IEEE80211_AUTH_SHARED)
2602 1.37.2.2 yamt assoc.auth = (ic->ic_crypto.cs_def_txkey << 4) | IWI_AUTH_SHARED;
2603 1.37.2.2 yamt if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_wme_ie != NULL)
2604 1.37.2.2 yamt assoc.policy |= htole16(IWI_POLICY_WME);
2605 1.37.2.2 yamt if (ic->ic_opt_ie != NULL)
2606 1.37.2.2 yamt assoc.policy |= htole16(IWI_POLICY_WPA);
2607 1.37.2.2 yamt memcpy(assoc.tstamp, ni->ni_tstamp.data, 8);
2608 1.37.2.2 yamt
2609 1.37.2.2 yamt if (ic->ic_opmode == IEEE80211_M_IBSS)
2610 1.37.2.2 yamt capinfo = IEEE80211_CAPINFO_IBSS;
2611 1.37.2.2 yamt else
2612 1.37.2.2 yamt capinfo = IEEE80211_CAPINFO_ESS;
2613 1.37.2.2 yamt if (ic->ic_flags & IEEE80211_F_PRIVACY)
2614 1.37.2.2 yamt capinfo |= IEEE80211_CAPINFO_PRIVACY;
2615 1.37.2.2 yamt if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
2616 1.37.2.2 yamt IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
2617 1.37.2.2 yamt capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
2618 1.37.2.2 yamt if (ic->ic_flags & IEEE80211_F_SHSLOT)
2619 1.37.2.2 yamt capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
2620 1.37.2.2 yamt assoc.capinfo = htole16(capinfo);
2621 1.37.2.2 yamt
2622 1.37.2.2 yamt assoc.lintval = htole16(ic->ic_lintval);
2623 1.37.2.2 yamt assoc.intval = htole16(ni->ni_intval);
2624 1.37.2.2 yamt IEEE80211_ADDR_COPY(assoc.bssid, ni->ni_bssid);
2625 1.37.2.2 yamt if (ic->ic_opmode == IEEE80211_M_IBSS)
2626 1.37.2.2 yamt IEEE80211_ADDR_COPY(assoc.dst, ifp->if_broadcastaddr);
2627 1.37.2.2 yamt else
2628 1.37.2.2 yamt IEEE80211_ADDR_COPY(assoc.dst, ni->ni_bssid);
2629 1.37.2.2 yamt DPRINTF(("Trying to associate to %s channel %u auth %u\n",
2630 1.37.2.2 yamt ether_sprintf(assoc.bssid), assoc.chan, assoc.auth));
2631 1.37.2.2 yamt return iwi_cmd(sc, IWI_CMD_ASSOCIATE, &assoc, sizeof assoc, 1);
2632 1.37.2.2 yamt }
2633 1.37.2.2 yamt
2634 1.37.2.2 yamt static int
2635 1.37.2.2 yamt iwi_init(struct ifnet *ifp)
2636 1.37.2.2 yamt {
2637 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
2638 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
2639 1.37.2.2 yamt struct iwi_firmware *fw = &sc->fw;
2640 1.37.2.2 yamt int i, error;
2641 1.37.2.2 yamt
2642 1.37.2.2 yamt /* exit immediately if firmware has not been ioctl'd */
2643 1.37.2.2 yamt if (!(sc->flags & IWI_FLAG_FW_CACHED)) {
2644 1.37.2.2 yamt if (!(sc->flags & IWI_FLAG_FW_WARNED))
2645 1.37.2.2 yamt aprint_error("%s: Firmware not loaded\n",
2646 1.37.2.2 yamt sc->sc_dev.dv_xname);
2647 1.37.2.2 yamt sc->flags |= IWI_FLAG_FW_WARNED;
2648 1.37.2.2 yamt ifp->if_flags &= ~IFF_UP;
2649 1.37.2.2 yamt return EIO;
2650 1.37.2.2 yamt }
2651 1.37.2.2 yamt
2652 1.37.2.2 yamt iwi_stop(ifp, 0);
2653 1.37.2.2 yamt
2654 1.37.2.2 yamt if ((error = iwi_reset(sc)) != 0) {
2655 1.37.2.2 yamt aprint_error("%s: could not reset adapter\n",
2656 1.37.2.2 yamt sc->sc_dev.dv_xname);
2657 1.37.2.2 yamt goto fail;
2658 1.37.2.2 yamt }
2659 1.37.2.2 yamt
2660 1.37.2.2 yamt if ((error = iwi_load_firmware(sc, fw->boot, fw->boot_size)) != 0) {
2661 1.37.2.2 yamt aprint_error("%s: could not load boot firmware\n",
2662 1.37.2.2 yamt sc->sc_dev.dv_xname);
2663 1.37.2.2 yamt goto fail;
2664 1.37.2.2 yamt }
2665 1.37.2.2 yamt
2666 1.37.2.2 yamt if ((error = iwi_load_ucode(sc, fw->ucode, fw->ucode_size)) != 0) {
2667 1.37.2.2 yamt aprint_error("%s: could not load microcode\n",
2668 1.37.2.2 yamt sc->sc_dev.dv_xname);
2669 1.37.2.2 yamt goto fail;
2670 1.37.2.2 yamt }
2671 1.37.2.2 yamt
2672 1.37.2.2 yamt iwi_stop_master(sc);
2673 1.37.2.2 yamt
2674 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CMD_BASE, sc->cmdq.desc_map->dm_segs[0].ds_addr);
2675 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CMD_SIZE, sc->cmdq.count);
2676 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_CMD_WIDX, sc->cmdq.cur);
2677 1.37.2.2 yamt
2678 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX1_BASE, sc->txq[0].desc_map->dm_segs[0].ds_addr);
2679 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX1_SIZE, sc->txq[0].count);
2680 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX1_WIDX, sc->txq[0].cur);
2681 1.37.2.2 yamt
2682 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX2_BASE, sc->txq[1].desc_map->dm_segs[0].ds_addr);
2683 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX2_SIZE, sc->txq[1].count);
2684 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX2_WIDX, sc->txq[1].cur);
2685 1.37.2.2 yamt
2686 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX3_BASE, sc->txq[2].desc_map->dm_segs[0].ds_addr);
2687 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX3_SIZE, sc->txq[2].count);
2688 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX3_WIDX, sc->txq[2].cur);
2689 1.37.2.2 yamt
2690 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX4_BASE, sc->txq[3].desc_map->dm_segs[0].ds_addr);
2691 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX4_SIZE, sc->txq[3].count);
2692 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_TX4_WIDX, sc->txq[3].cur);
2693 1.37.2.2 yamt
2694 1.37.2.2 yamt for (i = 0; i < sc->rxq.count; i++)
2695 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RX_BASE + i * 4,
2696 1.37.2.2 yamt sc->rxq.data[i].map->dm_segs[0].ds_addr);
2697 1.37.2.2 yamt
2698 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RX_WIDX, sc->rxq.count -1);
2699 1.37.2.2 yamt
2700 1.37.2.2 yamt if ((error = iwi_load_firmware(sc, fw->main, fw->main_size)) != 0) {
2701 1.37.2.2 yamt aprint_error("%s: could not load main firmware\n",
2702 1.37.2.2 yamt sc->sc_dev.dv_xname);
2703 1.37.2.2 yamt goto fail;
2704 1.37.2.2 yamt }
2705 1.37.2.2 yamt
2706 1.37.2.2 yamt sc->flags |= IWI_FLAG_FW_INITED;
2707 1.37.2.2 yamt
2708 1.37.2.2 yamt if ((error = iwi_config(sc)) != 0) {
2709 1.37.2.2 yamt aprint_error("%s: device configuration failed\n",
2710 1.37.2.2 yamt sc->sc_dev.dv_xname);
2711 1.37.2.2 yamt goto fail;
2712 1.37.2.2 yamt }
2713 1.37.2.2 yamt
2714 1.37.2.2 yamt if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2715 1.37.2.2 yamt if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
2716 1.37.2.2 yamt ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2717 1.37.2.2 yamt } else
2718 1.37.2.2 yamt ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
2719 1.37.2.2 yamt
2720 1.37.2.2 yamt ifp->if_flags &= ~IFF_OACTIVE;
2721 1.37.2.2 yamt ifp->if_flags |= IFF_RUNNING;
2722 1.37.2.2 yamt
2723 1.37.2.2 yamt return 0;
2724 1.37.2.2 yamt
2725 1.37.2.2 yamt fail: ifp->if_flags &= ~IFF_UP;
2726 1.37.2.2 yamt iwi_stop(ifp, 0);
2727 1.37.2.2 yamt
2728 1.37.2.2 yamt return error;
2729 1.37.2.2 yamt }
2730 1.37.2.2 yamt
2731 1.37.2.2 yamt static void
2732 1.37.2.2 yamt iwi_stop(struct ifnet *ifp, int disable)
2733 1.37.2.2 yamt {
2734 1.37.2.2 yamt struct iwi_softc *sc = ifp->if_softc;
2735 1.37.2.2 yamt struct ieee80211com *ic = &sc->sc_ic;
2736 1.37.2.2 yamt
2737 1.37.2.3 yamt IWI_LED_OFF(sc);
2738 1.37.2.3 yamt
2739 1.37.2.2 yamt iwi_stop_master(sc);
2740 1.37.2.2 yamt CSR_WRITE_4(sc, IWI_CSR_RST, IWI_RST_SW_RESET);
2741 1.37.2.2 yamt
2742 1.37.2.2 yamt /* reset rings */
2743 1.37.2.2 yamt iwi_reset_cmd_ring(sc, &sc->cmdq);
2744 1.37.2.2 yamt iwi_reset_tx_ring(sc, &sc->txq[0]);
2745 1.37.2.2 yamt iwi_reset_tx_ring(sc, &sc->txq[1]);
2746 1.37.2.2 yamt iwi_reset_tx_ring(sc, &sc->txq[2]);
2747 1.37.2.2 yamt iwi_reset_tx_ring(sc, &sc->txq[3]);
2748 1.37.2.2 yamt iwi_reset_rx_ring(sc, &sc->rxq);
2749 1.37.2.2 yamt
2750 1.37.2.2 yamt ifp->if_timer = 0;
2751 1.37.2.2 yamt ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2752 1.37.2.2 yamt
2753 1.37.2.2 yamt ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2754 1.37.2.2 yamt }
2755 1.37.2.2 yamt
2756 1.37.2.2 yamt static void
2757 1.37.2.3 yamt iwi_led_set(struct iwi_softc *sc, uint32_t state, int toggle)
2758 1.37.2.3 yamt {
2759 1.37.2.3 yamt uint32_t val;
2760 1.37.2.3 yamt
2761 1.37.2.3 yamt val = MEM_READ_4(sc, IWI_MEM_EVENT_CTL);
2762 1.37.2.3 yamt
2763 1.37.2.3 yamt switch (sc->nictype) {
2764 1.37.2.3 yamt case 1:
2765 1.37.2.3 yamt /* special NIC type: reversed leds */
2766 1.37.2.3 yamt if (state == IWI_LED_ACTIVITY) {
2767 1.37.2.3 yamt state &= ~IWI_LED_ACTIVITY;
2768 1.37.2.3 yamt state |= IWI_LED_ASSOCIATED;
2769 1.37.2.3 yamt } else if (state == IWI_LED_ASSOCIATED) {
2770 1.37.2.3 yamt state &= ~IWI_LED_ASSOCIATED;
2771 1.37.2.3 yamt state |= IWI_LED_ACTIVITY;
2772 1.37.2.3 yamt }
2773 1.37.2.3 yamt /* and ignore toggle effect */
2774 1.37.2.3 yamt val |= state;
2775 1.37.2.3 yamt break;
2776 1.37.2.3 yamt case 0:
2777 1.37.2.3 yamt case 2:
2778 1.37.2.3 yamt case 3:
2779 1.37.2.3 yamt case 4:
2780 1.37.2.3 yamt val = (toggle && (val & state)) ? val & ~state : val | state;
2781 1.37.2.3 yamt break;
2782 1.37.2.3 yamt default:
2783 1.37.2.3 yamt aprint_normal("%s: unknown NIC type %d\n",
2784 1.37.2.3 yamt sc->sc_dev.dv_xname, sc->nictype);
2785 1.37.2.3 yamt return;
2786 1.37.2.3 yamt break;
2787 1.37.2.3 yamt }
2788 1.37.2.3 yamt
2789 1.37.2.3 yamt MEM_WRITE_4(sc, IWI_MEM_EVENT_CTL, val);
2790 1.37.2.3 yamt
2791 1.37.2.3 yamt return;
2792 1.37.2.3 yamt }
2793 1.37.2.3 yamt
2794 1.37.2.3 yamt static void
2795 1.37.2.2 yamt iwi_error_log(struct iwi_softc *sc)
2796 1.37.2.2 yamt {
2797 1.37.2.2 yamt uint32_t b, n;
2798 1.37.2.2 yamt int i;
2799 1.37.2.2 yamt
2800 1.37.2.2 yamt static const char *const msg[] = {
2801 1.37.2.2 yamt "no error",
2802 1.37.2.2 yamt "failed",
2803 1.37.2.2 yamt "memory range low",
2804 1.37.2.2 yamt "memory range high",
2805 1.37.2.2 yamt "bad parameter",
2806 1.37.2.2 yamt "checksum",
2807 1.37.2.2 yamt "NMI",
2808 1.37.2.2 yamt "bad database",
2809 1.37.2.2 yamt "allocation failed",
2810 1.37.2.2 yamt "DMA underrun",
2811 1.37.2.2 yamt "DMA status",
2812 1.37.2.2 yamt "DINO",
2813 1.37.2.2 yamt "EEPROM",
2814 1.37.2.2 yamt "device assert",
2815 1.37.2.2 yamt "fatal"
2816 1.37.2.2 yamt };
2817 1.37.2.2 yamt
2818 1.37.2.2 yamt b = CSR_READ_4(sc, IWI_CSR_ERRORLOG);
2819 1.37.2.2 yamt n = MEM_READ_4(sc, b);
2820 1.37.2.2 yamt
2821 1.37.2.2 yamt b += 4;
2822 1.37.2.2 yamt
2823 1.37.2.2 yamt for (i = 0; i < n ; i++) {
2824 1.37.2.2 yamt struct iwi_error fw_error;
2825 1.37.2.2 yamt
2826 1.37.2.2 yamt MEM_CPY(sc, &fw_error, b, sizeof(fw_error));
2827 1.37.2.2 yamt
2828 1.37.2.2 yamt printf("%s: %s\n", sc->sc_dev.dv_xname,
2829 1.37.2.2 yamt msg[fw_error.type]);
2830 1.37.2.2 yamt
2831 1.37.2.2 yamt b += sizeof(fw_error);
2832 1.37.2.2 yamt }
2833 1.37.2.2 yamt }
2834