Annotation of src/sys/dev/usb/if_urtwn.c, Revision 1.26
1.26 ! christos 1: /* $NetBSD: if_urtwn.c,v 1.25 2013/08/10 21:15:26 jnemeth Exp $ */
1.1 nonaka 2: /* $OpenBSD: if_urtwn.c,v 1.20 2011/11/26 06:39:33 ckuethe Exp $ */
3:
4: /*-
5: * Copyright (c) 2010 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:
1.8 christos 20: /*-
1.1 nonaka 21: * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188RU/RTL8192CU.
22: */
23:
24: #include <sys/cdefs.h>
1.26 ! christos 25: __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.25 2013/08/10 21:15:26 jnemeth Exp $");
1.11 jmcneill 26:
27: #ifdef _KERNEL_OPT
28: #include "opt_inet.h"
29: #endif
1.1 nonaka 30:
31: #include <sys/param.h>
32: #include <sys/sockio.h>
33: #include <sys/sysctl.h>
34: #include <sys/mbuf.h>
35: #include <sys/kernel.h>
36: #include <sys/socket.h>
37: #include <sys/systm.h>
38: #include <sys/malloc.h>
39: #include <sys/module.h>
40: #include <sys/conf.h>
41: #include <sys/device.h>
42:
43: #include <sys/bus.h>
44: #include <machine/endian.h>
45: #include <sys/intr.h>
46:
47: #include <net/bpf.h>
48: #include <net/if.h>
49: #include <net/if_arp.h>
50: #include <net/if_dl.h>
51: #include <net/if_ether.h>
52: #include <net/if_media.h>
53: #include <net/if_types.h>
54:
55: #include <netinet/in.h>
56: #include <netinet/in_systm.h>
57: #include <netinet/in_var.h>
58: #include <netinet/ip.h>
1.11 jmcneill 59: #include <netinet/if_inarp.h>
1.1 nonaka 60:
61: #include <net80211/ieee80211_netbsd.h>
62: #include <net80211/ieee80211_var.h>
63: #include <net80211/ieee80211_radiotap.h>
64:
65: #include <dev/firmload.h>
66:
67: #include <dev/usb/usb.h>
68: #include <dev/usb/usbdi.h>
69: #include <dev/usb/usbdivar.h>
70: #include <dev/usb/usbdi_util.h>
71: #include <dev/usb/usbdevs.h>
72:
73: #include <dev/usb/if_urtwnreg.h>
74: #include <dev/usb/if_urtwnvar.h>
75: #include <dev/usb/if_urtwn_data.h>
76:
1.12 christos 77: /*
78: * The sc_write_mtx locking is to prevent sequences of writes from
79: * being intermingled with each other. I don't know if this is really
80: * needed. I have added it just to be on the safe side.
81: */
82:
1.1 nonaka 83: #ifdef URTWN_DEBUG
84: #define DBG_INIT __BIT(0)
85: #define DBG_FN __BIT(1)
86: #define DBG_TX __BIT(2)
87: #define DBG_RX __BIT(3)
88: #define DBG_STM __BIT(4)
89: #define DBG_RF __BIT(5)
90: #define DBG_REG __BIT(6)
91: #define DBG_ALL 0xffffffffU
1.10 jmcneill 92: u_int urtwn_debug = 0;
1.1 nonaka 93: #define DPRINTFN(n, s) \
94: do { if (urtwn_debug & (n)) printf s; } while (/*CONSTCOND*/0)
95: #else
96: #define DPRINTFN(n, s)
97: #endif
98:
99: static const struct usb_devno urtwn_devs[] = {
100: { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RTL8188CU_1 },
101: { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RTL8188CU_2 },
102: { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RTL8192CU },
1.3 nonaka 103: { USB_VENDOR_ASUSTEK, USB_PRODUCT_ASUSTEK_RTL8192CU },
1.1 nonaka 104: { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8188CE_1 },
105: { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8188CE_2 },
1.3 nonaka 106: { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8188CU },
1.1 nonaka 107: { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8188CU },
1.3 nonaka 108: { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8192CU },
109: { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_RTL8188CUS_1 },
110: { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_RTL8188CUS_2 },
111: { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_RTL8188CUS_3 },
112: { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_RTL8188CUS_4 },
113: { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_RTL8188CUS_5 },
1.1 nonaka 114: { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_RTL8192CU },
115: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RTL8188CU },
116: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RTL8192CU_1 },
117: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RTL8192CU_2 },
118: { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RTL8192CU_3 },
119: { USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_RTL8188CU },
120: { USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_RTL8192CU },
121: { USB_VENDOR_FEIXUN, USB_PRODUCT_FEIXUN_RTL8188CU },
122: { USB_VENDOR_FEIXUN, USB_PRODUCT_FEIXUN_RTL8192CU },
123: { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWNUP150 },
1.3 nonaka 124: { USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_RTL8192CU },
1.1 nonaka 125: { USB_VENDOR_HP3, USB_PRODUCT_HP3_RTL8188CU },
126: { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WNA1000M },
1.3 nonaka 127: { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_RTL8192CU },
128: { USB_VENDOR_NETGEAR4, USB_PRODUCT_NETGEAR4_RTL8188CU },
1.1 nonaka 129: { USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RTL8188CU },
130: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RTL8188CU_1 },
131: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RTL8188CU_2 },
132: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RTL8192CU },
1.3 nonaka 133: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RTL8188CU_3 },
134: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RTL8188CU_4 },
135: { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RTL8188CUS },
1.1 nonaka 136: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CE_0 },
137: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CE_1 },
1.3 nonaka 138: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CTV },
1.1 nonaka 139: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CU_0 },
140: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CU_1 },
141: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CU_2 },
1.3 nonaka 142: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CU_COMBO },
143: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188CUS },
1.1 nonaka 144: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188RU },
1.3 nonaka 145: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8188RU_2 },
1.1 nonaka 146: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8191CU },
147: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8192CE },
148: { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8192CU },
149: { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8188CU },
1.3 nonaka 150: { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8188CU_2 },
151: { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8192CU },
1.25 jnemeth 152: { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8192CUR2 },
1.1 nonaka 153: { USB_VENDOR_TRENDNET, USB_PRODUCT_TRENDNET_RTL8188CU },
1.3 nonaka 154: { USB_VENDOR_TRENDNET, USB_PRODUCT_TRENDNET_RTL8192CU },
1.1 nonaka 155: { USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RTL8192CU }
156: };
157:
158: static int urtwn_match(device_t, cfdata_t, void *);
159: static void urtwn_attach(device_t, device_t, void *);
160: static int urtwn_detach(device_t, int);
161: static int urtwn_activate(device_t, enum devact);
162:
163: CFATTACH_DECL_NEW(urtwn, sizeof(struct urtwn_softc), urtwn_match,
164: urtwn_attach, urtwn_detach, urtwn_activate);
165:
166: static int urtwn_open_pipes(struct urtwn_softc *);
167: static void urtwn_close_pipes(struct urtwn_softc *);
168: static int urtwn_alloc_rx_list(struct urtwn_softc *);
169: static void urtwn_free_rx_list(struct urtwn_softc *);
170: static int urtwn_alloc_tx_list(struct urtwn_softc *);
171: static void urtwn_free_tx_list(struct urtwn_softc *);
172: static void urtwn_task(void *);
173: static void urtwn_do_async(struct urtwn_softc *,
174: void (*)(struct urtwn_softc *, void *), void *, int);
175: static void urtwn_wait_async(struct urtwn_softc *);
176: static int urtwn_write_region_1(struct urtwn_softc *, uint16_t, uint8_t *,
177: int);
1.12 christos 178: static void urtwn_write_1(struct urtwn_softc *, uint16_t, uint8_t);
179: static void urtwn_write_2(struct urtwn_softc *, uint16_t, uint16_t);
180: static void urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t);
181: static int urtwn_write_region(struct urtwn_softc *, uint16_t, uint8_t *,
182: int);
1.1 nonaka 183: static int urtwn_read_region_1(struct urtwn_softc *, uint16_t, uint8_t *,
184: int);
1.12 christos 185: static uint8_t urtwn_read_1(struct urtwn_softc *, uint16_t);
186: static uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t);
187: static uint32_t urtwn_read_4(struct urtwn_softc *, uint16_t);
1.1 nonaka 188: static int urtwn_fw_cmd(struct urtwn_softc *, uint8_t, const void *, int);
1.12 christos 189: static void urtwn_rf_write(struct urtwn_softc *, int, uint8_t, uint32_t);
1.1 nonaka 190: static uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t);
191: static int urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t);
192: static uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t);
193: static void urtwn_efuse_read(struct urtwn_softc *);
194: static int urtwn_read_chipid(struct urtwn_softc *);
1.12 christos 195: #ifdef URTWN_DEBUG
196: static void urtwn_dump_rom(struct urtwn_softc *, struct r92c_rom *);
197: #endif
1.1 nonaka 198: static void urtwn_read_rom(struct urtwn_softc *);
199: static int urtwn_media_change(struct ifnet *);
200: static int urtwn_ra_init(struct urtwn_softc *);
1.12 christos 201: static int urtwn_get_nettype(struct urtwn_softc *);
202: static void urtwn_set_nettype0_msr(struct urtwn_softc *, uint8_t);
1.1 nonaka 203: static void urtwn_tsf_sync_enable(struct urtwn_softc *);
204: static void urtwn_set_led(struct urtwn_softc *, int, int);
205: static void urtwn_calib_to(void *);
206: static void urtwn_calib_to_cb(struct urtwn_softc *, void *);
207: static void urtwn_next_scan(void *);
208: static int urtwn_newstate(struct ieee80211com *, enum ieee80211_state,
209: int);
210: static void urtwn_newstate_cb(struct urtwn_softc *, void *);
211: static int urtwn_wme_update(struct ieee80211com *);
212: static void urtwn_wme_update_cb(struct urtwn_softc *, void *);
213: static void urtwn_update_avgrssi(struct urtwn_softc *, int, int8_t);
214: static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *);
215: static void urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int);
216: static void urtwn_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
217: static void urtwn_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
218: static int urtwn_tx(struct urtwn_softc *, struct mbuf *,
1.12 christos 219: struct ieee80211_node *, struct urtwn_tx_data *);
1.1 nonaka 220: static void urtwn_start(struct ifnet *);
221: static void urtwn_watchdog(struct ifnet *);
222: static int urtwn_ioctl(struct ifnet *, u_long, void *);
223: static int urtwn_power_on(struct urtwn_softc *);
224: static int urtwn_llt_init(struct urtwn_softc *);
225: static void urtwn_fw_reset(struct urtwn_softc *);
226: static int urtwn_fw_loadpage(struct urtwn_softc *, int, uint8_t *, int);
227: static int urtwn_load_firmware(struct urtwn_softc *);
228: static int urtwn_dma_init(struct urtwn_softc *);
229: static void urtwn_mac_init(struct urtwn_softc *);
230: static void urtwn_bb_init(struct urtwn_softc *);
231: static void urtwn_rf_init(struct urtwn_softc *);
232: static void urtwn_cam_init(struct urtwn_softc *);
233: static void urtwn_pa_bias_init(struct urtwn_softc *);
234: static void urtwn_rxfilter_init(struct urtwn_softc *);
235: static void urtwn_edca_init(struct urtwn_softc *);
236: static void urtwn_write_txpower(struct urtwn_softc *, int, uint16_t[]);
1.22 christos 237: static void urtwn_get_txpower(struct urtwn_softc *, size_t, u_int, u_int,
1.1 nonaka 238: uint16_t[]);
239: static void urtwn_set_txpower(struct urtwn_softc *, u_int, u_int);
240: static void urtwn_set_chan(struct urtwn_softc *, struct ieee80211_channel *,
241: u_int);
242: static void urtwn_iq_calib(struct urtwn_softc *, bool);
243: static void urtwn_lc_calib(struct urtwn_softc *);
244: static void urtwn_temp_calib(struct urtwn_softc *);
245: static int urtwn_init(struct ifnet *);
246: static void urtwn_stop(struct ifnet *, int);
1.16 jmcneill 247: static int urtwn_reset(struct ifnet *);
1.1 nonaka 248: static void urtwn_chip_stop(struct urtwn_softc *);
1.26 ! christos 249: static void urtwn_newassoc(struct ieee80211_node *, int);
1.1 nonaka 250:
251: /* Aliases. */
252: #define urtwn_bb_write urtwn_write_4
253: #define urtwn_bb_read urtwn_read_4
254:
255: static int
256: urtwn_match(device_t parent, cfdata_t match, void *aux)
257: {
258: struct usb_attach_arg *uaa = aux;
259:
260: return ((usb_lookup(urtwn_devs, uaa->vendor, uaa->product) != NULL) ?
261: UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
262: }
263:
264: static void
265: urtwn_attach(device_t parent, device_t self, void *aux)
266: {
267: struct urtwn_softc *sc = device_private(self);
268: struct ieee80211com *ic = &sc->sc_ic;
269: struct ifnet *ifp = &sc->sc_if;
270: struct usb_attach_arg *uaa = aux;
271: char *devinfop;
1.22 christos 272: size_t i;
273: int error;
1.1 nonaka 274:
275: sc->sc_dev = self;
276: sc->sc_udev = uaa->device;
277:
278: aprint_naive("\n");
279: aprint_normal("\n");
280:
1.12 christos 281: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
282:
1.1 nonaka 283: devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
284: aprint_normal_dev(self, "%s\n", devinfop);
285: usbd_devinfo_free(devinfop);
286:
287: mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
1.12 christos 288: mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
1.1 nonaka 289: mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE);
1.12 christos 290: mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE);
1.1 nonaka 291:
1.18 jmcneill 292: usb_init_task(&sc->sc_task, urtwn_task, sc, 0);
1.1 nonaka 293:
294: callout_init(&sc->sc_scan_to, 0);
295: callout_setfunc(&sc->sc_scan_to, urtwn_next_scan, sc);
296: callout_init(&sc->sc_calib_to, 0);
297: callout_setfunc(&sc->sc_calib_to, urtwn_calib_to, sc);
298:
1.6 skrll 299: error = usbd_set_config_no(sc->sc_udev, 1, 0);
300: if (error != 0) {
301: aprint_error_dev(self, "failed to set configuration"
302: ", err=%s\n", usbd_errstr(error));
1.1 nonaka 303: goto fail;
304: }
305:
306: /* Get the first interface handle. */
307: error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
308: if (error != 0) {
309: aprint_error_dev(self, "could not get interface handle\n");
310: goto fail;
311: }
312:
313: error = urtwn_read_chipid(sc);
314: if (error != 0) {
315: aprint_error_dev(self, "unsupported test chip\n");
316: goto fail;
317: }
318:
319: /* Determine number of Tx/Rx chains. */
320: if (sc->chip & URTWN_CHIP_92C) {
321: sc->ntxchains = (sc->chip & URTWN_CHIP_92C_1T2R) ? 1 : 2;
322: sc->nrxchains = 2;
323: } else {
324: sc->ntxchains = 1;
325: sc->nrxchains = 1;
326: }
327: urtwn_read_rom(sc);
328:
1.22 christos 329: aprint_normal_dev(self, "MAC/BB RTL%s, RF 6052 %zdT%zdR, address %s\n",
1.1 nonaka 330: (sc->chip & URTWN_CHIP_92C) ? "8192CU" :
331: (sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" :
332: (sc->board_type == R92C_BOARD_TYPE_MINICARD) ? "8188CE-VAU" :
333: "8188CUS", sc->ntxchains, sc->nrxchains,
334: ether_sprintf(ic->ic_myaddr));
335:
336: error = urtwn_open_pipes(sc);
337: if (error != 0) {
338: aprint_error_dev(sc->sc_dev, "could not open pipes\n");
339: goto fail;
340: }
341: aprint_normal_dev(self, "%d rx pipe%s, %d tx pipe%s\n",
342: sc->rx_npipe, sc->rx_npipe > 1 ? "s" : "",
343: sc->tx_npipe, sc->tx_npipe > 1 ? "s" : "");
344:
345: /*
346: * Setup the 802.11 device.
347: */
348: ic->ic_ifp = ifp;
349: ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
350: ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */
351: ic->ic_state = IEEE80211_S_INIT;
352:
353: /* Set device capabilities. */
354: ic->ic_caps =
355: IEEE80211_C_MONITOR | /* Monitor mode supported. */
1.26 ! christos 356: IEEE80211_C_IBSS | /* IBSS mode supported */
! 357: IEEE80211_C_HOSTAP | /* HostAp mode supported */
1.1 nonaka 358: IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */
359: IEEE80211_C_SHSLOT | /* Short slot time supported. */
360: IEEE80211_C_WME | /* 802.11e */
361: IEEE80211_C_WPA; /* 802.11i */
362:
363: /* Set supported .11b and .11g rates. */
364: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
365: ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
366:
367: /* Set supported .11b and .11g channels (1 through 14). */
368: for (i = 1; i <= 14; i++) {
369: ic->ic_channels[i].ic_freq =
370: ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
371: ic->ic_channels[i].ic_flags =
372: IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
373: IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
374: }
375:
376: ifp->if_softc = sc;
377: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
378: ifp->if_init = urtwn_init;
379: ifp->if_ioctl = urtwn_ioctl;
380: ifp->if_start = urtwn_start;
381: ifp->if_watchdog = urtwn_watchdog;
382: IFQ_SET_READY(&ifp->if_snd);
383: memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
384:
385: if_attach(ifp);
386: ieee80211_ifattach(ic);
1.16 jmcneill 387:
1.1 nonaka 388: /* override default methods */
1.26 ! christos 389: ic->ic_newassoc = urtwn_newassoc;
1.16 jmcneill 390: ic->ic_reset = urtwn_reset;
1.1 nonaka 391: ic->ic_wme.wme_update = urtwn_wme_update;
392:
393: /* Override state transition machine. */
394: sc->sc_newstate = ic->ic_newstate;
395: ic->ic_newstate = urtwn_newstate;
396: ieee80211_media_init(ic, urtwn_media_change, ieee80211_media_status);
397:
398: bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
399: sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
400: &sc->sc_drvbpf);
401:
402: sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
403: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
404: sc->sc_rxtap.wr_ihdr.it_present = htole32(URTWN_RX_RADIOTAP_PRESENT);
405:
406: sc->sc_txtap_len = sizeof(sc->sc_txtapu);
407: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
408: sc->sc_txtap.wt_ihdr.it_present = htole32(URTWN_TX_RADIOTAP_PRESENT);
409:
410: ieee80211_announce(ic);
411:
412: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
413:
414: SET(sc->sc_flags, URTWN_FLAG_ATTACHED);
415: return;
416:
417: fail:
418: sc->sc_dying = 1;
419: aprint_error_dev(self, "attach failed\n");
420: }
421:
422: static int
423: urtwn_detach(device_t self, int flags)
424: {
425: struct urtwn_softc *sc = device_private(self);
426: struct ifnet *ifp = &sc->sc_if;
427: int s;
428:
429: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
430:
431: s = splusb();
432:
433: sc->sc_dying = 1;
434:
435: callout_stop(&sc->sc_scan_to);
436: callout_stop(&sc->sc_calib_to);
437:
438: if (ISSET(sc->sc_flags, URTWN_FLAG_ATTACHED)) {
439: usb_rem_task(sc->sc_udev, &sc->sc_task);
440: urtwn_stop(ifp, 0);
441:
442: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
443: bpf_detach(ifp);
444: ieee80211_ifdetach(&sc->sc_ic);
445: if_detach(ifp);
446:
447: /* Abort and close Tx/Rx pipes. */
448: urtwn_close_pipes(sc);
449: }
450:
451: splx(s);
452:
453: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
454:
455: callout_destroy(&sc->sc_scan_to);
456: callout_destroy(&sc->sc_calib_to);
1.12 christos 457:
458: mutex_destroy(&sc->sc_write_mtx);
1.1 nonaka 459: mutex_destroy(&sc->sc_fwcmd_mtx);
460: mutex_destroy(&sc->sc_tx_mtx);
461: mutex_destroy(&sc->sc_task_mtx);
462:
463: return (0);
464: }
465:
466: static int
467: urtwn_activate(device_t self, enum devact act)
468: {
469: struct urtwn_softc *sc = device_private(self);
470:
471: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
472:
473: switch (act) {
474: case DVACT_DEACTIVATE:
475: if_deactivate(sc->sc_ic.ic_ifp);
476: return (0);
477: default:
478: return (EOPNOTSUPP);
479: }
480: }
481:
482: static int
483: urtwn_open_pipes(struct urtwn_softc *sc)
484: {
485: /* Bulk-out endpoints addresses (from highest to lowest prio). */
486: static const uint8_t epaddr[] = { 0x02, 0x03, 0x05 };
487: usb_interface_descriptor_t *id;
488: usb_endpoint_descriptor_t *ed;
1.22 christos 489: size_t i, ntx = 0;
490: int error;
1.1 nonaka 491:
492: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
493:
494: /* Determine the number of bulk-out pipes. */
495: id = usbd_get_interface_descriptor(sc->sc_iface);
496: for (i = 0; i < id->bNumEndpoints; i++) {
497: ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
498: if (ed != NULL &&
499: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK &&
500: UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
501: ntx++;
502: }
1.22 christos 503: DPRINTFN(DBG_INIT, ("%s: %s: found %zd bulk-out pipes\n",
1.1 nonaka 504: device_xname(sc->sc_dev), __func__, ntx));
505: if (ntx == 0 || ntx > R92C_MAX_EPOUT) {
506: aprint_error_dev(sc->sc_dev,
1.22 christos 507: "%zd: invalid number of Tx bulk pipes\n", ntx);
1.1 nonaka 508: return (EIO);
509: }
510: sc->rx_npipe = 1;
511: sc->tx_npipe = ntx;
512:
513: /* Open bulk-in pipe at address 0x81. */
514: error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE,
515: &sc->rx_pipe);
516: if (error != 0) {
1.12 christos 517: aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe"
518: ": %d\n", error);
1.1 nonaka 519: goto fail;
520: }
521:
522: /* Open bulk-out pipes (up to 3). */
523: for (i = 0; i < ntx; i++) {
524: error = usbd_open_pipe(sc->sc_iface, epaddr[i],
525: USBD_EXCLUSIVE_USE, &sc->tx_pipe[i]);
526: if (error != 0) {
527: aprint_error_dev(sc->sc_dev,
1.12 christos 528: "could not open Tx bulk pipe 0x%02x: %d\n",
529: epaddr[i], error);
1.1 nonaka 530: goto fail;
531: }
532: }
533:
534: /* Map 802.11 access categories to USB pipes. */
535: sc->ac2idx[WME_AC_BK] =
536: sc->ac2idx[WME_AC_BE] = (ntx == 3) ? 2 : ((ntx == 2) ? 1 : 0);
537: sc->ac2idx[WME_AC_VI] = (ntx == 3) ? 1 : 0;
538: sc->ac2idx[WME_AC_VO] = 0; /* Always use highest prio. */
539:
540: fail:
541: if (error != 0)
542: urtwn_close_pipes(sc);
543: return (error);
544: }
545:
546: static void
547: urtwn_close_pipes(struct urtwn_softc *sc)
548: {
1.22 christos 549: usbd_pipe_handle pipe;
550: size_t i;
1.1 nonaka 551:
552: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
553:
554: /* Close Rx pipe. */
1.22 christos 555: CTASSERT(sizeof(pipe) == sizeof(void *));
556: pipe = atomic_swap_ptr(&sc->rx_pipe, NULL);
557: if (pipe != NULL) {
558: usbd_abort_pipe(pipe);
559: usbd_close_pipe(pipe);
1.1 nonaka 560: }
561: /* Close Tx pipes. */
562: for (i = 0; i < R92C_MAX_EPOUT; i++) {
1.22 christos 563: pipe = atomic_swap_ptr(&sc->tx_pipe[i], NULL);
564: if (pipe != NULL) {
565: usbd_abort_pipe(pipe);
566: usbd_close_pipe(pipe);
567: }
1.1 nonaka 568: }
569: }
570:
571: static int
572: urtwn_alloc_rx_list(struct urtwn_softc *sc)
573: {
574: struct urtwn_rx_data *data;
1.22 christos 575: size_t i;
576: int error = 0;
1.1 nonaka 577:
578: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
579:
580: for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
581: data = &sc->rx_data[i];
582:
583: data->sc = sc; /* Backpointer for callbacks. */
584:
585: data->xfer = usbd_alloc_xfer(sc->sc_udev);
586: if (data->xfer == NULL) {
587: aprint_error_dev(sc->sc_dev,
588: "could not allocate xfer\n");
589: error = ENOMEM;
590: break;
591: }
592:
593: data->buf = usbd_alloc_buffer(data->xfer, URTWN_RXBUFSZ);
594: if (data->buf == NULL) {
595: aprint_error_dev(sc->sc_dev,
596: "could not allocate xfer buffer\n");
597: error = ENOMEM;
598: break;
599: }
600: }
601: if (error != 0)
602: urtwn_free_rx_list(sc);
603: return (error);
604: }
605:
606: static void
607: urtwn_free_rx_list(struct urtwn_softc *sc)
608: {
1.22 christos 609: usbd_xfer_handle xfer;
610: size_t i;
1.1 nonaka 611:
612: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
613:
614: /* NB: Caller must abort pipe first. */
615: for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
1.22 christos 616: CTASSERT(sizeof(xfer) == sizeof(void *));
1.24 nonaka 617: xfer = atomic_swap_ptr(&sc->rx_data[i].xfer, NULL);
1.22 christos 618: if (xfer != NULL)
619: usbd_free_xfer(xfer);
1.1 nonaka 620: }
621: }
622:
623: static int
624: urtwn_alloc_tx_list(struct urtwn_softc *sc)
625: {
626: struct urtwn_tx_data *data;
1.22 christos 627: size_t i;
628: int error = 0;
1.1 nonaka 629:
630: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
631:
1.12 christos 632: mutex_enter(&sc->sc_tx_mtx);
1.1 nonaka 633: TAILQ_INIT(&sc->tx_free_list);
634: for (i = 0; i < URTWN_TX_LIST_COUNT; i++) {
635: data = &sc->tx_data[i];
636:
637: data->sc = sc; /* Backpointer for callbacks. */
638:
639: data->xfer = usbd_alloc_xfer(sc->sc_udev);
640: if (data->xfer == NULL) {
641: aprint_error_dev(sc->sc_dev,
642: "could not allocate xfer\n");
643: error = ENOMEM;
644: goto fail;
645: }
646:
647: data->buf = usbd_alloc_buffer(data->xfer, URTWN_TXBUFSZ);
648: if (data->buf == NULL) {
649: aprint_error_dev(sc->sc_dev,
650: "could not allocate xfer buffer\n");
651: error = ENOMEM;
652: goto fail;
653: }
654:
655: /* Append this Tx buffer to our free list. */
656: TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
657: }
1.12 christos 658: mutex_exit(&sc->sc_tx_mtx);
1.1 nonaka 659: return (0);
660:
661: fail:
662: urtwn_free_tx_list(sc);
1.12 christos 663: mutex_exit(&sc->sc_tx_mtx);
1.1 nonaka 664: return (error);
665: }
666:
667: static void
668: urtwn_free_tx_list(struct urtwn_softc *sc)
669: {
1.22 christos 670: usbd_xfer_handle xfer;
671: size_t i;
1.1 nonaka 672:
673: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
674:
675: /* NB: Caller must abort pipe first. */
676: for (i = 0; i < URTWN_TX_LIST_COUNT; i++) {
1.22 christos 677: CTASSERT(sizeof(xfer) == sizeof(void *));
678: xfer = atomic_swap_ptr(&sc->tx_data[i].xfer, NULL);
679: if (xfer != NULL)
680: usbd_free_xfer(xfer);
1.1 nonaka 681: }
682: }
683:
684: static void
685: urtwn_task(void *arg)
686: {
687: struct urtwn_softc *sc = arg;
688: struct urtwn_host_cmd_ring *ring = &sc->cmdq;
689: struct urtwn_host_cmd *cmd;
690: int s;
691:
692: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
693:
694: /* Process host commands. */
695: s = splusb();
696: mutex_spin_enter(&sc->sc_task_mtx);
697: while (ring->next != ring->cur) {
698: cmd = &ring->cmd[ring->next];
699: mutex_spin_exit(&sc->sc_task_mtx);
700: splx(s);
1.16 jmcneill 701: /* Invoke callback with kernel lock held. */
1.1 nonaka 702: cmd->cb(sc, cmd->data);
703: s = splusb();
704: mutex_spin_enter(&sc->sc_task_mtx);
705: ring->queued--;
706: ring->next = (ring->next + 1) % URTWN_HOST_CMD_RING_COUNT;
707: }
708: mutex_spin_exit(&sc->sc_task_mtx);
709: wakeup(&sc->cmdq);
710: splx(s);
711: }
712:
713: static void
714: urtwn_do_async(struct urtwn_softc *sc, void (*cb)(struct urtwn_softc *, void *),
715: void *arg, int len)
716: {
717: struct urtwn_host_cmd_ring *ring = &sc->cmdq;
718: struct urtwn_host_cmd *cmd;
719: int s;
720:
721: DPRINTFN(DBG_FN, ("%s: %s: cb=%p, arg=%p, len=%d\n",
722: device_xname(sc->sc_dev), __func__, cb, arg, len));
723:
724: s = splusb();
725: mutex_spin_enter(&sc->sc_task_mtx);
726: cmd = &ring->cmd[ring->cur];
727: cmd->cb = cb;
728: KASSERT(len <= sizeof(cmd->data));
729: memcpy(cmd->data, arg, len);
730: ring->cur = (ring->cur + 1) % URTWN_HOST_CMD_RING_COUNT;
731:
732: /* If there is no pending command already, schedule a task. */
733: if (!sc->sc_dying && ++ring->queued == 1) {
734: mutex_spin_exit(&sc->sc_task_mtx);
735: usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
736: } else
737: mutex_spin_exit(&sc->sc_task_mtx);
738: splx(s);
739: }
740:
741: static void
742: urtwn_wait_async(struct urtwn_softc *sc)
743: {
744:
745: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
746:
747: /* Wait for all queued asynchronous commands to complete. */
748: while (sc->cmdq.queued > 0)
749: tsleep(&sc->cmdq, 0, "endtask", 0);
750: }
751:
752: static int
753: urtwn_write_region_1(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf,
754: int len)
755: {
756: usb_device_request_t req;
757: usbd_status error;
758:
1.12 christos 759: KASSERT(mutex_owned(&sc->sc_write_mtx));
760:
1.1 nonaka 761: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
762: req.bRequest = R92C_REQ_REGS;
763: USETW(req.wValue, addr);
764: USETW(req.wIndex, 0);
765: USETW(req.wLength, len);
766: error = usbd_do_request(sc->sc_udev, &req, buf);
767: if (error != USBD_NORMAL_COMPLETION) {
768: DPRINTFN(DBG_REG, ("%s: %s: error=%d: addr=0x%x, len=%d\n",
769: device_xname(sc->sc_dev), __func__, error, addr, len));
770: }
771: return (error);
772: }
773:
774: static void
775: urtwn_write_1(struct urtwn_softc *sc, uint16_t addr, uint8_t val)
776: {
777:
778: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, val=0x%x\n",
779: device_xname(sc->sc_dev), __func__, addr, val));
780:
781: urtwn_write_region_1(sc, addr, &val, 1);
782: }
783:
784: static void
785: urtwn_write_2(struct urtwn_softc *sc, uint16_t addr, uint16_t val)
786: {
787: uint8_t buf[2];
788:
789: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, val=0x%x\n",
790: device_xname(sc->sc_dev), __func__, addr, val));
791:
792: buf[0] = (uint8_t)val;
793: buf[1] = (uint8_t)(val >> 8);
794: urtwn_write_region_1(sc, addr, buf, 2);
795: }
796:
797: static void
798: urtwn_write_4(struct urtwn_softc *sc, uint16_t addr, uint32_t val)
799: {
800: uint8_t buf[4];
801:
802: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, val=0x%x\n",
803: device_xname(sc->sc_dev), __func__, addr, val));
804:
805: buf[0] = (uint8_t)val;
806: buf[1] = (uint8_t)(val >> 8);
807: buf[2] = (uint8_t)(val >> 16);
808: buf[3] = (uint8_t)(val >> 24);
809: urtwn_write_region_1(sc, addr, buf, 4);
810: }
811:
812: static int
813: urtwn_write_region(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf, int len)
814: {
815:
816: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, len=0x%x\n",
817: device_xname(sc->sc_dev), __func__, addr, len));
818:
819: return urtwn_write_region_1(sc, addr, buf, len);
820: }
821:
822: static int
823: urtwn_read_region_1(struct urtwn_softc *sc, uint16_t addr, uint8_t *buf,
824: int len)
825: {
826: usb_device_request_t req;
827: usbd_status error;
828:
829: req.bmRequestType = UT_READ_VENDOR_DEVICE;
830: req.bRequest = R92C_REQ_REGS;
831: USETW(req.wValue, addr);
832: USETW(req.wIndex, 0);
833: USETW(req.wLength, len);
834: error = usbd_do_request(sc->sc_udev, &req, buf);
835: if (error != USBD_NORMAL_COMPLETION) {
836: DPRINTFN(DBG_REG, ("%s: %s: error=%d: addr=0x%x, len=%d\n",
837: device_xname(sc->sc_dev), __func__, error, addr, len));
838: }
839: return (error);
840: }
841:
842: static uint8_t
843: urtwn_read_1(struct urtwn_softc *sc, uint16_t addr)
844: {
845: uint8_t val;
846:
847: if (urtwn_read_region_1(sc, addr, &val, 1) != USBD_NORMAL_COMPLETION)
848: return (0xff);
849:
850: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, val=0x%x\n",
851: device_xname(sc->sc_dev), __func__, addr, val));
852: return (val);
853: }
854:
855: static uint16_t
856: urtwn_read_2(struct urtwn_softc *sc, uint16_t addr)
857: {
858: uint8_t buf[2];
859: uint16_t val;
860:
861: if (urtwn_read_region_1(sc, addr, buf, 2) != USBD_NORMAL_COMPLETION)
862: return (0xffff);
863:
864: val = LE_READ_2(&buf[0]);
865: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, val=0x%x\n",
866: device_xname(sc->sc_dev), __func__, addr, val));
867: return (val);
868: }
869:
870: static uint32_t
871: urtwn_read_4(struct urtwn_softc *sc, uint16_t addr)
872: {
873: uint8_t buf[4];
874: uint32_t val;
875:
876: if (urtwn_read_region_1(sc, addr, buf, 4) != USBD_NORMAL_COMPLETION)
877: return (0xffffffff);
878:
879: val = LE_READ_4(&buf[0]);
880: DPRINTFN(DBG_REG, ("%s: %s: addr=0x%x, val=0x%x\n",
881: device_xname(sc->sc_dev), __func__, addr, val));
882: return (val);
883: }
884:
885: static int
886: urtwn_fw_cmd(struct urtwn_softc *sc, uint8_t id, const void *buf, int len)
887: {
888: struct r92c_fw_cmd cmd;
889: uint8_t *cp;
890: int fwcur;
891: int ntries;
892:
893: DPRINTFN(DBG_REG, ("%s: %s: id=%d, buf=%p, len=%d\n",
894: device_xname(sc->sc_dev), __func__, id, buf, len));
895:
1.12 christos 896: KASSERT(mutex_owned(&sc->sc_write_mtx));
897:
1.1 nonaka 898: mutex_enter(&sc->sc_fwcmd_mtx);
899: fwcur = sc->fwcur;
900: sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX;
901: mutex_exit(&sc->sc_fwcmd_mtx);
902:
903: /* Wait for current FW box to be empty. */
904: for (ntries = 0; ntries < 100; ntries++) {
905: if (!(urtwn_read_1(sc, R92C_HMETFR) & (1 << fwcur)))
906: break;
907: DELAY(1);
908: }
909: if (ntries == 100) {
910: aprint_error_dev(sc->sc_dev,
911: "could not send firmware command %d\n", id);
912: return (ETIMEDOUT);
913: }
914:
915: memset(&cmd, 0, sizeof(cmd));
916: KASSERT(len <= sizeof(cmd.msg));
917: memcpy(cmd.msg, buf, len);
918:
919: /* Write the first word last since that will trigger the FW. */
920: cp = (uint8_t *)&cmd;
921: if (len >= 4) {
922: cmd.id = id | R92C_CMD_FLAG_EXT;
923: urtwn_write_region(sc, R92C_HMEBOX_EXT(fwcur), &cp[1], 2);
924: urtwn_write_4(sc, R92C_HMEBOX(fwcur),
925: cp[0] + (cp[3] << 8) + (cp[4] << 16) + (cp[5] << 24));
926: } else {
927: cmd.id = id;
928: urtwn_write_region(sc, R92C_HMEBOX(fwcur), cp, len);
929: }
930:
931: return (0);
932: }
933:
934: static void
935: urtwn_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, uint32_t val)
936: {
937:
938: urtwn_bb_write(sc, R92C_LSSI_PARAM(chain),
939: SM(R92C_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val));
940: }
941:
942: static uint32_t
943: urtwn_rf_read(struct urtwn_softc *sc, int chain, uint8_t addr)
944: {
945: uint32_t reg[R92C_MAX_CHAINS], val;
946:
947: reg[0] = urtwn_bb_read(sc, R92C_HSSI_PARAM2(0));
948: if (chain != 0) {
949: reg[chain] = urtwn_bb_read(sc, R92C_HSSI_PARAM2(chain));
950: }
951:
952: urtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
953: reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE);
954: DELAY(1000);
955:
956: urtwn_bb_write(sc, R92C_HSSI_PARAM2(chain),
957: RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) |
958: R92C_HSSI_PARAM2_READ_EDGE);
959: DELAY(1000);
960:
961: urtwn_bb_write(sc, R92C_HSSI_PARAM2(0),
962: reg[0] | R92C_HSSI_PARAM2_READ_EDGE);
963: DELAY(1000);
964:
965: if (urtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI) {
966: val = urtwn_bb_read(sc, R92C_HSPI_READBACK(chain));
967: } else {
968: val = urtwn_bb_read(sc, R92C_LSSI_READBACK(chain));
969: }
970: return (MS(val, R92C_LSSI_READBACK_DATA));
971: }
972:
973: static int
974: urtwn_llt_write(struct urtwn_softc *sc, uint32_t addr, uint32_t data)
975: {
976: int ntries;
977:
1.12 christos 978: KASSERT(mutex_owned(&sc->sc_write_mtx));
979:
1.1 nonaka 980: urtwn_write_4(sc, R92C_LLT_INIT,
981: SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) |
982: SM(R92C_LLT_INIT_ADDR, addr) |
983: SM(R92C_LLT_INIT_DATA, data));
984: /* Wait for write operation to complete. */
985: for (ntries = 0; ntries < 20; ntries++) {
986: if (MS(urtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) ==
987: R92C_LLT_INIT_OP_NO_ACTIVE) {
988: /* Done */
989: return (0);
990: }
991: DELAY(5);
992: }
993: return (ETIMEDOUT);
994: }
995:
996: static uint8_t
997: urtwn_efuse_read_1(struct urtwn_softc *sc, uint16_t addr)
998: {
999: uint32_t reg;
1000: int ntries;
1001:
1.12 christos 1002: KASSERT(mutex_owned(&sc->sc_write_mtx));
1003:
1.1 nonaka 1004: reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
1005: reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr);
1006: reg &= ~R92C_EFUSE_CTRL_VALID;
1007: urtwn_write_4(sc, R92C_EFUSE_CTRL, reg);
1008:
1009: /* Wait for read operation to complete. */
1010: for (ntries = 0; ntries < 100; ntries++) {
1011: reg = urtwn_read_4(sc, R92C_EFUSE_CTRL);
1012: if (reg & R92C_EFUSE_CTRL_VALID) {
1013: /* Done */
1014: return (MS(reg, R92C_EFUSE_CTRL_DATA));
1015: }
1016: DELAY(5);
1017: }
1018: aprint_error_dev(sc->sc_dev,
1019: "could not read efuse byte at address 0x%04x\n", addr);
1020: return (0xff);
1021: }
1022:
1023: static void
1024: urtwn_efuse_read(struct urtwn_softc *sc)
1025: {
1026: uint8_t *rom = (uint8_t *)&sc->rom;
1027: uint32_t reg;
1028: uint16_t addr = 0;
1029: uint8_t off, msk;
1.22 christos 1030: size_t i;
1.1 nonaka 1031:
1032: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1033:
1.12 christos 1034: KASSERT(mutex_owned(&sc->sc_write_mtx));
1035:
1.1 nonaka 1036: reg = urtwn_read_2(sc, R92C_SYS_ISO_CTRL);
1037: if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) {
1038: urtwn_write_2(sc, R92C_SYS_ISO_CTRL,
1039: reg | R92C_SYS_ISO_CTRL_PWC_EV12V);
1040: }
1041: reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN);
1042: if (!(reg & R92C_SYS_FUNC_EN_ELDR)) {
1043: urtwn_write_2(sc, R92C_SYS_FUNC_EN,
1044: reg | R92C_SYS_FUNC_EN_ELDR);
1045: }
1046: reg = urtwn_read_2(sc, R92C_SYS_CLKR);
1047: if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) !=
1048: (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) {
1049: urtwn_write_2(sc, R92C_SYS_CLKR,
1050: reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M);
1051: }
1052: memset(&sc->rom, 0xff, sizeof(sc->rom));
1053: while (addr < 512) {
1054: reg = urtwn_efuse_read_1(sc, addr);
1055: if (reg == 0xff)
1056: break;
1057: addr++;
1058: off = reg >> 4;
1059: msk = reg & 0xf;
1060: for (i = 0; i < 4; i++) {
1061: if (msk & (1U << i))
1062: continue;
1063:
1064: rom[off * 8 + i * 2 + 0] = urtwn_efuse_read_1(sc, addr);
1065: addr++;
1066: rom[off * 8 + i * 2 + 1] = urtwn_efuse_read_1(sc, addr);
1067: addr++;
1068: }
1069: }
1070: #ifdef URTWN_DEBUG
1071: if (urtwn_debug & DBG_INIT) {
1072: /* Dump ROM content. */
1073: printf("%s: %s", device_xname(sc->sc_dev), __func__);
1074: for (i = 0; i < (int)sizeof(sc->rom); i++)
1075: printf(":%02x", rom[i]);
1076: printf("\n");
1077: }
1078: #endif
1079: }
1080:
1081: static int
1082: urtwn_read_chipid(struct urtwn_softc *sc)
1083: {
1084: uint32_t reg;
1085:
1086: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1087:
1088: sc->chip = 0;
1089: reg = urtwn_read_4(sc, R92C_SYS_CFG);
1090: if (reg & R92C_SYS_CFG_TRP_VAUX_EN) {
1091: /* test chip, not supported */
1092: return (EIO);
1093: }
1094: if (reg & R92C_SYS_CFG_TYPE_92C) {
1095: sc->chip |= URTWN_CHIP_92C;
1096: /* Check if it is a castrated 8192C. */
1097: if (MS(urtwn_read_4(sc, R92C_HPON_FSM),
1098: R92C_HPON_FSM_CHIP_BONDING_ID) ==
1099: R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R) {
1100: sc->chip |= URTWN_CHIP_92C_1T2R;
1101: }
1102: }
1103: if (reg & R92C_SYS_CFG_VENDOR_UMC) {
1104: sc->chip |= URTWN_CHIP_UMC;
1105: if (MS(reg, R92C_SYS_CFG_CHIP_VER_RTL) == 0) {
1106: sc->chip |= URTWN_CHIP_UMC_A_CUT;
1107: }
1108: }
1109: return (0);
1110: }
1111:
1112: #ifdef URTWN_DEBUG
1113: static void
1114: urtwn_dump_rom(struct urtwn_softc *sc, struct r92c_rom *rp)
1115: {
1116:
1117: aprint_normal_dev(sc->sc_dev,
1118: "id 0x%04x, dbg_sel 0x%x, vid 0x%x, pid 0x%x\n",
1119: rp->id, rp->dbg_sel, rp->vid, rp->pid);
1120:
1121: aprint_normal_dev(sc->sc_dev,
1122: "usb_opt 0x%x, ep_setting 0x%x, usb_phy 0x%x\n",
1123: rp->usb_opt, rp->ep_setting, rp->usb_phy);
1124:
1125: aprint_normal_dev(sc->sc_dev,
1126: "macaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
1127: rp->macaddr[0], rp->macaddr[1],
1128: rp->macaddr[2], rp->macaddr[3],
1129: rp->macaddr[4], rp->macaddr[5]);
1130:
1131: aprint_normal_dev(sc->sc_dev,
1132: "string %s, subcustomer_id 0x%x\n",
1133: rp->string, rp->subcustomer_id);
1134:
1135: aprint_normal_dev(sc->sc_dev,
1136: "cck_tx_pwr c0: %d %d %d, c1: %d %d %d\n",
1137: rp->cck_tx_pwr[0][0], rp->cck_tx_pwr[0][1], rp->cck_tx_pwr[0][2],
1138: rp->cck_tx_pwr[1][0], rp->cck_tx_pwr[1][1], rp->cck_tx_pwr[1][2]);
1139:
1140: aprint_normal_dev(sc->sc_dev,
1141: "ht40_1s_tx_pwr c0 %d %d %d, c1 %d %d %d\n",
1142: rp->ht40_1s_tx_pwr[0][0], rp->ht40_1s_tx_pwr[0][1],
1143: rp->ht40_1s_tx_pwr[0][2],
1144: rp->ht40_1s_tx_pwr[1][0], rp->ht40_1s_tx_pwr[1][1],
1145: rp->ht40_1s_tx_pwr[1][2]);
1146:
1147: aprint_normal_dev(sc->sc_dev,
1148: "ht40_2s_tx_pwr_diff c0: %d %d %d, c1: %d %d %d\n",
1149: rp->ht40_2s_tx_pwr_diff[0] & 0xf, rp->ht40_2s_tx_pwr_diff[1] & 0xf,
1150: rp->ht40_2s_tx_pwr_diff[2] & 0xf,
1151: rp->ht40_2s_tx_pwr_diff[0] >> 4, rp->ht40_2s_tx_pwr_diff[1] & 0xf,
1152: rp->ht40_2s_tx_pwr_diff[2] >> 4);
1153:
1154: aprint_normal_dev(sc->sc_dev,
1155: "ht20_tx_pwr_diff c0: %d %d %d, c1: %d %d %d\n",
1156: rp->ht20_tx_pwr_diff[0] & 0xf, rp->ht20_tx_pwr_diff[1] & 0xf,
1157: rp->ht20_tx_pwr_diff[2] & 0xf,
1158: rp->ht20_tx_pwr_diff[0] >> 4, rp->ht20_tx_pwr_diff[1] >> 4,
1159: rp->ht20_tx_pwr_diff[2] >> 4);
1160:
1161: aprint_normal_dev(sc->sc_dev,
1162: "ofdm_tx_pwr_diff c0: %d %d %d, c1: %d %d %d\n",
1163: rp->ofdm_tx_pwr_diff[0] & 0xf, rp->ofdm_tx_pwr_diff[1] & 0xf,
1164: rp->ofdm_tx_pwr_diff[2] & 0xf,
1165: rp->ofdm_tx_pwr_diff[0] >> 4, rp->ofdm_tx_pwr_diff[1] >> 4,
1166: rp->ofdm_tx_pwr_diff[2] >> 4);
1167:
1168: aprint_normal_dev(sc->sc_dev,
1169: "ht40_max_pwr_offset c0: %d %d %d, c1: %d %d %d\n",
1170: rp->ht40_max_pwr[0] & 0xf, rp->ht40_max_pwr[1] & 0xf,
1171: rp->ht40_max_pwr[2] & 0xf,
1172: rp->ht40_max_pwr[0] >> 4, rp->ht40_max_pwr[1] >> 4,
1173: rp->ht40_max_pwr[2] >> 4);
1174:
1175: aprint_normal_dev(sc->sc_dev,
1176: "ht20_max_pwr_offset c0: %d %d %d, c1: %d %d %d\n",
1177: rp->ht20_max_pwr[0] & 0xf, rp->ht20_max_pwr[1] & 0xf,
1178: rp->ht20_max_pwr[2] & 0xf,
1179: rp->ht20_max_pwr[0] >> 4, rp->ht20_max_pwr[1] >> 4,
1180: rp->ht20_max_pwr[2] >> 4);
1181:
1182: aprint_normal_dev(sc->sc_dev,
1183: "xtal_calib %d, tssi %d %d, thermal %d\n",
1184: rp->xtal_calib, rp->tssi[0], rp->tssi[1], rp->thermal_meter);
1185:
1186: aprint_normal_dev(sc->sc_dev,
1187: "rf_opt1 0x%x, rf_opt2 0x%x, rf_opt3 0x%x, rf_opt4 0x%x\n",
1188: rp->rf_opt1, rp->rf_opt2, rp->rf_opt3, rp->rf_opt4);
1189:
1190: aprint_normal_dev(sc->sc_dev,
1191: "channnel_plan %d, version %d customer_id 0x%x\n",
1192: rp->channel_plan, rp->version, rp->curstomer_id);
1193: }
1194: #endif
1195:
1196: static void
1197: urtwn_read_rom(struct urtwn_softc *sc)
1198: {
1199: struct ieee80211com *ic = &sc->sc_ic;
1200: struct r92c_rom *rom = &sc->rom;
1201:
1202: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1203:
1.12 christos 1204: mutex_enter(&sc->sc_write_mtx);
1205:
1.1 nonaka 1206: /* Read full ROM image. */
1207: urtwn_efuse_read(sc);
1208: #ifdef URTWN_DEBUG
1209: if (urtwn_debug & DBG_REG)
1210: urtwn_dump_rom(sc, rom);
1211: #endif
1212:
1213: /* XXX Weird but this is what the vendor driver does. */
1214: sc->pa_setting = urtwn_efuse_read_1(sc, 0x1fa);
1215: sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE);
1216: sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
1217:
1218: DPRINTFN(DBG_INIT,
1219: ("%s: %s: PA setting=0x%x, board=0x%x, regulatory=%d\n",
1220: device_xname(sc->sc_dev), __func__, sc->pa_setting,
1221: sc->board_type, sc->regulatory));
1222:
1223: IEEE80211_ADDR_COPY(ic->ic_myaddr, rom->macaddr);
1.12 christos 1224:
1225: mutex_exit(&sc->sc_write_mtx);
1.1 nonaka 1226: }
1227:
1228: static int
1229: urtwn_media_change(struct ifnet *ifp)
1230: {
1231: #ifdef URTWN_DEBUG
1232: struct urtwn_softc *sc = ifp->if_softc;
1233: #endif
1234: int error;
1235:
1236: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1237:
1238: if ((error = ieee80211_media_change(ifp)) != ENETRESET)
1239: return (error);
1240:
1241: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1242: (IFF_UP | IFF_RUNNING)) {
1243: urtwn_init(ifp);
1244: }
1245: return (0);
1246: }
1247:
1248: /*
1249: * Initialize rate adaptation in firmware.
1250: */
1251: static int
1252: urtwn_ra_init(struct urtwn_softc *sc)
1253: {
1254: static const uint8_t map[] = {
1255: 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108
1256: };
1257: struct ieee80211com *ic = &sc->sc_ic;
1258: struct ieee80211_node *ni = ic->ic_bss;
1259: struct ieee80211_rateset *rs = &ni->ni_rates;
1260: struct r92c_fw_cmd_macid_cfg cmd;
1261: uint32_t rates, basicrates;
1262: uint32_t mask;
1263: uint8_t mode;
1.22 christos 1264: size_t maxrate, maxbasicrate, i, j;
1265: int error;
1.1 nonaka 1266:
1267: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1268:
1.12 christos 1269: KASSERT(mutex_owned(&sc->sc_write_mtx));
1270:
1.1 nonaka 1271: /* Get normal and basic rates mask. */
1272: rates = basicrates = 0;
1273: maxrate = maxbasicrate = 0;
1274: for (i = 0; i < rs->rs_nrates; i++) {
1275: /* Convert 802.11 rate to HW rate index. */
1.22 christos 1276: for (j = 0; j < __arraycount(map); j++) {
1.1 nonaka 1277: if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == map[j]) {
1278: break;
1279: }
1280: }
1281: if (j == __arraycount(map)) {
1282: /* Unknown rate, skip. */
1283: continue;
1284: }
1285:
1286: rates |= 1U << j;
1287: if (j > maxrate) {
1288: maxrate = j;
1289: }
1290:
1291: if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) {
1292: basicrates |= 1U << j;
1293: if (j > maxbasicrate) {
1294: maxbasicrate = j;
1295: }
1296: }
1297: }
1298: if (ic->ic_curmode == IEEE80211_MODE_11B) {
1299: mode = R92C_RAID_11B;
1300: } else {
1301: mode = R92C_RAID_11BG;
1302: }
1303: DPRINTFN(DBG_INIT, ("%s: %s: mode=0x%x rates=0x%x, basicrates=0x%x, "
1.22 christos 1304: "maxrate=%zx, maxbasicrate=%zx\n",
1.1 nonaka 1305: device_xname(sc->sc_dev), __func__, mode, rates, basicrates,
1306: maxrate, maxbasicrate));
1307: if (basicrates == 0) {
1308: basicrates |= 1; /* add 1Mbps */
1309: }
1310:
1311: /* Set rates mask for group addressed frames. */
1312: cmd.macid = URTWN_MACID_BC | URTWN_MACID_VALID;
1313: mask = (mode << 28) | basicrates;
1314: cmd.mask[0] = (uint8_t)mask;
1315: cmd.mask[1] = (uint8_t)(mask >> 8);
1316: cmd.mask[2] = (uint8_t)(mask >> 16);
1317: cmd.mask[3] = (uint8_t)(mask >> 24);
1318: error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
1319: if (error != 0) {
1320: aprint_error_dev(sc->sc_dev,
1321: "could not add broadcast station\n");
1322: return (error);
1323: }
1324: /* Set initial MRR rate. */
1.22 christos 1325: DPRINTFN(DBG_INIT, ("%s: %s: maxbasicrate=%zd\n",
1.1 nonaka 1326: device_xname(sc->sc_dev), __func__, maxbasicrate));
1327: urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BC), maxbasicrate);
1328:
1329: /* Set rates mask for unicast frames. */
1330: cmd.macid = URTWN_MACID_BSS | URTWN_MACID_VALID;
1331: mask = (mode << 28) | rates;
1332: cmd.mask[0] = (uint8_t)mask;
1333: cmd.mask[1] = (uint8_t)(mask >> 8);
1334: cmd.mask[2] = (uint8_t)(mask >> 16);
1335: cmd.mask[3] = (uint8_t)(mask >> 24);
1336: error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
1337: if (error != 0) {
1338: aprint_error_dev(sc->sc_dev, "could not add BSS station\n");
1339: return (error);
1340: }
1341: /* Set initial MRR rate. */
1.22 christos 1342: DPRINTFN(DBG_INIT, ("%s: %s: maxrate=%zd\n", device_xname(sc->sc_dev),
1.1 nonaka 1343: __func__, maxrate));
1344: urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BSS), maxrate);
1345:
1346: /* Indicate highest supported rate. */
1347: ni->ni_txrate = rs->rs_nrates - 1;
1348:
1349: return (0);
1350: }
1351:
1352: static int
1353: urtwn_get_nettype(struct urtwn_softc *sc)
1354: {
1355: struct ieee80211com *ic = &sc->sc_ic;
1356: int type;
1357:
1358: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1359:
1360: switch (ic->ic_opmode) {
1361: case IEEE80211_M_STA:
1362: type = R92C_CR_NETTYPE_INFRA;
1363: break;
1364:
1365: case IEEE80211_M_IBSS:
1366: type = R92C_CR_NETTYPE_ADHOC;
1367: break;
1368:
1369: default:
1370: type = R92C_CR_NETTYPE_NOLINK;
1371: break;
1372: }
1373:
1374: return (type);
1375: }
1376:
1377: static void
1378: urtwn_set_nettype0_msr(struct urtwn_softc *sc, uint8_t type)
1379: {
1380: uint8_t reg;
1381:
1382: DPRINTFN(DBG_FN, ("%s: %s: type=%d\n", device_xname(sc->sc_dev),
1383: __func__, type));
1384:
1.12 christos 1385: KASSERT(mutex_owned(&sc->sc_write_mtx));
1386:
1.1 nonaka 1387: reg = urtwn_read_1(sc, R92C_CR + 2) & 0x0c;
1388: urtwn_write_1(sc, R92C_CR + 2, reg | type);
1389: }
1390:
1391: static void
1392: urtwn_tsf_sync_enable(struct urtwn_softc *sc)
1393: {
1394: struct ieee80211_node *ni = sc->sc_ic.ic_bss;
1395: uint64_t tsf;
1396:
1397: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1398:
1.12 christos 1399: KASSERT(mutex_owned(&sc->sc_write_mtx));
1400:
1.1 nonaka 1401: /* Enable TSF synchronization. */
1402: urtwn_write_1(sc, R92C_BCN_CTRL,
1403: urtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_DIS_TSF_UDT0);
1404:
1405: /* Correct TSF */
1406: urtwn_write_1(sc, R92C_BCN_CTRL,
1407: urtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_EN_BCN);
1408:
1409: /* Set initial TSF. */
1410: tsf = ni->ni_tstamp.tsf;
1411: tsf = le64toh(tsf);
1412: tsf = tsf - (tsf % (ni->ni_intval * IEEE80211_DUR_TU));
1413: tsf -= IEEE80211_DUR_TU;
1414: urtwn_write_4(sc, R92C_TSFTR + 0, (uint32_t)tsf);
1415: urtwn_write_4(sc, R92C_TSFTR + 4, (uint32_t)(tsf >> 32));
1416:
1417: urtwn_write_1(sc, R92C_BCN_CTRL,
1418: urtwn_read_1(sc, R92C_BCN_CTRL) | R92C_BCN_CTRL_EN_BCN);
1419: }
1420:
1421: static void
1422: urtwn_set_led(struct urtwn_softc *sc, int led, int on)
1423: {
1424: uint8_t reg;
1425:
1426: DPRINTFN(DBG_FN, ("%s: %s: led=%d, on=%d\n", device_xname(sc->sc_dev),
1427: __func__, led, on));
1428:
1.12 christos 1429: KASSERT(mutex_owned(&sc->sc_write_mtx));
1430:
1.1 nonaka 1431: if (led == URTWN_LED_LINK) {
1432: reg = urtwn_read_1(sc, R92C_LEDCFG0) & 0x70;
1433: if (!on) {
1434: reg |= R92C_LEDCFG0_DIS;
1435: }
1436: urtwn_write_1(sc, R92C_LEDCFG0, reg);
1437: sc->ledlink = on; /* Save LED state. */
1438: }
1439: }
1440:
1441: static void
1442: urtwn_calib_to(void *arg)
1443: {
1444: struct urtwn_softc *sc = arg;
1445:
1446: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1447:
1448: if (sc->sc_dying)
1449: return;
1450:
1451: /* Do it in a process context. */
1452: urtwn_do_async(sc, urtwn_calib_to_cb, NULL, 0);
1453: }
1454:
1455: /* ARGSUSED */
1456: static void
1457: urtwn_calib_to_cb(struct urtwn_softc *sc, void *arg)
1458: {
1459: struct r92c_fw_cmd_rssi cmd;
1460:
1461: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1462:
1463: if (sc->sc_ic.ic_state != IEEE80211_S_RUN)
1464: goto restart_timer;
1465:
1.12 christos 1466: mutex_enter(&sc->sc_write_mtx);
1.1 nonaka 1467: if (sc->avg_pwdb != -1) {
1468: /* Indicate Rx signal strength to FW for rate adaptation. */
1469: memset(&cmd, 0, sizeof(cmd));
1470: cmd.macid = 0; /* BSS. */
1471: cmd.pwdb = sc->avg_pwdb;
1472: DPRINTFN(DBG_RF, ("%s: %s: sending RSSI command avg=%d\n",
1473: device_xname(sc->sc_dev), __func__, sc->avg_pwdb));
1474: urtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd));
1475: }
1476:
1477: /* Do temperature compensation. */
1478: urtwn_temp_calib(sc);
1.12 christos 1479: mutex_exit(&sc->sc_write_mtx);
1.1 nonaka 1480:
1481: restart_timer:
1482: if (!sc->sc_dying) {
1483: /* Restart calibration timer. */
1484: callout_schedule(&sc->sc_calib_to, hz);
1485: }
1486: }
1487:
1488: static void
1489: urtwn_next_scan(void *arg)
1490: {
1491: struct urtwn_softc *sc = arg;
1.16 jmcneill 1492: int s;
1.1 nonaka 1493:
1494: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1495:
1496: if (sc->sc_dying)
1497: return;
1498:
1.16 jmcneill 1499: s = splnet();
1.1 nonaka 1500: if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
1501: ieee80211_next_scan(&sc->sc_ic);
1.16 jmcneill 1502: splx(s);
1.1 nonaka 1503: }
1504:
1.26 ! christos 1505: static void
! 1506: urtwn_newassoc(struct ieee80211_node *ni, int isnew)
! 1507: {
! 1508: DPRINTFN(DBG_FN, ("%s: new node %s\n", __func__,
! 1509: ether_sprintf(ni->ni_macaddr)));
! 1510: /* start with lowest Tx rate */
! 1511: ni->ni_txrate = 0;
! 1512: }
! 1513:
1.1 nonaka 1514: static int
1515: urtwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1516: {
1517: struct urtwn_softc *sc = ic->ic_ifp->if_softc;
1518: struct urtwn_cmd_newstate cmd;
1519:
1520: DPRINTFN(DBG_FN, ("%s: %s: nstate=%s(%d), arg=%d\n",
1521: device_xname(sc->sc_dev), __func__,
1522: ieee80211_state_name[nstate], nstate, arg));
1523:
1524: callout_stop(&sc->sc_scan_to);
1525: callout_stop(&sc->sc_calib_to);
1526:
1527: /* Do it in a process context. */
1528: cmd.state = nstate;
1529: cmd.arg = arg;
1530: urtwn_do_async(sc, urtwn_newstate_cb, &cmd, sizeof(cmd));
1531: return (0);
1532: }
1533:
1534: static void
1535: urtwn_newstate_cb(struct urtwn_softc *sc, void *arg)
1536: {
1537: struct urtwn_cmd_newstate *cmd = arg;
1538: struct ieee80211com *ic = &sc->sc_ic;
1539: struct ieee80211_node *ni;
1540: enum ieee80211_state ostate = ic->ic_state;
1541: enum ieee80211_state nstate = cmd->state;
1542: uint32_t reg;
1.26 ! christos 1543: uint8_t sifs_time, msr;
1.1 nonaka 1544: int s;
1545:
1546: DPRINTFN(DBG_FN|DBG_STM, ("%s: %s: %s(%d)->%s(%d)\n",
1547: device_xname(sc->sc_dev), __func__,
1548: ieee80211_state_name[ostate], ostate,
1549: ieee80211_state_name[nstate], nstate));
1550:
1551: s = splnet();
1.12 christos 1552: mutex_enter(&sc->sc_write_mtx);
1553:
1554: callout_stop(&sc->sc_scan_to);
1555: callout_stop(&sc->sc_calib_to);
1.1 nonaka 1556:
1557: switch (ostate) {
1558: case IEEE80211_S_INIT:
1559: break;
1560:
1561: case IEEE80211_S_SCAN:
1562: if (nstate != IEEE80211_S_SCAN) {
1563: /*
1564: * End of scanning
1565: */
1566: /* flush 4-AC Queue after site_survey */
1567: urtwn_write_1(sc, R92C_TXPAUSE, 0x0);
1568:
1569: /* Allow Rx from our BSSID only. */
1570: urtwn_write_4(sc, R92C_RCR,
1571: urtwn_read_4(sc, R92C_RCR) |
1572: R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
1573: }
1574: break;
1.7 christos 1575:
1.1 nonaka 1576: case IEEE80211_S_AUTH:
1577: case IEEE80211_S_ASSOC:
1578: break;
1579:
1580: case IEEE80211_S_RUN:
1581: /* Turn link LED off. */
1582: urtwn_set_led(sc, URTWN_LED_LINK, 0);
1583:
1584: /* Set media status to 'No Link'. */
1585: urtwn_set_nettype0_msr(sc, R92C_CR_NETTYPE_NOLINK);
1586:
1587: /* Stop Rx of data frames. */
1588: urtwn_write_2(sc, R92C_RXFLTMAP2, 0);
1589:
1590: /* Reset TSF. */
1591: urtwn_write_1(sc, R92C_DUAL_TSF_RST, 0x03);
1592:
1593: /* Disable TSF synchronization. */
1594: urtwn_write_1(sc, R92C_BCN_CTRL,
1595: urtwn_read_1(sc, R92C_BCN_CTRL) |
1596: R92C_BCN_CTRL_DIS_TSF_UDT0);
1597:
1598: /* Back to 20MHz mode */
1.14 jmcneill 1599: urtwn_set_chan(sc, ic->ic_curchan,
1.1 nonaka 1600: IEEE80211_HTINFO_2NDCHAN_NONE);
1601:
1602: if (ic->ic_opmode == IEEE80211_M_IBSS ||
1603: ic->ic_opmode == IEEE80211_M_HOSTAP) {
1604: /* Stop BCN */
1605: urtwn_write_1(sc, R92C_BCN_CTRL,
1606: urtwn_read_1(sc, R92C_BCN_CTRL) &
1607: ~(R92C_BCN_CTRL_EN_BCN | R92C_BCN_CTRL_TXBCN_RPT));
1608: }
1609:
1610: /* Reset EDCA parameters. */
1611: urtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3217);
1612: urtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4317);
1613: urtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x00105320);
1614: urtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a444);
1615:
1616: /* flush all cam entries */
1617: urtwn_cam_init(sc);
1618: break;
1619: }
1620:
1621: switch (nstate) {
1622: case IEEE80211_S_INIT:
1623: /* Turn link LED off. */
1624: urtwn_set_led(sc, URTWN_LED_LINK, 0);
1625: break;
1626:
1627: case IEEE80211_S_SCAN:
1628: if (ostate != IEEE80211_S_SCAN) {
1629: /*
1630: * Begin of scanning
1631: */
1632:
1633: /* Set gain for scanning. */
1634: reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
1635: reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
1636: urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
1637:
1638: reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
1639: reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
1640: urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
1641:
1642: /* Set media status to 'No Link'. */
1643: urtwn_set_nettype0_msr(sc, R92C_CR_NETTYPE_NOLINK);
1644:
1645: /* Allow Rx from any BSSID. */
1646: urtwn_write_4(sc, R92C_RCR,
1647: urtwn_read_4(sc, R92C_RCR) &
1648: ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN));
1649:
1650: /* Stop Rx of data frames. */
1651: urtwn_write_2(sc, R92C_RXFLTMAP2, 0);
1652:
1653: /* Disable update TSF */
1654: urtwn_write_1(sc, R92C_BCN_CTRL,
1655: urtwn_read_1(sc, R92C_BCN_CTRL) |
1656: R92C_BCN_CTRL_DIS_TSF_UDT0);
1657: }
1658:
1659: /* Make link LED blink during scan. */
1660: urtwn_set_led(sc, URTWN_LED_LINK, !sc->ledlink);
1661:
1662: /* Pause AC Tx queues. */
1663: urtwn_write_1(sc, R92C_TXPAUSE,
1664: urtwn_read_1(sc, R92C_TXPAUSE) | 0x0f);
1665:
1666: urtwn_set_chan(sc, ic->ic_curchan,
1667: IEEE80211_HTINFO_2NDCHAN_NONE);
1668:
1669: /* Start periodic scan. */
1670: if (!sc->sc_dying)
1671: callout_schedule(&sc->sc_scan_to, hz / 5);
1672: break;
1673:
1674: case IEEE80211_S_AUTH:
1675: /* Set initial gain under link. */
1676: reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0));
1.12 christos 1677: #ifdef doaslinux
1.1 nonaka 1678: reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
1.12 christos 1679: #else
1680: reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
1681: #endif
1.1 nonaka 1682: urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg);
1683:
1684: reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1));
1.12 christos 1685: #ifdef doaslinux
1.1 nonaka 1686: reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32);
1.12 christos 1687: #else
1688: reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20);
1689: #endif
1.1 nonaka 1690: urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg);
1691:
1692: /* Set media status to 'No Link'. */
1693: urtwn_set_nettype0_msr(sc, R92C_CR_NETTYPE_NOLINK);
1694:
1695: /* Allow Rx from any BSSID. */
1696: urtwn_write_4(sc, R92C_RCR,
1697: urtwn_read_4(sc, R92C_RCR) &
1698: ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN));
1699:
1700: urtwn_set_chan(sc, ic->ic_curchan,
1701: IEEE80211_HTINFO_2NDCHAN_NONE);
1702: break;
1703:
1704: case IEEE80211_S_ASSOC:
1705: break;
1706:
1707: case IEEE80211_S_RUN:
1708: ni = ic->ic_bss;
1709:
1710: /* XXX: Set 20MHz mode */
1711: urtwn_set_chan(sc, ic->ic_curchan,
1712: IEEE80211_HTINFO_2NDCHAN_NONE);
1713:
1714: if (ic->ic_opmode == IEEE80211_M_MONITOR) {
1715: /* Back to 20MHz mode */
1.13 jmcneill 1716: urtwn_set_chan(sc, ic->ic_curchan,
1.1 nonaka 1717: IEEE80211_HTINFO_2NDCHAN_NONE);
1718:
1.19 christos 1719: /* Set media status to 'No Link'. */
1720: urtwn_set_nettype0_msr(sc, R92C_CR_NETTYPE_NOLINK);
1721:
1.1 nonaka 1722: /* Enable Rx of data frames. */
1723: urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
1724:
1.19 christos 1725: /* Allow Rx from any BSSID. */
1726: urtwn_write_4(sc, R92C_RCR,
1727: urtwn_read_4(sc, R92C_RCR) &
1728: ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN));
1729:
1730: /* Accept Rx data/control/management frames */
1731: urtwn_write_4(sc, R92C_RCR,
1732: urtwn_read_4(sc, R92C_RCR) |
1733: R92C_RCR_ADF | R92C_RCR_ACF | R92C_RCR_AMF);
1734:
1.1 nonaka 1735: /* Turn link LED on. */
1736: urtwn_set_led(sc, URTWN_LED_LINK, 1);
1737: break;
1738: }
1739:
1740: /* Set media status to 'Associated'. */
1741: urtwn_set_nettype0_msr(sc, urtwn_get_nettype(sc));
1742:
1743: /* Set BSSID. */
1744: urtwn_write_4(sc, R92C_BSSID + 0, LE_READ_4(&ni->ni_bssid[0]));
1745: urtwn_write_4(sc, R92C_BSSID + 4, LE_READ_2(&ni->ni_bssid[4]));
1746:
1747: if (ic->ic_curmode == IEEE80211_MODE_11B) {
1748: urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
1749: } else {
1750: /* 802.11b/g */
1751: urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
1752: }
1753:
1754: /* Enable Rx of data frames. */
1755: urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
1756:
1757: /* Set beacon interval. */
1758: urtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval);
1759:
1.26 ! christos 1760: msr = urtwn_read_1(sc, R92C_MSR);
! 1761: msr &= 0xfc;
! 1762: switch (ic->ic_opmode) {
! 1763: case IEEE80211_M_STA:
1.1 nonaka 1764: /* Allow Rx from our BSSID only. */
1765: urtwn_write_4(sc, R92C_RCR,
1766: urtwn_read_4(sc, R92C_RCR) |
1767: R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
1768:
1769: /* Enable TSF synchronization. */
1770: urtwn_tsf_sync_enable(sc);
1.26 ! christos 1771: /*FALLTHROUGH*/
! 1772: default:
! 1773: msr |= R92C_MSR_ADHOC;
! 1774: break;
! 1775: case IEEE80211_M_HOSTAP:
! 1776: urtwn_write_2(sc, R92C_BCNTCFG, 0x000f);
! 1777:
! 1778: /* Allow Rx from any BSSID. */
! 1779: urtwn_write_4(sc, R92C_RCR,
! 1780: urtwn_read_4(sc, R92C_RCR) &
! 1781: ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN));
! 1782:
! 1783: /* Reset TSF timer to zero. */
! 1784: reg = urtwn_read_4(sc, R92C_TCR);
! 1785: reg &= ~0x01;
! 1786: urtwn_write_4(sc, R92C_TCR, reg);
! 1787: reg |= 0x01;
! 1788: urtwn_write_4(sc, R92C_TCR, reg);
! 1789: msr |= R92C_MSR_AP;
! 1790: break;
! 1791: }
! 1792: urtwn_write_1(sc, R92C_MSR, msr);
1.1 nonaka 1793:
1794: sifs_time = 10;
1795: urtwn_write_1(sc, R92C_SIFS_CCK + 1, sifs_time);
1796: urtwn_write_1(sc, R92C_SIFS_OFDM + 1, sifs_time);
1797: urtwn_write_1(sc, R92C_SPEC_SIFS + 1, sifs_time);
1798: urtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, sifs_time);
1799: urtwn_write_1(sc, R92C_R2T_SIFS + 1, sifs_time);
1800: urtwn_write_1(sc, R92C_T2T_SIFS + 1, sifs_time);
1801:
1802: /* Intialize rate adaptation. */
1803: urtwn_ra_init(sc);
1804:
1805: /* Turn link LED on. */
1806: urtwn_set_led(sc, URTWN_LED_LINK, 1);
1807:
1808: /* Reset average RSSI. */
1809: sc->avg_pwdb = -1;
1810:
1811: /* Reset temperature calibration state machine. */
1812: sc->thcal_state = 0;
1813: sc->thcal_lctemp = 0;
1814:
1815: /* Start periodic calibration. */
1816: if (!sc->sc_dying)
1817: callout_schedule(&sc->sc_calib_to, hz);
1818: break;
1819: }
1820:
1821: (*sc->sc_newstate)(ic, nstate, cmd->arg);
1822:
1.12 christos 1823: mutex_exit(&sc->sc_write_mtx);
1.1 nonaka 1824: splx(s);
1825: }
1826:
1827: static int
1828: urtwn_wme_update(struct ieee80211com *ic)
1829: {
1830: struct urtwn_softc *sc = ic->ic_ifp->if_softc;
1831:
1832: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
1833:
1834: /* don't override default WME values if WME is not actually enabled */
1835: if (!(ic->ic_flags & IEEE80211_F_WME))
1836: return (0);
1837:
1838: /* Do it in a process context. */
1839: urtwn_do_async(sc, urtwn_wme_update_cb, NULL, 0);
1840: return (0);
1841: }
1842:
1843: static void
1844: urtwn_wme_update_cb(struct urtwn_softc *sc, void *arg)
1845: {
1846: static const uint16_t ac2reg[WME_NUM_AC] = {
1847: R92C_EDCA_BE_PARAM,
1848: R92C_EDCA_BK_PARAM,
1849: R92C_EDCA_VI_PARAM,
1850: R92C_EDCA_VO_PARAM
1851: };
1852: struct ieee80211com *ic = &sc->sc_ic;
1853: const struct wmeParams *wmep;
1854: int ac, aifs, slottime;
1855: int s;
1856:
1857: DPRINTFN(DBG_FN|DBG_STM, ("%s: %s\n", device_xname(sc->sc_dev),
1858: __func__));
1859:
1860: s = splnet();
1.12 christos 1861: mutex_enter(&sc->sc_write_mtx);
1.1 nonaka 1862: slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
1863: for (ac = 0; ac < WME_NUM_AC; ac++) {
1864: wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
1865: /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */
1866: aifs = wmep->wmep_aifsn * slottime + 10;
1867: urtwn_write_4(sc, ac2reg[ac],
1868: SM(R92C_EDCA_PARAM_TXOP, wmep->wmep_txopLimit) |
1869: SM(R92C_EDCA_PARAM_ECWMIN, wmep->wmep_logcwmin) |
1870: SM(R92C_EDCA_PARAM_ECWMAX, wmep->wmep_logcwmax) |
1871: SM(R92C_EDCA_PARAM_AIFS, aifs));
1872: }
1.12 christos 1873: mutex_exit(&sc->sc_write_mtx);
1.1 nonaka 1874: splx(s);
1875: }
1876:
1877: static void
1878: urtwn_update_avgrssi(struct urtwn_softc *sc, int rate, int8_t rssi)
1879: {
1880: int pwdb;
1881:
1882: DPRINTFN(DBG_FN, ("%s: %s: rate=%d, rsst=%d\n",
1883: device_xname(sc->sc_dev), __func__, rate, rssi));
1884:
1885: /* Convert antenna signal to percentage. */
1886: if (rssi <= -100 || rssi >= 20)
1887: pwdb = 0;
1888: else if (rssi >= 0)
1889: pwdb = 100;
1890: else
1891: pwdb = 100 + rssi;
1892: if (rate <= 3) {
1893: /* CCK gain is smaller than OFDM/MCS gain. */
1894: pwdb += 6;
1895: if (pwdb > 100)
1896: pwdb = 100;
1897: if (pwdb <= 14)
1898: pwdb -= 4;
1899: else if (pwdb <= 26)
1900: pwdb -= 8;
1901: else if (pwdb <= 34)
1902: pwdb -= 6;
1903: else if (pwdb <= 42)
1904: pwdb -= 2;
1905: }
1906: if (sc->avg_pwdb == -1) /* Init. */
1907: sc->avg_pwdb = pwdb;
1908: else if (sc->avg_pwdb < pwdb)
1909: sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20) + 1;
1910: else
1911: sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20);
1912:
1.12 christos 1913: DPRINTFN(DBG_RF, ("%s: %s: rate=%d rssi=%d PWDB=%d EMA=%d\n",
1914: device_xname(sc->sc_dev), __func__,
1915: rate, rssi, pwdb, sc->avg_pwdb));
1.1 nonaka 1916: }
1917:
1918: static int8_t
1919: urtwn_get_rssi(struct urtwn_softc *sc, int rate, void *physt)
1920: {
1921: static const int8_t cckoff[] = { 16, -12, -26, -46 };
1922: struct r92c_rx_phystat *phy;
1923: struct r92c_rx_cck *cck;
1924: uint8_t rpt;
1925: int8_t rssi;
1926:
1927: DPRINTFN(DBG_FN, ("%s: %s: rate=%d\n", device_xname(sc->sc_dev),
1928: __func__, rate));
1929:
1930: if (rate <= 3) {
1931: cck = (struct r92c_rx_cck *)physt;
1932: if (ISSET(sc->sc_flags, URTWN_FLAG_CCK_HIPWR)) {
1933: rpt = (cck->agc_rpt >> 5) & 0x3;
1934: rssi = (cck->agc_rpt & 0x1f) << 1;
1935: } else {
1936: rpt = (cck->agc_rpt >> 6) & 0x3;
1937: rssi = cck->agc_rpt & 0x3e;
1938: }
1939: rssi = cckoff[rpt] - rssi;
1940: } else { /* OFDM/HT. */
1941: phy = (struct r92c_rx_phystat *)physt;
1942: rssi = ((le32toh(phy->phydw1) >> 1) & 0x7f) - 110;
1943: }
1944: return (rssi);
1945: }
1946:
1947: static void
1948: urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen)
1949: {
1950: struct ieee80211com *ic = &sc->sc_ic;
1951: struct ifnet *ifp = ic->ic_ifp;
1952: struct ieee80211_frame *wh;
1953: struct ieee80211_node *ni;
1954: struct r92c_rx_stat *stat;
1955: uint32_t rxdw0, rxdw3;
1956: struct mbuf *m;
1957: uint8_t rate;
1958: int8_t rssi = 0;
1959: int s, infosz;
1960:
1961: DPRINTFN(DBG_FN, ("%s: %s: buf=%p, pktlen=%d\n",
1962: device_xname(sc->sc_dev), __func__, buf, pktlen));
1963:
1964: stat = (struct r92c_rx_stat *)buf;
1965: rxdw0 = le32toh(stat->rxdw0);
1966: rxdw3 = le32toh(stat->rxdw3);
1967:
1968: if (__predict_false(rxdw0 & (R92C_RXDW0_CRCERR | R92C_RXDW0_ICVERR))) {
1969: /*
1970: * This should not happen since we setup our Rx filter
1971: * to not receive these frames.
1972: */
1973: DPRINTFN(DBG_RX, ("%s: %s: CRC error\n",
1974: device_xname(sc->sc_dev), __func__));
1975: ifp->if_ierrors++;
1976: return;
1977: }
1.19 christos 1978: /*
1979: * XXX: This will drop most control packets. Do we really
1980: * want this in IEEE80211_M_MONITOR mode?
1981: */
1.22 christos 1982: // if (__predict_false(pktlen < (int)sizeof(*wh))) {
1983: if (__predict_false(pktlen < (int)sizeof(struct ieee80211_frame_ack))) {
1.1 nonaka 1984: DPRINTFN(DBG_RX, ("%s: %s: packet too short %d\n",
1985: device_xname(sc->sc_dev), __func__, pktlen));
1986: ic->ic_stats.is_rx_tooshort++;
1987: ifp->if_ierrors++;
1988: return;
1989: }
1990: if (__predict_false(pktlen > MCLBYTES)) {
1991: DPRINTFN(DBG_RX, ("%s: %s: packet too big %d\n",
1992: device_xname(sc->sc_dev), __func__, pktlen));
1993: ifp->if_ierrors++;
1994: return;
1995: }
1996:
1997: rate = MS(rxdw3, R92C_RXDW3_RATE);
1998: infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
1999:
2000: /* Get RSSI from PHY status descriptor if present. */
2001: if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) {
2002: rssi = urtwn_get_rssi(sc, rate, &stat[1]);
2003: /* Update our average RSSI. */
2004: urtwn_update_avgrssi(sc, rate, rssi);
2005: }
2006:
2007: DPRINTFN(DBG_RX, ("%s: %s: Rx frame len=%d rate=%d infosz=%d rssi=%d\n",
2008: device_xname(sc->sc_dev), __func__, pktlen, rate, infosz, rssi));
2009:
2010: MGETHDR(m, M_DONTWAIT, MT_DATA);
2011: if (__predict_false(m == NULL)) {
2012: aprint_error_dev(sc->sc_dev, "couldn't allocate rx mbuf\n");
2013: ic->ic_stats.is_rx_nobuf++;
2014: ifp->if_ierrors++;
2015: return;
2016: }
2017: if (pktlen > (int)MHLEN) {
2018: MCLGET(m, M_DONTWAIT);
2019: if (__predict_false(!(m->m_flags & M_EXT))) {
2020: aprint_error_dev(sc->sc_dev,
2021: "couldn't allocate rx mbuf cluster\n");
2022: m_freem(m);
2023: ic->ic_stats.is_rx_nobuf++;
2024: ifp->if_ierrors++;
2025: return;
2026: }
2027: }
2028:
2029: /* Finalize mbuf. */
2030: m->m_pkthdr.rcvif = ifp;
2031: wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
2032: memcpy(mtod(m, uint8_t *), wh, pktlen);
2033: m->m_pkthdr.len = m->m_len = pktlen;
2034:
2035: s = splnet();
2036: if (__predict_false(sc->sc_drvbpf != NULL)) {
2037: struct urtwn_rx_radiotap_header *tap = &sc->sc_rxtap;
2038:
1.19 christos 2039: tap->wr_flags = 0;
1.1 nonaka 2040: if (!(rxdw3 & R92C_RXDW3_HT)) {
2041: switch (rate) {
2042: /* CCK. */
2043: case 0: tap->wr_rate = 2; break;
2044: case 1: tap->wr_rate = 4; break;
2045: case 2: tap->wr_rate = 11; break;
2046: case 3: tap->wr_rate = 22; break;
2047: /* OFDM. */
2048: case 4: tap->wr_rate = 12; break;
2049: case 5: tap->wr_rate = 18; break;
2050: case 6: tap->wr_rate = 24; break;
2051: case 7: tap->wr_rate = 36; break;
2052: case 8: tap->wr_rate = 48; break;
2053: case 9: tap->wr_rate = 72; break;
2054: case 10: tap->wr_rate = 96; break;
2055: case 11: tap->wr_rate = 108; break;
2056: }
2057: } else if (rate >= 12) { /* MCS0~15. */
2058: /* Bit 7 set means HT MCS instead of rate. */
2059: tap->wr_rate = 0x80 | (rate - 12);
2060: }
2061: tap->wr_dbm_antsignal = rssi;
1.13 jmcneill 2062: tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
2063: tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
1.1 nonaka 2064:
2065: bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
2066: }
2067:
2068: ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
2069:
2070: /* push the frame up to the 802.11 stack */
2071: ieee80211_input(ic, m, ni, rssi, 0);
2072:
2073: /* Node is no longer needed. */
2074: ieee80211_free_node(ni);
2075:
2076: splx(s);
2077: }
2078:
2079: static void
2080: urtwn_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
2081: {
2082: struct urtwn_rx_data *data = priv;
2083: struct urtwn_softc *sc = data->sc;
2084: struct r92c_rx_stat *stat;
2085: uint32_t rxdw0;
2086: uint8_t *buf;
2087: int len, totlen, pktlen, infosz, npkts;
2088:
2089: DPRINTFN(DBG_FN|DBG_RX, ("%s: %s: status=%d\n",
2090: device_xname(sc->sc_dev), __func__, status));
2091:
2092: if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
2093: if (status == USBD_STALLED)
2094: usbd_clear_endpoint_stall_async(sc->rx_pipe);
2095: else if (status != USBD_CANCELLED)
2096: goto resubmit;
2097: return;
2098: }
2099: usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
2100:
2101: if (__predict_false(len < (int)sizeof(*stat))) {
2102: DPRINTFN(DBG_RX, ("%s: %s: xfer too short %d\n",
2103: device_xname(sc->sc_dev), __func__, len));
2104: goto resubmit;
2105: }
2106: buf = data->buf;
2107:
2108: /* Get the number of encapsulated frames. */
2109: stat = (struct r92c_rx_stat *)buf;
2110: npkts = MS(le32toh(stat->rxdw2), R92C_RXDW2_PKTCNT);
2111: DPRINTFN(DBG_RX, ("%s: %s: Rx %d frames in one chunk\n",
2112: device_xname(sc->sc_dev), __func__, npkts));
2113:
2114: /* Process all of them. */
2115: while (npkts-- > 0) {
2116: if (__predict_false(len < (int)sizeof(*stat))) {
2117: DPRINTFN(DBG_RX,
2118: ("%s: %s: len(%d) is short than header\n",
2119: device_xname(sc->sc_dev), __func__, len));
2120: break;
2121: }
2122: stat = (struct r92c_rx_stat *)buf;
2123: rxdw0 = le32toh(stat->rxdw0);
2124:
2125: pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
2126: if (__predict_false(pktlen == 0)) {
2127: DPRINTFN(DBG_RX, ("%s: %s: pktlen is 0 byte\n",
2128: device_xname(sc->sc_dev), __func__));
1.19 christos 2129: break;
1.1 nonaka 2130: }
2131:
2132: infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
2133:
2134: /* Make sure everything fits in xfer. */
2135: totlen = sizeof(*stat) + infosz + pktlen;
2136: if (__predict_false(totlen > len)) {
2137: DPRINTFN(DBG_RX, ("%s: %s: pktlen %d(%d+%d+%d) > %d\n",
2138: device_xname(sc->sc_dev), __func__, totlen,
2139: (int)sizeof(*stat), infosz, pktlen, len));
2140: break;
2141: }
2142:
2143: /* Process 802.11 frame. */
2144: urtwn_rx_frame(sc, buf, pktlen);
2145:
2146: /* Next chunk is 128-byte aligned. */
2147: totlen = roundup2(totlen, 128);
2148: buf += totlen;
2149: len -= totlen;
2150: }
2151:
2152: resubmit:
2153: /* Setup a new transfer. */
2154: usbd_setup_xfer(xfer, sc->rx_pipe, data, data->buf, URTWN_RXBUFSZ,
2155: USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, urtwn_rxeof);
2156: (void)usbd_transfer(xfer);
2157: }
2158:
2159: static void
2160: urtwn_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
2161: {
2162: struct urtwn_tx_data *data = priv;
2163: struct urtwn_softc *sc = data->sc;
2164: struct ifnet *ifp = &sc->sc_if;
1.20 christos 2165: usbd_pipe_handle pipe = data->pipe;
1.1 nonaka 2166: int s;
2167:
2168: DPRINTFN(DBG_FN|DBG_TX, ("%s: %s: status=%d\n",
2169: device_xname(sc->sc_dev), __func__, status));
2170:
2171: mutex_enter(&sc->sc_tx_mtx);
2172: /* Put this Tx buffer back to our free list. */
2173: TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
2174: mutex_exit(&sc->sc_tx_mtx);
2175:
1.16 jmcneill 2176: s = splnet();
2177: sc->tx_timer = 0;
2178: ifp->if_flags &= ~IFF_OACTIVE;
2179:
1.1 nonaka 2180: if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
2181: if (status != USBD_NOT_STARTED && status != USBD_CANCELLED) {
2182: if (status == USBD_STALLED)
1.20 christos 2183: usbd_clear_endpoint_stall_async(pipe);
1.1 nonaka 2184: ifp->if_oerrors++;
2185: }
1.16 jmcneill 2186: splx(s);
1.1 nonaka 2187: return;
2188: }
2189:
1.21 christos 2190: ifp->if_opackets++;
1.16 jmcneill 2191: urtwn_start(ifp);
1.1 nonaka 2192:
2193: splx(s);
2194: }
2195:
2196: static int
1.12 christos 2197: urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
2198: struct urtwn_tx_data *data)
1.1 nonaka 2199: {
2200: struct ieee80211com *ic = &sc->sc_ic;
2201: struct ieee80211_frame *wh;
2202: struct ieee80211_key *k = NULL;
2203: struct r92c_tx_desc *txd;
2204: usbd_pipe_handle pipe;
1.22 christos 2205: size_t i, padsize, xferlen;
1.1 nonaka 2206: uint16_t seq, sum;
2207: uint8_t raid, type, tid, qid;
1.22 christos 2208: int s, hasqos, error;
1.1 nonaka 2209:
2210: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2211:
2212: wh = mtod(m, struct ieee80211_frame *);
2213: type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
2214:
2215: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2216: k = ieee80211_crypto_encap(ic, ni, m);
1.12 christos 2217: if (k == NULL)
2218: return ENOBUFS;
2219:
1.1 nonaka 2220: /* packet header may have moved, reset our local pointer */
2221: wh = mtod(m, struct ieee80211_frame *);
2222: }
2223:
2224: if (__predict_false(sc->sc_drvbpf != NULL)) {
2225: struct urtwn_tx_radiotap_header *tap = &sc->sc_txtap;
2226:
2227: tap->wt_flags = 0;
1.14 jmcneill 2228: tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
2229: tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
1.1 nonaka 2230: if (wh->i_fc[1] & IEEE80211_FC1_WEP)
2231: tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2232:
1.19 christos 2233: /* XXX: set tap->wt_rate? */
2234:
1.1 nonaka 2235: bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m);
2236: }
2237:
1.23 christos 2238: if ((hasqos = ieee80211_has_qos(wh))) {
1.1 nonaka 2239: /* data frames in 11n mode */
2240: struct ieee80211_qosframe *qwh = (void *)wh;
2241: tid = qwh->i_qos[0] & IEEE80211_QOS_TID;
2242: qid = TID_TO_WME_AC(tid);
2243: } else if (type != IEEE80211_FC0_TYPE_DATA) {
2244: /* Use AC_VO for management frames. */
2245: qid = WME_AC_VO;
2246: tid = 0; /* compiler happy */
2247: } else {
2248: /* non-qos data frames */
2249: tid = R92C_TXDW1_QSEL_BE;
2250: qid = WME_AC_BE;
2251: }
2252:
2253: /* Get the USB pipe to use for this AC. */
2254: pipe = sc->tx_pipe[sc->ac2idx[qid]];
2255:
2256: if (((sizeof(*txd) + m->m_pkthdr.len) % 64) == 0) /* XXX: 64 */
2257: padsize = 8;
2258: else
2259: padsize = 0;
2260:
2261: /* Fill Tx descriptor. */
2262: txd = (struct r92c_tx_desc *)data->buf;
2263: memset(txd, 0, sizeof(*txd) + padsize);
2264:
2265: txd->txdw0 |= htole32(
2266: SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) |
2267: SM(R92C_TXDW0_OFFSET, sizeof(*txd)) |
2268: R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG);
2269:
2270: if (IEEE80211_IS_MULTICAST(wh->i_addr1))
2271: txd->txdw0 |= htole32(R92C_TXDW0_BMCAST);
2272:
2273: /* fix pad field */
2274: if (padsize > 0) {
1.22 christos 2275: DPRINTFN(DBG_TX, ("%s: %s: padding: size=%zd\n",
1.1 nonaka 2276: device_xname(sc->sc_dev), __func__, padsize));
2277: txd->txdw1 |= htole32(SM(R92C_TXDW1_PKTOFF, (padsize / 8)));
2278: }
2279:
2280: if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
2281: type == IEEE80211_FC0_TYPE_DATA) {
2282: if (ic->ic_curmode == IEEE80211_MODE_11B)
2283: raid = R92C_RAID_11B;
2284: else
2285: raid = R92C_RAID_11BG;
2286: DPRINTFN(DBG_TX,
2287: ("%s: %s: data packet: tid=%d, raid=%d\n",
2288: device_xname(sc->sc_dev), __func__, tid, raid));
2289:
2290: txd->txdw1 |= htole32(
2291: SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) |
2292: SM(R92C_TXDW1_QSEL, tid) |
2293: SM(R92C_TXDW1_RAID, raid) |
2294: R92C_TXDW1_AGGBK);
2295:
2296: if (hasqos) {
2297: txd->txdw4 |= htole32(R92C_TXDW4_QOS);
2298: }
2299:
2300: if (ic->ic_flags & IEEE80211_F_USEPROT) {
2301: /* for 11g */
2302: if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
2303: txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF |
2304: R92C_TXDW4_HWRTSEN);
2305: } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) {
2306: txd->txdw4 |= htole32(R92C_TXDW4_RTSEN |
2307: R92C_TXDW4_HWRTSEN);
2308: }
2309: }
2310: /* Send RTS at OFDM24. */
2311: txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, 8));
2312: txd->txdw5 |= htole32(0x0001ff00);
2313: /* Send data at OFDM54. */
2314: txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11));
2315: } else if (type == IEEE80211_FC0_TYPE_MGT) {
2316: DPRINTFN(DBG_TX, ("%s: %s: mgmt packet\n",
2317: device_xname(sc->sc_dev), __func__));
2318: txd->txdw1 |= htole32(
2319: SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) |
2320: SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT) |
2321: SM(R92C_TXDW1_RAID, R92C_RAID_11B));
2322:
2323: /* Force CCK1. */
2324: txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
2325: /* Use 1Mbps */
2326: txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0));
2327: } else {
2328: /* broadcast or multicast packets */
2329: DPRINTFN(DBG_TX, ("%s: %s: bc or mc packet\n",
2330: device_xname(sc->sc_dev), __func__));
2331: txd->txdw1 |= htole32(
2332: SM(R92C_TXDW1_MACID, URTWN_MACID_BC) |
2333: SM(R92C_TXDW1_RAID, R92C_RAID_11B));
2334:
2335: /* Force CCK1. */
2336: txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
2337: /* Use 1Mbps */
2338: txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0));
2339: }
2340:
2341: /* Set sequence number */
2342: seq = LE_READ_2(&wh->i_seq[0]) >> IEEE80211_SEQ_SEQ_SHIFT;
2343: txd->txdseq |= htole16(seq);
2344:
2345: if (!hasqos) {
2346: /* Use HW sequence numbering for non-QoS frames. */
2347: txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ);
2348: txd->txdseq |= htole16(0x8000); /* WTF? */
2349: }
2350:
2351: /* Compute Tx descriptor checksum. */
2352: sum = 0;
1.22 christos 2353: for (i = 0; i < sizeof(*txd) / 2; i++)
1.1 nonaka 2354: sum ^= ((uint16_t *)txd)[i];
2355: txd->txdsum = sum; /* NB: already little endian. */
2356:
2357: xferlen = sizeof(*txd) + m->m_pkthdr.len + padsize;
2358: m_copydata(m, 0, m->m_pkthdr.len, (char *)&txd[1] + padsize);
2359:
2360: s = splnet();
2361: data->pipe = pipe;
2362: usbd_setup_xfer(data->xfer, pipe, data, data->buf, xferlen,
2363: USBD_FORCE_SHORT_XFER | USBD_NO_COPY, URTWN_TX_TIMEOUT,
2364: urtwn_txeof);
2365: error = usbd_transfer(data->xfer);
2366: if (__predict_false(error != USBD_NORMAL_COMPLETION &&
2367: error != USBD_IN_PROGRESS)) {
2368: splx(s);
2369: DPRINTFN(DBG_TX, ("%s: %s: transfer failed %d\n",
2370: device_xname(sc->sc_dev), __func__, error));
1.12 christos 2371: return error;
1.1 nonaka 2372: }
2373: splx(s);
1.12 christos 2374: return 0;
1.1 nonaka 2375: }
2376:
2377: static void
2378: urtwn_start(struct ifnet *ifp)
2379: {
2380: struct urtwn_softc *sc = ifp->if_softc;
2381: struct ieee80211com *ic = &sc->sc_ic;
1.12 christos 2382: struct urtwn_tx_data *data;
1.1 nonaka 2383: struct ether_header *eh;
2384: struct ieee80211_node *ni;
2385: struct mbuf *m;
2386:
2387: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2388:
2389: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
2390: return;
2391:
1.12 christos 2392: data = NULL;
1.1 nonaka 2393: for (;;) {
2394: mutex_enter(&sc->sc_tx_mtx);
1.17 jmcneill 2395: if (data == NULL && !TAILQ_EMPTY(&sc->tx_free_list)) {
1.12 christos 2396: data = TAILQ_FIRST(&sc->tx_free_list);
2397: TAILQ_REMOVE(&sc->tx_free_list, data, next);
1.1 nonaka 2398: }
1.17 jmcneill 2399: mutex_exit(&sc->sc_tx_mtx);
2400:
2401: if (data == NULL) {
2402: ifp->if_flags |= IFF_OACTIVE;
2403: DPRINTFN(DBG_TX, ("%s: empty tx_free_list\n",
2404: device_xname(sc->sc_dev)));
2405: return;
2406: }
1.1 nonaka 2407:
2408: /* Send pending management frames first. */
2409: IF_DEQUEUE(&ic->ic_mgtq, m);
2410: if (m != NULL) {
2411: ni = (void *)m->m_pkthdr.rcvif;
2412: m->m_pkthdr.rcvif = NULL;
2413: goto sendit;
2414: }
2415: if (ic->ic_state != IEEE80211_S_RUN)
2416: break;
2417:
2418: /* Encapsulate and send data frames. */
2419: IFQ_DEQUEUE(&ifp->if_snd, m);
2420: if (m == NULL)
2421: break;
1.12 christos 2422:
1.1 nonaka 2423: if (m->m_len < (int)sizeof(*eh) &&
2424: (m = m_pullup(m, sizeof(*eh))) == NULL) {
2425: ifp->if_oerrors++;
2426: continue;
2427: }
2428: eh = mtod(m, struct ether_header *);
2429: ni = ieee80211_find_txnode(ic, eh->ether_dhost);
2430: if (ni == NULL) {
2431: m_freem(m);
2432: ifp->if_oerrors++;
2433: continue;
2434: }
2435:
2436: bpf_mtap(ifp, m);
2437:
2438: if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
2439: ieee80211_free_node(ni);
2440: ifp->if_oerrors++;
2441: continue;
2442: }
2443: sendit:
2444: bpf_mtap3(ic->ic_rawbpf, m);
2445:
1.12 christos 2446: if (urtwn_tx(sc, m, ni, data) != 0) {
2447: m_freem(m);
1.1 nonaka 2448: ieee80211_free_node(ni);
2449: ifp->if_oerrors++;
2450: continue;
2451: }
1.12 christos 2452: data = NULL;
2453: m_freem(m);
2454: ieee80211_free_node(ni);
1.1 nonaka 2455: sc->tx_timer = 5;
2456: ifp->if_timer = 1;
2457: }
1.12 christos 2458:
2459: /* Return the Tx buffer to the free list */
1.17 jmcneill 2460: mutex_enter(&sc->sc_tx_mtx);
1.12 christos 2461: TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
2462: mutex_exit(&sc->sc_tx_mtx);
1.1 nonaka 2463: }
2464:
2465: static void
2466: urtwn_watchdog(struct ifnet *ifp)
2467: {
2468: struct urtwn_softc *sc = ifp->if_softc;
2469:
2470: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2471:
2472: ifp->if_timer = 0;
2473:
2474: if (sc->tx_timer > 0) {
2475: if (--sc->tx_timer == 0) {
2476: aprint_error_dev(sc->sc_dev, "device timeout\n");
2477: /* urtwn_init(ifp); XXX needs a process context! */
2478: ifp->if_oerrors++;
2479: return;
2480: }
2481: ifp->if_timer = 1;
2482: }
2483: ieee80211_watchdog(&sc->sc_ic);
2484: }
2485:
2486: static int
2487: urtwn_ioctl(struct ifnet *ifp, u_long cmd, void *data)
2488: {
2489: struct urtwn_softc *sc = ifp->if_softc;
2490: struct ieee80211com *ic = &sc->sc_ic;
2491: int s, error = 0;
2492:
2493: DPRINTFN(DBG_FN, ("%s: %s: cmd=0x%08lx, data=%p\n",
2494: device_xname(sc->sc_dev), __func__, cmd, data));
2495:
2496: s = splnet();
2497:
2498: switch (cmd) {
2499: case SIOCSIFFLAGS:
2500: if ((error = ifioctl_common(ifp, cmd, data)) != 0)
2501: break;
1.12 christos 2502: switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
2503: case IFF_UP | IFF_RUNNING:
1.1 nonaka 2504: break;
2505: case IFF_UP:
2506: urtwn_init(ifp);
2507: break;
2508: case IFF_RUNNING:
2509: urtwn_stop(ifp, 1);
2510: break;
2511: case 0:
2512: break;
2513: }
2514: break;
2515:
2516: case SIOCADDMULTI:
2517: case SIOCDELMULTI:
2518: if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
2519: /* setup multicast filter, etc */
2520: error = 0;
2521: }
2522: break;
2523:
2524: default:
2525: error = ieee80211_ioctl(ic, cmd, data);
2526: break;
2527: }
2528: if (error == ENETRESET) {
2529: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1.16 jmcneill 2530: (IFF_UP | IFF_RUNNING) &&
2531: ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
1.1 nonaka 2532: urtwn_init(ifp);
2533: }
2534: error = 0;
2535: }
2536:
2537: splx(s);
2538:
2539: return (error);
2540: }
2541:
2542: static int
2543: urtwn_power_on(struct urtwn_softc *sc)
2544: {
2545: uint32_t reg;
2546: int ntries;
2547:
2548: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2549:
1.12 christos 2550: KASSERT(mutex_owned(&sc->sc_write_mtx));
2551:
1.1 nonaka 2552: /* Wait for autoload done bit. */
2553: for (ntries = 0; ntries < 1000; ntries++) {
2554: if (urtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN)
2555: break;
2556: DELAY(5);
2557: }
2558: if (ntries == 1000) {
2559: aprint_error_dev(sc->sc_dev,
2560: "timeout waiting for chip autoload\n");
2561: return (ETIMEDOUT);
2562: }
2563:
2564: /* Unlock ISO/CLK/Power control register. */
2565: urtwn_write_1(sc, R92C_RSV_CTRL, 0);
2566: /* Move SPS into PWM mode. */
2567: urtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b);
2568: DELAY(100);
2569:
2570: reg = urtwn_read_1(sc, R92C_LDOV12D_CTRL);
2571: if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) {
2572: urtwn_write_1(sc, R92C_LDOV12D_CTRL,
2573: reg | R92C_LDOV12D_CTRL_LDV12_EN);
2574: DELAY(100);
2575: urtwn_write_1(sc, R92C_SYS_ISO_CTRL,
2576: urtwn_read_1(sc, R92C_SYS_ISO_CTRL) &
2577: ~R92C_SYS_ISO_CTRL_MD2PP);
2578: }
2579:
2580: /* Auto enable WLAN. */
2581: urtwn_write_2(sc, R92C_APS_FSMCO,
2582: urtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC);
2583: for (ntries = 0; ntries < 1000; ntries++) {
2584: if (!(urtwn_read_2(sc, R92C_APS_FSMCO) &
2585: R92C_APS_FSMCO_APFM_ONMAC))
2586: break;
2587: DELAY(5);
2588: }
2589: if (ntries == 1000) {
2590: aprint_error_dev(sc->sc_dev,
2591: "timeout waiting for MAC auto ON\n");
2592: return (ETIMEDOUT);
2593: }
2594:
2595: /* Enable radio, GPIO and LED functions. */
2596: KASSERT((R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_PDN_EN |
2597: R92C_APS_FSMCO_PFM_ALDN) == 0x0812);
2598: urtwn_write_2(sc, R92C_APS_FSMCO,
2599: R92C_APS_FSMCO_AFSM_HSUS |
2600: R92C_APS_FSMCO_PDN_EN |
2601: R92C_APS_FSMCO_PFM_ALDN);
2602:
2603: /* Release RF digital isolation. */
2604: urtwn_write_2(sc, R92C_SYS_ISO_CTRL,
2605: urtwn_read_2(sc, R92C_SYS_ISO_CTRL) & ~R92C_SYS_ISO_CTRL_DIOR);
2606:
2607: /* Initialize MAC. */
2608: urtwn_write_1(sc, R92C_APSD_CTRL,
2609: urtwn_read_1(sc, R92C_APSD_CTRL) & ~R92C_APSD_CTRL_OFF);
2610: for (ntries = 0; ntries < 200; ntries++) {
2611: if (!(urtwn_read_1(sc, R92C_APSD_CTRL) &
2612: R92C_APSD_CTRL_OFF_STATUS))
2613: break;
2614: DELAY(5);
2615: }
2616: if (ntries == 200) {
2617: aprint_error_dev(sc->sc_dev,
2618: "timeout waiting for MAC initialization\n");
2619: return (ETIMEDOUT);
2620: }
2621:
2622: /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */
2623: reg = urtwn_read_2(sc, R92C_CR);
2624: reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN |
2625: R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN |
2626: R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN |
2627: R92C_CR_ENSEC;
2628: urtwn_write_2(sc, R92C_CR, reg);
2629:
2630: urtwn_write_1(sc, 0xfe10, 0x19);
2631: return (0);
2632: }
2633:
2634: static int
2635: urtwn_llt_init(struct urtwn_softc *sc)
2636: {
1.22 christos 2637: size_t i;
2638: int error;
1.1 nonaka 2639:
2640: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2641:
1.12 christos 2642: KASSERT(mutex_owned(&sc->sc_write_mtx));
2643:
1.1 nonaka 2644: /* Reserve pages [0; R92C_TX_PAGE_COUNT]. */
2645: for (i = 0; i < R92C_TX_PAGE_COUNT; i++) {
2646: if ((error = urtwn_llt_write(sc, i, i + 1)) != 0)
2647: return (error);
2648: }
2649: /* NB: 0xff indicates end-of-list. */
2650: if ((error = urtwn_llt_write(sc, i, 0xff)) != 0)
2651: return (error);
2652: /*
2653: * Use pages [R92C_TX_PAGE_COUNT + 1; R92C_TXPKTBUF_COUNT - 1]
2654: * as ring buffer.
2655: */
2656: for (++i; i < R92C_TXPKTBUF_COUNT - 1; i++) {
2657: if ((error = urtwn_llt_write(sc, i, i + 1)) != 0)
2658: return (error);
2659: }
2660: /* Make the last page point to the beginning of the ring buffer. */
2661: error = urtwn_llt_write(sc, i, R92C_TX_PAGE_COUNT + 1);
2662: return (error);
2663: }
2664:
2665: static void
2666: urtwn_fw_reset(struct urtwn_softc *sc)
2667: {
2668: uint16_t reg;
2669: int ntries;
2670:
2671: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2672:
1.12 christos 2673: KASSERT(mutex_owned(&sc->sc_write_mtx));
2674:
1.1 nonaka 2675: /* Tell 8051 to reset itself. */
2676: urtwn_write_1(sc, R92C_HMETFR + 3, 0x20);
2677:
2678: /* Wait until 8051 resets by itself. */
2679: for (ntries = 0; ntries < 100; ntries++) {
2680: reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN);
2681: if (!(reg & R92C_SYS_FUNC_EN_CPUEN))
2682: return;
2683: DELAY(50);
2684: }
2685: /* Force 8051 reset. */
2686: urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN);
2687: }
2688:
2689: static int
2690: urtwn_fw_loadpage(struct urtwn_softc *sc, int page, uint8_t *buf, int len)
2691: {
2692: uint32_t reg;
2693: int off, mlen, error = 0;
2694:
2695: DPRINTFN(DBG_FN, ("%s: %s: page=%d, buf=%p, len=%d\n",
2696: device_xname(sc->sc_dev), __func__, page, buf, len));
2697:
2698: reg = urtwn_read_4(sc, R92C_MCUFWDL);
2699: reg = RW(reg, R92C_MCUFWDL_PAGE, page);
2700: urtwn_write_4(sc, R92C_MCUFWDL, reg);
2701:
2702: off = R92C_FW_START_ADDR;
2703: while (len > 0) {
2704: if (len > 196)
2705: mlen = 196;
2706: else if (len > 4)
2707: mlen = 4;
2708: else
2709: mlen = 1;
2710: error = urtwn_write_region(sc, off, buf, mlen);
2711: if (error != 0)
2712: break;
2713: off += mlen;
2714: buf += mlen;
2715: len -= mlen;
2716: }
2717: return (error);
2718: }
2719:
2720: static int
2721: urtwn_load_firmware(struct urtwn_softc *sc)
2722: {
2723: firmware_handle_t fwh;
2724: const struct r92c_fw_hdr *hdr;
2725: const char *name;
2726: u_char *fw, *ptr;
2727: size_t len;
2728: uint32_t reg;
2729: int mlen, ntries, page, error;
2730:
2731: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2732:
1.12 christos 2733: KASSERT(mutex_owned(&sc->sc_write_mtx));
2734:
1.1 nonaka 2735: /* Read firmware image from the filesystem. */
2736: if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) ==
2737: URTWN_CHIP_UMC_A_CUT)
1.5 riz 2738: name = "rtl8192cfwU.bin";
1.1 nonaka 2739: else
1.5 riz 2740: name = "rtl8192cfw.bin";
2741: if ((error = firmware_open("if_urtwn", name, &fwh)) != 0) {
1.1 nonaka 2742: aprint_error_dev(sc->sc_dev,
2743: "failed loadfirmware of file %s (error %d)\n", name, error);
2744: return (error);
2745: }
2746: len = firmware_get_size(fwh);
2747: fw = firmware_malloc(len);
2748: if (fw == NULL) {
2749: aprint_error_dev(sc->sc_dev,
2750: "failed to allocate firmware memory\n");
2751: firmware_close(fwh);
2752: return (ENOMEM);
2753: }
2754: error = firmware_read(fwh, 0, fw, len);
2755: firmware_close(fwh);
2756: if (error != 0) {
2757: aprint_error_dev(sc->sc_dev,
2758: "failed to read firmware (error %d)\n", error);
2759: firmware_free(fw, 0);
2760: return (error);
2761: }
2762:
2763: ptr = fw;
2764: hdr = (const struct r92c_fw_hdr *)ptr;
2765: /* Check if there is a valid FW header and skip it. */
2766: if ((le16toh(hdr->signature) >> 4) == 0x88c ||
2767: (le16toh(hdr->signature) >> 4) == 0x92c) {
2768: DPRINTFN(DBG_INIT, ("%s: %s: FW V%d.%d %02d-%02d %02d:%02d\n",
2769: device_xname(sc->sc_dev), __func__,
2770: le16toh(hdr->version), le16toh(hdr->subversion),
2771: hdr->month, hdr->date, hdr->hour, hdr->minute));
2772: ptr += sizeof(*hdr);
2773: len -= sizeof(*hdr);
2774: }
2775:
2776: if (urtwn_read_1(sc, R92C_MCUFWDL) & 0x80) {
2777: urtwn_fw_reset(sc);
2778: urtwn_write_1(sc, R92C_MCUFWDL, 0);
2779: }
2780:
2781: /* download enabled */
2782: urtwn_write_2(sc, R92C_SYS_FUNC_EN,
2783: urtwn_read_2(sc, R92C_SYS_FUNC_EN) |
2784: R92C_SYS_FUNC_EN_CPUEN);
2785: urtwn_write_1(sc, R92C_MCUFWDL,
2786: urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN);
2787: urtwn_write_1(sc, R92C_MCUFWDL + 2,
2788: urtwn_read_1(sc, R92C_MCUFWDL + 2) & ~0x08);
2789:
2790: /* download firmware */
2791: for (page = 0; len > 0; page++) {
2792: mlen = MIN(len, R92C_FW_PAGE_SIZE);
2793: error = urtwn_fw_loadpage(sc, page, ptr, mlen);
2794: if (error != 0) {
2795: aprint_error_dev(sc->sc_dev,
2796: "could not load firmware page %d\n", page);
2797: goto fail;
2798: }
2799: ptr += mlen;
2800: len -= mlen;
2801: }
2802:
2803: /* download disable */
2804: urtwn_write_1(sc, R92C_MCUFWDL,
2805: urtwn_read_1(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_EN);
2806: urtwn_write_1(sc, R92C_MCUFWDL + 1, 0);
2807:
2808: /* Wait for checksum report. */
2809: for (ntries = 0; ntries < 1000; ntries++) {
2810: if (urtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT)
2811: break;
2812: DELAY(5);
2813: }
2814: if (ntries == 1000) {
2815: aprint_error_dev(sc->sc_dev,
2816: "timeout waiting for checksum report\n");
2817: error = ETIMEDOUT;
2818: goto fail;
2819: }
2820:
2821: /* Wait for firmware readiness. */
2822: reg = urtwn_read_4(sc, R92C_MCUFWDL);
2823: reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY;
2824: urtwn_write_4(sc, R92C_MCUFWDL, reg);
2825: for (ntries = 0; ntries < 1000; ntries++) {
2826: if (urtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY)
2827: break;
2828: DELAY(5);
2829: }
2830: if (ntries == 1000) {
2831: aprint_error_dev(sc->sc_dev,
2832: "timeout waiting for firmware readiness\n");
2833: error = ETIMEDOUT;
2834: goto fail;
2835: }
2836: fail:
2837: firmware_free(fw, 0);
2838: return (error);
2839: }
2840:
2841: static int
2842: urtwn_dma_init(struct urtwn_softc *sc)
2843: {
2844: int hashq, hasnq, haslq, nqueues, nqpages, nrempages;
2845: uint32_t reg;
2846: int error;
2847:
2848: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2849:
1.12 christos 2850: KASSERT(mutex_owned(&sc->sc_write_mtx));
2851:
1.1 nonaka 2852: /* Initialize LLT table. */
2853: error = urtwn_llt_init(sc);
2854: if (error != 0)
2855: return (error);
2856:
2857: /* Get Tx queues to USB endpoints mapping. */
2858: hashq = hasnq = haslq = 0;
2859: reg = urtwn_read_2(sc, R92C_USB_EP + 1);
2860: DPRINTFN(DBG_INIT, ("%s: %s: USB endpoints mapping 0x%x\n",
2861: device_xname(sc->sc_dev), __func__, reg));
2862: if (MS(reg, R92C_USB_EP_HQ) != 0)
2863: hashq = 1;
2864: if (MS(reg, R92C_USB_EP_NQ) != 0)
2865: hasnq = 1;
2866: if (MS(reg, R92C_USB_EP_LQ) != 0)
2867: haslq = 1;
2868: nqueues = hashq + hasnq + haslq;
2869: if (nqueues == 0)
2870: return (EIO);
2871: /* Get the number of pages for each queue. */
2872: nqpages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) / nqueues;
2873: /* The remaining pages are assigned to the high priority queue. */
2874: nrempages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) % nqueues;
2875:
2876: /* Set number of pages for normal priority queue. */
2877: urtwn_write_1(sc, R92C_RQPN_NPQ, hasnq ? nqpages : 0);
2878: urtwn_write_4(sc, R92C_RQPN,
2879: /* Set number of pages for public queue. */
2880: SM(R92C_RQPN_PUBQ, R92C_PUBQ_NPAGES) |
2881: /* Set number of pages for high priority queue. */
2882: SM(R92C_RQPN_HPQ, hashq ? nqpages + nrempages : 0) |
2883: /* Set number of pages for low priority queue. */
2884: SM(R92C_RQPN_LPQ, haslq ? nqpages : 0) |
2885: /* Load values. */
2886: R92C_RQPN_LD);
2887:
2888: urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R92C_TX_PAGE_BOUNDARY);
2889: urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R92C_TX_PAGE_BOUNDARY);
2890: urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R92C_TX_PAGE_BOUNDARY);
2891: urtwn_write_1(sc, R92C_TRXFF_BNDY, R92C_TX_PAGE_BOUNDARY);
2892: urtwn_write_1(sc, R92C_TDECTRL + 1, R92C_TX_PAGE_BOUNDARY);
2893:
2894: /* Set queue to USB pipe mapping. */
2895: reg = urtwn_read_2(sc, R92C_TRXDMA_CTRL);
2896: reg &= ~R92C_TRXDMA_CTRL_QMAP_M;
2897: if (nqueues == 1) {
2898: if (hashq) {
2899: reg |= R92C_TRXDMA_CTRL_QMAP_HQ;
2900: } else if (hasnq) {
2901: reg |= R92C_TRXDMA_CTRL_QMAP_NQ;
2902: } else {
2903: reg |= R92C_TRXDMA_CTRL_QMAP_LQ;
2904: }
2905: } else if (nqueues == 2) {
2906: /* All 2-endpoints configs have a high priority queue. */
2907: if (!hashq) {
2908: return (EIO);
2909: }
2910: if (hasnq) {
2911: reg |= R92C_TRXDMA_CTRL_QMAP_HQ_NQ;
2912: } else {
2913: reg |= R92C_TRXDMA_CTRL_QMAP_HQ_LQ;
2914: }
2915: } else {
2916: reg |= R92C_TRXDMA_CTRL_QMAP_3EP;
2917: }
2918: urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg);
2919:
2920: /* Set Tx/Rx transfer page boundary. */
2921: urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x27ff);
2922:
2923: /* Set Tx/Rx transfer page size. */
2924: urtwn_write_1(sc, R92C_PBP,
2925: SM(R92C_PBP_PSRX, R92C_PBP_128) | SM(R92C_PBP_PSTX, R92C_PBP_128));
2926: return (0);
2927: }
2928:
2929: static void
2930: urtwn_mac_init(struct urtwn_softc *sc)
2931: {
1.22 christos 2932: size_t i;
1.1 nonaka 2933:
2934: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2935:
1.12 christos 2936: KASSERT(mutex_owned(&sc->sc_write_mtx));
2937:
1.1 nonaka 2938: /* Write MAC initialization values. */
1.22 christos 2939: for (i = 0; i < __arraycount(rtl8192cu_mac); i++)
1.1 nonaka 2940: urtwn_write_1(sc, rtl8192cu_mac[i].reg, rtl8192cu_mac[i].val);
2941: }
2942:
2943: static void
2944: urtwn_bb_init(struct urtwn_softc *sc)
2945: {
2946: const struct urtwn_bb_prog *prog;
2947: uint32_t reg;
1.22 christos 2948: size_t i;
1.1 nonaka 2949:
2950: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
2951:
1.12 christos 2952: KASSERT(mutex_owned(&sc->sc_write_mtx));
2953:
1.1 nonaka 2954: /* Enable BB and RF. */
2955: urtwn_write_2(sc, R92C_SYS_FUNC_EN,
2956: urtwn_read_2(sc, R92C_SYS_FUNC_EN) |
2957: R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST |
2958: R92C_SYS_FUNC_EN_DIO_RF);
2959:
2960: urtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x83);
2961: urtwn_write_1(sc, R92C_AFE_PLL_CTRL + 1, 0xdb);
2962:
2963: urtwn_write_1(sc, R92C_RF_CTRL,
2964: R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB);
2965: urtwn_write_1(sc, R92C_SYS_FUNC_EN,
2966: R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD |
2967: R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB);
2968:
2969: urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f);
2970: urtwn_write_1(sc, 0x15, 0xe9);
2971: urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80);
2972:
2973: /* Select BB programming based on board type. */
2974: if (!(sc->chip & URTWN_CHIP_92C)) {
2975: if (sc->board_type == R92C_BOARD_TYPE_MINICARD) {
2976: prog = &rtl8188ce_bb_prog;
2977: } else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) {
2978: prog = &rtl8188ru_bb_prog;
2979: } else {
2980: prog = &rtl8188cu_bb_prog;
2981: }
2982: } else {
2983: if (sc->board_type == R92C_BOARD_TYPE_MINICARD) {
2984: prog = &rtl8192ce_bb_prog;
2985: } else {
2986: prog = &rtl8192cu_bb_prog;
2987: }
2988: }
2989: /* Write BB initialization values. */
2990: for (i = 0; i < prog->count; i++) {
2991: /* additional delay depend on registers */
2992: switch (prog->regs[i]) {
2993: case 0xfe:
2994: usbd_delay_ms(sc->sc_udev, 50);
2995: break;
2996: case 0xfd:
2997: usbd_delay_ms(sc->sc_udev, 5);
2998: break;
2999: case 0xfc:
3000: usbd_delay_ms(sc->sc_udev, 1);
3001: break;
3002: case 0xfb:
3003: DELAY(50);
3004: break;
3005: case 0xfa:
3006: DELAY(5);
3007: break;
3008: case 0xf9:
3009: DELAY(1);
3010: break;
3011: }
3012: urtwn_bb_write(sc, prog->regs[i], prog->vals[i]);
3013: DELAY(1);
3014: }
3015:
3016: if (sc->chip & URTWN_CHIP_92C_1T2R) {
3017: /* 8192C 1T only configuration. */
3018: reg = urtwn_bb_read(sc, R92C_FPGA0_TXINFO);
3019: reg = (reg & ~0x00000003) | 0x2;
3020: urtwn_bb_write(sc, R92C_FPGA0_TXINFO, reg);
3021:
3022: reg = urtwn_bb_read(sc, R92C_FPGA1_TXINFO);
3023: reg = (reg & ~0x00300033) | 0x00200022;
3024: urtwn_bb_write(sc, R92C_FPGA1_TXINFO, reg);
3025:
3026: reg = urtwn_bb_read(sc, R92C_CCK0_AFESETTING);
3027: reg = (reg & ~0xff000000) | (0x45 << 24);
3028: urtwn_bb_write(sc, R92C_CCK0_AFESETTING, reg);
3029:
3030: reg = urtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA);
3031: reg = (reg & ~0x000000ff) | 0x23;
3032: urtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, reg);
3033:
3034: reg = urtwn_bb_read(sc, R92C_OFDM0_AGCPARAM1);
3035: reg = (reg & ~0x00000030) | (1 << 4);
3036: urtwn_bb_write(sc, R92C_OFDM0_AGCPARAM1, reg);
3037:
3038: reg = urtwn_bb_read(sc, 0xe74);
3039: reg = (reg & ~0x0c000000) | (2 << 26);
3040: urtwn_bb_write(sc, 0xe74, reg);
3041: reg = urtwn_bb_read(sc, 0xe78);
3042: reg = (reg & ~0x0c000000) | (2 << 26);
3043: urtwn_bb_write(sc, 0xe78, reg);
3044: reg = urtwn_bb_read(sc, 0xe7c);
3045: reg = (reg & ~0x0c000000) | (2 << 26);
3046: urtwn_bb_write(sc, 0xe7c, reg);
3047: reg = urtwn_bb_read(sc, 0xe80);
3048: reg = (reg & ~0x0c000000) | (2 << 26);
3049: urtwn_bb_write(sc, 0xe80, reg);
3050: reg = urtwn_bb_read(sc, 0xe88);
3051: reg = (reg & ~0x0c000000) | (2 << 26);
3052: urtwn_bb_write(sc, 0xe88, reg);
3053: }
3054:
3055: /* Write AGC values. */
3056: for (i = 0; i < prog->agccount; i++) {
3057: urtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, prog->agcvals[i]);
3058: DELAY(1);
3059: }
3060:
3061: if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) &
3062: R92C_HSSI_PARAM2_CCK_HIPWR) {
3063: SET(sc->sc_flags, URTWN_FLAG_CCK_HIPWR);
3064: }
3065: }
3066:
3067: static void
3068: urtwn_rf_init(struct urtwn_softc *sc)
3069: {
3070: const struct urtwn_rf_prog *prog;
3071: uint32_t reg, mask, saved;
1.22 christos 3072: size_t i, j, idx;
1.1 nonaka 3073:
3074: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3075:
3076: /* Select RF programming based on board type. */
3077: if (!(sc->chip & URTWN_CHIP_92C)) {
3078: if (sc->board_type == R92C_BOARD_TYPE_MINICARD) {
3079: prog = rtl8188ce_rf_prog;
3080: } else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) {
3081: prog = rtl8188ru_rf_prog;
3082: } else {
3083: prog = rtl8188cu_rf_prog;
3084: }
3085: } else {
3086: prog = rtl8192ce_rf_prog;
3087: }
3088:
3089: for (i = 0; i < sc->nrxchains; i++) {
3090: /* Save RF_ENV control type. */
3091: idx = i / 2;
3092: mask = 0xffffU << ((i % 2) * 16);
3093: saved = urtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)) & mask;
3094:
3095: /* Set RF_ENV enable. */
3096: reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
3097: reg |= 0x100000;
3098: urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
3099: DELAY(1);
3100:
3101: /* Set RF_ENV output high. */
3102: reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i));
3103: reg |= 0x10;
3104: urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg);
3105: DELAY(1);
3106:
3107: /* Set address and data lengths of RF registers. */
3108: reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
3109: reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH;
3110: urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
3111: DELAY(1);
3112: reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i));
3113: reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH;
3114: urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg);
3115: DELAY(1);
3116:
3117: /* Write RF initialization values for this chain. */
3118: for (j = 0; j < prog[i].count; j++) {
3119: if (prog[i].regs[j] >= 0xf9 &&
3120: prog[i].regs[j] <= 0xfe) {
3121: /*
3122: * These are fake RF registers offsets that
3123: * indicate a delay is required.
3124: */
3125: usbd_delay_ms(sc->sc_udev, 50);
3126: continue;
3127: }
3128: urtwn_rf_write(sc, i, prog[i].regs[j], prog[i].vals[j]);
3129: DELAY(1);
3130: }
3131:
3132: /* Restore RF_ENV control type. */
3133: reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)) & ~mask;
3134: urtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg | saved);
3135: }
3136:
3137: if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) ==
3138: URTWN_CHIP_UMC_A_CUT) {
3139: urtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255);
3140: urtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00);
3141: }
3142:
3143: /* Cache RF register CHNLBW. */
3144: for (i = 0; i < 2; i++) {
3145: sc->rf_chnlbw[i] = urtwn_rf_read(sc, i, R92C_RF_CHNLBW);
3146: }
3147: }
3148:
3149: static void
3150: urtwn_cam_init(struct urtwn_softc *sc)
3151: {
3152: uint32_t content, command;
3153: uint8_t idx;
1.22 christos 3154: size_t i;
1.1 nonaka 3155:
3156: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3157:
1.12 christos 3158: KASSERT(mutex_owned(&sc->sc_write_mtx));
3159:
1.1 nonaka 3160: for (idx = 0; idx < R92C_CAM_ENTRY_COUNT; idx++) {
3161: content = (idx & 3)
3162: | (R92C_CAM_ALGO_AES << R92C_CAM_ALGO_S)
3163: | R92C_CAM_VALID;
3164:
3165: command = R92C_CAMCMD_POLLING
3166: | R92C_CAMCMD_WRITE
3167: | R92C_CAM_CTL0(idx);
3168:
3169: urtwn_write_4(sc, R92C_CAMWRITE, content);
3170: urtwn_write_4(sc, R92C_CAMCMD, command);
3171: }
3172:
3173: for (idx = 0; idx < R92C_CAM_ENTRY_COUNT; idx++) {
3174: for (i = 0; i < /* CAM_CONTENT_COUNT */ 8; i++) {
3175: if (i == 0) {
3176: content = (idx & 3)
3177: | (R92C_CAM_ALGO_AES << R92C_CAM_ALGO_S)
3178: | R92C_CAM_VALID;
3179: } else {
3180: content = 0;
3181: }
3182:
3183: command = R92C_CAMCMD_POLLING
3184: | R92C_CAMCMD_WRITE
3185: | R92C_CAM_CTL0(idx)
1.22 christos 3186: | i;
1.1 nonaka 3187:
3188: urtwn_write_4(sc, R92C_CAMWRITE, content);
3189: urtwn_write_4(sc, R92C_CAMCMD, command);
3190: }
3191: }
3192:
3193: /* Invalidate all CAM entries. */
3194: urtwn_write_4(sc, R92C_CAMCMD, R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
3195: }
3196:
3197: static void
3198: urtwn_pa_bias_init(struct urtwn_softc *sc)
3199: {
3200: uint8_t reg;
1.22 christos 3201: size_t i;
1.1 nonaka 3202:
3203: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3204:
1.12 christos 3205: KASSERT(mutex_owned(&sc->sc_write_mtx));
3206:
1.1 nonaka 3207: for (i = 0; i < sc->nrxchains; i++) {
3208: if (sc->pa_setting & (1U << i))
3209: continue;
3210:
3211: urtwn_rf_write(sc, i, R92C_RF_IPA, 0x0f406);
3212: urtwn_rf_write(sc, i, R92C_RF_IPA, 0x4f406);
3213: urtwn_rf_write(sc, i, R92C_RF_IPA, 0x8f406);
3214: urtwn_rf_write(sc, i, R92C_RF_IPA, 0xcf406);
3215: }
3216: if (!(sc->pa_setting & 0x10)) {
3217: reg = urtwn_read_1(sc, 0x16);
3218: reg = (reg & ~0xf0) | 0x90;
3219: urtwn_write_1(sc, 0x16, reg);
3220: }
3221: }
3222:
3223: static void
3224: urtwn_rxfilter_init(struct urtwn_softc *sc)
3225: {
3226:
3227: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3228:
1.12 christos 3229: KASSERT(mutex_owned(&sc->sc_write_mtx));
3230:
1.1 nonaka 3231: /* Initialize Rx filter. */
3232: /* TODO: use better filter for monitor mode. */
3233: urtwn_write_4(sc, R92C_RCR,
3234: R92C_RCR_AAP | R92C_RCR_APM | R92C_RCR_AM | R92C_RCR_AB |
3235: R92C_RCR_APP_ICV | R92C_RCR_AMF | R92C_RCR_HTC_LOC_CTRL |
3236: R92C_RCR_APP_MIC | R92C_RCR_APP_PHYSTS);
3237: /* Accept all multicast frames. */
3238: urtwn_write_4(sc, R92C_MAR + 0, 0xffffffff);
3239: urtwn_write_4(sc, R92C_MAR + 4, 0xffffffff);
3240: /* Accept all management frames. */
3241: urtwn_write_2(sc, R92C_RXFLTMAP0, 0xffff);
3242: /* Reject all control frames. */
3243: urtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
3244: /* Accept all data frames. */
3245: urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
3246: }
3247:
3248: static void
3249: urtwn_edca_init(struct urtwn_softc *sc)
3250: {
3251:
3252: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3253:
1.12 christos 3254: KASSERT(mutex_owned(&sc->sc_write_mtx));
3255:
1.1 nonaka 3256: /* set spec SIFS (used in NAV) */
3257: urtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a);
3258: urtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a);
3259:
3260: /* set SIFS CCK/OFDM */
3261: urtwn_write_2(sc, R92C_SIFS_CCK, 0x100a);
3262: urtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a);
3263:
3264: /* TXOP */
3265: urtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b);
3266: urtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f);
3267: urtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005ea324);
3268: urtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002fa226);
3269: }
3270:
3271: static void
3272: urtwn_write_txpower(struct urtwn_softc *sc, int chain,
3273: uint16_t power[URTWN_RIDX_COUNT])
3274: {
3275: uint32_t reg;
3276:
3277: DPRINTFN(DBG_FN, ("%s: %s: chain=%d\n", device_xname(sc->sc_dev),
3278: __func__, chain));
3279:
3280: /* Write per-CCK rate Tx power. */
3281: if (chain == 0) {
3282: reg = urtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32);
3283: reg = RW(reg, R92C_TXAGC_A_CCK1, power[0]);
3284: urtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg);
3285:
3286: reg = urtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
3287: reg = RW(reg, R92C_TXAGC_A_CCK2, power[1]);
3288: reg = RW(reg, R92C_TXAGC_A_CCK55, power[2]);
3289: reg = RW(reg, R92C_TXAGC_A_CCK11, power[3]);
3290: urtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
3291: } else {
3292: reg = urtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32);
3293: reg = RW(reg, R92C_TXAGC_B_CCK1, power[0]);
3294: reg = RW(reg, R92C_TXAGC_B_CCK2, power[1]);
3295: reg = RW(reg, R92C_TXAGC_B_CCK55, power[2]);
3296: urtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg);
3297:
3298: reg = urtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11);
3299: reg = RW(reg, R92C_TXAGC_B_CCK11, power[3]);
3300: urtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg);
3301: }
3302: /* Write per-OFDM rate Tx power. */
3303: urtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain),
3304: SM(R92C_TXAGC_RATE06, power[ 4]) |
3305: SM(R92C_TXAGC_RATE09, power[ 5]) |
3306: SM(R92C_TXAGC_RATE12, power[ 6]) |
3307: SM(R92C_TXAGC_RATE18, power[ 7]));
3308: urtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain),
3309: SM(R92C_TXAGC_RATE24, power[ 8]) |
3310: SM(R92C_TXAGC_RATE36, power[ 9]) |
3311: SM(R92C_TXAGC_RATE48, power[10]) |
3312: SM(R92C_TXAGC_RATE54, power[11]));
3313: /* Write per-MCS Tx power. */
3314: urtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain),
3315: SM(R92C_TXAGC_MCS00, power[12]) |
3316: SM(R92C_TXAGC_MCS01, power[13]) |
3317: SM(R92C_TXAGC_MCS02, power[14]) |
3318: SM(R92C_TXAGC_MCS03, power[15]));
3319: urtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain),
3320: SM(R92C_TXAGC_MCS04, power[16]) |
3321: SM(R92C_TXAGC_MCS05, power[17]) |
3322: SM(R92C_TXAGC_MCS06, power[18]) |
3323: SM(R92C_TXAGC_MCS07, power[19]));
3324: urtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain),
3325: SM(R92C_TXAGC_MCS08, power[20]) |
3326: SM(R92C_TXAGC_MCS09, power[21]) |
3327: SM(R92C_TXAGC_MCS10, power[22]) |
3328: SM(R92C_TXAGC_MCS11, power[23]));
3329: urtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain),
3330: SM(R92C_TXAGC_MCS12, power[24]) |
3331: SM(R92C_TXAGC_MCS13, power[25]) |
3332: SM(R92C_TXAGC_MCS14, power[26]) |
3333: SM(R92C_TXAGC_MCS15, power[27]));
3334: }
3335:
3336: static void
1.22 christos 3337: urtwn_get_txpower(struct urtwn_softc *sc, size_t chain, u_int chan, u_int ht40m,
1.1 nonaka 3338: uint16_t power[URTWN_RIDX_COUNT])
3339: {
3340: struct r92c_rom *rom = &sc->rom;
3341: uint16_t cckpow, ofdmpow, htpow, diff, maxpow;
3342: const struct urtwn_txpwr *base;
3343: int ridx, group;
3344:
1.22 christos 3345: DPRINTFN(DBG_FN, ("%s: %s: chain=%zd, chan=%d\n",
1.1 nonaka 3346: device_xname(sc->sc_dev), __func__, chain, chan));
3347:
3348: /* Determine channel group. */
3349: if (chan <= 3) {
3350: group = 0;
3351: } else if (chan <= 9) {
3352: group = 1;
3353: } else {
3354: group = 2;
3355: }
3356:
3357: /* Get original Tx power based on board type and RF chain. */
3358: if (!(sc->chip & URTWN_CHIP_92C)) {
3359: if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) {
3360: base = &rtl8188ru_txagc[chain];
3361: } else {
3362: base = &rtl8192cu_txagc[chain];
3363: }
3364: } else {
3365: base = &rtl8192cu_txagc[chain];
3366: }
3367:
3368: memset(power, 0, URTWN_RIDX_COUNT * sizeof(power[0]));
3369: if (sc->regulatory == 0) {
3370: for (ridx = 0; ridx <= 3; ridx++) {
3371: power[ridx] = base->pwr[0][ridx];
3372: }
3373: }
3374: for (ridx = 4; ridx < URTWN_RIDX_COUNT; ridx++) {
3375: if (sc->regulatory == 3) {
3376: power[ridx] = base->pwr[0][ridx];
3377: /* Apply vendor limits. */
3378: if (ht40m != IEEE80211_HTINFO_2NDCHAN_NONE) {
3379: maxpow = rom->ht40_max_pwr[group];
3380: } else {
3381: maxpow = rom->ht20_max_pwr[group];
3382: }
3383: maxpow = (maxpow >> (chain * 4)) & 0xf;
3384: if (power[ridx] > maxpow) {
3385: power[ridx] = maxpow;
3386: }
3387: } else if (sc->regulatory == 1) {
3388: if (ht40m == IEEE80211_HTINFO_2NDCHAN_NONE) {
3389: power[ridx] = base->pwr[group][ridx];
3390: }
3391: } else if (sc->regulatory != 2) {
3392: power[ridx] = base->pwr[0][ridx];
3393: }
3394: }
3395:
3396: /* Compute per-CCK rate Tx power. */
3397: cckpow = rom->cck_tx_pwr[chain][group];
3398: for (ridx = 0; ridx <= 3; ridx++) {
3399: power[ridx] += cckpow;
3400: if (power[ridx] > R92C_MAX_TX_PWR) {
3401: power[ridx] = R92C_MAX_TX_PWR;
3402: }
3403: }
3404:
3405: htpow = rom->ht40_1s_tx_pwr[chain][group];
3406: if (sc->ntxchains > 1) {
3407: /* Apply reduction for 2 spatial streams. */
3408: diff = rom->ht40_2s_tx_pwr_diff[group];
3409: diff = (diff >> (chain * 4)) & 0xf;
3410: htpow = (htpow > diff) ? htpow - diff : 0;
3411: }
3412:
3413: /* Compute per-OFDM rate Tx power. */
3414: diff = rom->ofdm_tx_pwr_diff[group];
3415: diff = (diff >> (chain * 4)) & 0xf;
3416: ofdmpow = htpow + diff; /* HT->OFDM correction. */
3417: for (ridx = 4; ridx <= 11; ridx++) {
3418: power[ridx] += ofdmpow;
3419: if (power[ridx] > R92C_MAX_TX_PWR) {
3420: power[ridx] = R92C_MAX_TX_PWR;
3421: }
3422: }
3423:
3424: /* Compute per-MCS Tx power. */
3425: if (ht40m == IEEE80211_HTINFO_2NDCHAN_NONE) {
3426: diff = rom->ht20_tx_pwr_diff[group];
3427: diff = (diff >> (chain * 4)) & 0xf;
3428: htpow += diff; /* HT40->HT20 correction. */
3429: }
3430: for (ridx = 12; ridx < URTWN_RIDX_COUNT; ridx++) {
3431: power[ridx] += htpow;
3432: if (power[ridx] > R92C_MAX_TX_PWR) {
3433: power[ridx] = R92C_MAX_TX_PWR;
3434: }
3435: }
3436: #ifdef URTWN_DEBUG
3437: if (urtwn_debug & DBG_RF) {
3438: /* Dump per-rate Tx power values. */
1.22 christos 3439: printf("%s: %s: Tx power for chain %zd:\n",
1.1 nonaka 3440: device_xname(sc->sc_dev), __func__, chain);
3441: for (ridx = 0; ridx < URTWN_RIDX_COUNT; ridx++) {
3442: printf("%s: %s: Rate %d = %u\n",
3443: device_xname(sc->sc_dev), __func__, ridx,
3444: power[ridx]);
3445: }
3446: }
3447: #endif
3448: }
3449:
3450: static void
3451: urtwn_set_txpower(struct urtwn_softc *sc, u_int chan, u_int ht40m)
3452: {
3453: uint16_t power[URTWN_RIDX_COUNT];
1.22 christos 3454: size_t i;
1.1 nonaka 3455:
3456: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3457:
3458: for (i = 0; i < sc->ntxchains; i++) {
3459: /* Compute per-rate Tx power values. */
3460: urtwn_get_txpower(sc, i, chan, ht40m, power);
3461: /* Write per-rate Tx power values to hardware. */
3462: urtwn_write_txpower(sc, i, power);
3463: }
3464: }
3465:
3466: static void
3467: urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c, u_int ht40m)
3468: {
3469: struct ieee80211com *ic = &sc->sc_ic;
3470: u_int chan;
1.22 christos 3471: size_t i;
1.1 nonaka 3472:
3473: chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */
3474:
3475: DPRINTFN(DBG_FN, ("%s: %s: chan=%d\n", device_xname(sc->sc_dev),
3476: __func__, chan));
3477:
1.12 christos 3478: KASSERT(mutex_owned(&sc->sc_write_mtx));
3479:
1.1 nonaka 3480: if (ht40m == IEEE80211_HTINFO_2NDCHAN_ABOVE) {
3481: chan += 2;
3482: } else if (ht40m == IEEE80211_HTINFO_2NDCHAN_BELOW){
3483: chan -= 2;
3484: }
3485:
3486: /* Set Tx power for this new channel. */
3487: urtwn_set_txpower(sc, chan, ht40m);
3488:
3489: for (i = 0; i < sc->nrxchains; i++) {
3490: urtwn_rf_write(sc, i, R92C_RF_CHNLBW,
3491: RW(sc->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan));
3492: }
3493:
3494: if (ht40m) {
3495: /* Is secondary channel below or above primary? */
3496: int prichlo = (ht40m == IEEE80211_HTINFO_2NDCHAN_ABOVE);
3497: uint32_t reg;
3498:
3499: urtwn_write_1(sc, R92C_BWOPMODE,
3500: urtwn_read_1(sc, R92C_BWOPMODE) & ~R92C_BWOPMODE_20MHZ);
3501:
3502: reg = urtwn_read_1(sc, R92C_RRSR + 2);
3503: reg = (reg & ~0x6f) | (prichlo ? 1 : 2) << 5;
3504: urtwn_write_1(sc, R92C_RRSR + 2, (uint8_t)reg);
3505:
3506: urtwn_bb_write(sc, R92C_FPGA0_RFMOD,
3507: urtwn_bb_read(sc, R92C_FPGA0_RFMOD) | R92C_RFMOD_40MHZ);
3508: urtwn_bb_write(sc, R92C_FPGA1_RFMOD,
3509: urtwn_bb_read(sc, R92C_FPGA1_RFMOD) | R92C_RFMOD_40MHZ);
3510:
3511: /* Set CCK side band. */
3512: reg = urtwn_bb_read(sc, R92C_CCK0_SYSTEM);
3513: reg = (reg & ~0x00000010) | (prichlo ? 0 : 1) << 4;
3514: urtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg);
3515:
3516: reg = urtwn_bb_read(sc, R92C_OFDM1_LSTF);
3517: reg = (reg & ~0x00000c00) | (prichlo ? 1 : 2) << 10;
3518: urtwn_bb_write(sc, R92C_OFDM1_LSTF, reg);
3519:
3520: urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
3521: urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) &
3522: ~R92C_FPGA0_ANAPARAM2_CBW20);
3523:
3524: reg = urtwn_bb_read(sc, 0x818);
3525: reg = (reg & ~0x0c000000) | (prichlo ? 2 : 1) << 26;
3526: urtwn_bb_write(sc, 0x818, reg);
3527:
3528: /* Select 40MHz bandwidth. */
3529: urtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
3530: (sc->rf_chnlbw[0] & ~0xfff) | chan);
3531: } else {
3532: urtwn_write_1(sc, R92C_BWOPMODE,
3533: urtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ);
3534:
3535: urtwn_bb_write(sc, R92C_FPGA0_RFMOD,
3536: urtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ);
3537: urtwn_bb_write(sc, R92C_FPGA1_RFMOD,
3538: urtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ);
3539:
3540: urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2,
3541: urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) |
3542: R92C_FPGA0_ANAPARAM2_CBW20);
3543:
3544: /* Select 20MHz bandwidth. */
3545: urtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
3546: (sc->rf_chnlbw[0] & ~0xfff) | R92C_RF_CHNLBW_BW20 | chan);
3547: }
3548: }
3549:
3550: static void
3551: urtwn_iq_calib(struct urtwn_softc *sc, bool inited)
3552: {
3553:
3554: DPRINTFN(DBG_FN, ("%s: %s: inited=%d\n", device_xname(sc->sc_dev),
3555: __func__, inited));
3556:
3557: /* TODO */
3558: }
3559:
3560: static void
3561: urtwn_lc_calib(struct urtwn_softc *sc)
3562: {
3563: uint32_t rf_ac[2];
3564: uint8_t txmode;
1.22 christos 3565: size_t i;
1.1 nonaka 3566:
3567: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3568:
1.12 christos 3569: KASSERT(mutex_owned(&sc->sc_write_mtx));
3570:
1.1 nonaka 3571: txmode = urtwn_read_1(sc, R92C_OFDM1_LSTF + 3);
3572: if ((txmode & 0x70) != 0) {
3573: /* Disable all continuous Tx. */
3574: urtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70);
3575:
3576: /* Set RF mode to standby mode. */
3577: for (i = 0; i < sc->nrxchains; i++) {
3578: rf_ac[i] = urtwn_rf_read(sc, i, R92C_RF_AC);
3579: urtwn_rf_write(sc, i, R92C_RF_AC,
3580: RW(rf_ac[i], R92C_RF_AC_MODE,
3581: R92C_RF_AC_MODE_STANDBY));
3582: }
3583: } else {
3584: /* Block all Tx queues. */
3585: urtwn_write_1(sc, R92C_TXPAUSE, 0xff);
3586: }
3587: /* Start calibration. */
3588: urtwn_rf_write(sc, 0, R92C_RF_CHNLBW,
3589: urtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART);
3590:
3591: /* Give calibration the time to complete. */
3592: usbd_delay_ms(sc->sc_udev, 100);
3593:
3594: /* Restore configuration. */
3595: if ((txmode & 0x70) != 0) {
3596: /* Restore Tx mode. */
3597: urtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode);
3598: /* Restore RF mode. */
3599: for (i = 0; i < sc->nrxchains; i++) {
3600: urtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]);
3601: }
3602: } else {
3603: /* Unblock all Tx queues. */
3604: urtwn_write_1(sc, R92C_TXPAUSE, 0x00);
3605: }
3606: }
3607:
3608: static void
3609: urtwn_temp_calib(struct urtwn_softc *sc)
3610: {
3611: int temp;
3612:
3613: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3614:
1.12 christos 3615: KASSERT(mutex_owned(&sc->sc_write_mtx));
3616:
1.1 nonaka 3617: if (sc->thcal_state == 0) {
3618: /* Start measuring temperature. */
3619: DPRINTFN(DBG_RF, ("%s: %s: start measuring temperature\n",
3620: device_xname(sc->sc_dev), __func__));
3621: urtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60);
3622: sc->thcal_state = 1;
3623: return;
3624: }
3625: sc->thcal_state = 0;
3626:
3627: /* Read measured temperature. */
3628: temp = urtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f;
3629: DPRINTFN(DBG_RF, ("%s: %s: temperature=%d\n", device_xname(sc->sc_dev),
3630: __func__, temp));
3631: if (temp == 0) /* Read failed, skip. */
3632: return;
3633:
3634: /*
3635: * Redo LC calibration if temperature changed significantly since
3636: * last calibration.
3637: */
3638: if (sc->thcal_lctemp == 0) {
3639: /* First LC calibration is performed in urtwn_init(). */
3640: sc->thcal_lctemp = temp;
3641: } else if (abs(temp - sc->thcal_lctemp) > 1) {
3642: DPRINTFN(DBG_RF,
3643: ("%s: %s: LC calib triggered by temp: %d -> %d\n",
3644: device_xname(sc->sc_dev), __func__, sc->thcal_lctemp,
3645: temp));
3646: urtwn_lc_calib(sc);
3647: /* Record temperature of last LC calibration. */
3648: sc->thcal_lctemp = temp;
3649: }
3650: }
3651:
3652: static int
3653: urtwn_init(struct ifnet *ifp)
3654: {
3655: struct urtwn_softc *sc = ifp->if_softc;
3656: struct ieee80211com *ic = &sc->sc_ic;
3657: struct urtwn_rx_data *data;
3658: uint32_t reg;
1.22 christos 3659: size_t i;
3660: int error;
1.1 nonaka 3661:
3662: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3663:
3664: urtwn_stop(ifp, 0);
3665:
1.12 christos 3666: mutex_enter(&sc->sc_write_mtx);
3667:
1.1 nonaka 3668: mutex_enter(&sc->sc_task_mtx);
3669: /* Init host async commands ring. */
3670: sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
3671: mutex_exit(&sc->sc_task_mtx);
3672:
3673: mutex_enter(&sc->sc_fwcmd_mtx);
3674: /* Init firmware commands ring. */
3675: sc->fwcur = 0;
3676: mutex_exit(&sc->sc_fwcmd_mtx);
3677:
1.12 christos 3678: /* Allocate Tx/Rx buffers. */
3679: error = urtwn_alloc_rx_list(sc);
3680: if (error != 0) {
3681: aprint_error_dev(sc->sc_dev,
3682: "could not allocate Rx buffers\n");
3683: goto fail;
3684: }
3685: error = urtwn_alloc_tx_list(sc);
3686: if (error != 0) {
3687: aprint_error_dev(sc->sc_dev,
3688: "could not allocate Tx buffers\n");
3689: goto fail;
1.1 nonaka 3690: }
3691:
3692: /* Power on adapter. */
3693: error = urtwn_power_on(sc);
3694: if (error != 0)
3695: goto fail;
3696:
3697: /* Initialize DMA. */
3698: error = urtwn_dma_init(sc);
3699: if (error != 0)
3700: goto fail;
3701:
3702: /* Set info size in Rx descriptors (in 64-bit words). */
3703: urtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4);
3704:
3705: /* Init interrupts. */
3706: urtwn_write_4(sc, R92C_HISR, 0xffffffff);
3707: urtwn_write_4(sc, R92C_HIMR, 0xffffffff);
3708:
3709: /* Set MAC address. */
3710: IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
3711: urtwn_write_region(sc, R92C_MACID, ic->ic_myaddr, IEEE80211_ADDR_LEN);
3712:
3713: /* Set initial network type. */
3714: reg = urtwn_read_4(sc, R92C_CR);
3715: switch (ic->ic_opmode) {
3716: case IEEE80211_M_STA:
3717: default:
3718: reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA);
3719: break;
1.7 christos 3720:
1.1 nonaka 3721: case IEEE80211_M_IBSS:
3722: reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_ADHOC);
3723: break;
3724: }
3725: urtwn_write_4(sc, R92C_CR, reg);
3726:
3727: /* Set response rate */
3728: reg = urtwn_read_4(sc, R92C_RRSR);
3729: reg = RW(reg, R92C_RRSR_RATE_BITMAP, R92C_RRSR_RATE_CCK_ONLY_1M);
3730: urtwn_write_4(sc, R92C_RRSR, reg);
3731:
3732: /* SIFS (used in NAV) */
3733: urtwn_write_2(sc, R92C_SPEC_SIFS,
3734: SM(R92C_SPEC_SIFS_CCK, 0x10) | SM(R92C_SPEC_SIFS_OFDM, 0x10));
3735:
3736: /* Set short/long retry limits. */
3737: urtwn_write_2(sc, R92C_RL,
3738: SM(R92C_RL_SRL, 0x30) | SM(R92C_RL_LRL, 0x30));
3739:
3740: /* Initialize EDCA parameters. */
3741: urtwn_edca_init(sc);
3742:
3743: /* Setup rate fallback. */
3744: urtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000);
3745: urtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404);
3746: urtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201);
3747: urtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605);
3748:
3749: urtwn_write_1(sc, R92C_FWHW_TXQ_CTRL,
3750: urtwn_read_1(sc, R92C_FWHW_TXQ_CTRL) |
3751: R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW);
3752: /* Set ACK timeout. */
3753: urtwn_write_1(sc, R92C_ACKTO, 0x40);
3754:
3755: /* Setup USB aggregation. */
3756: /* Tx */
3757: reg = urtwn_read_4(sc, R92C_TDECTRL);
3758: reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, 6);
3759: urtwn_write_4(sc, R92C_TDECTRL, reg);
3760: /* Rx */
3761: urtwn_write_1(sc, R92C_TRXDMA_CTRL,
3762: urtwn_read_1(sc, R92C_TRXDMA_CTRL) |
3763: R92C_TRXDMA_CTRL_RXDMA_AGG_EN);
3764: urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION,
3765: urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) &
3766: ~R92C_USB_SPECIAL_OPTION_AGG_EN);
3767: urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48);
3768: urtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4);
3769:
3770: /* Initialize beacon parameters. */
3771: urtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404);
1.26 ! christos 3772: urtwn_write_1(sc, R92C_DRVERLYINT, R92C_DRIVER_EARLY_INT_TIME);
! 3773: urtwn_write_1(sc, R92C_BCNDMATIM, R92C_DMA_ATIME_INT_TIME);
1.1 nonaka 3774: urtwn_write_2(sc, R92C_BCNTCFG, 0x660f);
3775:
3776: /* Setup AMPDU aggregation. */
3777: urtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */
3778: urtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16);
3779: urtwn_write_2(sc, 0x4ca, 0x0708);
3780:
3781: urtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff);
3782: urtwn_write_1(sc, R92C_BCN_CTRL, R92C_BCN_CTRL_DIS_TSF_UDT0);
3783:
3784: /* Load 8051 microcode. */
3785: error = urtwn_load_firmware(sc);
3786: if (error != 0)
3787: goto fail;
3788: SET(sc->sc_flags, URTWN_FLAG_FWREADY);
3789:
3790: /* Initialize MAC/BB/RF blocks. */
1.19 christos 3791: /*
3792: * XXX: urtwn_mac_init() sets R92C_RCR[0:15] = R92C_RCR_APM |
3793: * R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_AICV | R92C_RCR_AMF.
3794: * XXX: This setting should be removed from rtl8192cu_mac[].
3795: */
3796: urtwn_mac_init(sc); // sets R92C_RCR[0:15]
3797: urtwn_rxfilter_init(sc); // reset R92C_RCR
1.1 nonaka 3798: urtwn_bb_init(sc);
3799: urtwn_rf_init(sc);
3800:
3801: /* Turn CCK and OFDM blocks on. */
3802: reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD);
3803: reg |= R92C_RFMOD_CCK_EN;
3804: urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg);
3805: reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD);
3806: reg |= R92C_RFMOD_OFDM_EN;
3807: urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg);
3808:
3809: /* Clear per-station keys table. */
3810: urtwn_cam_init(sc);
3811:
3812: /* Enable hardware sequence numbering. */
3813: urtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
3814:
3815: /* Perform LO and IQ calibrations. */
3816: urtwn_iq_calib(sc, sc->iqk_inited);
3817: sc->iqk_inited = true;
3818:
3819: /* Perform LC calibration. */
3820: urtwn_lc_calib(sc);
3821:
3822: /* Fix USB interference issue. */
3823: urtwn_write_1(sc, 0xfe40, 0xe0);
3824: urtwn_write_1(sc, 0xfe41, 0x8d);
3825: urtwn_write_1(sc, 0xfe42, 0x80);
3826: urtwn_write_4(sc, 0x20c, 0xfd0320);
3827:
3828: urtwn_pa_bias_init(sc);
3829:
3830: if (!(sc->chip & (URTWN_CHIP_92C | URTWN_CHIP_92C_1T2R))) {
3831: /* 1T1R */
3832: urtwn_bb_write(sc, R92C_FPGA0_RFPARAM(0),
3833: urtwn_bb_read(sc, R92C_FPGA0_RFPARAM(0)) | __BIT(13));
3834: }
3835:
3836: /* Initialize GPIO setting. */
3837: urtwn_write_1(sc, R92C_GPIO_MUXCFG,
3838: urtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT);
3839:
3840: /* Fix for lower temperature. */
3841: urtwn_write_1(sc, 0x15, 0xe9);
3842:
3843: /* Set default channel. */
1.13 jmcneill 3844: urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE);
1.1 nonaka 3845:
3846: /* Queue Rx xfers. */
3847: for (i = 0; i < URTWN_RX_LIST_COUNT; i++) {
3848: data = &sc->rx_data[i];
3849: usbd_setup_xfer(data->xfer, sc->rx_pipe, data, data->buf,
3850: URTWN_RXBUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
3851: USBD_NO_TIMEOUT, urtwn_rxeof);
3852: error = usbd_transfer(data->xfer);
3853: if (__predict_false(error != USBD_NORMAL_COMPLETION &&
3854: error != USBD_IN_PROGRESS))
3855: goto fail;
3856: }
3857:
3858: /* We're ready to go. */
3859: ifp->if_flags &= ~IFF_OACTIVE;
3860: ifp->if_flags |= IFF_RUNNING;
3861:
1.16 jmcneill 3862: mutex_exit(&sc->sc_write_mtx);
3863:
1.1 nonaka 3864: if (ic->ic_opmode == IEEE80211_M_MONITOR)
3865: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
1.16 jmcneill 3866: else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
1.1 nonaka 3867: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1.16 jmcneill 3868: urtwn_wait_async(sc);
1.12 christos 3869:
1.1 nonaka 3870: return (0);
3871:
3872: fail:
1.12 christos 3873: mutex_exit(&sc->sc_write_mtx);
3874:
1.1 nonaka 3875: urtwn_stop(ifp, 1);
3876: return (error);
3877: }
3878:
3879: static void
3880: urtwn_stop(struct ifnet *ifp, int disable)
3881: {
3882: struct urtwn_softc *sc = ifp->if_softc;
3883: struct ieee80211com *ic = &sc->sc_ic;
1.22 christos 3884: size_t i;
3885: int s;
1.1 nonaka 3886:
3887: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3888:
3889: s = splusb();
3890: ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
3891: urtwn_wait_async(sc);
3892: splx(s);
3893:
1.16 jmcneill 3894: sc->tx_timer = 0;
3895: ifp->if_timer = 0;
3896: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
3897:
1.1 nonaka 3898: callout_stop(&sc->sc_scan_to);
3899: callout_stop(&sc->sc_calib_to);
3900:
3901: /* Abort Tx. */
3902: for (i = 0; i < R92C_MAX_EPOUT; i++) {
3903: if (sc->tx_pipe[i] != NULL)
3904: usbd_abort_pipe(sc->tx_pipe[i]);
3905: }
3906:
3907: /* Stop Rx pipe. */
3908: usbd_abort_pipe(sc->rx_pipe);
3909:
1.12 christos 3910: /* Free Tx/Rx buffers. */
3911: urtwn_free_tx_list(sc);
3912: urtwn_free_rx_list(sc);
3913:
1.1 nonaka 3914: if (disable)
3915: urtwn_chip_stop(sc);
3916: }
3917:
1.16 jmcneill 3918: static int
3919: urtwn_reset(struct ifnet *ifp)
3920: {
3921: struct urtwn_softc *sc = ifp->if_softc;
3922: struct ieee80211com *ic = &sc->sc_ic;
3923:
3924: if (ic->ic_opmode != IEEE80211_M_MONITOR)
3925: return ENETRESET;
3926:
3927: urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE);
3928:
3929: return 0;
3930: }
3931:
1.1 nonaka 3932: static void
3933: urtwn_chip_stop(struct urtwn_softc *sc)
3934: {
3935: uint32_t reg;
3936: bool disabled = true;
3937:
3938: DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
3939:
1.12 christos 3940: mutex_enter(&sc->sc_write_mtx);
3941:
1.1 nonaka 3942: /*
3943: * RF Off Sequence
3944: */
3945: /* Pause MAC TX queue */
3946: urtwn_write_1(sc, R92C_TXPAUSE, 0xFF);
3947:
3948: /* Disable RF */
3949: urtwn_rf_write(sc, 0, 0, 0);
3950:
3951: urtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF);
3952:
3953: /* Reset BB state machine */
3954: urtwn_write_1(sc, R92C_SYS_FUNC_EN,
3955: R92C_SYS_FUNC_EN_USBD |
3956: R92C_SYS_FUNC_EN_USBA |
3957: R92C_SYS_FUNC_EN_BB_GLB_RST);
3958: urtwn_write_1(sc, R92C_SYS_FUNC_EN,
3959: R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA);
3960:
3961: /*
3962: * Reset digital sequence
3963: */
3964: if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) {
3965: /* Reset MCU ready status */
3966: urtwn_write_1(sc, R92C_MCUFWDL, 0);
3967: /* If firmware in ram code, do reset */
3968: if (ISSET(sc->sc_flags, URTWN_FLAG_FWREADY)) {
3969: urtwn_fw_reset(sc);
3970: CLR(sc->sc_flags, URTWN_FLAG_FWREADY);
3971: }
3972: }
3973:
3974: /* Reset MAC and Enable 8051 */
3975: urtwn_write_1(sc, R92C_SYS_FUNC_EN + 1, 0x54);
3976:
3977: /* Reset MCU ready status */
3978: urtwn_write_1(sc, R92C_MCUFWDL, 0);
3979:
3980: if (disabled) {
3981: /* Disable MAC clock */
3982: urtwn_write_2(sc, R92C_SYS_CLKR, 0x70A3);
3983: /* Disable AFE PLL */
3984: urtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x80);
3985: /* Gated AFE DIG_CLOCK */
3986: urtwn_write_2(sc, R92C_AFE_XTAL_CTRL, 0x880F);
3987: /* Isolated digital to PON */
3988: urtwn_write_1(sc, R92C_SYS_ISO_CTRL, 0xF9);
3989: }
3990:
3991: /*
3992: * Pull GPIO PIN to balance level and LED control
3993: */
3994: /* 1. Disable GPIO[7:0] */
3995: urtwn_write_2(sc, R92C_GPIO_PIN_CTRL + 2, 0x0000);
3996:
3997: reg = urtwn_read_4(sc, R92C_GPIO_PIN_CTRL) & ~0x0000ff00;
3998: reg |= ((reg << 8) & 0x0000ff00) | 0x00ff0000;
3999: urtwn_write_4(sc, R92C_GPIO_PIN_CTRL, reg);
4000:
4001: /* Disable GPIO[10:8] */
4002: urtwn_write_1(sc, R92C_GPIO_MUXCFG + 3, 0x00);
4003:
4004: reg = urtwn_read_2(sc, R92C_GPIO_MUXCFG + 2) & ~0x00f0;
4005: reg |= (((reg & 0x000f) << 4) | 0x0780);
4006: urtwn_write_2(sc, R92C_GPIO_PIN_CTRL+2, reg);
4007:
4008: /* Disable LED0 & 1 */
4009: urtwn_write_2(sc, R92C_LEDCFG0, 0x8080);
4010:
4011: /*
4012: * Reset digital sequence
4013: */
4014: if (disabled) {
4015: /* Disable ELDR clock */
4016: urtwn_write_2(sc, R92C_SYS_CLKR, 0x70A3);
4017: /* Isolated ELDR to PON */
4018: urtwn_write_1(sc, R92C_SYS_ISO_CTRL + 1, 0x82);
4019: }
4020:
4021: /*
4022: * Disable analog sequence
4023: */
4024: if (disabled) {
4025: /* Disable A15 power */
4026: urtwn_write_1(sc, R92C_LDOA15_CTRL, 0x04);
4027: /* Disable digital core power */
4028: urtwn_write_1(sc, R92C_LDOV12D_CTRL,
4029: urtwn_read_1(sc, R92C_LDOV12D_CTRL) &
4030: ~R92C_LDOV12D_CTRL_LDV12_EN);
4031: }
4032:
4033: /* Enter PFM mode */
4034: urtwn_write_1(sc, R92C_SPS0_CTRL, 0x23);
4035:
4036: /* Set USB suspend */
4037: urtwn_write_2(sc, R92C_APS_FSMCO,
4038: R92C_APS_FSMCO_APDM_HOST |
4039: R92C_APS_FSMCO_AFSM_HSUS |
4040: R92C_APS_FSMCO_PFM_ALDN);
4041:
4042: urtwn_write_1(sc, R92C_RSV_CTRL, 0x0E);
1.12 christos 4043:
4044: mutex_exit(&sc->sc_write_mtx);
1.1 nonaka 4045: }
4046:
1.4 nonaka 4047: MODULE(MODULE_CLASS_DRIVER, if_urtwn, "bpf");
1.1 nonaka 4048:
4049: #ifdef _MODULE
4050: #include "ioconf.c"
4051: #endif
4052:
4053: static int
4054: if_urtwn_modcmd(modcmd_t cmd, void *aux)
4055: {
4056: int error = 0;
4057:
4058: switch (cmd) {
4059: case MODULE_CMD_INIT:
4060: #ifdef _MODULE
4061: error = config_init_component(cfdriver_ioconf_urtwn,
4062: cfattach_ioconf_urtwn, cfdata_ioconf_urtwn);
4063: #endif
4064: return (error);
4065: case MODULE_CMD_FINI:
4066: #ifdef _MODULE
4067: error = config_fini_component(cfdriver_ioconf_urtwn,
4068: cfattach_ioconf_urtwn, cfdata_ioconf_urtwn);
4069: #endif
4070: return (error);
4071: default:
4072: return (ENOTTY);
4073: }
4074: }
CVSweb <webmaster@jp.NetBSD.org>