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