Annotation of src/sys/dev/pci/if_iwn.c, Revision 1.22.2.1
1.22.2.1! skrll 1: /* $NetBSD: if_iwn.c,v 1.28 2008/12/22 11:32:04 blymn Exp $ */
1.1 ober 2:
3: /*-
4: * Copyright (c) 2007
5: * Damien Bergamini <damien.bergamini@free.fr>
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/cdefs.h>
1.22.2.1! skrll 21: __KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.28 2008/12/22 11:32:04 blymn Exp $");
1.1 ober 22:
23:
24: /*
25: * Driver for Intel Wireless WiFi Link 4965AGN 802.11 network adapters.
26: */
27:
28: #include "bpfilter.h"
29:
30: #include <sys/param.h>
31: #include <sys/sockio.h>
32: #include <sys/sysctl.h>
33: #include <sys/mbuf.h>
34: #include <sys/kernel.h>
35: #include <sys/socket.h>
36: #include <sys/systm.h>
37: #include <sys/malloc.h>
1.17 cube 38: #include <sys/mutex.h>
1.1 ober 39: #include <sys/conf.h>
40: #include <sys/kauth.h>
41: #include <sys/callout.h>
42:
43: #include <machine/bus.h>
44: #include <machine/endian.h>
45: #include <machine/intr.h>
46:
47: #include <dev/pci/pcireg.h>
48: #include <dev/pci/pcivar.h>
49: #include <dev/pci/pcidevs.h>
50:
51: #if NBPFILTER > 0
52: #include <net/bpf.h>
53: #endif
54: #include <net/if.h>
55: #include <net/if_arp.h>
56: #include <net/if_dl.h>
57: #include <net/if_media.h>
58: #include <net/if_types.h>
59:
60: #include <netinet/in.h>
61: #include <netinet/in_systm.h>
62: #include <netinet/in_var.h>
63: #include <net/if_ether.h>
64: #include <netinet/ip.h>
65:
66: #include <net80211/ieee80211_var.h>
67: #include <net80211/ieee80211_amrr.h>
68: #include <net80211/ieee80211_radiotap.h>
69:
70: #include <dev/firmload.h>
71:
72: #include <dev/pci/if_iwnreg.h>
73: #include <dev/pci/if_iwnvar.h>
74:
1.8 blymn 75: #if 0
1.1 ober 76: static const struct pci_matchid iwn_devices[] = {
77: { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_4965AGN_1 },
78: { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PRO_WL_4965AGN_2 }
79: };
80: #endif
81:
82: /*
83: * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
84: */
85: static const struct ieee80211_rateset iwn_rateset_11a =
86: { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
87:
88: static const struct ieee80211_rateset iwn_rateset_11b =
89: { 4, { 2, 4, 11, 22 } };
90:
91: static const struct ieee80211_rateset iwn_rateset_11g =
92: { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
93:
94:
1.15 christos 95: #define EDCA_NUM_AC 4
1.1 ober 96: static int iwn_match(device_t , struct cfdata *, void *);
97: static void iwn_attach(device_t , device_t, void *);
98: static int iwn_detach(device_t, int);
99:
100: static void iwn_radiotap_attach(struct iwn_softc *);
101: static int iwn_dma_contig_alloc(bus_dma_tag_t, struct iwn_dma_info *,
1.2 ober 102: void **, bus_size_t, bus_size_t, int);
1.1 ober 103: static void iwn_dma_contig_free(struct iwn_dma_info *);
104: static int iwn_alloc_shared(struct iwn_softc *);
105: static void iwn_free_shared(struct iwn_softc *);
106: static int iwn_alloc_kw(struct iwn_softc *);
107: static void iwn_free_kw(struct iwn_softc *);
108: static int iwn_alloc_fwmem(struct iwn_softc *);
109: static void iwn_free_fwmem(struct iwn_softc *);
110: static struct iwn_rbuf *iwn_alloc_rbuf(struct iwn_softc *);
111: static void iwn_free_rbuf(struct mbuf *, void *, size_t, void *);
112: static int iwn_alloc_rpool(struct iwn_softc *);
113: static void iwn_free_rpool(struct iwn_softc *);
114: static int iwn_alloc_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
115: static void iwn_reset_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
116: static void iwn_free_rx_ring(struct iwn_softc *, struct iwn_rx_ring *);
117: static int iwn_alloc_tx_ring(struct iwn_softc *, struct iwn_tx_ring *,
1.2 ober 118: int, int);
1.1 ober 119: static void iwn_reset_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);
120: static void iwn_free_tx_ring(struct iwn_softc *, struct iwn_tx_ring *);
121: static struct ieee80211_node *iwn_node_alloc(struct ieee80211_node_table *);
122: static void iwn_newassoc(struct ieee80211_node *, int);
123: static int iwn_media_change(struct ifnet *);
124: static int iwn_newstate(struct ieee80211com *, enum ieee80211_state, int);
125: static void iwn_mem_lock(struct iwn_softc *);
126: static void iwn_mem_unlock(struct iwn_softc *);
1.15 christos 127: static uint32_t iwn_mem_read(struct iwn_softc *, uint32_t);
1.1 ober 128: static void iwn_mem_write(struct iwn_softc *, uint32_t, uint32_t);
129: static void iwn_mem_write_region_4(struct iwn_softc *, uint32_t,
1.2 ober 130: const uint32_t *, int);
1.1 ober 131: static int iwn_eeprom_lock(struct iwn_softc *);
132: static void iwn_eeprom_unlock(struct iwn_softc *);
133: static int iwn_read_prom_data(struct iwn_softc *, uint32_t, void *, int);
134: static int iwn_load_microcode(struct iwn_softc *, const uint8_t *, int);
135: static int iwn_load_firmware(struct iwn_softc *);
136: static void iwn_calib_timeout(void *);
137: static void iwn_iter_func(void *, struct ieee80211_node *);
138: static void iwn_ampdu_rx_start(struct iwn_softc *, struct iwn_rx_desc *);
139: static void iwn_rx_intr(struct iwn_softc *, struct iwn_rx_desc *,
1.2 ober 140: struct iwn_rx_data *);
1.1 ober 141: static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *);
142: static void iwn_tx_intr(struct iwn_softc *, struct iwn_rx_desc *);
143: static void iwn_cmd_intr(struct iwn_softc *, struct iwn_rx_desc *);
144: static void iwn_notif_intr(struct iwn_softc *);
145: static int iwn_intr(void *);
146: static void iwn_read_eeprom(struct iwn_softc *);
147: static void iwn_read_eeprom_channels(struct iwn_softc *, int);
148: static uint8_t iwn_plcp_signal(int);
149: static int iwn_tx_data(struct iwn_softc *, struct mbuf *,
1.2 ober 150: struct ieee80211_node *, int);
1.1 ober 151: static void iwn_start(struct ifnet *);
152: static void iwn_watchdog(struct ifnet *);
153: static int iwn_ioctl(struct ifnet *, u_long, void *);
154: static int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
1.15 christos 155: static int iwn_wme_update(struct ieee80211com *);
1.1 ober 156: static int iwn_setup_node_mrr(struct iwn_softc *, uint8_t, int);
157: static void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t);
158: static int iwn_set_critical_temp(struct iwn_softc *);
159: static void iwn_enable_tsf(struct iwn_softc *, struct ieee80211_node *);
160: static void iwn_power_calibration(struct iwn_softc *, int);
161: static int iwn_set_txpower(struct iwn_softc *,
1.2 ober 162: struct ieee80211_channel *, int);
1.1 ober 163: static int iwn_get_rssi(const struct iwn_rx_stat *);
164: static int iwn_get_noise(const struct iwn_rx_general_stats *);
165: static int iwn_get_temperature(struct iwn_softc *);
166: static int iwn_init_sensitivity(struct iwn_softc *);
167: static void iwn_compute_differential_gain(struct iwn_softc *,
1.2 ober 168: const struct iwn_rx_general_stats *);
1.1 ober 169: static void iwn_tune_sensitivity(struct iwn_softc *,
1.2 ober 170: const struct iwn_rx_stats *);
1.1 ober 171: static int iwn_send_sensitivity(struct iwn_softc *);
1.20 blymn 172: static int iwn_setup_beacon(struct iwn_softc *, struct ieee80211_node *);
1.1 ober 173: static int iwn_auth(struct iwn_softc *);
174: static int iwn_run(struct iwn_softc *);
175: static int iwn_scan(struct iwn_softc *, uint16_t);
176: static int iwn_config(struct iwn_softc *);
177: static void iwn_post_alive(struct iwn_softc *);
178: static void iwn_stop_master(struct iwn_softc *);
179: static int iwn_reset(struct iwn_softc *);
180: static void iwn_hw_config(struct iwn_softc *);
181: static int iwn_init(struct ifnet *);
182: static void iwn_stop(struct ifnet *, int);
183: static void iwn_fix_channel(struct ieee80211com *, struct mbuf *);
1.7 taca 184: static bool iwn_resume(device_t PMF_FN_PROTO);
1.11 blymn 185: static int iwn_add_node(struct iwn_softc *sc,
1.20 blymn 186: struct ieee80211_node *ni, bool broadcast, bool async, uint32_t htflags);
1.1 ober 187:
188:
189:
190: #define IWN_DEBUG
191:
192: #ifdef IWN_DEBUG
193: #define DPRINTF(x) do { if (iwn_debug > 0) printf x; } while (0)
194: #define DPRINTFN(n, x) do { if (iwn_debug >= (n)) printf x; } while (0)
1.11 blymn 195: int iwn_debug = 0;
1.1 ober 196: #else
197: #define DPRINTF(x)
198: #define DPRINTFN(n, x)
199: #endif
200:
1.11 blymn 201: #ifdef IWN_DEBUG
202: static void iwn_print_power_group(struct iwn_softc *, int);
203: #endif
204:
1.8 blymn 205: CFATTACH_DECL_NEW(iwn, sizeof(struct iwn_softc), iwn_match, iwn_attach,
1.2 ober 206: iwn_detach, NULL);
1.1 ober 207:
208: static int
209: iwn_match(device_t parent, struct cfdata *match __unused, void *aux)
210: {
1.2 ober 211: struct pci_attach_args *pa = aux;
1.8 blymn 212:
1.2 ober 213: if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL)
214: return 0;
1.1 ober 215:
1.8 blymn 216: if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_4965AGN_1 ||
1.2 ober 217: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_PRO_WL_4965AGN_2)
218: return 1;
1.1 ober 219:
1.2 ober 220: return 0;
1.1 ober 221: }
222:
223: /* Base Address Register */
224: #define IWN_PCI_BAR0 0x10
225:
226: static void
227: iwn_attach(device_t parent __unused, device_t self, void *aux)
228: {
229: struct iwn_softc *sc = device_private(self);
230: struct ieee80211com *ic = &sc->sc_ic;
231: struct ifnet *ifp = &sc->sc_ec.ec_if;
232: struct pci_attach_args *pa = aux;
233: const char *intrstr;
234: char devinfo[256];
235: pci_intr_handle_t ih;
236: pcireg_t memtype, data;
1.8 blymn 237: int i, error, revision;
1.1 ober 238:
239: sc->sc_dev = self;
1.2 ober 240: sc->sc_pct = pa->pa_pc;
1.1 ober 241: sc->sc_pcitag = pa->pa_tag;
242:
243: callout_init(&sc->calib_to, 0);
244: callout_setfunc(&sc->calib_to, iwn_calib_timeout, sc);
1.8 blymn 245:
1.1 ober 246: pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof devinfo);
247: revision = PCI_REVISION(pa->pa_class);
248: aprint_normal(": %s (rev. 0x%2x)\n", devinfo, revision);
1.8 blymn 249:
1.1 ober 250:
251: /* clear device specific PCI configuration register 0x41 */
252: data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40);
253: data &= ~0x0000ff00;
254: pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data);
255:
256: data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
257: data |= PCI_COMMAND_MASTER_ENABLE;
258: pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, data);
259:
260: /* enable bus-mastering */
261: data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
262: data |= PCI_COMMAND_MASTER_ENABLE;
263: pci_conf_write(sc->sc_pct, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, data);
264:
265: /* map the register window */
266: memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, IWN_PCI_BAR0);
267: error = pci_mapreg_map(pa, IWN_PCI_BAR0, memtype, 0, &sc->sc_st,
268: &sc->sc_sh, NULL, &sc->sc_sz);
269: if (error != 0) {
270: aprint_error_dev(self, "could not map memory space\n");
271: return;
272: }
273:
1.20 blymn 274: #if 0
1.1 ober 275: sc->sc_dmat = pa->pa_dmat;
1.20 blymn 276: #endif
277: /* XXX may not be needed */
278: if (bus_dmatag_subregion(pa->pa_dmat, 0, 3 << 30,
279: &(sc->sc_dmat), BUS_DMA_NOWAIT) != 0) {
280: aprint_error_dev(self,
281: "WARNING: failed to restrict dma range, "
282: "falling back to parent bus dma range\n");
283: sc->sc_dmat = pa->pa_dmat;
284: }
1.1 ober 285:
286: if (pci_intr_map(pa, &ih) != 0) {
287: aprint_error_dev(self, "could not map interrupt\n");
288: return;
289: }
290:
291: intrstr = pci_intr_string(sc->sc_pct, ih);
292: sc->sc_ih = pci_intr_establish(sc->sc_pct, ih, IPL_NET, iwn_intr, sc);
1.3 skrll 293:
1.1 ober 294: if (sc->sc_ih == NULL) {
1.8 blymn 295: aprint_error_dev(self, "could not establish interrupt");
1.1 ober 296: if (intrstr != NULL)
297: aprint_error(" at %s", intrstr);
298: aprint_error("\n");
299: return;
300: }
301: aprint_normal_dev(self, "interrupting at %s\n", intrstr);
302:
303: if (iwn_reset(sc) != 0) {
1.2 ober 304: aprint_error_dev(self, "could not reset adapter\n");
305: return;
1.1 ober 306: }
1.8 blymn 307:
1.1 ober 308: /*
309: * Allocate DMA memory for firmware transfers.
310: */
311: if ((error = iwn_alloc_fwmem(sc)) != 0) {
312: aprint_error_dev(self, "could not allocate firmware memory\n");
313: return;
314: }
315:
316: /*
317: * Allocate a "keep warm" page.
318: */
319: if ((error = iwn_alloc_kw(sc)) != 0) {
320: aprint_error_dev(self, "could not allocate keep warm page\n");
321: goto fail1;
322: }
323:
324: /*
325: * Allocate shared area (communication area).
326: */
327: if ((error = iwn_alloc_shared(sc)) != 0) {
328: aprint_error_dev(self, "could not allocate shared area\n");
329: goto fail2;
330: }
331:
332: /*
333: * Allocate Rx buffers and Tx/Rx rings.
334: */
335: if ((error = iwn_alloc_rpool(sc)) != 0) {
336: aprint_error_dev(self, "could not allocate Rx buffers\n");
337: goto fail3;
338: }
339:
340: for (i = 0; i < IWN_NTXQUEUES; i++) {
341: struct iwn_tx_ring *txq = &sc->txq[i];
342: error = iwn_alloc_tx_ring(sc, txq, IWN_TX_RING_COUNT, i);
343: if (error != 0) {
344: aprint_error_dev(self, "could not allocate Tx ring %d\n", i);
345: goto fail4;
346: }
347: }
1.8 blymn 348:
1.1 ober 349: if (iwn_alloc_rx_ring(sc, &sc->rxq) != 0) {
1.2 ober 350: aprint_error_dev(self, "could not allocate Rx ring\n");
351: goto fail4;
1.1 ober 352: }
353:
354:
1.22.2.1! skrll 355: /* Set the state of the RF kill switch */
! 356: sc->sc_radio = (IWN_READ(sc, IWN_GPIO_CTL) & IWN_GPIO_RF_ENABLED);
! 357:
1.1 ober 358: ic->ic_ifp = ifp;
359: ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
360: ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
361: ic->ic_state = IEEE80211_S_INIT;
362:
363: /* set device capabilities */
364: ic->ic_caps =
365: IEEE80211_C_IBSS | /* IBSS mode support */
1.15 christos 366: IEEE80211_C_WPA | /* 802.11i */
1.1 ober 367: IEEE80211_C_MONITOR | /* monitor mode supported */
368: IEEE80211_C_TXPMGT | /* tx power management */
369: IEEE80211_C_SHSLOT | /* short slot time supported */
370: IEEE80211_C_SHPREAMBLE| /* short preamble supported */
1.15 christos 371: IEEE80211_C_WME; /* 802.11e */
1.8 blymn 372:
1.1 ober 373: /* read supported channels and MAC address from EEPROM */
374: iwn_read_eeprom(sc);
375:
376: /* set supported .11a, .11b and .11g rates */
377: ic->ic_sup_rates[IEEE80211_MODE_11A] = iwn_rateset_11a;
378: ic->ic_sup_rates[IEEE80211_MODE_11B] = iwn_rateset_11b;
379: ic->ic_sup_rates[IEEE80211_MODE_11G] = iwn_rateset_11g;
380:
381: /* IBSS channel undefined for now */
382: ic->ic_ibss_chan = &ic->ic_channels[0];
383:
1.22.2.1! skrll 384: memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
! 385: ic->ic_des_esslen = 0;
! 386:
1.1 ober 387: ifp->if_softc = sc;
388: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
389: ifp->if_init = iwn_init;
390: ifp->if_stop = iwn_stop;
391: ifp->if_ioctl = iwn_ioctl;
392: ifp->if_start = iwn_start;
393: ifp->if_watchdog = iwn_watchdog;
394: IFQ_SET_READY(&ifp->if_snd);
395: memcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
396:
397: if_attach(ifp);
398: ieee80211_ifattach(ic);
399: ic->ic_node_alloc = iwn_node_alloc;
400: ic->ic_newassoc = iwn_newassoc;
401: ic->ic_wme.wme_update = iwn_wme_update;
402:
403: /* override state transition machine */
404: sc->sc_newstate = ic->ic_newstate;
405: ic->ic_newstate = iwn_newstate;
406: ieee80211_media_init(ic, iwn_media_change, ieee80211_media_status);
407:
408: sc->amrr.amrr_min_success_threshold = 1;
409: sc->amrr.amrr_max_success_threshold = 15;
410:
411: if (!pmf_device_register(self, NULL, iwn_resume))
412: aprint_error_dev(self, "couldn't establish power handler\n");
413: else
414: pmf_class_network_register(self, ifp);
415:
416: iwn_radiotap_attach(sc);
1.8 blymn 417:
1.1 ober 418: ieee80211_announce(ic);
419:
420: return;
421:
422: /* free allocated memory if something failed during attachment */
423: fail4: while (--i >= 0)
424: iwn_free_tx_ring(sc, &sc->txq[i]);
425: iwn_free_rpool(sc);
426: fail3: iwn_free_shared(sc);
427: fail2: iwn_free_kw(sc);
428: fail1: iwn_free_fwmem(sc);
429: }
430:
431: static int
432: iwn_detach(struct device* self, int flags __unused)
433: {
434: struct iwn_softc *sc = (struct iwn_softc *)self;
435: struct ifnet *ifp = sc->sc_ic.ic_ifp;
436: int ac;
437:
438: iwn_stop(ifp, 1);
439:
440: #if NBPFILTER > 0
441: if (ifp != NULL)
442: bpfdetach(ifp);
443: #endif
444: ieee80211_ifdetach(&sc->sc_ic);
445: if (ifp != NULL)
446: if_detach(ifp);
447:
448: for (ac = 0; ac < IWN_NTXQUEUES; ac++)
449: iwn_free_tx_ring(sc, &sc->txq[ac]);
450: iwn_free_rx_ring(sc, &sc->rxq);
451: iwn_free_rpool(sc);
452: iwn_free_shared(sc);
453:
454: if (sc->sc_ih != NULL) {
455: pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
456: sc->sc_ih = NULL;
457: }
458:
459: bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
460:
461: return 0;
462: }
463:
464: /*
465: * Attach the interface to 802.11 radiotap.
466: */
467: static void
468: iwn_radiotap_attach(struct iwn_softc *sc)
469: {
470: struct ifnet *ifp = sc->sc_ic.ic_ifp;
471:
472: #if NBPFILTER > 0
473: bpfattach2(ifp, DLT_IEEE802_11_RADIO,
1.8 blymn 474: sizeof (struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
1.2 ober 475: &sc->sc_drvbpf);
1.1 ober 476:
477: sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
478: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
479: sc->sc_rxtap.wr_ihdr.it_present = htole32(IWN_RX_RADIOTAP_PRESENT);
480:
481: sc->sc_txtap_len = sizeof sc->sc_txtapu;
482: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
483: sc->sc_txtap.wt_ihdr.it_present = htole32(IWN_TX_RADIOTAP_PRESENT);
484: #endif
485: }
486:
487:
488: /*
489: * Build a beacon frame that the firmware will broadcast periodically in
490: * IBSS or HostAP modes.
491: */
492: static int
493: iwn_setup_beacon(struct iwn_softc *sc, struct ieee80211_node *ni)
494: {
495: struct ieee80211com *ic = &sc->sc_ic;
496: struct iwn_tx_ring *ring = &sc->txq[4];
497: struct iwn_tx_desc *desc;
498: struct iwn_tx_data *data;
499: struct iwn_tx_cmd *cmd;
500: struct iwn_cmd_beacon *bcn;
501: struct ieee80211_beacon_offsets bo;
502: struct mbuf *m0;
503: bus_addr_t paddr;
504: int error;
505:
506: desc = &ring->desc[ring->cur];
507: data = &ring->data[ring->cur];
508:
509: m0 = ieee80211_beacon_alloc(ic, ni, &bo);
510: if (m0 == NULL) {
511: aprint_error_dev(sc->sc_dev, "could not allocate beacon frame\n");
512: return ENOMEM;
513: }
514:
515: cmd = &ring->cmd[ring->cur];
516: cmd->code = IWN_CMD_SET_BEACON;
517: cmd->flags = 0;
518: cmd->qid = ring->qid;
519: cmd->idx = ring->cur;
520:
521: bcn = (struct iwn_cmd_beacon *)cmd->data;
522: memset(bcn, 0, sizeof (struct iwn_cmd_beacon));
523: bcn->id = IWN_ID_BROADCAST;
524: bcn->lifetime = htole32(IWN_LIFETIME_INFINITE);
525: bcn->len = htole16(m0->m_pkthdr.len);
526: bcn->rate = (ic->ic_curmode == IEEE80211_MODE_11A) ?
1.2 ober 527: iwn_plcp_signal(12) : iwn_plcp_signal(2);
1.20 blymn 528: bcn->flags2 = 0x2; /* RATE_MCS_CCK_MSK */
529:
530: bcn->flags = htole32(IWN_TX_AUTO_SEQ | IWN_TX_INSERT_TSTAMP
531: | IWN_TX_USE_NODE_RATE);
1.1 ober 532:
533: /* save and trim IEEE802.11 header */
534: m_copydata(m0, 0, sizeof (struct ieee80211_frame), (void *)&bcn->wh);
535: m_adj(m0, sizeof (struct ieee80211_frame));
536:
537: /* assume beacon frame is contiguous */
538: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
1.2 ober 539: BUS_DMA_READ | BUS_DMA_NOWAIT);
1.1 ober 540: if (error) {
541: aprint_error_dev(sc->sc_dev, "could not map beacon\n");
542: m_freem(m0);
543: return error;
544: }
545:
546: data->m = m0;
547:
548: /* first scatter/gather segment is used by the beacon command */
549: paddr = ring->cmd_dma.paddr + ring->cur * sizeof (struct iwn_tx_cmd);
1.8 blymn 550:
1.1 ober 551: IWN_SET_DESC_NSEGS(desc, 2);
552: IWN_SET_DESC_SEG(desc, 0, paddr , 4 + sizeof(struct iwn_cmd_beacon));
553: IWN_SET_DESC_SEG(desc, 1, data->map->dm_segs[0].ds_addr,
1.2 ober 554: data->map->dm_segs[1].ds_len);
1.8 blymn 555:
1.20 blymn 556: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
557: data->map->dm_mapsize /* calc? */, BUS_DMASYNC_PREWRITE);
1.1 ober 558:
559: /* kick cmd ring */
560: ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
561: IWN_WRITE(sc, IWN_TX_WIDX, ring->qid << 8 | ring->cur);
562:
563: return 0;
564: }
565:
566: static int
567: iwn_dma_contig_alloc(bus_dma_tag_t tag, struct iwn_dma_info *dma, void **kvap,
568: bus_size_t size, bus_size_t alignment, int flags)
569: {
570: int nsegs, error;
571:
572: dma->tag = tag;
573: dma->size = size;
574:
575: error = bus_dmamap_create(tag, size, 1, size, 0, flags, &dma->map);
576: if (error != 0)
577: goto fail;
578:
579: error = bus_dmamem_alloc(tag, size, alignment, 0, &dma->seg, 1, &nsegs,
580: flags);
581: if (error != 0)
582: goto fail;
583:
584: error = bus_dmamem_map(tag, &dma->seg, 1, size, &dma->vaddr, flags);
585: if (error != 0)
586: goto fail;
587:
588: error = bus_dmamap_load(tag, dma->map, dma->vaddr, size, NULL, flags);
589: if (error != 0)
590: goto fail;
591:
592: memset(dma->vaddr, 0, size);
593:
594: dma->paddr = dma->map->dm_segs[0].ds_addr;
595: if (kvap != NULL)
596: *kvap = dma->vaddr;
597:
598: return 0;
599:
600: fail: iwn_dma_contig_free(dma);
601: return error;
602: }
603:
604: static void
605: iwn_dma_contig_free(struct iwn_dma_info *dma)
606: {
607: if (dma->map != NULL) {
608: if (dma->vaddr != NULL) {
609: bus_dmamap_unload(dma->tag, dma->map);
610: bus_dmamem_unmap(dma->tag, dma->vaddr, dma->size);
611: bus_dmamem_free(dma->tag, &dma->seg, 1);
612: dma->vaddr = NULL;
613: }
614: bus_dmamap_destroy(dma->tag, dma->map);
615: dma->map = NULL;
616: }
617: }
618:
619: static int
620: iwn_alloc_shared(struct iwn_softc *sc)
621: {
1.15 christos 622: int error;
1.14 christos 623: void *p;
1.15 christos 624: /* must be aligned on a 1KB boundary */
1.1 ober 625: error = iwn_dma_contig_alloc(sc->sc_dmat, &sc->shared_dma,
1.14 christos 626: &p, sizeof (struct iwn_shared), 1024,BUS_DMA_NOWAIT);
1.16 christos 627: sc->shared = p;
1.1 ober 628: if (error != 0)
1.2 ober 629: aprint_error_dev(sc->sc_dev,
630: "could not allocate shared area DMA memory\n");
1.1 ober 631:
632: return error;
633:
634: }
635:
636: static void
637: iwn_free_shared(struct iwn_softc *sc)
638: {
639: iwn_dma_contig_free(&sc->shared_dma);
640: }
641:
642: static int
643: iwn_alloc_kw(struct iwn_softc *sc)
644: {
645: /* must be aligned on a 16-byte boundary */
646: return iwn_dma_contig_alloc(sc->sc_dmat, &sc->kw_dma, NULL,
647: PAGE_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT);
648: }
649:
650: static void
651: iwn_free_kw(struct iwn_softc *sc)
652: {
653: iwn_dma_contig_free(&sc->kw_dma);
654: }
655:
656: static int
657: iwn_alloc_fwmem(struct iwn_softc *sc)
658: {
659: int error;
660: /* allocate enough contiguous space to store text and data */
661: error = iwn_dma_contig_alloc(sc->sc_dmat, &sc->fw_dma, NULL,
1.2 ober 662: IWN_FW_MAIN_TEXT_MAXSZ + IWN_FW_MAIN_DATA_MAXSZ, 16,
663: BUS_DMA_NOWAIT);
1.1 ober 664:
665: if (error != 0){
666: aprint_error_dev(sc->sc_dev,
1.2 ober 667: "could not allocate firmware transfer area DMA memory\n" );
1.8 blymn 668:
1.1 ober 669: }
670: return error;
671: }
672:
673: static void
674: iwn_free_fwmem(struct iwn_softc *sc)
675: {
676: iwn_dma_contig_free(&sc->fw_dma);
677: }
678:
679: static struct iwn_rbuf *
680: iwn_alloc_rbuf(struct iwn_softc *sc)
681: {
682: struct iwn_rbuf *rbuf;
683:
1.17 cube 684: mutex_enter(&sc->rxq.freelist_mtx);
1.1 ober 685: rbuf = SLIST_FIRST(&sc->rxq.freelist);
1.17 cube 686: if (rbuf != NULL) {
687: SLIST_REMOVE_HEAD(&sc->rxq.freelist, next);
688: sc->rxq.nb_free_entries --;
689: }
690: mutex_exit(&sc->rxq.freelist_mtx);
691:
1.1 ober 692: return rbuf;
693: }
694:
695: /*
696: * This is called automatically by the network stack when the mbuf to which
697: * our Rx buffer is attached is freed.
698: */
699: static void
700: iwn_free_rbuf(struct mbuf* m, void *buf, size_t size, void *arg)
701: {
702: struct iwn_rbuf *rbuf = arg;
703: struct iwn_softc *sc = rbuf->sc;
704:
705: /* put the buffer back in the free list */
1.17 cube 706: mutex_enter(&sc->rxq.freelist_mtx);
1.1 ober 707: SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
1.17 cube 708: mutex_exit(&sc->rxq.freelist_mtx);
1.1 ober 709: sc->rxq.nb_free_entries ++;
710:
711: if (__predict_true(m != NULL))
712: pool_cache_put(mb_cache, m);
713: }
714:
715:
716: static int
717: iwn_alloc_rpool(struct iwn_softc *sc)
718: {
719: struct iwn_rx_ring *ring = &sc->rxq;
720: struct iwn_rbuf *rbuf;
721: int i, error;
722:
1.17 cube 723: mutex_init(&ring->freelist_mtx, MUTEX_DEFAULT, IPL_NET);
724:
1.1 ober 725: /* allocate a big chunk of DMA'able memory.. */
726: error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->buf_dma, NULL,
727: IWN_RBUF_COUNT * IWN_RBUF_SIZE, IWN_BUF_ALIGN, BUS_DMA_NOWAIT);
728: if (error != 0) {
1.3 skrll 729: aprint_error_dev(sc->sc_dev,
730: "could not allocate Rx buffers DMA memory\n");
1.1 ober 731: return error;
732: }
733:
734: /* ..and split it into chunks of "rbufsz" bytes */
735: SLIST_INIT(&ring->freelist);
736: for (i = 0; i < IWN_RBUF_COUNT; i++) {
737: rbuf = &ring->rbuf[i];
738:
739: rbuf->sc = sc; /* backpointer for callbacks */
740: rbuf->vaddr = (char *)ring->buf_dma.vaddr + i * IWN_RBUF_SIZE;
741: rbuf->paddr = ring->buf_dma.paddr + i * IWN_RBUF_SIZE;
742:
743: SLIST_INSERT_HEAD(&ring->freelist, rbuf, next);
744: }
745: ring->nb_free_entries = IWN_RBUF_COUNT;
746: return 0;
747: }
748:
749: static void
750: iwn_free_rpool(struct iwn_softc *sc)
751: {
752: iwn_dma_contig_free(&sc->rxq.buf_dma);
753: }
754:
755: static int
756: iwn_alloc_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
757: {
1.15 christos 758: struct iwn_rx_data *data;
759: struct iwn_rbuf *rbuf;
760: int i, error;
1.14 christos 761: void *p;
1.8 blymn 762:
1.1 ober 763: ring->cur = 0;
764:
765: error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
1.14 christos 766: &p, IWN_RX_RING_COUNT * sizeof (struct iwn_rx_desc),
1.1 ober 767: IWN_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
768: if (error != 0) {
1.3 skrll 769: aprint_error_dev(sc->sc_dev,
770: "could not allocate rx ring DMA memory\n");
1.1 ober 771: goto fail;
772: }
1.14 christos 773: ring->desc = p;
1.1 ober 774:
775: /*
776: * Setup Rx buffers.
777: */
778: for (i = 0; i < IWN_RX_RING_COUNT; i++) {
779: data = &ring->data[i];
1.8 blymn 780:
1.1 ober 781: MGETHDR(data->m, M_DONTWAIT, MT_DATA);
782: if (data->m == NULL) {
783: aprint_error_dev(sc->sc_dev, "could not allocate rx mbuf\n");
784: error = ENOMEM;
785: goto fail;
786: }
787: if ((rbuf = iwn_alloc_rbuf(sc)) == NULL) {
788: m_freem(data->m);
789: data->m = NULL;
790: aprint_error_dev(sc->sc_dev, "could not allocate rx buffer\n");
791: error = ENOMEM;
792: goto fail;
793: }
794: /* attach Rx buffer to mbuf */
795: MEXTADD(data->m, rbuf->vaddr, IWN_RBUF_SIZE, 0, iwn_free_rbuf,
796: rbuf);
797:
798: data->m->m_flags |= M_EXT_RW;
799: /* Rx buffers are aligned on a 256-byte boundary */
800: ring->desc[i] = htole32(rbuf->paddr >> 8);
801: }
802:
803: return 0;
804:
805: fail: iwn_free_rx_ring(sc, ring);
806: return error;
807: }
808:
809: static void
810: iwn_reset_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
811: {
812: int ntries;
813:
814: iwn_mem_lock(sc);
815:
816: IWN_WRITE(sc, IWN_RX_CONFIG, 0);
817: for (ntries = 0; ntries < 100; ntries++) {
818: if (IWN_READ(sc, IWN_RX_STATUS) & IWN_RX_IDLE)
819: break;
820: DELAY(10);
821: }
822: #ifdef IWN_DEBUG
823: if (ntries == 100 && iwn_debug > 0)
824: aprint_error_dev(sc->sc_dev, "timeout resetting Rx ring\n");
825: #endif
826: iwn_mem_unlock(sc);
827:
828: ring->cur = 0;
829: }
830:
831: static void
832: iwn_free_rx_ring(struct iwn_softc *sc, struct iwn_rx_ring *ring)
833: {
834: int i;
835:
836: iwn_dma_contig_free(&ring->desc_dma);
837:
838: for (i = 0; i < IWN_RX_RING_COUNT; i++) {
839: if (ring->data[i].m != NULL)
840: m_freem(ring->data[i].m);
841: }
842: }
843:
844: static int
845: iwn_alloc_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring, int count,
846: int qid)
847: {
1.2 ober 848: struct iwn_tx_data *data;
1.1 ober 849: int i, error;
1.14 christos 850: void *p;
1.1 ober 851:
852: ring->qid = qid;
853: ring->count = count;
854: ring->queued = 0;
855: ring->cur = 0;
856:
857: error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
1.14 christos 858: &p, count * sizeof (struct iwn_tx_desc),
1.1 ober 859: IWN_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
860: if (error != 0) {
861: aprint_error_dev(sc->sc_dev, "could not allocate tx ring DMA memory\n");
862: goto fail;
863: }
1.14 christos 864: ring->desc = p;
1.1 ober 865:
866: error = iwn_dma_contig_alloc(sc->sc_dmat, &ring->cmd_dma,
1.14 christos 867: &p, count * sizeof (struct iwn_tx_cmd), 4, BUS_DMA_NOWAIT);
1.1 ober 868: if (error != 0) {
869: aprint_error_dev(sc->sc_dev, "could not allocate tx cmd DMA memory\n");
870: goto fail;
871: }
1.14 christos 872: ring->cmd = p;
1.1 ober 873:
874: ring->data = malloc(count * sizeof (struct iwn_tx_data), M_DEVBUF, M_NOWAIT);
1.8 blymn 875:
1.1 ober 876: if (ring->data == NULL) {
877: aprint_error_dev(sc->sc_dev,"could not allocate tx data slots\n");
878: goto fail;
879: }
880:
881: memset(ring->data, 0, count * sizeof (struct iwn_tx_data));
882:
883: for (i = 0; i < count; i++) {
1.2 ober 884: data = &ring->data[i];
1.1 ober 885:
886: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
887: IWN_MAX_SCATTER - 1, MCLBYTES, 0, BUS_DMA_NOWAIT,
888: &data->map);
889: if (error != 0) {
890: aprint_error_dev(sc->sc_dev, "could not create tx buf DMA map\n");
891: goto fail;
892: }
893: }
894:
895: return 0;
896:
897: fail: iwn_free_tx_ring(sc, ring);
898: return error;
899: }
900:
901: static void
902: iwn_reset_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)
903: {
1.15 christos 904: struct iwn_tx_data *data;
1.1 ober 905: uint32_t tmp;
906: int i, ntries;
907:
908: iwn_mem_lock(sc);
909:
910: IWN_WRITE(sc, IWN_TX_CONFIG(ring->qid), 0);
911: for (ntries = 0; ntries < 100; ntries++) {
912: tmp = IWN_READ(sc, IWN_TX_STATUS);
913: if ((tmp & IWN_TX_IDLE(ring->qid)) == IWN_TX_IDLE(ring->qid))
914: break;
915: DELAY(10);
916: }
917: #ifdef IWN_DEBUG
918: if (ntries == 100 && iwn_debug > 1) {
919: aprint_error_dev(sc->sc_dev, "timeout resetting Tx ring %d\n", ring->qid);
920: }
921: #endif
922: iwn_mem_unlock(sc);
923:
924: for (i = 0; i < ring->count; i++) {
925: data = &ring->data[i];
926:
927: if (data->m != NULL) {
928: bus_dmamap_unload(sc->sc_dmat, data->map);
929: m_freem(data->m);
930: data->m = NULL;
931: }
932: }
933:
934: ring->queued = 0;
935: ring->cur = 0;
936: }
937:
938: static void
939: iwn_free_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring)
940: {
1.2 ober 941: struct iwn_tx_data *data;
942: int i;
1.1 ober 943:
944: iwn_dma_contig_free(&ring->desc_dma);
945: iwn_dma_contig_free(&ring->cmd_dma);
946:
947: if (ring->data != NULL) {
948: for (i = 0; i < ring->count; i++) {
949: data = &ring->data[i];
950:
951: if (data->m != NULL) {
952: bus_dmamap_unload(sc->sc_dmat, data->map);
953: m_freem(data->m);
954: }
955: }
956: free(ring->data, M_DEVBUF);
957: }
958: }
959:
960: /*ARGUSED*/
961: struct ieee80211_node *
962: iwn_node_alloc(struct ieee80211_node_table *nt __unused)
963: {
964: struct iwn_node *wn;
965:
1.19 freza 966: wn = malloc(sizeof (struct iwn_node), M_80211_NODE, M_NOWAIT | M_ZERO);
1.1 ober 967:
968: return (struct ieee80211_node *)wn;
969: }
970:
971: static void
972: iwn_newassoc(struct ieee80211_node *ni, int isnew)
973: {
974: struct iwn_softc *sc = ni->ni_ic->ic_ifp->if_softc;
975: int i;
976:
977: ieee80211_amrr_node_init(&sc->amrr, &((struct iwn_node *)ni)->amn);
978:
979: /* set rate to some reasonable initial value */
980: for (i = ni->ni_rates.rs_nrates - 1;
981: i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
982: i--);
983: ni->ni_txrate = i;
984: }
985:
986: static int
987: iwn_media_change(struct ifnet *ifp)
988: {
989: int error;
990:
991: error = ieee80211_media_change(ifp);
992: if (error != ENETRESET)
993: return error;
994:
995: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
996: iwn_init(ifp);
997:
998: return 0;
999: }
1000:
1001: static int
1002: iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1003: {
1004: struct ifnet *ifp = ic->ic_ifp;
1005: struct iwn_softc *sc = ifp->if_softc;
1006: int error;
1007:
1008: callout_stop(&sc->calib_to);
1009:
1.11 blymn 1010: DPRINTF(("iwn_newstate: nstate = %d, ic->ic_state = %d\n", nstate,
1011: ic->ic_state));
1012:
1.1 ober 1013: switch (nstate) {
1014:
1015: case IEEE80211_S_SCAN:
1.8 blymn 1016:
1.1 ober 1017: if (sc->is_scanning)
1018: break;
1019:
1020: sc->is_scanning = true;
1021: ieee80211_node_table_reset(&ic->ic_scan);
1022: ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN;
1023:
1024: /* make the link LED blink while we're scanning */
1025: iwn_set_led(sc, IWN_LED_LINK, 20, 2);
1026:
1027: if ((error = iwn_scan(sc, IEEE80211_CHAN_G)) != 0) {
1028: aprint_error_dev(sc->sc_dev, "could not initiate scan\n");
1.8 blymn 1029: ic->ic_flags &= ~(IEEE80211_F_SCAN | IEEE80211_F_ASCAN);
1.1 ober 1030: return error;
1031: }
1032: ic->ic_state = nstate;
1033: return 0;
1034:
1035: case IEEE80211_S_ASSOC:
1036: if (ic->ic_state != IEEE80211_S_RUN)
1037: break;
1038: /* FALLTHROUGH */
1039: case IEEE80211_S_AUTH:
1.20 blymn 1040: /* cancel any active scan - it apparently breaks auth */
1.22.2.1! skrll 1041: /*(void)iwn_cmd(sc, IWN_CMD_SCAN_ABORT, NULL, 0, 1);*/
1.1 ober 1042:
1043: if ((error = iwn_auth(sc)) != 0) {
1.20 blymn 1044: aprint_error_dev(sc->sc_dev,
1045: "could not move to auth state\n");
1.1 ober 1046: return error;
1047: }
1048: break;
1049:
1050: case IEEE80211_S_RUN:
1051: if ((error = iwn_run(sc)) != 0) {
1.20 blymn 1052: aprint_error_dev(sc->sc_dev,
1053: "could not move to run state\n");
1.1 ober 1054: return error;
1055: }
1056: break;
1057:
1058: case IEEE80211_S_INIT:
1059: sc->is_scanning = false;
1060: break;
1061: }
1062:
1063: return sc->sc_newstate(ic, nstate, arg);
1064: }
1065:
1066: /*
1067: * Grab exclusive access to NIC memory.
1068: */
1069: static void
1070: iwn_mem_lock(struct iwn_softc *sc)
1071: {
1072: uint32_t tmp;
1073: int ntries;
1074:
1075: tmp = IWN_READ(sc, IWN_GPIO_CTL);
1076: IWN_WRITE(sc, IWN_GPIO_CTL, tmp | IWN_GPIO_MAC);
1077:
1078: /* spin until we actually get the lock */
1079: for (ntries = 0; ntries < 1000; ntries++) {
1080: if ((IWN_READ(sc, IWN_GPIO_CTL) &
1.2 ober 1081: (IWN_GPIO_CLOCK | IWN_GPIO_SLEEP)) == IWN_GPIO_CLOCK)
1.1 ober 1082: break;
1083: DELAY(10);
1084: }
1085: if (ntries == 1000)
1086: aprint_error_dev(sc->sc_dev, "could not lock memory\n");
1087: }
1088:
1089: /*
1090: * Release lock on NIC memory.
1091: */
1092: static void
1093: iwn_mem_unlock(struct iwn_softc *sc)
1094: {
1095: uint32_t tmp = IWN_READ(sc, IWN_GPIO_CTL);
1096: IWN_WRITE(sc, IWN_GPIO_CTL, tmp & ~IWN_GPIO_MAC);
1097: }
1098:
1099: static uint32_t
1100: iwn_mem_read(struct iwn_softc *sc, uint32_t addr)
1101: {
1102: IWN_WRITE(sc, IWN_READ_MEM_ADDR, IWN_MEM_4 | addr);
1103: return IWN_READ(sc, IWN_READ_MEM_DATA);
1104: }
1105:
1106: static void
1107: iwn_mem_write(struct iwn_softc *sc, uint32_t addr, uint32_t data)
1108: {
1109: IWN_WRITE(sc, IWN_WRITE_MEM_ADDR, IWN_MEM_4 | addr);
1110: IWN_WRITE(sc, IWN_WRITE_MEM_DATA, data);
1111: }
1112:
1113: static void
1114: iwn_mem_write_region_4(struct iwn_softc *sc, uint32_t addr,
1115: const uint32_t *data, int wlen)
1116: {
1117: for (; wlen > 0; wlen--, data++, addr += 4)
1118: iwn_mem_write(sc, addr, *data);
1119: }
1120:
1121: static int
1122: iwn_eeprom_lock(struct iwn_softc *sc)
1123: {
1124: uint32_t tmp;
1125: int ntries;
1126:
1127: tmp = IWN_READ(sc, IWN_HWCONFIG);
1128: IWN_WRITE(sc, IWN_HWCONFIG, tmp | IWN_HW_EEPROM_LOCKED);
1129:
1130: /* spin until we actually get the lock */
1131: for (ntries = 0; ntries < 100; ntries++) {
1132: if (IWN_READ(sc, IWN_HWCONFIG) & IWN_HW_EEPROM_LOCKED)
1133: return 0;
1134: DELAY(10);
1135: }
1136: return ETIMEDOUT;
1137: }
1138:
1139: static void
1140: iwn_eeprom_unlock(struct iwn_softc *sc)
1141: {
1142: uint32_t tmp = IWN_READ(sc, IWN_HWCONFIG);
1143: IWN_WRITE(sc, IWN_HWCONFIG, tmp & ~IWN_HW_EEPROM_LOCKED);
1144: }
1145:
1146: /*
1.15 christos 1147: * Read `len' bytes from the EEPROM. We access the EEPROM through the MAC
1.1 ober 1148: * instead of using the traditional bit-bang method.
1149: */
1150: static int
1151: iwn_read_prom_data(struct iwn_softc *sc, uint32_t addr, void *data, int len)
1152: {
1153: uint8_t *out = data;
1154: uint32_t val;
1155: int ntries;
1156:
1157: iwn_mem_lock(sc);
1158: for (; len > 0; len -= 2, addr++) {
1159: IWN_WRITE(sc, IWN_EEPROM_CTL, addr << 2);
1160: IWN_WRITE(sc, IWN_EEPROM_CTL,
1161: IWN_READ(sc, IWN_EEPROM_CTL) & ~IWN_EEPROM_CMD);
1162:
1163: for (ntries = 0; ntries < 10; ntries++) {
1164: if ((val = IWN_READ(sc, IWN_EEPROM_CTL)) &
1165: IWN_EEPROM_READY)
1166: break;
1167: DELAY(5);
1168: }
1169: if (ntries == 10) {
1170: aprint_error_dev(sc->sc_dev, "could not read EEPROM\n");
1171: return ETIMEDOUT;
1172: }
1173: *out++ = val >> 16;
1174: if (len > 1)
1175: *out++ = val >> 24;
1176: }
1177: iwn_mem_unlock(sc);
1178:
1179: return 0;
1180: }
1181:
1182: /*
1183: * The firmware boot code is small and is intended to be copied directly into
1184: * the NIC internal memory.
1185: */
1186: static int
1187: iwn_load_microcode(struct iwn_softc *sc, const uint8_t *ucode, int size)
1188: {
1189: int ntries;
1190:
1191: size /= sizeof (uint32_t);
1192:
1193: iwn_mem_lock(sc);
1194:
1195: /* copy microcode image into NIC memory */
1196: iwn_mem_write_region_4(sc, IWN_MEM_UCODE_BASE,
1197: (const uint32_t *)ucode, size);
1198:
1199: iwn_mem_write(sc, IWN_MEM_UCODE_SRC, 0);
1200: iwn_mem_write(sc, IWN_MEM_UCODE_DST, IWN_FW_TEXT);
1201: iwn_mem_write(sc, IWN_MEM_UCODE_SIZE, size);
1202:
1203: /* run microcode */
1204: iwn_mem_write(sc, IWN_MEM_UCODE_CTL, IWN_UC_RUN);
1205:
1206: /* wait for transfer to complete */
1207: for (ntries = 0; ntries < 1000; ntries++) {
1208: if (!(iwn_mem_read(sc, IWN_MEM_UCODE_CTL) & IWN_UC_RUN))
1209: break;
1210: DELAY(10);
1211: }
1212: if (ntries == 1000) {
1213: iwn_mem_unlock(sc);
1214: aprint_error_dev(sc->sc_dev, "could not load boot firmware\n");
1215: return ETIMEDOUT;
1216: }
1217: iwn_mem_write(sc, IWN_MEM_UCODE_CTL, IWN_UC_ENABLE);
1218:
1219: iwn_mem_unlock(sc);
1220:
1221: return 0;
1222: }
1223:
1224: static int
1225: iwn_load_firmware(struct iwn_softc *sc)
1226: {
1227: struct iwn_dma_info *dma = &sc->fw_dma;
1228: struct iwn_firmware_hdr hdr;
1229: const uint8_t *init_text, *init_data, *main_text, *main_data;
1230: const uint8_t *boot_text;
1231: uint32_t init_textsz, init_datasz, main_textsz, main_datasz;
1232: uint32_t boot_textsz;
1233: firmware_handle_t fw;
1234: u_char *dfw;
1235: size_t size;
1236: int error;
1237:
1238: /* load firmware image from disk */
1.22.2.1! skrll 1239: if ((error = firmware_open("if_iwn","iwlwifi-4965-1.ucode", &fw)) != 0) {
1.1 ober 1240: aprint_error_dev(sc->sc_dev, "could not read firmware file\n");
1241: goto fail1;
1242: }
1.8 blymn 1243:
1.1 ober 1244: size = firmware_get_size(fw);
1245:
1246: /* extract firmware header information */
1247: if (size < sizeof (struct iwn_firmware_hdr)) {
1248: aprint_error_dev(sc->sc_dev, "truncated firmware header: %zu bytes\n", size);
1.8 blymn 1249:
1.1 ober 1250: error = EINVAL;
1251: goto fail2;
1252: }
1253:
1254:
1255: if ((error = firmware_read(fw, 0, &hdr,
1.2 ober 1256: sizeof (struct iwn_firmware_hdr))) != 0) {
1.1 ober 1257: aprint_error_dev(sc->sc_dev, "can't get firmware header\n");
1258: goto fail2;
1259: }
1260:
1261: main_textsz = le32toh(hdr.main_textsz);
1262: main_datasz = le32toh(hdr.main_datasz);
1263: init_textsz = le32toh(hdr.init_textsz);
1264: init_datasz = le32toh(hdr.init_datasz);
1265: boot_textsz = le32toh(hdr.boot_textsz);
1266:
1267: /* sanity-check firmware segments sizes */
1268: if (main_textsz > IWN_FW_MAIN_TEXT_MAXSZ ||
1269: main_datasz > IWN_FW_MAIN_DATA_MAXSZ ||
1270: init_textsz > IWN_FW_INIT_TEXT_MAXSZ ||
1271: init_datasz > IWN_FW_INIT_DATA_MAXSZ ||
1272: boot_textsz > IWN_FW_BOOT_TEXT_MAXSZ ||
1273: (boot_textsz & 3) != 0) {
1274: aprint_error_dev(sc->sc_dev, "invalid firmware header\n");
1275: error = EINVAL;
1276: goto fail2;
1277: }
1278:
1279: /* check that all firmware segments are present */
1280: if (size < sizeof (struct iwn_firmware_hdr) + main_textsz +
1281: main_datasz + init_textsz + init_datasz + boot_textsz) {
1282: aprint_error_dev(sc->sc_dev, "firmware file too short: %zu bytes\n", size);
1283: error = EINVAL;
1284: goto fail2;
1285: }
1286:
1287: dfw = firmware_malloc(size);
1288: if (dfw == NULL) {
1289: aprint_error_dev(sc->sc_dev, "not enough memory to stock firmware\n");
1290: error = ENOMEM;
1291: goto fail2;
1292: }
1293:
1294: if ((error = firmware_read(fw, 0, dfw, size)) != 0) {
1295: aprint_error_dev(sc->sc_dev, "can't get firmware\n");
1296: goto fail2;
1297: }
1298:
1299: /* get pointers to firmware segments */
1300: main_text = dfw + sizeof (struct iwn_firmware_hdr);
1301: main_data = main_text + main_textsz;
1302: init_text = main_data + main_datasz;
1303: init_data = init_text + init_textsz;
1304: boot_text = init_data + init_datasz;
1305:
1306: /* copy initialization images into pre-allocated DMA-safe memory */
1307: memcpy(dma->vaddr, init_data, init_datasz);
1308: memcpy((char *)dma->vaddr + IWN_FW_INIT_DATA_MAXSZ, init_text, init_textsz);
1309:
1310: /* tell adapter where to find initialization images */
1311: iwn_mem_lock(sc);
1312: iwn_mem_write(sc, IWN_MEM_DATA_BASE, dma->paddr >> 4);
1313: iwn_mem_write(sc, IWN_MEM_DATA_SIZE, init_datasz);
1314: iwn_mem_write(sc, IWN_MEM_TEXT_BASE,
1315: (dma->paddr + IWN_FW_INIT_DATA_MAXSZ) >> 4);
1316: iwn_mem_write(sc, IWN_MEM_TEXT_SIZE, init_textsz);
1317: iwn_mem_unlock(sc);
1318:
1319: /* load firmware boot code */
1320: if ((error = iwn_load_microcode(sc, boot_text, boot_textsz)) != 0) {
1321: aprint_error_dev(sc->sc_dev, "could not load boot firmware\n");
1322: goto fail3;
1323: }
1324:
1325: /* now press "execute" ;-) */
1326: IWN_WRITE(sc, IWN_RESET, 0);
1327:
1.8 blymn 1328: /* ..and wait at most one second for adapter to initialize */
1.1 ober 1329: if ((error = tsleep(sc, PCATCH, "iwninit", hz)) != 0) {
1330: /* this isn't what was supposed to happen.. */
1331: aprint_error_dev(sc->sc_dev, "timeout waiting for adapter to initialize\n");
1332: }
1333:
1334: /* copy runtime images into pre-allocated DMA-safe memory */
1335: memcpy((char *)dma->vaddr, main_data, main_datasz);
1336: memcpy((char *)dma->vaddr + IWN_FW_MAIN_DATA_MAXSZ, main_text, main_textsz);
1337:
1338: /* tell adapter where to find runtime images */
1339: iwn_mem_lock(sc);
1340: iwn_mem_write(sc, IWN_MEM_DATA_BASE, dma->paddr >> 4);
1341: iwn_mem_write(sc, IWN_MEM_DATA_SIZE, main_datasz);
1342: iwn_mem_write(sc, IWN_MEM_TEXT_BASE,
1343: (dma->paddr + IWN_FW_MAIN_DATA_MAXSZ) >> 4);
1344: iwn_mem_write(sc, IWN_MEM_TEXT_SIZE, IWN_FW_UPDATED | main_textsz);
1345: iwn_mem_unlock(sc);
1346:
1347: /* wait at most one second for second alive notification */
1348: if ((error = tsleep(sc, PCATCH, "iwninit", hz)) != 0) {
1349: /* this isn't what was supposed to happen.. */
1350: aprint_error_dev(sc->sc_dev, "timeout waiting for adapter to initialize\n");
1351: }
1352:
1353: fail3: firmware_free(dfw,size);
1354: fail2: firmware_close(fw);
1355: fail1: return error;
1356: }
1357:
1358: static void
1359: iwn_calib_timeout(void *arg)
1360: {
1361: struct iwn_softc *sc = arg;
1362: struct ieee80211com *ic = &sc->sc_ic;
1363: int s;
1364:
1365: /* automatic rate control triggered every 500ms */
1366: if (ic->ic_fixed_rate == -1) {
1367: s = splnet();
1368: if (ic->ic_opmode == IEEE80211_M_STA)
1369: iwn_iter_func(sc, ic->ic_bss);
1370: else
1371: ieee80211_iterate_nodes(&ic->ic_sta, iwn_iter_func, sc);
1372: splx(s);
1373: }
1374:
1375: /* automatic calibration every 60s */
1376: if (++sc->calib_cnt >= 120) {
1377: DPRINTF(("sending request for statistics\n"));
1378: (void)iwn_cmd(sc, IWN_CMD_GET_STATISTICS, NULL, 0, 1);
1379: sc->calib_cnt = 0;
1380: }
1381:
1382: callout_schedule(&sc->calib_to, hz/2);
1383:
1384: }
1385:
1386: static void
1387: iwn_iter_func(void *arg, struct ieee80211_node *ni)
1388: {
1389: struct iwn_softc *sc = arg;
1390: struct iwn_node *wn = (struct iwn_node *)ni;
1391:
1392: ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
1393: }
1394:
1395: static void
1396: iwn_ampdu_rx_start(struct iwn_softc *sc, struct iwn_rx_desc *desc)
1397: {
1398: struct iwn_rx_stat *stat;
1399:
1400: DPRINTFN(2, ("received AMPDU stats\n"));
1401: /* save Rx statistics, they will be used on IWN_AMPDU_RX_DONE */
1402: stat = (struct iwn_rx_stat *)(desc + 1);
1403: memcpy(&sc->last_rx_stat, stat, sizeof (*stat));
1404: sc->last_rx_valid = 1;
1405: }
1406:
1407: void
1408: iwn_rx_intr(struct iwn_softc *sc, struct iwn_rx_desc *desc,
1409: struct iwn_rx_data *data)
1410: {
1411: struct ieee80211com *ic = &sc->sc_ic;
1412: struct ifnet *ifp = ic->ic_ifp;
1413: struct iwn_rx_ring *ring = &sc->rxq;
1414: struct iwn_rbuf *rbuf;
1415: struct ieee80211_frame *wh;
1416: struct ieee80211_node *ni;
1417: struct mbuf *m, *mnew;
1418: struct iwn_rx_stat *stat;
1419: char *head;
1420: uint32_t *tail;
1421: int len, rssi;
1422:
1423: if (desc->type == IWN_AMPDU_RX_DONE) {
1424: /* check for prior AMPDU_RX_START */
1425: if (!sc->last_rx_valid) {
1426: DPRINTF(("missing AMPDU_RX_START\n"));
1427: ifp->if_ierrors++;
1428: return;
1429: }
1430: sc->last_rx_valid = 0;
1431: stat = &sc->last_rx_stat;
1432: } else
1433: stat = (struct iwn_rx_stat *)(desc + 1);
1434:
1435: if (stat->cfg_phy_len > IWN_STAT_MAXLEN) {
1436: aprint_error_dev(sc->sc_dev, "invalid rx statistic header\n");
1437: ifp->if_ierrors++;
1438: return;
1439: }
1440:
1441: if (desc->type == IWN_AMPDU_RX_DONE) {
1442: struct iwn_rx_ampdu *ampdu =
1443: (struct iwn_rx_ampdu *)(desc + 1);
1444: head = (char *)(ampdu + 1);
1445: len = le16toh(ampdu->len);
1446: } else {
1447: head = (char *)(stat + 1) + stat->cfg_phy_len;
1448: len = le16toh(stat->len);
1449: }
1450:
1.11 blymn 1451: DPRINTF(("rx packet len %d\n", len));
1.1 ober 1452: /* discard Rx frames with bad CRC early */
1453: tail = (uint32_t *)(head + len);
1454: if ((le32toh(*tail) & IWN_RX_NOERROR) != IWN_RX_NOERROR) {
1455: DPRINTFN(2, ("rx flags error %x\n", le32toh(*tail)));
1456: ifp->if_ierrors++;
1457: return;
1458: }
1459: /* XXX for ieee80211_find_rxnode() */
1460: if (len < sizeof (struct ieee80211_frame)) {
1461: DPRINTF(("frame too short: %d\n", len));
1462: ic->ic_stats.is_rx_tooshort++;
1463: ifp->if_ierrors++;
1464: return;
1465: }
1466:
1467: m = data->m;
1468:
1469: /* finalize mbuf */
1470: m->m_pkthdr.rcvif = ifp;
1471: m->m_data = head;
1472: m->m_pkthdr.len = m->m_len = len;
1473:
1.17 cube 1474: /*
1475: * See comment in if_wpi.c:wpi_rx_intr() about locking
1476: * nb_free_entries here. In short: it's not required.
1477: */
1.18 freza 1478: if (sc->rxq.nb_free_entries > 0) {
1.1 ober 1479: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
1480: if (mnew == NULL) {
1481: ic->ic_stats.is_rx_nobuf++;
1482: ifp->if_ierrors++;
1483: return;
1484: }
1485:
1.17 cube 1486: rbuf = iwn_alloc_rbuf(sc);
1487:
1.1 ober 1488: /* attach Rx buffer to mbuf */
1489: MEXTADD(mnew, rbuf->vaddr, IWN_RBUF_SIZE, 0, iwn_free_rbuf,
1490: rbuf);
1491: mnew->m_flags |= M_EXT_RW;
1492:
1493: data->m = mnew;
1494:
1495: /* update Rx descriptor */
1496: ring->desc[ring->cur] = htole32(rbuf->paddr >> 8);
1497: } else {
1498: /* no free rbufs, copy frame */
1499: m = m_dup(m, 0, M_COPYALL, M_DONTWAIT);
1500: if (m == NULL) {
1501: /* no free mbufs either, drop frame */
1502: ic->ic_stats.is_rx_nobuf++;
1503: ifp->if_ierrors++;
1504: return;
1505: }
1506: }
1507:
1508: rssi = iwn_get_rssi(stat);
1509:
1.22 rtr 1510: if (ic->ic_state == IEEE80211_S_SCAN)
1.1 ober 1511: iwn_fix_channel(ic, m);
1512:
1513: #if NBPFILTER > 0
1514: if (sc->sc_drvbpf != NULL) {
1.2 ober 1515: struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;
1.1 ober 1516:
1517: tap->wr_flags = 0;
1518: tap->wr_chan_freq =
1519: htole16(ic->ic_channels[stat->chan].ic_freq);
1520: tap->wr_chan_flags =
1521: htole16(ic->ic_channels[stat->chan].ic_flags);
1522: tap->wr_dbm_antsignal = (int8_t)rssi;
1523: tap->wr_dbm_antnoise = (int8_t)sc->noise;
1524: tap->wr_tsft = stat->tstamp;
1525: switch (stat->rate) {
1.2 ober 1526: /* CCK rates */
1.1 ober 1527: case 10: tap->wr_rate = 2; break;
1528: case 20: tap->wr_rate = 4; break;
1529: case 55: tap->wr_rate = 11; break;
1530: case 110: tap->wr_rate = 22; break;
1.2 ober 1531: /* OFDM rates */
1.1 ober 1532: case 0xd: tap->wr_rate = 12; break;
1533: case 0xf: tap->wr_rate = 18; break;
1534: case 0x5: tap->wr_rate = 24; break;
1535: case 0x7: tap->wr_rate = 36; break;
1536: case 0x9: tap->wr_rate = 48; break;
1537: case 0xb: tap->wr_rate = 72; break;
1538: case 0x1: tap->wr_rate = 96; break;
1539: case 0x3: tap->wr_rate = 108; break;
1.2 ober 1540: /* unknown rate: should not happen */
1.1 ober 1541: default: tap->wr_rate = 0;
1542: }
1543:
1544: bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
1545: }
1546: #endif
1547:
1548: /* grab a reference to the source node */
1549: wh = mtod(m, struct ieee80211_frame *);
1550: ni = ieee80211_find_rxnode(ic,(struct ieee80211_frame_min *)wh);
1551:
1552: /* send the frame to the 802.11 layer */
1553: ieee80211_input(ic, m, ni, rssi, 0);
1554:
1555: /* node is no longer needed */
1556: ieee80211_free_node(ni);
1557: }
1558:
1559:
1560: /*
1561: * XXX: Hack to set the current channel to the value advertised in beacons or
1562: * probe responses. Only used during AP detection.
1563: * XXX: Duplicated from if_iwi.c
1564: */
1565: static void
1566: iwn_fix_channel(struct ieee80211com *ic, struct mbuf *m)
1567: {
1568: struct ieee80211_frame *wh;
1569: uint8_t subtype;
1570: uint8_t *frm, *efrm;
1571:
1572: wh = mtod(m, struct ieee80211_frame *);
1573:
1574: if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
1575: return;
1576:
1577: subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1578:
1579: if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
1580: subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
1581: return;
1582:
1583: frm = (uint8_t *)(wh + 1);
1584: efrm = mtod(m, uint8_t *) + m->m_len;
1585:
1586: frm += 12; /* skip tstamp, bintval and capinfo fields */
1587: while (frm < efrm) {
1588: if (*frm == IEEE80211_ELEMID_DSPARMS)
1589: #if IEEE80211_CHAN_MAX < 255
1.2 ober 1590: if (frm[2] <= IEEE80211_CHAN_MAX)
1.1 ober 1591: #endif
1.2 ober 1592: ic->ic_curchan = &ic->ic_channels[frm[2]];
1.1 ober 1593:
1594: frm += frm[1] + 2;
1595: }
1596: }
1597:
1598: static void
1599: iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc)
1600: {
1601: struct ieee80211com *ic = &sc->sc_ic;
1602: struct iwn_calib_state *calib = &sc->calib;
1603: struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
1604:
1605: /* ignore beacon statistics received during a scan */
1606: if (ic->ic_state != IEEE80211_S_RUN)
1607: return;
1608:
1609: DPRINTFN(3, ("received statistics (cmd=%d)\n", desc->type));
1610: sc->calib_cnt = 0; /* reset timeout */
1611:
1612: /* test if temperature has changed */
1613: if (stats->general.temp != sc->rawtemp) {
1614: int temp;
1615:
1616: sc->rawtemp = stats->general.temp;
1617: temp = iwn_get_temperature(sc);
1618: DPRINTFN(2, ("temperature=%d\n", temp));
1619:
1620: /* update Tx power if need be */
1621: iwn_power_calibration(sc, temp);
1622: }
1623:
1624: if (desc->type != IWN_BEACON_STATISTICS)
1.15 christos 1625: return; /* reply to a statistics request */
1.1 ober 1626:
1627: sc->noise = iwn_get_noise(&stats->rx.general);
1628: DPRINTFN(3, ("noise=%d\n", sc->noise));
1629:
1630: /* test that RSSI and noise are present in stats report */
1631: if (le32toh(stats->rx.general.flags) != 1) {
1632: DPRINTF(("received statistics without RSSI\n"));
1633: return;
1634: }
1635:
1636: if (calib->state == IWN_CALIB_STATE_ASSOC)
1637: iwn_compute_differential_gain(sc, &stats->rx.general);
1638: else if (calib->state == IWN_CALIB_STATE_RUN)
1639: iwn_tune_sensitivity(sc, &stats->rx);
1640: }
1641:
1642: static void
1643: iwn_tx_intr(struct iwn_softc *sc, struct iwn_rx_desc *desc)
1644: {
1645: struct ifnet *ifp = sc->sc_ic.ic_ifp;
1646: struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
1647: struct iwn_tx_data *txdata = &ring->data[desc->idx];
1648: struct iwn_tx_stat *stat = (struct iwn_tx_stat *)(desc + 1);
1649: struct iwn_node *wn = (struct iwn_node *)txdata->ni;
1650: uint32_t status;
1651:
1652: DPRINTFN(4, ("tx done: qid=%d idx=%d retries=%d nkill=%d rate=%x "
1.2 ober 1653: "duration=%d status=%x\n", desc->qid, desc->idx, stat->ntries,
1654: stat->nkill, stat->rate, le16toh(stat->duration),
1655: le32toh(stat->status)));
1.1 ober 1656:
1657: /*
1658: * Update rate control statistics for the node.
1659: */
1660: wn->amn.amn_txcnt++;
1661: if (stat->ntries > 0) {
1662: DPRINTFN(3, ("tx intr ntries %d\n", stat->ntries));
1663: wn->amn.amn_retrycnt++;
1664: }
1665:
1666: status = le32toh(stat->status) & 0xff;
1667: if (status != 1 && status != 2)
1668: ifp->if_oerrors++;
1669: else
1670: ifp->if_opackets++;
1671:
1672: bus_dmamap_unload(sc->sc_dmat, txdata->map);
1673: m_freem(txdata->m);
1674: txdata->m = NULL;
1675: ieee80211_free_node(txdata->ni);
1676: txdata->ni = NULL;
1677:
1678: ring->queued--;
1679:
1680: sc->sc_tx_timer = 0;
1681: ifp->if_flags &= ~IFF_OACTIVE;
1682: iwn_start(ifp);
1683: }
1684:
1685: static void
1686: iwn_cmd_intr(struct iwn_softc *sc, struct iwn_rx_desc *desc)
1687: {
1688: struct iwn_tx_ring *ring = &sc->txq[4];
1689: struct iwn_tx_data *data;
1690:
1691: if ((desc->qid & 0xf) != 4)
1.15 christos 1692: return; /* not a command ack */
1.1 ober 1693:
1694: data = &ring->data[desc->idx];
1695:
1696: /* if the command was mapped in a mbuf, free it */
1697: if (data->m != NULL) {
1698: bus_dmamap_unload(sc->sc_dmat, data->map);
1699: m_freem(data->m);
1700: data->m = NULL;
1701: }
1702:
1703: wakeup(&ring->cmd[desc->idx]);
1704: }
1705:
1706: static void
1.22.2.1! skrll 1707: iwn_microcode_ready(struct iwn_softc *sc, struct iwn_ucode_info *uc)
! 1708: {
! 1709:
! 1710: /* the microcontroller is ready */
! 1711: DPRINTF(("microcode alive notification version=%d.%d "
! 1712: "subtype=%x alive=%x\n", uc->major, uc->minor,
! 1713: uc->subtype, le32toh(uc->valid)));
! 1714:
! 1715: if (le32toh(uc->valid) != 1) {
! 1716: aprint_error_dev(sc->sc_dev, "microcontroller initialization "
! 1717: "failed\n");
! 1718: return;
! 1719: }
! 1720: if (uc->subtype == IWN_UCODE_INIT) {
! 1721: /* save microcontroller's report */
! 1722: memcpy(&sc->ucode_info, uc, sizeof (*uc));
! 1723: }
! 1724: }
! 1725:
! 1726:
! 1727: static void
1.1 ober 1728: iwn_notif_intr(struct iwn_softc *sc)
1729: {
1730: struct ieee80211com *ic = &sc->sc_ic;
1731: struct ifnet *ifp = ic->ic_ifp;
1.22.2.1! skrll 1732: struct iwn_rx_data *data;
! 1733: struct iwn_rx_desc *desc;
1.1 ober 1734: uint16_t hw;
1735:
1736: hw = le16toh(sc->shared->closed_count);
1.22.2.1! skrll 1737:
! 1738: /*
! 1739: * If the radio is disabled then down the interface and stop
! 1740: * processing - scan the queue for a microcode load command
! 1741: * result. It is the only thing that we can do with the radio
! 1742: * off.
! 1743: */
! 1744: if (!sc->sc_radio) {
! 1745: while (sc->rxq.cur != hw) {
! 1746: data = &sc->rxq.data[sc->rxq.cur];
! 1747: desc = (void *)data->m->m_ext.ext_buf;
! 1748: if (desc->type == IWN_UC_READY) {
! 1749: iwn_microcode_ready(sc,
! 1750: (struct iwn_ucode_info *)(desc + 1));
! 1751: } else if (desc->type == IWN_STATE_CHANGED) {
! 1752: uint32_t *status = (uint32_t *)(desc + 1);
! 1753:
! 1754: /* enabled/disabled notification */
! 1755: DPRINTF(("state changed to %x\n",
! 1756: le32toh(*status)));
! 1757:
! 1758: sc->sc_radio = !(le32toh(*status) & 1);
! 1759: }
! 1760:
! 1761: sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT;
! 1762: }
! 1763:
! 1764: if (!sc->sc_radio) {
! 1765: ifp->if_flags &= ~IFF_UP;
! 1766: iwn_stop(ifp, 1);
! 1767: }
! 1768:
! 1769: return;
! 1770: }
! 1771:
1.1 ober 1772: while (sc->rxq.cur != hw) {
1.22.2.1! skrll 1773: data = &sc->rxq.data[sc->rxq.cur];
! 1774: desc = (void *)data->m->m_ext.ext_buf;
1.1 ober 1775:
1776: DPRINTFN(4,("rx notification qid=%x idx=%d flags=%x type=%d "
1.2 ober 1777: "len=%d\n", desc->qid, desc->idx, desc->flags, desc->type,
1778: le32toh(desc->len)));
1.1 ober 1779:
1780: if (!(desc->qid & 0x80)) /* reply to a command */
1781: iwn_cmd_intr(sc, desc);
1782:
1783: switch (desc->type) {
1784: case IWN_RX_DONE:
1785: case IWN_AMPDU_RX_DONE:
1786: iwn_rx_intr(sc, desc, data);
1787: break;
1788:
1789: case IWN_AMPDU_RX_START:
1790: iwn_ampdu_rx_start(sc, desc);
1791: break;
1792:
1793: case IWN_TX_DONE:
1794: /* a 802.11 frame has been transmitted */
1795: iwn_tx_intr(sc, desc);
1796: break;
1797:
1798: case IWN_RX_STATISTICS:
1799: case IWN_BEACON_STATISTICS:
1800: iwn_rx_statistics(sc, desc);
1801: break;
1802:
1803: case IWN_BEACON_MISSED:
1804: {
1805: struct iwn_beacon_missed *miss =
1806: (struct iwn_beacon_missed *)(desc + 1);
1807: /*
1808: * If more than 5 consecutive beacons are missed,
1809: * reinitialize the sensitivity state machine.
1810: */
1811: DPRINTFN(2, ("beacons missed %d/%d\n",
1.2 ober 1812: le32toh(miss->consecutive), le32toh(miss->total)));
1.1 ober 1813: if (ic->ic_state == IEEE80211_S_RUN &&
1814: le32toh(miss->consecutive) > 5)
1815: (void)iwn_init_sensitivity(sc);
1816: break;
1817: }
1818:
1819: case IWN_UC_READY:
1820: {
1.22.2.1! skrll 1821: iwn_microcode_ready(sc,
! 1822: (struct iwn_ucode_info *)(desc + 1));
1.1 ober 1823: break;
1824: }
1825: case IWN_STATE_CHANGED:
1826: {
1827: uint32_t *status = (uint32_t *)(desc + 1);
1828:
1829: /* enabled/disabled notification */
1830: DPRINTF(("state changed to %x\n", le32toh(*status)));
1831:
1.22.2.1! skrll 1832: sc->sc_radio = !(le32toh(*status) & 1);
1.1 ober 1833: if (le32toh(*status) & 1) {
1834: /* the radio button has to be pushed */
1835: aprint_error_dev(sc->sc_dev, "Radio transmitter is off\n");
1836: /* turn the interface down */
1837: ifp->if_flags &= ~IFF_UP;
1838: iwn_stop(ifp, 1);
1.15 christos 1839: return; /* no further processing */
1.1 ober 1840: }
1841: break;
1842: }
1843: case IWN_START_SCAN:
1844: {
1845: struct iwn_start_scan *scan =
1846: (struct iwn_start_scan *)(desc + 1);
1847:
1848: DPRINTFN(2, ("scanning channel %d status %x\n",
1.2 ober 1849: scan->chan, le32toh(scan->status)));
1.1 ober 1850:
1851: /* fix current channel */
1852: ic->ic_bss->ni_chan = &ic->ic_channels[scan->chan];
1853: break;
1854: }
1855: case IWN_STOP_SCAN:
1856: {
1857: struct iwn_stop_scan *scan =
1858: (struct iwn_stop_scan *)(desc + 1);
1859:
1860: DPRINTF(("scan finished nchan=%d status=%d chan=%d\n",
1.2 ober 1861: scan->nchan, scan->status, scan->chan));
1.1 ober 1862:
1863: if (scan->status == 1 && scan->chan <= 14) {
1864: /*
1865: * We just finished scanning 802.11g channels,
1866: * start scanning 802.11a ones.
1867: */
1868: if (iwn_scan(sc, IEEE80211_CHAN_A) == 0)
1869: break;
1870: }
1871: sc->is_scanning = false;
1872: ieee80211_end_scan(ic);
1873: break;
1874: }
1875: }
1876:
1877: sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT;
1878: }
1879:
1880: /* tell the firmware what we have processed */
1881: hw = (hw == 0) ? IWN_RX_RING_COUNT - 1 : hw - 1;
1882: IWN_WRITE(sc, IWN_RX_WIDX, hw & ~7);
1883: }
1884:
1885: static int
1886: iwn_intr(void *arg)
1887: {
1888: struct iwn_softc *sc = arg;
1889: struct ifnet *ifp = sc->sc_ic.ic_ifp;
1890: uint32_t r1, r2;
1891:
1892: /* disable interrupts */
1893: IWN_WRITE(sc, IWN_MASK, 0);
1894:
1895: r1 = IWN_READ(sc, IWN_INTR);
1896: r2 = IWN_READ(sc, IWN_INTR_STATUS);
1897:
1898: if (r1 == 0 && r2 == 0) {
1899: if (ifp->if_flags & IFF_UP)
1900: IWN_WRITE(sc, IWN_MASK, IWN_INTR_MASK);
1901: return 0; /* not for us */
1902: }
1903:
1904: if (r1 == 0xffffffff)
1905: return 0; /* hardware gone */
1906:
1907: /* ack interrupts */
1908: IWN_WRITE(sc, IWN_INTR, r1);
1909: IWN_WRITE(sc, IWN_INTR_STATUS, r2);
1910:
1911: DPRINTFN(5, ("interrupt reg1=%x reg2=%x\n", r1, r2));
1912:
1913: if (r1 & IWN_RF_TOGGLED) {
1914: uint32_t tmp = IWN_READ(sc, IWN_GPIO_CTL);
1.8 blymn 1915: aprint_error_dev(sc->sc_dev, "RF switch: radio %s\n",
1.1 ober 1916: (tmp & IWN_GPIO_RF_ENABLED) ? "enabled" : "disabled");
1.22.2.1! skrll 1917: sc->sc_radio = (tmp & IWN_GPIO_RF_ENABLED);
1.1 ober 1918: }
1919: if (r1 & IWN_CT_REACHED) {
1920: aprint_error_dev(sc->sc_dev, "critical temperature reached!\n");
1921: }
1922: if (r1 & (IWN_SW_ERROR | IWN_HW_ERROR)) {
1923: aprint_error_dev(sc->sc_dev, "fatal firmware error\n");
1924: sc->sc_ic.ic_ifp->if_flags &= ~IFF_UP;
1925: iwn_stop(sc->sc_ic.ic_ifp, 1);
1926: return 1;
1927: }
1928:
1929: if ((r1 & (IWN_RX_INTR | IWN_SW_RX_INTR)) ||
1930: (r2 & IWN_RX_STATUS_INTR))
1931: iwn_notif_intr(sc);
1932:
1933: if (r1 & IWN_ALIVE_INTR)
1934: wakeup(sc);
1935:
1936: /* re-enable interrupts */
1937: if (ifp->if_flags & IFF_UP)
1938: IWN_WRITE(sc, IWN_MASK, IWN_INTR_MASK);
1939:
1940: return 1;
1941: }
1942:
1943: static uint8_t
1944: iwn_plcp_signal(int rate)
1945: {
1946: switch (rate) {
1.2 ober 1947: /* CCK rates (returned values are device-dependent) */
1.1 ober 1948: case 2: return 10;
1949: case 4: return 20;
1950: case 11: return 55;
1951: case 22: return 110;
1952:
1.2 ober 1953: /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
1954: /* R1-R4, (u)ral is R4-R1 */
1.1 ober 1955: case 12: return 0xd;
1956: case 18: return 0xf;
1957: case 24: return 0x5;
1958: case 36: return 0x7;
1959: case 48: return 0x9;
1960: case 72: return 0xb;
1961: case 96: return 0x1;
1962: case 108: return 0x3;
1963: case 120: return 0x3;
1964: }
1965: /* unknown rate (should not get there) */
1966: return 0;
1967: }
1968:
1969: /* determine if a given rate is CCK or OFDM */
1970: #define IWN_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
1971:
1972: static int
1973: iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
1974: int ac)
1975: {
1976: struct ieee80211com *ic = &sc->sc_ic;
1977: struct iwn_tx_ring *ring = &sc->txq[ac];
1978: struct iwn_tx_desc *desc;
1979: struct iwn_tx_data *data;
1980: struct iwn_tx_cmd *cmd;
1981: struct iwn_cmd_data *tx;
1982: struct ieee80211_frame *wh;
1983: struct ieee80211_key *k;
1984: const struct chanAccParams *cap;
1985: struct mbuf *mnew;
1986: bus_addr_t paddr;
1987: uint32_t flags;
1988: uint8_t type;
1989: int i, error, pad, rate, hdrlen, noack = 0;
1990:
1.11 blymn 1991: DPRINTFN(5, ("iwn_tx_data entry\n"));
1992:
1.1 ober 1993: desc = &ring->desc[ring->cur];
1994: data = &ring->data[ring->cur];
1995:
1996: wh = mtod(m0, struct ieee80211_frame *);
1997: type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1998:
1999: if (IEEE80211_QOS_HAS_SEQ(wh)) {
2000: hdrlen = sizeof (struct ieee80211_qosframe);
2001: cap = &ic->ic_wme.wme_chanParams;
2002: noack = cap->cap_wmeParams[ac].wmep_noackPolicy;
2003: } else
2004: hdrlen = sizeof (struct ieee80211_frame);
2005:
2006: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2007: k = ieee80211_crypto_encap(ic, ni, m0);
2008: if (k == NULL) {
2009: m_freem(m0);
2010: return ENOBUFS;
2011: }
2012: /* packet header may have moved, reset our local pointer */
2013: wh = mtod(m0, struct ieee80211_frame *);
2014: }
2015:
2016: /* pickup a rate */
1.11 blymn 2017: if (type == IEEE80211_FC0_TYPE_MGT) {
1.1 ober 2018: /* mgmt frames are sent at the lowest available bit-rate */
2019: rate = ni->ni_rates.rs_rates[0];
2020: } else {
1.2 ober 2021: if (ic->ic_fixed_rate != -1) {
2022: rate = ic->ic_sup_rates[ic->ic_curmode].
2023: rs_rates[ic->ic_fixed_rate];
2024: } else
2025: rate = ni->ni_rates.rs_rates[ni->ni_txrate];
1.1 ober 2026: }
2027: rate &= IEEE80211_RATE_VAL;
2028:
2029: #if NBPFILTER > 0
2030: if (sc->sc_drvbpf != NULL) {
2031: struct iwn_tx_radiotap_header *tap = &sc->sc_txtap;
2032:
2033: tap->wt_flags = 0;
2034: tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
2035: tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
2036: tap->wt_rate = rate;
2037: tap->wt_hwqueue = ac;
2038: if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2039: tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2040:
2041: bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
2042: }
2043: #endif
2044:
2045: cmd = &ring->cmd[ring->cur];
2046: cmd->code = IWN_CMD_TX_DATA;
2047: cmd->flags = 0;
2048: cmd->qid = ring->qid;
2049: cmd->idx = ring->cur;
1.8 blymn 2050:
1.1 ober 2051: tx = (struct iwn_cmd_data *)cmd->data;
1.8 blymn 2052:
1.1 ober 2053: flags = IWN_TX_AUTO_SEQ;
2054: if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)){
2055: flags |= IWN_TX_NEED_ACK;
2056: }else if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold)
1.9 blymn 2057: flags |= (IWN_TX_NEED_RTS | IWN_TX_FULL_TXOP);
1.8 blymn 2058:
1.20 blymn 2059: if (IEEE80211_IS_MULTICAST(wh->i_addr1)
2060: || (type != IEEE80211_FC0_TYPE_DATA))
2061: tx->id = IWN_ID_BROADCAST;
2062: else
2063: tx->id = IWN_ID_BSS;
1.1 ober 2064:
1.11 blymn 2065: DPRINTFN(5, ("addr1: %x:%x:%x:%x:%x:%x, id = 0x%x\n",
2066: wh->i_addr1[0], wh->i_addr1[1], wh->i_addr1[2],
2067: wh->i_addr1[3], wh->i_addr1[4], wh->i_addr1[5], tx->id));
2068:
1.1 ober 2069: if (type == IEEE80211_FC0_TYPE_MGT) {
2070: uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2071:
2072: /* tell h/w to set timestamp in probe responses */
1.11 blymn 2073: if ((subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) ||
2074: (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ))
1.1 ober 2075: flags |= IWN_TX_INSERT_TSTAMP;
2076:
2077: if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
1.20 blymn 2078: subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ ||
2079: subtype == IEEE80211_FC0_SUBTYPE_AUTH ||
2080: subtype == IEEE80211_FC0_SUBTYPE_DEAUTH) {
1.11 blymn 2081: flags &= ~IWN_TX_NEED_RTS;
2082: flags |= IWN_TX_NEED_CTS;
1.1 ober 2083: tx->timeout = htole16(3);
1.11 blymn 2084: } else
1.1 ober 2085: tx->timeout = htole16(2);
2086: } else
2087: tx->timeout = htole16(0);
1.8 blymn 2088:
1.1 ober 2089: if (hdrlen & 3) {
2090: /* first segment's length must be a multiple of 4 */
2091: flags |= IWN_TX_NEED_PADDING;
2092: pad = 4 - (hdrlen & 3);
2093: } else
2094: pad = 0;
2095:
1.11 blymn 2096: if (type == IEEE80211_FC0_TYPE_CTL) {
2097: uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2098:
2099: /* tell h/w to set timestamp in probe responses */
2100: if (subtype == 0x0080) /* linux says this is "back request" */
2101: /* linux says (1 << 6) is IMM_BA_RSP_MASK */
2102: flags |= (IWN_TX_NEED_ACK | (1 << 6));
2103: }
2104:
2105:
1.1 ober 2106: tx->flags = htole32(flags);
2107: tx->len = htole16(m0->m_pkthdr.len);
2108: tx->rate = iwn_plcp_signal(rate);
2109: tx->rts_ntries = 60;
2110: tx->data_ntries = 15;
2111: tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
2112:
2113: /* XXX alternate between Ant A and Ant B ? */
2114: tx->rflags = IWN_RFLAG_ANT_B;
2115: if (tx->id == IWN_ID_BROADCAST) {
2116: tx->ridx = IWN_MAX_TX_RETRIES - 1;
2117: if (!IWN_RATE_IS_OFDM(rate))
2118: tx->rflags |= IWN_RFLAG_CCK;
2119: } else {
2120: tx->ridx = 0;
2121: /* tell adapter to ignore rflags */
2122: tx->flags |= htole32(IWN_TX_USE_NODE_RATE);
2123: }
2124:
2125: /* copy and trim IEEE802.11 header */
1.20 blymn 2126: memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen);
1.1 ober 2127: m_adj(m0, hdrlen);
2128:
2129: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
2130: BUS_DMA_WRITE | BUS_DMA_NOWAIT);
2131: if (error != 0 && error != EFBIG) {
2132: aprint_error_dev(sc->sc_dev, "could not map mbuf (error %d)\n", error);
2133: m_freem(m0);
2134: return error;
2135: }
2136: if (error != 0) {
2137: /* too many fragments, linearize */
2138:
2139: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
2140: if (mnew == NULL) {
2141: m_freem(m0);
2142: return ENOMEM;
2143: }
2144: M_COPY_PKTHDR(mnew, m0);
2145: if (m0->m_pkthdr.len > MHLEN) {
2146: MCLGET(mnew, M_DONTWAIT);
2147: if (!(mnew->m_flags & M_EXT)) {
2148: m_freem(m0);
2149: m_freem(mnew);
2150: return ENOMEM;
2151: }
2152: }
2153:
2154: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mnew, void *));
2155: m_freem(m0);
2156: mnew->m_len = mnew->m_pkthdr.len;
2157: m0 = mnew;
2158:
2159: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
2160: BUS_DMA_WRITE | BUS_DMA_NOWAIT);
2161: if (error != 0) {
2162: aprint_error_dev(sc->sc_dev, "could not map mbuf (error %d)\n", error);
2163: m_freem(m0);
2164: return error;
2165: }
2166: }
2167:
2168: data->m = m0;
2169: data->ni = ni;
2170:
2171: DPRINTFN(4, ("sending data: qid=%d idx=%d len=%d nsegs=%d\n",
1.2 ober 2172: ring->qid, ring->cur, m0->m_pkthdr.len, data->map->dm_nsegs));
1.1 ober 2173:
2174: paddr = ring->cmd_dma.paddr + ring->cur * sizeof (struct iwn_tx_cmd);
2175: tx->loaddr = htole32(paddr + 4 +
2176: offsetof(struct iwn_cmd_data, ntries));
1.15 christos 2177: tx->hiaddr = 0; /* limit to 32-bit physical addresses */
1.1 ober 2178:
2179: /* first scatter/gather segment is used by the tx data command */
2180: IWN_SET_DESC_NSEGS(desc, 1 + data->map->dm_nsegs);
2181: IWN_SET_DESC_SEG(desc, 0, paddr, 4 + sizeof (*tx) + hdrlen + pad);
2182: for (i = 1; i <= data->map->dm_nsegs; i++) {
2183: IWN_SET_DESC_SEG(desc, i, data->map->dm_segs[i - 1].ds_addr,
1.2 ober 2184: data->map->dm_segs[i - 1].ds_len);
1.1 ober 2185: }
2186: sc->shared->len[ring->qid][ring->cur] =
2187: htole16(hdrlen + m0->m_pkthdr.len + 8);
2188: if (ring->cur < IWN_TX_WINDOW) {
2189: sc->shared->len[ring->qid][ring->cur + IWN_TX_RING_COUNT] =
2190: htole16(hdrlen + m0->m_pkthdr.len + 8);
2191: }
2192:
2193: ring->queued++;
2194:
1.20 blymn 2195: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
2196: data->map->dm_mapsize /* calc? */, BUS_DMASYNC_PREWRITE);
2197:
1.1 ober 2198: /* kick ring */
2199: ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
2200: IWN_WRITE(sc, IWN_TX_WIDX, ring->qid << 8 | ring->cur);
2201:
2202: return 0;
2203: }
2204:
2205: static void
2206: iwn_start(struct ifnet *ifp)
2207: {
2208: struct iwn_softc *sc = ifp->if_softc;
2209: struct ieee80211com *ic = &sc->sc_ic;
2210: struct ieee80211_node *ni;
2211: struct ether_header *eh;
2212: struct mbuf *m0;
2213: int ac;
2214:
1.11 blymn 2215: DPRINTFN(5, ("iwn_start enter\n"));
2216:
1.1 ober 2217: /*
2218: * net80211 may still try to send management frames even if the
1.22.2.1! skrll 2219: * IFF_RUNNING flag is not set... Also, don't bother if the radio
! 2220: * is not enabled.
1.1 ober 2221: */
1.22.2.1! skrll 2222: if (((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) ||
! 2223: !sc->sc_radio)
1.1 ober 2224: return;
2225:
2226: for (;;) {
2227: IF_DEQUEUE(&ic->ic_mgtq, m0);
2228: if (m0 != NULL) {
2229: /* management frames go into ring 0 */
1.8 blymn 2230:
1.1 ober 2231:
2232: ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
2233: m0->m_pkthdr.rcvif = NULL;
2234:
2235: /* management goes into ring 0 */
2236: if (sc->txq[0].queued > sc->txq[0].count - 8) {
1.2 ober 2237: ifp->if_oerrors++;
2238: continue;
1.1 ober 2239: }
2240:
2241: #if NBPFILTER > 0
2242: if (ic->ic_rawbpf != NULL)
2243: bpf_mtap(ic->ic_rawbpf, m0);
2244: #endif
2245: if (iwn_tx_data(sc, m0, ni, 0) != 0) {
1.2 ober 2246: ifp->if_oerrors++;
2247: break;
1.1 ober 2248: }
2249: } else {
2250: if (ic->ic_state != IEEE80211_S_RUN)
2251: break;
2252: IFQ_POLL(&ifp->if_snd, m0);
2253: if (m0 == NULL)
2254: break;
1.8 blymn 2255:
1.1 ober 2256: if (m0->m_len < sizeof (*eh) &&
1.10 degroote 2257: (m0 = m_pullup(m0, sizeof (*eh))) == NULL) {
1.2 ober 2258: ifp->if_oerrors++;
2259: continue;
1.1 ober 2260: }
2261: eh = mtod(m0, struct ether_header *);
2262: ni = ieee80211_find_txnode(ic, eh->ether_dhost);
2263: if (ni == NULL) {
2264: m_freem(m0);
2265: ifp->if_oerrors++;
2266: continue;
2267: }
2268: /* classify mbuf so we can find which tx ring to use */
2269: if (ieee80211_classify(ic, m0, ni) != 0) {
2270: m_freem(m0);
2271: ieee80211_free_node(ni);
2272: ifp->if_oerrors++;
2273: continue;
2274: }
1.8 blymn 2275:
1.1 ober 2276: /* no QoS encapsulation for EAPOL frames */
2277: ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
1.2 ober 2278: M_WME_GETAC(m0) : WME_AC_BE;
1.8 blymn 2279:
1.1 ober 2280: if (sc->txq[ac].queued > sc->txq[ac].count - 8) {
1.8 blymn 2281:
1.1 ober 2282: /* there is no place left in this ring */
2283: ifp->if_flags |= IFF_OACTIVE;
1.2 ober 2284: break;
1.1 ober 2285: }
2286: IFQ_DEQUEUE(&ifp->if_snd, m0);
2287: #if NBPFILTER > 0
2288: if (ifp->if_bpf != NULL)
2289: bpf_mtap(ifp->if_bpf, m0);
2290: #endif
2291: m0 = ieee80211_encap(ic, m0, ni);
2292: if (m0 == NULL) {
2293: ieee80211_free_node(ni);
2294: ifp->if_oerrors++;
2295: continue;
2296: }
2297: #if NBPFILTER > 0
2298: if (ic->ic_rawbpf != NULL)
2299: bpf_mtap(ic->ic_rawbpf, m0);
2300: #endif
2301: if (iwn_tx_data(sc, m0, ni, ac) != 0) {
2302: ieee80211_free_node(ni);
2303: ifp->if_oerrors++;
2304: break;
2305: }
2306: }
2307:
2308: sc->sc_tx_timer = 5;
2309: ifp->if_timer = 1;
2310: }
2311: }
2312:
2313: static void
2314: iwn_watchdog(struct ifnet *ifp)
2315: {
2316: struct iwn_softc *sc = ifp->if_softc;
2317:
2318: ifp->if_timer = 0;
2319:
2320: if (sc->sc_tx_timer > 0) {
2321: if (--sc->sc_tx_timer == 0) {
1.8 blymn 2322: aprint_error_dev(sc->sc_dev, "device timeout\n");
1.1 ober 2323: ifp->if_flags &= ~IFF_UP;
2324: iwn_stop(ifp, 1);
2325: ifp->if_oerrors++;
2326: return;
2327: }
2328: ifp->if_timer = 1;
2329: }
2330:
2331: ieee80211_watchdog(&sc->sc_ic);
2332: }
2333:
2334: static int
2335: iwn_ioctl(struct ifnet *ifp, u_long cmd, void * data)
2336: {
2337:
1.2 ober 2338: #define IS_RUNNING(ifp) \
1.1 ober 2339: ((ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING))
1.8 blymn 2340:
1.1 ober 2341: struct iwn_softc *sc = ifp->if_softc;
2342: struct ieee80211com *ic = &sc->sc_ic;
2343: int s, error = 0;
2344:
2345: s = splnet();
2346:
2347: switch (cmd) {
2348: case SIOCSIFFLAGS:
1.22.2.1! skrll 2349: if ((error = ifioctl_common(ifp, cmd, data)) != 0)
! 2350: break;
1.1 ober 2351: if (ifp->if_flags & IFF_UP) {
1.22.2.1! skrll 2352: /*
! 2353: * resync the radio state just in case we missed
! 2354: * and event.
! 2355: */
! 2356: sc->sc_radio =
! 2357: (IWN_READ(sc, IWN_GPIO_CTL) & IWN_GPIO_RF_ENABLED);
! 2358:
! 2359: if (!sc->sc_radio) {
! 2360: ifp->if_flags &= ~IFF_UP;
! 2361: error = EBUSY; /* XXX not really but same as elsewhere in driver */
! 2362: if (ifp->if_flags & IFF_RUNNING)
! 2363: iwn_stop(ifp, 1);
! 2364: } else if (!(ifp->if_flags & IFF_RUNNING))
1.1 ober 2365: iwn_init(ifp);
2366: } else {
2367: if (ifp->if_flags & IFF_RUNNING)
2368: iwn_stop(ifp, 1);
2369: }
2370: break;
2371:
2372: case SIOCADDMULTI:
2373: case SIOCDELMULTI:
2374: /* XXX no h/w multicast filter? --dyoung */
2375: if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
2376: /* setup multicast filter, etc */
2377: error = 0;
2378: }
2379: break;
2380:
2381: default:
2382: error = ieee80211_ioctl(ic, cmd, data);
2383: }
2384:
2385: if (error == ENETRESET) {
1.8 blymn 2386: if (IS_RUNNING(ifp) &&
1.1 ober 2387: (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
2388: iwn_init(ifp);
2389: error = 0;
2390: }
2391:
2392: splx(s);
2393: return error;
2394:
2395: #undef IS_RUNNING
2396: }
2397:
2398: static void
2399: iwn_read_eeprom(struct iwn_softc *sc)
2400: {
2401: struct ieee80211com *ic = &sc->sc_ic;
2402: char domain[4];
2403: uint16_t val;
2404: int i, error;
2405:
2406: if ((error = iwn_eeprom_lock(sc)) != 0) {
2407: aprint_error_dev(sc->sc_dev, "could not lock EEPROM (error=%d)\n", error);
2408: return;
2409: }
2410: /* read and print regulatory domain */
2411: iwn_read_prom_data(sc, IWN_EEPROM_DOMAIN, domain, 4);
2412: aprint_error_dev(sc->sc_dev, "%.4s", domain);
2413:
2414: /* read and print MAC address */
2415: iwn_read_prom_data(sc, IWN_EEPROM_MAC, ic->ic_myaddr, 6);
2416: aprint_error(", address %s\n", ether_sprintf(ic->ic_myaddr));
2417:
2418: /* read the list of authorized channels */
2419: for (i = 0; i < IWN_CHAN_BANDS_COUNT; i++)
2420: iwn_read_eeprom_channels(sc, i);
2421:
2422: /* read maximum allowed Tx power for 2GHz and 5GHz bands */
2423: iwn_read_prom_data(sc, IWN_EEPROM_MAXPOW, &val, 2);
2424: sc->maxpwr2GHz = val & 0xff;
2425: sc->maxpwr5GHz = val >> 8;
2426: /* check that EEPROM values are correct */
2427: if (sc->maxpwr5GHz < 20 || sc->maxpwr5GHz > 50)
2428: sc->maxpwr5GHz = 38;
2429: if (sc->maxpwr2GHz < 20 || sc->maxpwr2GHz > 50)
2430: sc->maxpwr2GHz = 38;
2431: DPRINTF(("maxpwr 2GHz=%d 5GHz=%d\n", sc->maxpwr2GHz, sc->maxpwr5GHz));
2432:
2433: /* read voltage at which samples were taken */
2434: iwn_read_prom_data(sc, IWN_EEPROM_VOLTAGE, &val, 2);
2435: sc->eeprom_voltage = (int16_t)le16toh(val);
2436: DPRINTF(("voltage=%d (in 0.3V)\n", sc->eeprom_voltage));
2437:
2438: /* read power groups */
2439: iwn_read_prom_data(sc, IWN_EEPROM_BANDS, sc->bands, sizeof sc->bands);
2440: #ifdef IWN_DEBUG
2441: if (iwn_debug > 0) {
2442: for (i = 0; i < IWN_NBANDS; i++)
2443: iwn_print_power_group(sc, i);
2444: }
2445: #endif
2446: iwn_eeprom_unlock(sc);
2447: }
2448:
2449: static void
2450: iwn_read_eeprom_channels(struct iwn_softc *sc, int n)
2451: {
2452: struct ieee80211com *ic = &sc->sc_ic;
2453: const struct iwn_chan_band *band = &iwn_bands[n];
2454: struct iwn_eeprom_chan channels[IWN_MAX_CHAN_PER_BAND];
2455: int chan, i;
2456:
2457: iwn_read_prom_data(sc, band->addr, channels,
2458: band->nchan * sizeof (struct iwn_eeprom_chan));
2459:
2460: for (i = 0; i < band->nchan; i++) {
2461: if (!(channels[i].flags & IWN_EEPROM_CHAN_VALID))
2462: continue;
2463:
2464: chan = band->chan[i];
2465:
2466: if (n == 0) { /* 2GHz band */
2467: ic->ic_channels[chan].ic_freq =
2468: ieee80211_ieee2mhz(chan, IEEE80211_CHAN_2GHZ);
2469: ic->ic_channels[chan].ic_flags =
2470: IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
2471: IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
2472:
2473: } else { /* 5GHz band */
2474: /*
2475: * Some adapters support channels 7, 8, 11 and 12
2476: * both in the 2GHz *and* 5GHz bands.
2477: * Because of limitations in our net80211(9) stack,
2478: * we can't support these channels in 5GHz band.
2479: */
2480: if (chan <= 14)
2481: continue;
2482:
2483: ic->ic_channels[chan].ic_freq =
2484: ieee80211_ieee2mhz(chan, IEEE80211_CHAN_5GHZ);
2485: ic->ic_channels[chan].ic_flags = IEEE80211_CHAN_A;
2486: }
2487:
2488: /* is active scan allowed on this channel? */
2489: if (!(channels[i].flags & IWN_EEPROM_CHAN_ACTIVE)) {
2490: ic->ic_channels[chan].ic_flags |=
2491: IEEE80211_CHAN_PASSIVE;
2492: }
2493:
2494: /* save maximum allowed power for this channel */
2495: sc->maxpwr[chan] = channels[i].maxpwr;
2496:
2497: DPRINTF(("adding chan %d flags=0x%x maxpwr=%d\n",
1.2 ober 2498: chan, channels[i].flags, sc->maxpwr[chan]));
1.1 ober 2499: }
2500: }
2501:
2502: #ifdef IWN_DEBUG
2503: static void
2504: iwn_print_power_group(struct iwn_softc *sc, int i)
2505: {
2506: struct iwn_eeprom_band *band = &sc->bands[i];
2507: struct iwn_eeprom_chan_samples *chans = band->chans;
2508: int j, c;
2509:
2510: DPRINTF(("===band %d===\n", i));
2511: DPRINTF(("chan lo=%d, chan hi=%d\n", band->lo, band->hi));
2512: DPRINTF(("chan1 num=%d\n", chans[0].num));
2513: for (c = 0; c < IWN_NTXCHAINS; c++) {
2514: for (j = 0; j < IWN_NSAMPLES; j++) {
2515: DPRINTF(("chain %d, sample %d: temp=%d gain=%d "
1.2 ober 2516: "power=%d pa_det=%d\n", c, j,
2517: chans[0].samples[c][j].temp,
2518: chans[0].samples[c][j].gain,
2519: chans[0].samples[c][j].power,
2520: chans[0].samples[c][j].pa_det));
1.1 ober 2521: }
2522: }
2523: DPRINTF(("chan2 num=%d\n", chans[1].num));
2524: for (c = 0; c < IWN_NTXCHAINS; c++) {
2525: for (j = 0; j < IWN_NSAMPLES; j++) {
2526: DPRINTF(("chain %d, sample %d: temp=%d gain=%d "
1.2 ober 2527: "power=%d pa_det=%d\n", c, j,
2528: chans[1].samples[c][j].temp,
2529: chans[1].samples[c][j].gain,
2530: chans[1].samples[c][j].power,
2531: chans[1].samples[c][j].pa_det));
1.1 ober 2532: }
2533: }
2534: }
2535: #endif
2536:
2537: /*
2538: * Send a command to the firmware.
2539: */
2540: static int
2541: iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
2542: {
2543: struct iwn_tx_ring *ring = &sc->txq[4];
2544: struct iwn_tx_desc *desc;
2545: struct iwn_tx_cmd *cmd;
2546: bus_addr_t paddr;
2547:
2548: KASSERT(size <= sizeof cmd->data);
2549:
2550: desc = &ring->desc[ring->cur];
2551: cmd = &ring->cmd[ring->cur];
2552:
2553: cmd->code = code;
2554: cmd->flags = 0;
2555: cmd->qid = ring->qid;
2556: cmd->idx = ring->cur;
2557: memcpy(cmd->data, buf, size);
2558:
2559: paddr = ring->cmd_dma.paddr + ring->cur * sizeof (struct iwn_tx_cmd);
2560:
2561: IWN_SET_DESC_NSEGS(desc, 1);
2562: IWN_SET_DESC_SEG(desc, 0, paddr, 4 + size);
2563: sc->shared->len[ring->qid][ring->cur] = htole16(8);
2564: if (ring->cur < IWN_TX_WINDOW) {
2565: sc->shared->len[ring->qid][ring->cur + IWN_TX_RING_COUNT] =
2566: htole16(8);
2567: }
2568:
1.20 blymn 2569: bus_dmamap_sync(sc->sc_dmat, ring->cmd_dma.map, 0,
2570: 4 + size, BUS_DMASYNC_PREWRITE);
2571:
1.1 ober 2572: /* kick cmd ring */
2573: ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
2574: IWN_WRITE(sc, IWN_TX_WIDX, ring->qid << 8 | ring->cur);
2575:
2576: return async ? 0 : tsleep(cmd, PCATCH, "iwncmd", hz);
2577: }
2578:
2579: /*
2580: * Configure hardware multi-rate retries for one node.
2581: */
2582: static int
2583: iwn_setup_node_mrr(struct iwn_softc *sc, uint8_t id, int async)
2584: {
2585: struct ieee80211com *ic = &sc->sc_ic;
2586: struct iwn_cmd_mrr mrr;
2587: int i, ridx;
2588:
2589: memset(&mrr, 0, sizeof mrr);
2590: mrr.id = id;
2591: mrr.ssmask = 2;
2592: mrr.dsmask = 3;
2593: mrr.ampdu_disable = 3;
1.12 christos 2594: mrr.ampdu_limit = htole16(4000);
1.1 ober 2595:
2596: if (id == IWN_ID_BSS)
2597: ridx = IWN_OFDM54;
2598: else if (ic->ic_curmode == IEEE80211_MODE_11A)
2599: ridx = IWN_OFDM6;
2600: else
2601: ridx = IWN_CCK1;
2602: for (i = 0; i < IWN_MAX_TX_RETRIES; i++) {
2603: mrr.table[i].rate = iwn_ridx_to_plcp[ridx];
2604: mrr.table[i].rflags = IWN_RFLAG_ANT_B;
2605: if (ridx <= IWN_CCK11)
2606: mrr.table[i].rflags |= IWN_RFLAG_CCK;
2607: ridx = iwn_prev_ridx[ridx];
2608: }
2609: return iwn_cmd(sc, IWN_CMD_NODE_MRR_SETUP, &mrr, sizeof mrr, async);
2610: }
2611:
2612: static int
2613: iwn_wme_update(struct ieee80211com *ic)
2614: {
2615: #define IWN_EXP2(v) htole16((1 << (v)) - 1)
2616: #define IWN_USEC(v) htole16(IEEE80211_TXOP_TO_US(v))
2617: struct iwn_softc *sc = ic->ic_ifp->if_softc;
2618: const struct wmeParams *wmep;
2619: struct iwn_wme_setup wme;
2620: int ac;
2621:
2622: /* don't override default WME values if WME is not actually enabled */
2623: if (!(ic->ic_flags & IEEE80211_F_WME))
2624: return 0;
2625:
2626: wme.flags = 0;
2627: for (ac = 0; ac < WME_NUM_AC; ac++) {
2628: wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
2629: wme.ac[ac].aifsn = wmep->wmep_aifsn;
2630: wme.ac[ac].cwmin = IWN_EXP2(wmep->wmep_logcwmin);
2631: wme.ac[ac].cwmax = IWN_EXP2(wmep->wmep_logcwmax);
1.15 christos 2632: wme.ac[ac].txop = IWN_USEC(wmep->wmep_txopLimit);
1.1 ober 2633:
2634: DPRINTF(("setting WME for queue %d aifsn=%d cwmin=%d cwmax=%d "
1.2 ober 2635: "txop=%d\n", ac, wme.ac[ac].aifsn, wme.ac[ac].cwmin,
2636: wme.ac[ac].cwmax, wme.ac[ac].txop));
1.1 ober 2637: }
2638:
2639: return iwn_cmd(sc, IWN_CMD_SET_WME, &wme, sizeof wme, 1);
2640: #undef IWN_USEC
2641: #undef IWN_EXP2
2642: }
2643:
2644:
2645:
2646: static void
2647: iwn_set_led(struct iwn_softc *sc, uint8_t which, uint8_t off, uint8_t on)
2648: {
2649: struct iwn_cmd_led led;
2650:
2651: led.which = which;
2652: led.unit = htole32(100000); /* on/off in unit of 100ms */
2653: led.off = off;
2654: led.on = on;
2655:
2656: (void)iwn_cmd(sc, IWN_CMD_SET_LED, &led, sizeof led, 1);
2657: }
2658:
2659: /*
2660: * Set the critical temperature at which the firmware will automatically stop
2661: * the radio transmitter.
2662: */
2663: static int
2664: iwn_set_critical_temp(struct iwn_softc *sc)
2665: {
2666: struct iwn_ucode_info *uc = &sc->ucode_info;
2667: struct iwn_critical_temp crit;
2668: uint32_t r1, r2, r3, temp;
2669:
2670: IWN_WRITE(sc, IWN_UCODE_CLR, IWN_CTEMP_STOP_RF);
2671:
2672: r1 = le32toh(uc->temp[0].chan20MHz);
2673: r2 = le32toh(uc->temp[1].chan20MHz);
2674: r3 = le32toh(uc->temp[2].chan20MHz);
2675: /* inverse function of iwn_get_temperature() */
2676:
2677: temp = r2 + ((IWN_CTOK(110) * (r3 - r1)) / 259);
2678:
2679: memset(&crit, 0, sizeof crit);
2680: crit.tempR = htole32(temp);
2681: DPRINTF(("setting critical temperature to %u\n", temp));
2682: return iwn_cmd(sc, IWN_CMD_SET_CRITICAL_TEMP, &crit, sizeof crit, 0);
2683: }
2684:
2685: static void
2686: iwn_enable_tsf(struct iwn_softc *sc, struct ieee80211_node *ni)
2687: {
2688: struct iwn_cmd_tsf tsf;
2689: uint64_t val, mod;
2690:
2691: memset(&tsf, 0, sizeof tsf);
2692: memcpy(&tsf.tstamp, ni->ni_tstamp.data, 8);
2693: tsf.bintval = htole16(ni->ni_intval);
2694: tsf.lintval = htole16(10);
2695:
2696: /* compute remaining time until next beacon */
2697: val = (uint64_t)ni->ni_intval * 1024; /* msecs -> usecs */
2698: mod = le64toh(tsf.tstamp) % val;
2699: tsf.binitval = htole32((uint32_t)(val - mod));
2700:
1.4 skrll 2701: DPRINTF(("TSF bintval=%u tstamp=%" PRIu64 ", init=%" PRIu64 "\n",
2702: ni->ni_intval, le64toh(tsf.tstamp), val - mod));
1.1 ober 2703:
2704: if (iwn_cmd(sc, IWN_CMD_TSF, &tsf, sizeof tsf, 1) != 0)
2705: aprint_error_dev(sc->sc_dev, "could not enable TSF\n");
2706: }
2707:
2708: static void
2709: iwn_power_calibration(struct iwn_softc *sc, int temp)
2710: {
2711: struct ieee80211com *ic = &sc->sc_ic;
2712:
2713: DPRINTF(("temperature %d->%d\n", sc->temp, temp));
2714:
2715: /* adjust Tx power if need be (delta >= 3�C) */
2716: if (abs(temp - sc->temp) < 3)
2717: return;
2718:
2719: sc->temp = temp;
2720:
2721: DPRINTF(("setting Tx power for channel %d\n",
1.2 ober 2722: ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)));
1.1 ober 2723: if (iwn_set_txpower(sc, ic->ic_bss->ni_chan, 1) != 0) {
2724: /* just warn, too bad for the automatic calibration... */
2725: aprint_error_dev(sc->sc_dev, "could not adjust Tx power\n");
2726: }
2727: }
2728:
2729: /*
2730: * Set Tx power for a given channel (each rate has its own power settings).
2731: * This function takes into account the regulatory information from EEPROM,
2732: * the current temperature and the current voltage.
2733: */
2734: static int
2735: iwn_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, int async)
2736: {
2737: /* fixed-point arithmetic division using a n-bit fractional part */
1.2 ober 2738: #define fdivround(a, b, n) \
1.1 ober 2739: ((((1 << n) * (a)) / (b) + (1 << n) / 2) / (1 << n))
2740: /* linear interpolation */
1.2 ober 2741: #define interpolate(x, x1, y1, x2, y2, n) \
1.1 ober 2742: ((y1) + fdivround(((int)(x) - (x1)) * ((y2) - (y1)), (x2) - (x1), n))
2743:
2744: static const int tdiv[IWN_NATTEN_GROUPS] = { 9, 8, 8, 8, 6 };
2745: struct ieee80211com *ic = &sc->sc_ic;
2746: struct iwn_ucode_info *uc = &sc->ucode_info;
2747: struct iwn_cmd_txpower cmd;
2748: struct iwn_eeprom_chan_samples *chans;
2749: const uint8_t *rf_gain, *dsp_gain;
2750: int32_t vdiff, tdiff;
2751: int i, c, grp, maxpwr;
2752: u_int chan;
2753:
2754: /* get channel number */
2755: chan = ieee80211_chan2ieee(ic, ch);
2756:
2757: memset(&cmd, 0, sizeof cmd);
2758: cmd.band = IEEE80211_IS_CHAN_5GHZ(ch) ? 0 : 1;
2759: cmd.chan = chan;
2760:
2761: if (IEEE80211_IS_CHAN_5GHZ(ch)) {
1.15 christos 2762: maxpwr = sc->maxpwr5GHz;
2763: rf_gain = iwn_rf_gain_5ghz;
1.1 ober 2764: dsp_gain = iwn_dsp_gain_5ghz;
2765: } else {
1.15 christos 2766: maxpwr = sc->maxpwr2GHz;
2767: rf_gain = iwn_rf_gain_2ghz;
1.1 ober 2768: dsp_gain = iwn_dsp_gain_2ghz;
2769: }
2770:
2771: /* compute voltage compensation */
2772: vdiff = ((int32_t)le32toh(uc->volt) - sc->eeprom_voltage) / 7;
2773: if (vdiff > 0)
2774: vdiff *= 2;
2775: if (abs(vdiff) > 2)
2776: vdiff = 0;
2777: DPRINTF(("voltage compensation=%d (UCODE=%d, EEPROM=%d)\n",
1.2 ober 2778: vdiff, le32toh(uc->volt), sc->eeprom_voltage));
1.1 ober 2779:
2780: /* get channel's attenuation group */
2781: if (chan <= 20) /* 1-20 */
2782: grp = 4;
2783: else if (chan <= 43) /* 34-43 */
2784: grp = 0;
2785: else if (chan <= 70) /* 44-70 */
2786: grp = 1;
2787: else if (chan <= 124) /* 71-124 */
2788: grp = 2;
2789: else /* 125-200 */
2790: grp = 3;
2791: DPRINTF(("chan %d, attenuation group=%d\n", chan, grp));
2792:
2793: /* get channel's sub-band */
2794: for (i = 0; i < IWN_NBANDS; i++)
2795: if (sc->bands[i].lo != 0 &&
2796: sc->bands[i].lo <= chan && chan <= sc->bands[i].hi)
2797: break;
2798: chans = sc->bands[i].chans;
2799: DPRINTF(("chan %d sub-band=%d\n", chan, i));
2800:
2801: for (c = 0; c < IWN_NTXCHAINS; c++) {
2802: uint8_t power, gain, temp;
2803: int maxchpwr, pwr, ridx, idx;
2804:
2805: power = interpolate(chan,
2806: chans[0].num, chans[0].samples[c][1].power,
2807: chans[1].num, chans[1].samples[c][1].power, 1);
2808: gain = interpolate(chan,
2809: chans[0].num, chans[0].samples[c][1].gain,
2810: chans[1].num, chans[1].samples[c][1].gain, 1);
2811: temp = interpolate(chan,
2812: chans[0].num, chans[0].samples[c][1].temp,
2813: chans[1].num, chans[1].samples[c][1].temp, 1);
2814: DPRINTF(("Tx chain %d: power=%d gain=%d temp=%d\n",
1.2 ober 2815: c, power, gain, temp));
1.1 ober 2816:
2817: /* compute temperature compensation */
2818: tdiff = ((sc->temp - temp) * 2) / tdiv[grp];
2819: DPRINTF(("temperature compensation=%d (current=%d, "
1.2 ober 2820: "EEPROM=%d)\n", tdiff, sc->temp, temp));
1.1 ober 2821:
2822: for (ridx = 0; ridx <= IWN_RIDX_MAX; ridx++) {
2823: maxchpwr = sc->maxpwr[chan] * 2;
2824: if ((ridx / 8) & 1) {
2825: /* MIMO: decrease Tx power (-3dB) */
2826: maxchpwr -= 6;
2827: }
2828:
2829: pwr = maxpwr - 10;
2830:
2831: /* decrease power for highest OFDM rates */
2832: if ((ridx % 8) == 5) /* 48Mbit/s */
2833: pwr -= 5;
2834: else if ((ridx % 8) == 6) /* 54Mbit/s */
2835: pwr -= 7;
2836: else if ((ridx % 8) == 7) /* 60Mbit/s */
2837: pwr -= 10;
2838:
2839: if (pwr > maxchpwr)
2840: pwr = maxchpwr;
2841:
2842: idx = gain - (pwr - power) - tdiff - vdiff;
2843: if ((ridx / 8) & 1) /* MIMO */
2844: idx += (int32_t)le32toh(uc->atten[grp][c]);
2845:
2846: if (cmd.band == 0)
2847: idx += 9; /* 5GHz */
2848: if (ridx == IWN_RIDX_MAX)
2849: idx += 5; /* CCK */
2850:
2851: /* make sure idx stays in a valid range */
2852: if (idx < 0)
2853: idx = 0;
2854: else if (idx > IWN_MAX_PWR_INDEX)
2855: idx = IWN_MAX_PWR_INDEX;
2856:
2857: DPRINTF(("Tx chain %d, rate idx %d: power=%d\n",
1.2 ober 2858: c, ridx, idx));
1.1 ober 2859: cmd.power[ridx].rf_gain[c] = rf_gain[idx];
2860: cmd.power[ridx].dsp_gain[c] = dsp_gain[idx];
2861: }
2862: }
2863:
2864: DPRINTF(("setting tx power for chan %d\n", chan));
2865: return iwn_cmd(sc, IWN_CMD_TXPOWER, &cmd, sizeof cmd, async);
2866:
2867: #undef interpolate
2868: #undef fdivround
2869: }
2870:
2871: /*
2872: * Get the best (maximum) RSSI among Rx antennas (in dBm).
2873: */
2874: static int
2875: iwn_get_rssi(const struct iwn_rx_stat *stat)
2876: {
2877: uint8_t mask, agc;
2878: int rssi;
2879:
2880: mask = (le16toh(stat->antenna) >> 4) & 0x7;
2881: agc = (le16toh(stat->agc) >> 7) & 0x7f;
2882:
2883: rssi = 0;
2884: if (mask & (1 << 0)) /* Ant A */
2885: rssi = max(rssi, stat->rssi[0]);
2886: if (mask & (1 << 1)) /* Ant B */
2887: rssi = max(rssi, stat->rssi[2]);
2888: if (mask & (1 << 2)) /* Ant C */
2889: rssi = max(rssi, stat->rssi[4]);
2890:
2891: return rssi - agc - IWN_RSSI_TO_DBM;
2892: }
2893:
2894: /*
2895: * Get the average noise among Rx antennas (in dBm).
2896: */
2897: static int
2898: iwn_get_noise(const struct iwn_rx_general_stats *stats)
2899: {
2900: int i, total, nbant, noise;
2901:
2902: total = nbant = 0;
2903: for (i = 0; i < 3; i++) {
2904: if ((noise = le32toh(stats->noise[i]) & 0xff) == 0)
2905: continue;
2906: total += noise;
2907: nbant++;
2908: }
2909: /* there should be at least one antenna but check anyway */
2910: return (nbant == 0) ? -127 : (total / nbant) - 107;
2911: }
2912:
2913: /*
2914: * Read temperature (in degC) from the on-board thermal sensor.
2915: */
2916: static int
2917: iwn_get_temperature(struct iwn_softc *sc)
2918: {
2919: struct iwn_ucode_info *uc = &sc->ucode_info;
2920: int32_t r1, r2, r3, r4, temp;
2921:
2922: r1 = le32toh(uc->temp[0].chan20MHz);
2923: r2 = le32toh(uc->temp[1].chan20MHz);
2924: r3 = le32toh(uc->temp[2].chan20MHz);
2925: r4 = le32toh(sc->rawtemp);
2926:
2927: if (r1 == r3) /* prevents division by 0 (should not happen) */
2928: return 0;
2929:
2930: /* sign-extend 23-bit R4 value to 32-bit */
2931: r4 = (r4 << 8) >> 8;
2932: /* compute temperature */
2933: temp = (259 * (r4 - r2)) / (r3 - r1);
2934: temp = (temp * 97) / 100 + 8;
2935:
2936: DPRINTF(("temperature %dK/%dC\n", temp, IWN_KTOC(temp)));
2937: return IWN_KTOC(temp);
2938: }
2939:
2940: /*
2941: * Initialize sensitivity calibration state machine.
2942: */
2943: static int
2944: iwn_init_sensitivity(struct iwn_softc *sc)
2945: {
2946: struct iwn_calib_state *calib = &sc->calib;
2947: struct iwn_phy_calib_cmd cmd;
2948: int error;
2949:
2950: /* reset calibration state */
2951: memset(calib, 0, sizeof (*calib));
2952: calib->state = IWN_CALIB_STATE_INIT;
2953: calib->cck_state = IWN_CCK_STATE_HIFA;
2954: /* initial values taken from the reference driver */
1.15 christos 2955: calib->corr_ofdm_x1 = 105;
1.1 ober 2956: calib->corr_ofdm_mrc_x1 = 220;
1.15 christos 2957: calib->corr_ofdm_x4 = 90;
1.1 ober 2958: calib->corr_ofdm_mrc_x4 = 170;
1.15 christos 2959: calib->corr_cck_x4 = 125;
2960: calib->corr_cck_mrc_x4 = 200;
2961: calib->energy_cck = 100;
1.1 ober 2962:
2963: /* write initial sensitivity values */
2964: if ((error = iwn_send_sensitivity(sc)) != 0)
2965: return error;
2966:
2967: memset(&cmd, 0, sizeof cmd);
2968: cmd.code = IWN_SET_DIFF_GAIN;
2969: /* differential gains initially set to 0 for all 3 antennas */
2970: DPRINTF(("setting differential gains\n"));
2971: return iwn_cmd(sc, IWN_PHY_CALIB, &cmd, sizeof cmd, 1);
2972: }
2973:
2974: /*
2975: * Collect noise and RSSI statistics for the first 20 beacons received
2976: * after association and use them to determine connected antennas and
2977: * set differential gains.
2978: */
2979: static void
2980: iwn_compute_differential_gain(struct iwn_softc *sc,
2981: const struct iwn_rx_general_stats *stats)
2982: {
2983: struct iwn_calib_state *calib = &sc->calib;
2984: struct iwn_phy_calib_cmd cmd;
2985: int i, val;
2986:
2987: /* accumulate RSSI and noise for all 3 antennas */
2988: for (i = 0; i < 3; i++) {
2989: calib->rssi[i] += le32toh(stats->rssi[i]) & 0xff;
2990: calib->noise[i] += le32toh(stats->noise[i]) & 0xff;
2991: }
2992:
2993: /* we update differential gain only once after 20 beacons */
2994: if (++calib->nbeacons < 20)
2995: return;
2996:
2997: /* determine antenna with highest average RSSI */
2998: val = max(calib->rssi[0], calib->rssi[1]);
2999: val = max(calib->rssi[2], val);
3000:
3001: /* determine which antennas are connected */
3002: sc->antmsk = 0;
3003: for (i = 0; i < 3; i++)
3004: if (val - calib->rssi[i] <= 15 * 20)
3005: sc->antmsk |= 1 << i;
3006: /* if neither Ant A and Ant B are connected.. */
3007: if ((sc->antmsk & (1 << 0 | 1 << 1)) == 0)
3008: sc->antmsk |= 1 << 1; /* ..mark Ant B as connected! */
3009:
3010: /* get minimal noise among connected antennas */
3011: val = INT_MAX; /* ok, there's at least one */
3012: for (i = 0; i < 3; i++)
3013: if (sc->antmsk & (1 << i))
3014: val = min(calib->noise[i], val);
3015:
3016: memset(&cmd, 0, sizeof cmd);
3017: cmd.code = IWN_SET_DIFF_GAIN;
3018: /* set differential gains for connected antennas */
3019: for (i = 0; i < 3; i++) {
3020: if (sc->antmsk & (1 << i)) {
3021: cmd.gain[i] = (calib->noise[i] - val) / 30;
3022: /* limit differential gain to 3 */
3023: cmd.gain[i] = min(cmd.gain[i], 3);
3024: cmd.gain[i] |= IWN_GAIN_SET;
3025: }
3026: }
3027: DPRINTF(("setting differential gains Ant A/B/C: %x/%x/%x (%x)\n",
1.2 ober 3028: cmd.gain[0], cmd.gain[1], cmd.gain[2], sc->antmsk));
1.1 ober 3029: if (iwn_cmd(sc, IWN_PHY_CALIB, &cmd, sizeof cmd, 1) == 0)
3030: calib->state = IWN_CALIB_STATE_RUN;
3031: }
3032:
3033: /*
3034: * Tune RF Rx sensitivity based on the number of false alarms detected
3035: * during the last beacon period.
3036: */
3037: static void
3038: iwn_tune_sensitivity(struct iwn_softc *sc, const struct iwn_rx_stats *stats)
3039: {
1.2 ober 3040: #define inc_clip(val, inc, max) \
3041: if ((val) < (max)) { \
3042: if ((val) < (max) - (inc)) \
3043: (val) += (inc); \
3044: else \
3045: (val) = (max); \
3046: needs_update = 1; \
3047: }
3048: #define dec_clip(val, dec, min) \
3049: if ((val) > (min)) { \
3050: if ((val) > (min) + (dec)) \
3051: (val) -= (dec); \
3052: else \
3053: (val) = (min); \
3054: needs_update = 1; \
1.1 ober 3055: }
3056:
3057: struct iwn_calib_state *calib = &sc->calib;
3058: uint32_t val, rxena, fa;
3059: uint32_t energy[3], energy_min;
3060: uint8_t noise[3], noise_ref;
3061: int i, needs_update = 0;
3062:
3063: /* check that we've been enabled long enough */
3064: if ((rxena = le32toh(stats->general.load)) == 0)
3065: return;
3066:
3067: /* compute number of false alarms since last call for OFDM */
3068: fa = le32toh(stats->ofdm.bad_plcp) - calib->bad_plcp_ofdm;
3069: fa += le32toh(stats->ofdm.fa) - calib->fa_ofdm;
3070: fa *= 200 * 1024; /* 200TU */
3071:
3072: /* save counters values for next call */
3073: calib->bad_plcp_ofdm = le32toh(stats->ofdm.bad_plcp);
3074: calib->fa_ofdm = le32toh(stats->ofdm.fa);
3075:
3076: if (fa > 50 * rxena) {
3077: /* high false alarm count, decrease sensitivity */
3078: DPRINTFN(2, ("OFDM high false alarm count: %u\n", fa));
1.15 christos 3079: inc_clip(calib->corr_ofdm_x1, 1, 140);
1.1 ober 3080: inc_clip(calib->corr_ofdm_mrc_x1, 1, 270);
1.15 christos 3081: inc_clip(calib->corr_ofdm_x4, 1, 120);
1.1 ober 3082: inc_clip(calib->corr_ofdm_mrc_x4, 1, 210);
3083:
3084: } else if (fa < 5 * rxena) {
3085: /* low false alarm count, increase sensitivity */
3086: DPRINTFN(2, ("OFDM low false alarm count: %u\n", fa));
1.15 christos 3087: dec_clip(calib->corr_ofdm_x1, 1, 105);
1.1 ober 3088: dec_clip(calib->corr_ofdm_mrc_x1, 1, 220);
1.15 christos 3089: dec_clip(calib->corr_ofdm_x4, 1, 85);
1.1 ober 3090: dec_clip(calib->corr_ofdm_mrc_x4, 1, 170);
3091: }
3092:
3093: /* compute maximum noise among 3 antennas */
3094: for (i = 0; i < 3; i++)
3095: noise[i] = (le32toh(stats->general.noise[i]) >> 8) & 0xff;
3096: val = max(noise[0], noise[1]);
3097: val = max(noise[2], val);
3098: /* insert it into our samples table */
3099: calib->noise_samples[calib->cur_noise_sample] = val;
3100: calib->cur_noise_sample = (calib->cur_noise_sample + 1) % 20;
3101:
3102: /* compute maximum noise among last 20 samples */
3103: noise_ref = calib->noise_samples[0];
3104: for (i = 1; i < 20; i++)
3105: noise_ref = max(noise_ref, calib->noise_samples[i]);
3106:
3107: /* compute maximum energy among 3 antennas */
3108: for (i = 0; i < 3; i++)
3109: energy[i] = le32toh(stats->general.energy[i]);
3110: val = min(energy[0], energy[1]);
3111: val = min(energy[2], val);
3112: /* insert it into our samples table */
3113: calib->energy_samples[calib->cur_energy_sample] = val;
3114: calib->cur_energy_sample = (calib->cur_energy_sample + 1) % 10;
3115:
3116: /* compute minimum energy among last 10 samples */
3117: energy_min = calib->energy_samples[0];
3118: for (i = 1; i < 10; i++)
3119: energy_min = max(energy_min, calib->energy_samples[i]);
3120: energy_min += 6;
3121:
3122: /* compute number of false alarms since last call for CCK */
3123: fa = le32toh(stats->cck.bad_plcp) - calib->bad_plcp_cck;
3124: fa += le32toh(stats->cck.fa) - calib->fa_cck;
3125: fa *= 200 * 1024; /* 200TU */
3126:
3127: /* save counters values for next call */
3128: calib->bad_plcp_cck = le32toh(stats->cck.bad_plcp);
3129: calib->fa_cck = le32toh(stats->cck.fa);
3130:
3131: if (fa > 50 * rxena) {
3132: /* high false alarm count, decrease sensitivity */
3133: DPRINTFN(2, ("CCK high false alarm count: %u\n", fa));
3134: calib->cck_state = IWN_CCK_STATE_HIFA;
3135: calib->low_fa = 0;
3136:
3137: if (calib->corr_cck_x4 > 160) {
3138: calib->noise_ref = noise_ref;
3139: if (calib->energy_cck > 2)
3140: dec_clip(calib->energy_cck, 2, energy_min);
3141: }
3142: if (calib->corr_cck_x4 < 160) {
3143: calib->corr_cck_x4 = 161;
3144: needs_update = 1;
3145: } else
3146: inc_clip(calib->corr_cck_x4, 3, 200);
3147:
3148: inc_clip(calib->corr_cck_mrc_x4, 3, 400);
3149:
3150: } else if (fa < 5 * rxena) {
3151: /* low false alarm count, increase sensitivity */
3152: DPRINTFN(2, ("CCK low false alarm count: %u\n", fa));
3153: calib->cck_state = IWN_CCK_STATE_LOFA;
3154: calib->low_fa++;
3155:
3156: if (calib->cck_state != 0 &&
3157: ((calib->noise_ref - noise_ref) > 2 ||
1.2 ober 3158: calib->low_fa > 100)) {
1.15 christos 3159: inc_clip(calib->energy_cck, 2, 97);
3160: dec_clip(calib->corr_cck_x4, 3, 125);
1.1 ober 3161: dec_clip(calib->corr_cck_mrc_x4, 3, 200);
3162: }
3163: } else {
3164: /* not worth to increase or decrease sensitivity */
3165: DPRINTFN(2, ("CCK normal false alarm count: %u\n", fa));
3166: calib->low_fa = 0;
3167: calib->noise_ref = noise_ref;
3168:
3169: if (calib->cck_state == IWN_CCK_STATE_HIFA) {
3170: /* previous interval had many false alarms */
3171: dec_clip(calib->energy_cck, 8, energy_min);
3172: }
3173: calib->cck_state = IWN_CCK_STATE_INIT;
3174: }
3175:
3176: if (needs_update)
3177: (void)iwn_send_sensitivity(sc);
3178: #undef dec_clip
3179: #undef inc_clip
3180: }
3181:
3182: static int
3183: iwn_send_sensitivity(struct iwn_softc *sc)
3184: {
3185: struct iwn_calib_state *calib = &sc->calib;
3186: struct iwn_sensitivity_cmd cmd;
3187:
3188: memset(&cmd, 0, sizeof cmd);
3189: cmd.which = IWN_SENSITIVITY_WORKTBL;
3190: /* OFDM modulation */
3191: cmd.corr_ofdm_x1 = le16toh(calib->corr_ofdm_x1);
3192: cmd.corr_ofdm_mrc_x1 = le16toh(calib->corr_ofdm_mrc_x1);
3193: cmd.corr_ofdm_x4 = le16toh(calib->corr_ofdm_x4);
3194: cmd.corr_ofdm_mrc_x4 = le16toh(calib->corr_ofdm_mrc_x4);
1.15 christos 3195: cmd.energy_ofdm = le16toh(100);
1.1 ober 3196: cmd.energy_ofdm_th = le16toh(62);
3197: /* CCK modulation */
1.15 christos 3198: cmd.corr_cck_x4 = le16toh(calib->corr_cck_x4);
1.1 ober 3199: cmd.corr_cck_mrc_x4 = le16toh(calib->corr_cck_mrc_x4);
1.15 christos 3200: cmd.energy_cck = le16toh(calib->energy_cck);
1.1 ober 3201: /* Barker modulation: use default values */
1.15 christos 3202: cmd.corr_barker = le16toh(190);
1.1 ober 3203: cmd.corr_barker_mrc = le16toh(390);
3204:
3205: DPRINTFN(2, ("setting sensitivity\n"));
3206: return iwn_cmd(sc, IWN_SENSITIVITY, &cmd, sizeof cmd, 1);
3207: }
3208:
3209: static int
1.11 blymn 3210: iwn_add_node(struct iwn_softc *sc, struct ieee80211_node *ni, bool broadcast,
1.20 blymn 3211: bool async, uint32_t htflags)
1.11 blymn 3212: {
3213: struct iwn_node_info node;
3214: int error;
3215:
3216: error = 0;
3217:
3218: memset(&node, 0, sizeof node);
3219: if (broadcast == true) {
3220: IEEE80211_ADDR_COPY(node.macaddr, etherbroadcastaddr);
3221: node.id = IWN_ID_BROADCAST;
3222: DPRINTF(("adding broadcast node\n"));
3223: } else {
3224: IEEE80211_ADDR_COPY(node.macaddr, ni->ni_macaddr);
3225: node.id = IWN_ID_BSS;
1.20 blymn 3226: node.htflags = htole32(htflags);
1.11 blymn 3227: DPRINTF(("adding BSS node\n"));
3228: }
3229:
3230: error = iwn_cmd(sc, IWN_CMD_ADD_NODE, &node, sizeof node, async);
3231: if (error != 0) {
3232: aprint_error_dev(sc->sc_dev, "could not add %s node\n",
3233: (broadcast == 1)? "broadcast" : "BSS");
3234: return error;
3235: }
3236: DPRINTF(("setting MRR for node %d\n", node.id));
3237: if ((error = iwn_setup_node_mrr(sc, node.id, async)) != 0) {
3238: aprint_error_dev(sc->sc_dev,
3239: "could not setup MRR for %s node\n",
3240: (broadcast == 1)? "broadcast" : "BSS");
3241: return error;
3242: }
3243:
3244: return error;
3245: }
3246:
3247: static int
1.1 ober 3248: iwn_auth(struct iwn_softc *sc)
3249: {
3250: struct ieee80211com *ic = &sc->sc_ic;
3251: struct ieee80211_node *ni = ic->ic_bss;
3252: int error;
3253:
1.20 blymn 3254: sc->calib.state = IWN_CALIB_STATE_INIT;
3255:
1.1 ober 3256: /* update adapter's configuration */
1.20 blymn 3257: sc->config.associd = 0;
1.1 ober 3258: IEEE80211_ADDR_COPY(sc->config.bssid, ni->ni_bssid);
1.22.2.1! skrll 3259: sc->config.chan = htole16(ieee80211_chan2ieee(ic, ni->ni_chan));
1.1 ober 3260: sc->config.flags = htole32(IWN_CONFIG_TSF);
3261: if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
3262: sc->config.flags |= htole32(IWN_CONFIG_AUTO |
3263: IWN_CONFIG_24GHZ);
3264: }
1.22.2.1! skrll 3265: if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
1.1 ober 3266: sc->config.cck_mask = 0;
3267: sc->config.ofdm_mask = 0x15;
1.22.2.1! skrll 3268: } else if (IEEE80211_IS_CHAN_B(ni->ni_chan)) {
1.1 ober 3269: sc->config.cck_mask = 0x03;
3270: sc->config.ofdm_mask = 0;
1.22.2.1! skrll 3271: } else {
! 3272: /* assume 802.11b/g */
1.1 ober 3273: sc->config.cck_mask = 0xf;
3274: sc->config.ofdm_mask = 0x15;
3275: }
1.20 blymn 3276:
3277: if (ic->ic_flags & IEEE80211_F_SHSLOT)
3278: sc->config.flags |= htole32(IWN_CONFIG_SHSLOT);
3279: if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
3280: sc->config.flags |= htole32(IWN_CONFIG_SHPREAMBLE);
3281: sc->config.filter &= ~htole32(IWN_FILTER_BSS);
3282:
1.1 ober 3283: DPRINTF(("config chan %d flags %x cck %x ofdm %x\n", sc->config.chan,
1.2 ober 3284: sc->config.flags, sc->config.cck_mask, sc->config.ofdm_mask));
1.1 ober 3285: error = iwn_cmd(sc, IWN_CMD_CONFIGURE, &sc->config,
3286: sizeof (struct iwn_config), 1);
3287: if (error != 0) {
3288: aprint_error_dev(sc->sc_dev, "could not configure\n");
3289: return error;
3290: }
3291:
3292: /* configuration has changed, set Tx power accordingly */
3293: if ((error = iwn_set_txpower(sc, ni->ni_chan, 1)) != 0) {
1.8 blymn 3294: aprint_error_dev(sc->sc_dev, "could not set Tx power\n");
1.1 ober 3295: return error;
3296: }
3297:
3298: /*
3299: * Reconfiguring clears the adapter's nodes table so we must
3300: * add the broadcast node again.
3301: */
1.20 blymn 3302: if ((error = iwn_add_node(sc, ni, true, true, 0)) != 0)
1.11 blymn 3303: return error;
3304:
3305: /* add BSS node */
1.20 blymn 3306: if ((error = iwn_add_node(sc, ni, false, true, 0)) != 0)
1.1 ober 3307: return error;
1.11 blymn 3308:
3309: if (ic->ic_opmode == IEEE80211_M_STA) {
3310: /* fake a join to init the tx rate */
3311: iwn_newassoc(ni, 1);
1.1 ober 3312: }
1.11 blymn 3313:
3314: if ((error = iwn_init_sensitivity(sc)) != 0) {
3315: aprint_error_dev(sc->sc_dev, "could not set sensitivity\n");
1.1 ober 3316: return error;
3317: }
3318:
1.11 blymn 3319:
1.1 ober 3320: return 0;
3321: }
3322:
3323: /*
3324: * Configure the adapter for associated state.
3325: */
3326: static int
3327: iwn_run(struct iwn_softc *sc)
3328: {
3329: struct ieee80211com *ic = &sc->sc_ic;
3330: struct ieee80211_node *ni = ic->ic_bss;
3331: int error;
3332:
3333: if (ic->ic_opmode == IEEE80211_M_MONITOR) {
3334: /* link LED blinks while monitoring */
3335: iwn_set_led(sc, IWN_LED_LINK, 5, 5);
3336: return 0;
3337: }
3338:
3339: iwn_enable_tsf(sc, ni);
3340:
3341: /* update adapter's configuration */
3342: sc->config.associd = htole16(ni->ni_associd & ~0xc000);
3343: /* short preamble/slot time are negotiated when associating */
3344: sc->config.flags &= ~htole32(IWN_CONFIG_SHPREAMBLE |
3345: IWN_CONFIG_SHSLOT);
3346: if (ic->ic_flags & IEEE80211_F_SHSLOT)
3347: sc->config.flags |= htole32(IWN_CONFIG_SHSLOT);
3348: if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
3349: sc->config.flags |= htole32(IWN_CONFIG_SHPREAMBLE);
3350: sc->config.filter |= htole32(IWN_FILTER_BSS);
3351:
3352: DPRINTF(("config chan %d flags %x\n", sc->config.chan,
1.2 ober 3353: sc->config.flags));
1.1 ober 3354: error = iwn_cmd(sc, IWN_CMD_CONFIGURE, &sc->config,
3355: sizeof (struct iwn_config), 1);
3356: if (error != 0) {
1.11 blymn 3357: aprint_error_dev(sc->sc_dev,
3358: "could not update configuration\n");
1.1 ober 3359: return error;
3360: }
3361:
3362: /* configuration has changed, set Tx power accordingly */
3363: if ((error = iwn_set_txpower(sc, ni->ni_chan, 1)) != 0) {
3364: aprint_error_dev(sc->sc_dev, "could not set Tx power\n");
3365: return error;
3366: }
3367:
3368: /* add BSS node */
1.20 blymn 3369: iwn_add_node(sc, ni, false, true,
3370: (3 << IWN_AMDPU_SIZE_FACTOR_SHIFT |
3371: 5 << IWN_AMDPU_DENSITY_SHIFT));
1.1 ober 3372:
3373: if (ic->ic_opmode == IEEE80211_M_STA) {
3374: /* fake a join to init the tx rate */
1.2 ober 3375: iwn_newassoc(ni, 1);
1.1 ober 3376: }
3377:
3378: if ((error = iwn_init_sensitivity(sc)) != 0) {
3379: aprint_error_dev(sc->sc_dev, "could not set sensitivity\n");
3380: return error;
3381: }
3382:
3383: /* start periodic calibration timer */
1.8 blymn 3384: sc->calib.state = IWN_CALIB_STATE_ASSOC;
1.1 ober 3385: sc->calib_cnt = 0;
3386: callout_schedule(&sc->calib_to, hz / 2);
3387:
1.11 blymn 3388: if (0 == 1) { /* XXX don't do the beacon - we get a firmware error
1.15 christos 3389: XXX when we try. Something is wrong with the
3390: XXX setup of the frame. Just don't ever call
1.11 blymn 3391: XXX the function but reference it to keep gcc happy
3392: */
3393: /* now we are associated set up the beacon frame */
3394: if ((error = iwn_setup_beacon(sc, ni))) {
3395: aprint_error_dev(sc->sc_dev,
3396: "could not setup beacon frame\n");
3397: return error;
3398: }
3399: }
3400:
3401:
1.1 ober 3402: /* link LED always on while associated */
3403: iwn_set_led(sc, IWN_LED_LINK, 0, 1);
3404:
3405: return 0;
3406: }
3407:
3408: /*
1.15 christos 3409: * Send a scan request to the firmware. Since this command is huge, we map it
1.20 blymn 3410: * into a mbuf instead of using the pre-allocated set of commands. this function
3411: * implemented as iwl4965_bg_request_scan in the linux driver.
1.1 ober 3412: */
3413: static int
3414: iwn_scan(struct iwn_softc *sc, uint16_t flags)
3415: {
3416: struct ieee80211com *ic = &sc->sc_ic;
3417: struct iwn_tx_ring *ring = &sc->txq[4];
3418: struct iwn_tx_desc *desc;
3419: struct iwn_tx_data *data;
3420: struct iwn_tx_cmd *cmd;
3421: struct iwn_cmd_data *tx;
3422: struct iwn_scan_hdr *hdr;
3423: struct iwn_scan_chan *chan;
3424: struct ieee80211_frame *wh;
3425: struct ieee80211_rateset *rs;
3426: struct ieee80211_channel *c;
3427: enum ieee80211_phymode mode;
3428: uint8_t *frm;
3429: int pktlen, error, nrates;
3430:
3431: desc = &ring->desc[ring->cur];
3432: data = &ring->data[ring->cur];
3433:
1.20 blymn 3434: /*
3435: * allocate an mbuf and initialize it so that it contains a packet
3436: * header. M_DONTWAIT can fail and MT_DATA means it is dynamically
3437: * allocated.
3438: */
1.1 ober 3439: MGETHDR(data->m, M_DONTWAIT, MT_DATA);
3440: if (data->m == NULL) {
3441: aprint_error_dev(sc->sc_dev, "could not allocate mbuf for scan command\n");
3442: return ENOMEM;
3443: }
1.20 blymn 3444:
3445: /*
3446: * allocates and adds an mbuf cluster to a normal mbuf m. the how
3447: * is M_DONTWAIT and the flag M_EXT is set upon success.
3448: */
1.1 ober 3449: MCLGET(data->m, M_DONTWAIT);
3450: if (!(data->m->m_flags & M_EXT)) {
3451: m_freem(data->m);
3452: data->m = NULL;
3453: aprint_error_dev(sc->sc_dev, "could not allocate mbuf for scan command\n");
3454: return ENOMEM;
3455: }
3456:
1.20 blymn 3457: /*
3458: * returns a pointer to the data contained in the specified mbuf.
3459: * in this case it is our iwn_tx_cmd. we initialize the basic
3460: * members of the command here with exception to data[136].
3461: */
1.1 ober 3462: cmd = mtod(data->m, struct iwn_tx_cmd *);
3463: cmd->code = IWN_CMD_SCAN;
3464: cmd->flags = 0;
3465: cmd->qid = ring->qid;
3466: cmd->idx = ring->cur;
3467:
3468: hdr = (struct iwn_scan_hdr *)cmd->data;
3469: memset(hdr, 0, sizeof (struct iwn_scan_hdr));
3470: /*
3471: * Move to the next channel if no packets are received within 5 msecs
3472: * after sending the probe request (this helps to reduce the duration
3473: * of active scans).
3474: */
3475: hdr->quiet = htole16(5); /* timeout in milliseconds */
3476: hdr->plcp_threshold = htole16(1); /* min # of packets */
3477:
3478: /* select Ant B and Ant C for scanning */
3479: hdr->rxchain = htole16(0x3e1 | 7 << IWN_RXCHAIN_ANTMSK_SHIFT);
3480:
1.22.2.1! skrll 3481: tx = &(hdr->tx_cmd);
1.20 blymn 3482: /*
3483: * linux
3484: * flags = IWN_TX_AUTO_SEQ
3485: * 0x200 is rate selection?
3486: * id = ???
3487: * lifetime = IWN_LIFETIME_INFINITE
3488: *
3489: */
1.1 ober 3490: tx->flags = htole32(IWN_TX_AUTO_SEQ | 0x200); // XXX
3491: tx->id = IWN_ID_BROADCAST;
3492: tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
3493: tx->rflags = IWN_RFLAG_ANT_B;
3494:
3495: if (flags & IEEE80211_CHAN_A) {
3496: hdr->crc_threshold = htole16(1);
3497: /* send probe requests at 6Mbps */
3498: tx->rate = iwn_ridx_to_plcp[IWN_OFDM6];
3499: } else {
3500: hdr->flags = htole32(IWN_CONFIG_24GHZ | IWN_CONFIG_AUTO);
3501: /* send probe requests at 1Mbps */
3502: tx->rate = iwn_ridx_to_plcp[IWN_CCK1];
3503: tx->rflags |= IWN_RFLAG_CCK;
3504: }
3505:
1.22.2.1! skrll 3506: hdr->scan_essid[0].id = IEEE80211_ELEMID_SSID;
! 3507: hdr->scan_essid[0].len = ic->ic_des_esslen;
! 3508: memcpy(hdr->scan_essid[0].data, ic->ic_des_essid, ic->ic_des_esslen);
1.1 ober 3509:
3510: /*
1.15 christos 3511: * Build a probe request frame. Most of the following code is a
1.1 ober 3512: * copy & paste of what is done in net80211.
3513: */
1.22.2.1! skrll 3514: wh = &(hdr->wh);
1.1 ober 3515: wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
3516: IEEE80211_FC0_SUBTYPE_PROBE_REQ;
3517: wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
3518: IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
3519: IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
3520: IEEE80211_ADDR_COPY(wh->i_addr3, etherbroadcastaddr);
3521: *(u_int16_t *)&wh->i_dur[0] = 0; /* filled by h/w */
3522: *(u_int16_t *)&wh->i_seq[0] = 0; /* filled by h/w */
3523:
1.22.2.1! skrll 3524: frm = &(hdr->data[0]);
1.1 ober 3525:
1.22.2.1! skrll 3526: /* add empty SSID IE */
1.1 ober 3527: *frm++ = IEEE80211_ELEMID_SSID;
1.22.2.1! skrll 3528: *frm++ = ic->ic_des_esslen;
! 3529: memcpy(frm, ic->ic_des_essid, ic->ic_des_esslen);
! 3530: frm += ic->ic_des_esslen;
1.1 ober 3531:
3532: mode = ieee80211_chan2mode(ic, ic->ic_ibss_chan);
3533: rs = &ic->ic_sup_rates[mode];
3534:
3535: /* add supported rates IE */
3536:
3537: *frm++ = IEEE80211_ELEMID_RATES;
3538: nrates = rs->rs_nrates;
3539: if (nrates > IEEE80211_RATE_SIZE)
3540: nrates = IEEE80211_RATE_SIZE;
3541: *frm++ = nrates;
3542: memcpy(frm, rs->rs_rates, nrates);
3543: frm += nrates;
3544:
3545: /* add supported xrates IE */
3546:
3547: if (rs->rs_nrates > IEEE80211_RATE_SIZE) {
3548: nrates = rs->rs_nrates - IEEE80211_RATE_SIZE;
3549: *frm++ = IEEE80211_ELEMID_XRATES;
3550: *frm++ = nrates;
3551: memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates);
3552: frm += nrates;
3553: }
3554:
3555: /* setup length of probe request */
3556: tx->len = htole16(frm - (uint8_t *)wh);
3557:
3558: chan = (struct iwn_scan_chan *)frm;
1.15 christos 3559: for (c = &ic->ic_channels[1];
1.1 ober 3560: c <= &ic->ic_channels[IEEE80211_CHAN_MAX]; c++) {
3561: if ((c->ic_flags & flags) != flags)
3562: continue;
3563:
3564: chan->chan = ieee80211_chan2ieee(ic, c);
3565: chan->flags = 0;
3566: if (!(c->ic_flags & IEEE80211_CHAN_PASSIVE)) {
3567: chan->flags |= IWN_CHAN_ACTIVE;
3568: if (ic->ic_des_esslen != 0)
3569: chan->flags |= IWN_CHAN_DIRECT;
3570: }
3571: chan->dsp_gain = 0x6e;
3572: if (IEEE80211_IS_CHAN_5GHZ(c)) {
3573: chan->rf_gain = 0x3b;
3574: chan->active = htole16(10);
3575: chan->passive = htole16(110);
3576: } else {
3577: chan->rf_gain = 0x28;
3578: chan->active = htole16(20);
3579: chan->passive = htole16(120);
3580: }
3581: hdr->nchan++;
3582: chan++;
3583:
3584: frm += sizeof (struct iwn_scan_chan);
3585: }
3586:
3587: hdr->len = htole16(frm - (uint8_t *)hdr);
3588: pktlen = frm - (uint8_t *)cmd;
3589:
3590: error = bus_dmamap_load(sc->sc_dmat, data->map, cmd, pktlen, NULL,
3591: BUS_DMA_NOWAIT);
3592: if (error) {
3593: aprint_error_dev(sc->sc_dev, "could not map scan command\n");
3594: m_freem(data->m);
3595: data->m = NULL;
3596: return error;
3597: }
3598:
3599: IWN_SET_DESC_NSEGS(desc, 1);
3600: IWN_SET_DESC_SEG(desc, 0, data->map->dm_segs[0].ds_addr,
3601: data->map->dm_segs[0].ds_len);
3602: sc->shared->len[ring->qid][ring->cur] = htole16(8);
3603: if (ring->cur < IWN_TX_WINDOW) {
3604: sc->shared->len[ring->qid][ring->cur + IWN_TX_RING_COUNT] =
3605: htole16(8);
3606: }
3607:
1.20 blymn 3608: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
3609: data->map->dm_segs[0].ds_len, BUS_DMASYNC_PREWRITE);
3610:
1.1 ober 3611: /* kick cmd ring */
3612: ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT;
3613: IWN_WRITE(sc, IWN_TX_WIDX, ring->qid << 8 | ring->cur);
3614:
3615: return 0; /* will be notified async. of failure/success */
3616: }
3617:
3618: static int
3619: iwn_config(struct iwn_softc *sc)
3620: {
3621: struct ieee80211com *ic = &sc->sc_ic;
3622: struct ifnet *ifp = ic->ic_ifp;
3623: struct iwn_power power;
3624: struct iwn_bluetooth bluetooth;
3625: int error;
3626:
3627: /* set power mode */
3628: memset(&power, 0, sizeof power);
3629: power.flags = htole16(IWN_POWER_CAM | 0x8);
3630: DPRINTF(("setting power mode\n"));
3631: error = iwn_cmd(sc, IWN_CMD_SET_POWER_MODE, &power, sizeof power, 0);
3632: if (error != 0) {
3633: aprint_error_dev(sc->sc_dev, "could not set power mode\n");
3634: return error;
3635: }
3636:
3637: /* configure bluetooth coexistence */
3638: memset(&bluetooth, 0, sizeof bluetooth);
3639: bluetooth.flags = 3;
3640: bluetooth.lead = 0xaa;
3641: bluetooth.kill = 1;
3642: DPRINTF(("configuring bluetooth coexistence\n"));
3643: error = iwn_cmd(sc, IWN_CMD_BLUETOOTH, &bluetooth, sizeof bluetooth,
3644: 0);
3645: if (error != 0) {
3646: aprint_error_dev(sc->sc_dev, "could not configure bluetooth coexistence\n");
3647: return error;
3648: }
3649:
3650: /* configure adapter */
3651: memset(&sc->config, 0, sizeof (struct iwn_config));
3652: IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
3653: IEEE80211_ADDR_COPY(sc->config.myaddr, ic->ic_myaddr);
3654: IEEE80211_ADDR_COPY(sc->config.wlap, ic->ic_myaddr);
3655: /* set default channel */
1.22.2.1! skrll 3656: sc->config.chan = htole16(ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
1.1 ober 3657: sc->config.flags = htole32(IWN_CONFIG_TSF);
3658: if (IEEE80211_IS_CHAN_2GHZ(ic->ic_ibss_chan)) {
3659: sc->config.flags |= htole32(IWN_CONFIG_AUTO |
3660: IWN_CONFIG_24GHZ);
3661: }
3662: sc->config.filter = 0;
3663: switch (ic->ic_opmode) {
3664: case IEEE80211_M_STA:
3665: sc->config.mode = IWN_MODE_STA;
3666: sc->config.filter |= htole32(IWN_FILTER_MULTICAST);
3667: break;
3668: case IEEE80211_M_IBSS:
3669: case IEEE80211_M_AHDEMO:
3670: sc->config.mode = IWN_MODE_IBSS;
3671: break;
3672: case IEEE80211_M_HOSTAP:
3673: sc->config.mode = IWN_MODE_HOSTAP;
3674: break;
3675: case IEEE80211_M_MONITOR:
3676: sc->config.mode = IWN_MODE_MONITOR;
3677: sc->config.filter |= htole32(IWN_FILTER_MULTICAST |
3678: IWN_FILTER_CTL | IWN_FILTER_PROMISC);
3679: break;
3680: }
3681: sc->config.cck_mask = 0x0f; /* not yet negotiated */
3682: sc->config.ofdm_mask = 0xff; /* not yet negotiated */
3683: sc->config.ht_single_mask = 0xff;
3684: sc->config.ht_dual_mask = 0xff;
3685: sc->config.rxchain = htole16(0x2800 | 7 << IWN_RXCHAIN_ANTMSK_SHIFT);
3686: DPRINTF(("setting configuration\n"));
3687: error = iwn_cmd(sc, IWN_CMD_CONFIGURE, &sc->config,
3688: sizeof (struct iwn_config), 0);
3689: if (error != 0) {
3690: aprint_error_dev(sc->sc_dev, "configure command failed\n");
3691: return error;
3692: }
3693:
3694: /* configuration has changed, set Tx power accordingly */
3695: if ((error = iwn_set_txpower(sc, ic->ic_ibss_chan, 0)) != 0) {
3696: aprint_error_dev(sc->sc_dev, "could not set Tx power\n");
3697: return error;
3698: }
3699:
3700: /* add broadcast node */
1.20 blymn 3701: if ((error = iwn_add_node(sc, NULL, true, false, 0)) != 0)
1.1 ober 3702: return error;
3703:
3704: if ((error = iwn_set_critical_temp(sc)) != 0) {
3705: aprint_error_dev(sc->sc_dev, "could not set critical temperature\n");
3706: return error;
3707: }
3708:
3709: return 0;
3710: }
3711:
3712: /*
3713: * Do post-alive initialization of the NIC (after firmware upload).
3714: */
3715: static void
3716: iwn_post_alive(struct iwn_softc *sc)
3717: {
3718: uint32_t base;
3719: uint16_t offset;
3720: int qid;
3721:
3722: iwn_mem_lock(sc);
3723:
3724: /* clear SRAM */
3725: base = iwn_mem_read(sc, IWN_SRAM_BASE);
3726: for (offset = 0x380; offset < 0x520; offset += 4) {
3727: IWN_WRITE(sc, IWN_MEM_WADDR, base + offset);
3728: IWN_WRITE(sc, IWN_MEM_WDATA, 0);
3729: }
3730:
3731: /* shared area is aligned on a 1K boundary */
3732: iwn_mem_write(sc, IWN_SRAM_BASE, sc->shared_dma.paddr >> 10);
3733: iwn_mem_write(sc, IWN_SELECT_QCHAIN, 0);
3734:
3735: for (qid = 0; qid < IWN_NTXQUEUES; qid++) {
3736: iwn_mem_write(sc, IWN_QUEUE_RIDX(qid), 0);
3737: IWN_WRITE(sc, IWN_TX_WIDX, qid << 8 | 0);
3738:
3739: /* set sched. window size */
3740: IWN_WRITE(sc, IWN_MEM_WADDR, base + IWN_QUEUE_OFFSET(qid));
3741: IWN_WRITE(sc, IWN_MEM_WDATA, 64);
3742: /* set sched. frame limit */
3743: IWN_WRITE(sc, IWN_MEM_WADDR, base + IWN_QUEUE_OFFSET(qid) + 4);
3744: IWN_WRITE(sc, IWN_MEM_WDATA, 64 << 16);
3745: }
3746:
3747: /* enable interrupts for all 16 queues */
3748: iwn_mem_write(sc, IWN_QUEUE_INTR_MASK, 0xffff);
3749:
3750: /* identify active Tx rings (0-7) */
3751: iwn_mem_write(sc, IWN_TX_ACTIVE, 0xff);
3752:
3753: /* mark Tx rings (4 EDCA + cmd + 2 HCCA) as active */
3754: for (qid = 0; qid < 7; qid++) {
3755: iwn_mem_write(sc, IWN_TXQ_STATUS(qid),
3756: IWN_TXQ_STATUS_ACTIVE | qid << 1);
3757: }
3758:
3759: iwn_mem_unlock(sc);
3760: }
3761:
3762: static void
3763: iwn_stop_master(struct iwn_softc *sc)
3764: {
3765: uint32_t tmp;
3766: int ntries;
3767:
3768: tmp = IWN_READ(sc, IWN_RESET);
3769: IWN_WRITE(sc, IWN_RESET, tmp | IWN_STOP_MASTER);
3770:
3771: tmp = IWN_READ(sc, IWN_GPIO_CTL);
3772: if ((tmp & IWN_GPIO_PWR_STATUS) == IWN_GPIO_PWR_SLEEP)
1.15 christos 3773: return; /* already asleep */
1.1 ober 3774:
3775: for (ntries = 0; ntries < 100; ntries++) {
3776: if (IWN_READ(sc, IWN_RESET) & IWN_MASTER_DISABLED)
3777: break;
3778: DELAY(10);
3779: }
3780: if (ntries == 100) {
3781: aprint_error_dev(sc->sc_dev, "timeout waiting for master\n");
3782: }
3783: }
3784:
3785: static int
3786: iwn_reset(struct iwn_softc *sc)
3787: {
3788: uint32_t tmp;
3789: int ntries;
3790:
3791: /* clear any pending interrupts */
3792: IWN_WRITE(sc, IWN_INTR, 0xffffffff);
3793:
3794: tmp = IWN_READ(sc, IWN_CHICKEN);
3795: IWN_WRITE(sc, IWN_CHICKEN, tmp | IWN_CHICKEN_DISLOS);
3796:
3797: tmp = IWN_READ(sc, IWN_GPIO_CTL);
3798: IWN_WRITE(sc, IWN_GPIO_CTL, tmp | IWN_GPIO_INIT);
3799:
3800: /* wait for clock stabilization */
3801: for (ntries = 0; ntries < 1000; ntries++) {
3802: if (IWN_READ(sc, IWN_GPIO_CTL) & IWN_GPIO_CLOCK)
3803: break;
3804: DELAY(10);
3805: }
3806: if (ntries == 1000) {
3807: aprint_error_dev(sc->sc_dev, "timeout waiting for clock stabilization\n");
3808: return ETIMEDOUT;
3809: }
3810: return 0;
3811: }
3812:
3813: static void
3814: iwn_hw_config(struct iwn_softc *sc)
3815: {
3816: uint32_t tmp, hw;
3817:
3818: /* enable interrupts mitigation */
3819: IWN_WRITE(sc, IWN_INTR_MIT, 512 / 32);
3820:
3821: /* voodoo from the reference driver */
3822: tmp = pci_conf_read(sc->sc_pct, sc->sc_pcitag, PCI_CLASS_REG);
3823: tmp = PCI_REVISION(tmp);
3824: if ((tmp & 0x80) && (tmp & 0x7f) < 8) {
3825: /* enable "no snoop" field */
3826: tmp = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0xe8);
3827: tmp &= ~IWN_DIS_NOSNOOP;
3828: pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0xe8, tmp);
3829: }
3830:
3831: /* disable L1 entry to work around a hardware bug */
3832: tmp = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0xf0);
3833: tmp &= ~IWN_ENA_L1;
3834: pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0xf0, tmp);
3835:
3836: hw = IWN_READ(sc, IWN_HWCONFIG);
3837: IWN_WRITE(sc, IWN_HWCONFIG, hw | 0x310);
3838:
3839: iwn_mem_lock(sc);
3840: tmp = iwn_mem_read(sc, IWN_MEM_POWER);
3841: iwn_mem_write(sc, IWN_MEM_POWER, tmp | IWN_POWER_RESET);
3842: DELAY(5);
3843: tmp = iwn_mem_read(sc, IWN_MEM_POWER);
3844: iwn_mem_write(sc, IWN_MEM_POWER, tmp & ~IWN_POWER_RESET);
3845: iwn_mem_unlock(sc);
3846: }
3847:
3848: static int
3849: iwn_init(struct ifnet *ifp)
3850: {
3851: struct iwn_softc *sc = ifp->if_softc;
3852: struct ieee80211com *ic = &sc->sc_ic;
3853: uint32_t tmp;
3854: int error, qid;
3855:
3856: iwn_stop(ifp, 1);
3857: if ((error = iwn_reset(sc)) != 0) {
3858: aprint_error_dev(sc->sc_dev, "could not reset adapter\n");
3859: goto fail1;
3860: }
3861:
3862: iwn_mem_lock(sc);
3863: iwn_mem_read(sc, IWN_CLOCK_CTL);
3864: iwn_mem_write(sc, IWN_CLOCK_CTL, 0xa00);
3865: iwn_mem_read(sc, IWN_CLOCK_CTL);
3866: iwn_mem_unlock(sc);
3867:
3868: DELAY(20);
3869:
3870: iwn_mem_lock(sc);
3871: tmp = iwn_mem_read(sc, IWN_MEM_PCIDEV);
3872: iwn_mem_write(sc, IWN_MEM_PCIDEV, tmp | 0x800);
3873: iwn_mem_unlock(sc);
3874:
3875: iwn_mem_lock(sc);
3876: tmp = iwn_mem_read(sc, IWN_MEM_POWER);
3877: iwn_mem_write(sc, IWN_MEM_POWER, tmp & ~0x03000000);
3878: iwn_mem_unlock(sc);
3879:
3880: iwn_hw_config(sc);
3881:
3882: /* init Rx ring */
3883: iwn_mem_lock(sc);
3884: IWN_WRITE(sc, IWN_RX_CONFIG, 0);
3885: IWN_WRITE(sc, IWN_RX_WIDX, 0);
3886: /* Rx ring is aligned on a 256-byte boundary */
3887: IWN_WRITE(sc, IWN_RX_BASE, sc->rxq.desc_dma.paddr >> 8);
3888: /* shared area is aligned on a 16-byte boundary */
3889: IWN_WRITE(sc, IWN_RW_WIDX_PTR, (sc->shared_dma.paddr +
1.2 ober 3890: offsetof(struct iwn_shared, closed_count)) >> 4);
1.1 ober 3891: IWN_WRITE(sc, IWN_RX_CONFIG, 0x80601000);
3892: iwn_mem_unlock(sc);
3893:
3894: IWN_WRITE(sc, IWN_RX_WIDX, (IWN_RX_RING_COUNT - 1) & ~7);
3895:
3896: iwn_mem_lock(sc);
3897: iwn_mem_write(sc, IWN_TX_ACTIVE, 0);
3898:
3899: /* set physical address of "keep warm" page */
3900: IWN_WRITE(sc, IWN_KW_BASE, sc->kw_dma.paddr >> 4);
3901:
3902: /* init Tx rings */
3903: for (qid = 0; qid < IWN_NTXQUEUES; qid++) {
3904: struct iwn_tx_ring *txq = &sc->txq[qid];
3905: IWN_WRITE(sc, IWN_TX_BASE(qid), txq->desc_dma.paddr >> 8);
3906: IWN_WRITE(sc, IWN_TX_CONFIG(qid), 0x80000008);
3907: }
3908: iwn_mem_unlock(sc);
3909:
3910: /* clear "radio off" and "disable command" bits (reversed logic) */
3911: IWN_WRITE(sc, IWN_UCODE_CLR, IWN_RADIO_OFF);
3912: IWN_WRITE(sc, IWN_UCODE_CLR, IWN_DISABLE_CMD);
3913:
3914: /* clear any pending interrupts */
3915: IWN_WRITE(sc, IWN_INTR, 0xffffffff);
3916: /* enable interrupts */
3917: IWN_WRITE(sc, IWN_MASK, IWN_INTR_MASK);
3918:
3919: /* not sure why/if this is necessary... */
3920: IWN_WRITE(sc, IWN_UCODE_CLR, IWN_RADIO_OFF);
3921: IWN_WRITE(sc, IWN_UCODE_CLR, IWN_RADIO_OFF);
3922:
3923: /* check that the radio is not disabled by RF switch */
3924: if (!(IWN_READ(sc, IWN_GPIO_CTL) & IWN_GPIO_RF_ENABLED)) {
3925: aprint_error_dev(sc->sc_dev, "radio is disabled by hardware switch\n");
1.22.2.1! skrll 3926: sc->sc_radio = false;
1.1 ober 3927: error = EBUSY; /* XXX ;-) */
3928: goto fail1;
3929: }
3930:
1.22.2.1! skrll 3931: sc->sc_radio = true;
! 3932:
1.1 ober 3933: if ((error = iwn_load_firmware(sc)) != 0) {
3934: aprint_error_dev(sc->sc_dev, "could not load firmware\n");
3935: goto fail1;
3936: }
3937:
3938: /* firmware has notified us that it is alive.. */
3939: iwn_post_alive(sc); /* ..do post alive initialization */
3940:
3941: sc->rawtemp = sc->ucode_info.temp[3].chan20MHz;
3942: sc->temp = iwn_get_temperature(sc);
3943: DPRINTF(("temperature=%d\n", sc->temp));
1.8 blymn 3944:
1.1 ober 3945: if ((error = iwn_config(sc)) != 0) {
3946: aprint_error_dev(sc->sc_dev, "could not configure device\n");
3947: goto fail1;
3948: }
3949:
3950: DPRINTF(("iwn_config end\n"));
3951:
3952: ifp->if_flags &= ~IFF_OACTIVE;
3953: ifp->if_flags |= IFF_RUNNING;
3954:
3955: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1.13 christos 3956: if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
1.1 ober 3957: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
3958: }
3959: else
3960: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
3961:
3962: DPRINTF(("iwn_init ok\n"));
3963: return 0;
3964:
1.8 blymn 3965: fail1:
1.1 ober 3966: DPRINTF(("iwn_init error\n"));
3967: iwn_stop(ifp, 1);
3968: return error;
3969: }
3970:
3971: static void
3972: iwn_stop(struct ifnet *ifp, int disable)
3973: {
3974: struct iwn_softc *sc = ifp->if_softc;
3975: struct ieee80211com *ic = &sc->sc_ic;
3976: uint32_t tmp;
3977: int i;
3978:
3979: ifp->if_timer = sc->sc_tx_timer = 0;
3980: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
3981:
3982: ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3983:
3984: IWN_WRITE(sc, IWN_RESET, IWN_NEVO_RESET);
3985:
3986: /* disable interrupts */
3987: IWN_WRITE(sc, IWN_MASK, 0);
3988: IWN_WRITE(sc, IWN_INTR, 0xffffffff);
3989: IWN_WRITE(sc, IWN_INTR_STATUS, 0xffffffff);
3990:
3991: /* make sure we no longer hold the memory lock */
3992: iwn_mem_unlock(sc);
3993:
3994: /* reset all Tx rings */
3995: for (i = 0; i < IWN_NTXQUEUES; i++)
3996: iwn_reset_tx_ring(sc, &sc->txq[i]);
3997:
3998: /* reset Rx ring */
3999: iwn_reset_rx_ring(sc, &sc->rxq);
4000:
4001: iwn_mem_lock(sc);
4002: iwn_mem_write(sc, IWN_MEM_CLOCK2, 0x200);
4003: iwn_mem_unlock(sc);
4004:
4005: DELAY(5);
4006:
4007: iwn_stop_master(sc);
4008: tmp = IWN_READ(sc, IWN_RESET);
4009: IWN_WRITE(sc, IWN_RESET, tmp | IWN_SW_RESET);
4010: }
4011:
4012: static bool
1.7 taca 4013: iwn_resume(device_t dv PMF_FN_ARGS)
1.1 ober 4014: {
4015: struct iwn_softc *sc = device_private(dv);
4016:
4017: (void)iwn_reset(sc);
4018:
4019: return true;
4020: }
CVSweb <webmaster@jp.NetBSD.org>