if_rsu.c revision 1.1 1 1.1 nia /* $NetBSD: if_rsu.c,v 1.1 2026/10/18 20:17:42 nia Exp $ */
2 1.1 nia /* $OpenBSD: if_rsu.c,v 1.53 2024/05/23 03:21:08 jsg Exp $ */
3 1.1 nia
4 1.1 nia /*-
5 1.1 nia * Copyright (c) 2010 Damien Bergamini <damien.bergamini (at) free.fr>
6 1.1 nia *
7 1.1 nia * Permission to use, copy, modify, and distribute this software for any
8 1.1 nia * purpose with or without fee is hereby granted, provided that the above
9 1.1 nia * copyright notice and this permission notice appear in all copies.
10 1.1 nia *
11 1.1 nia * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 1.1 nia * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 1.1 nia * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 1.1 nia * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 1.1 nia * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 1.1 nia * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 1.1 nia * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 1.1 nia */
19 1.1 nia
20 1.1 nia /*
21 1.1 nia * Driver for Realtek RTL8188SU/RTL8191SU/RTL8192SU.
22 1.1 nia */
23 1.1 nia
24 1.1 nia /*
25 1.1 nia * XXX: This driver is unfinished. It attaches but is not yet usable.
26 1.1 nia */
27 1.1 nia
28 1.1 nia #include <sys/param.h>
29 1.1 nia #include <sys/sockio.h>
30 1.1 nia #include <sys/mbuf.h>
31 1.1 nia #include <sys/systm.h>
32 1.1 nia #include <sys/callout.h>
33 1.1 nia #include <sys/module.h>
34 1.1 nia #include <sys/device.h>
35 1.1 nia #include <sys/endian.h>
36 1.1 nia
37 1.1 nia #include <machine/intr.h>
38 1.1 nia
39 1.1 nia #include <net/if.h>
40 1.1 nia #include <net/if_dl.h>
41 1.1 nia #include <net/if_ether.h>
42 1.1 nia #include <net/if_media.h>
43 1.1 nia
44 1.1 nia #include <netinet/in.h>
45 1.1 nia
46 1.1 nia #include <net80211/ieee80211_var.h>
47 1.1 nia #include <net80211/ieee80211_radiotap.h>
48 1.1 nia
49 1.1 nia #include <dev/firmload.h>
50 1.1 nia
51 1.1 nia #include <dev/usb/usb.h>
52 1.1 nia #include <dev/usb/usbdi.h>
53 1.1 nia #include <dev/usb/usbdivar.h>
54 1.1 nia #include <dev/usb/usbdi_util.h>
55 1.1 nia #include <dev/usb/usbdevs.h>
56 1.1 nia
57 1.1 nia #include <dev/usb/if_rsureg.h>
58 1.1 nia
59 1.1 nia #ifdef RSU_DEBUG
60 1.1 nia #define DPRINTF(x) do { if (rsu_debug) printf x; } while (0)
61 1.1 nia #define DPRINTFN(n, x) do { if (rsu_debug >= (n)) printf x; } while (0)
62 1.1 nia int rsu_debug = 4;
63 1.1 nia #else
64 1.1 nia #define DPRINTF(x)
65 1.1 nia #define DPRINTFN(n, x)
66 1.1 nia #endif
67 1.1 nia
68 1.1 nia /*
69 1.1 nia * NB: When updating this list of devices, beware to also update the list
70 1.1 nia * of devices that have HT support disabled below, if applicable.
71 1.1 nia */
72 1.1 nia static const struct usb_devno rsu_devs[] = {
73 1.1 nia { USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RTL8192SU },
74 1.1 nia { USB_VENDOR_ASUSTEK, USB_PRODUCT_ASUSTEK_USBN10 },
75 1.1 nia { USB_VENDOR_ASUSTEK, USB_PRODUCT_ASUSTEK_RTL8192SU_1 },
76 1.1 nia { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8192SU_1 },
77 1.1 nia { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8192SU_2 },
78 1.1 nia { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8192SU_3 },
79 1.1 nia { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8192SU_4 },
80 1.1 nia { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8192SU_5 },
81 1.1 nia { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8192SU_1 },
82 1.1 nia { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8192SU_2 },
83 1.1 nia { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8192SU_3 },
84 1.1 nia { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_RTL8192SU_1 },
85 1.1 nia { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_RTL8192SU_2 },
86 1.1 nia { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_RTL8192SU_3 },
87 1.1 nia { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB300GNM },
88 1.1 nia { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA131A1 },
89 1.1 nia { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RTL8192SU_1 },
90 1.1 nia { USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RTL8192SU_2 },
91 1.1 nia { USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_RTL8192SU_1 },
92 1.1 nia { USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_RTL8192SU_2 },
93 1.1 nia { USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_RTL8192SU_3 },
94 1.1 nia { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUN54 },
95 1.1 nia { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWNUM300 },
96 1.1 nia { USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_RTL8192SU_1 },
97 1.1 nia { USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_RTL8192SU_2 },
98 1.1 nia { USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSNANO },
99 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8171 },
100 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8172 },
101 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8173 },
102 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8174 },
103 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8192SU },
104 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8712 },
105 1.1 nia { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8713 },
106 1.1 nia { USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RTL8192SU_1 },
107 1.1 nia { USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RTL8192SU_2 },
108 1.1 nia { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL349V1 },
109 1.1 nia { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL353 },
110 1.1 nia { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RTL8188S },
111 1.1 nia { USB_VENDOR_SWEEX2, USB_PRODUCT_SWEEX2_LW154 }
112 1.1 nia };
113 1.1 nia
114 1.1 nia #ifdef notyet
115 1.1 nia /* List of devices that have HT support disabled. */
116 1.1 nia static const struct usb_devno rsu_devs_noht[] = {
117 1.1 nia { USB_VENDOR_ASUSTEK, USB_PRODUCT_ASUS_RTL8192SU_1 },
118 1.1 nia { USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RTL8192SU_4 }
119 1.1 nia };
120 1.1 nia #endif
121 1.1 nia
122 1.1 nia static int rsu_match(device_t, cfdata_t, void *);
123 1.1 nia static void rsu_attach(device_t, device_t, void *);
124 1.1 nia static int rsu_detach(device_t, int);
125 1.1 nia static int rsu_activate(device_t, enum devact);
126 1.1 nia
127 1.1 nia int rsu_open_pipes(struct rsu_softc *);
128 1.1 nia void rsu_close_pipes(struct rsu_softc *);
129 1.1 nia int rsu_alloc_rx_list(struct rsu_softc *);
130 1.1 nia void rsu_free_rx_list(struct rsu_softc *);
131 1.1 nia int rsu_alloc_tx_list(struct rsu_softc *);
132 1.1 nia void rsu_free_tx_list(struct rsu_softc *);
133 1.1 nia void rsu_task(void *);
134 1.1 nia void rsu_do_async(struct rsu_softc *,
135 1.1 nia void (*)(struct rsu_softc *, void *), void *, int);
136 1.1 nia void rsu_wait_async(struct rsu_softc *);
137 1.1 nia int rsu_write_region_1(struct rsu_softc *, uint16_t, uint8_t *,
138 1.1 nia int);
139 1.1 nia void rsu_write_1(struct rsu_softc *, uint16_t, uint8_t);
140 1.1 nia void rsu_write_2(struct rsu_softc *, uint16_t, uint16_t);
141 1.1 nia void rsu_write_4(struct rsu_softc *, uint16_t, uint32_t);
142 1.1 nia int rsu_read_region_1(struct rsu_softc *, uint16_t, uint8_t *,
143 1.1 nia int);
144 1.1 nia uint8_t rsu_read_1(struct rsu_softc *, uint16_t);
145 1.1 nia uint16_t rsu_read_2(struct rsu_softc *, uint16_t);
146 1.1 nia uint32_t rsu_read_4(struct rsu_softc *, uint16_t);
147 1.1 nia int rsu_fw_iocmd(struct rsu_softc *, uint32_t);
148 1.1 nia uint8_t rsu_efuse_read_1(struct rsu_softc *, uint16_t);
149 1.1 nia int rsu_read_rom(struct rsu_softc *);
150 1.1 nia int rsu_fw_cmd(struct rsu_softc *, uint8_t, void *, int);
151 1.1 nia int rsu_media_change(struct ifnet *);
152 1.1 nia void rsu_calib_to(void *);
153 1.1 nia void rsu_calib_cb(struct rsu_softc *, void *);
154 1.1 nia int rsu_newstate(struct ieee80211com *, enum ieee80211_state, int);
155 1.1 nia void rsu_newstate_cb(struct rsu_softc *, void *);
156 1.1 nia int rsu_site_survey(struct rsu_softc *);
157 1.1 nia int rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
158 1.1 nia int rsu_disconnect(struct rsu_softc *);
159 1.1 nia void rsu_event_survey(struct rsu_softc *, uint8_t *, int);
160 1.1 nia void rsu_event_join_bss(struct rsu_softc *, uint8_t *, int);
161 1.1 nia void rsu_rx_event(struct rsu_softc *, uint8_t, uint8_t *, int);
162 1.1 nia void rsu_rx_multi_event(struct rsu_softc *, uint8_t *, int);
163 1.1 nia int8_t rsu_get_rssi(struct rsu_softc *, int, void *);
164 1.1 nia void rsu_rx_frame(struct rsu_softc *, uint8_t *, int);
165 1.1 nia void rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int);
166 1.1 nia void rsu_rxeof(struct usbd_xfer *, void *, usbd_status);
167 1.1 nia void rsu_txeof(struct usbd_xfer *, void *, usbd_status);
168 1.1 nia int rsu_tx(struct rsu_softc *, struct mbuf *,
169 1.1 nia struct ieee80211_node *);
170 1.1 nia int rsu_send_mgmt(struct ieee80211com *, struct ieee80211_node *,
171 1.1 nia int, int);
172 1.1 nia void rsu_start(struct ifnet *);
173 1.1 nia void rsu_watchdog(struct ifnet *);
174 1.1 nia int rsu_ioctl(struct ifnet *, u_long, void *);
175 1.1 nia void rsu_power_on_acut(struct rsu_softc *);
176 1.1 nia void rsu_power_on_bcut(struct rsu_softc *);
177 1.1 nia void rsu_power_off(struct rsu_softc *);
178 1.1 nia int rsu_fw_loadsection(struct rsu_softc *, uint8_t *, int);
179 1.1 nia int rsu_load_firmware(struct rsu_softc *);
180 1.1 nia int rsu_init(struct ifnet *);
181 1.1 nia void rsu_stop(struct ifnet *);
182 1.1 nia
183 1.1 nia CFATTACH_DECL_NEW(rsu, sizeof(struct rsu_softc), rsu_match,
184 1.1 nia rsu_attach, rsu_detach, rsu_activate);
185 1.1 nia
186 1.1 nia static int
187 1.1 nia rsu_activate(device_t self, enum devact act)
188 1.1 nia {
189 1.1 nia struct rsu_softc *sc = device_private(self);
190 1.1 nia switch (act) {
191 1.1 nia case DVACT_DEACTIVATE:
192 1.1 nia if_deactivate(sc->sc_ic.ic_ifp);
193 1.1 nia return 0;
194 1.1 nia default:
195 1.1 nia return EOPNOTSUPP;
196 1.1 nia }
197 1.1 nia }
198 1.1 nia
199 1.1 nia static int
200 1.1 nia rsu_match(device_t parent, cfdata_t match, void *aux)
201 1.1 nia {
202 1.1 nia struct usb_attach_arg *uaa = aux;
203 1.1 nia
204 1.1 nia return ((usb_lookup(rsu_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL) ?
205 1.1 nia UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
206 1.1 nia }
207 1.1 nia
208 1.1 nia static void
209 1.1 nia rsu_attach(device_t parent, device_t self, void *aux)
210 1.1 nia {
211 1.1 nia struct rsu_softc *sc = device_private(self);
212 1.1 nia struct usb_attach_arg *uaa = aux;
213 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
214 1.1 nia struct ifnet *ifp = &sc->sc_ec.ec_if;
215 1.1 nia int i, error;
216 1.1 nia
217 1.1 nia sc->sc_dev = self;
218 1.1 nia sc->sc_udev = uaa->uaa_device;
219 1.1 nia
220 1.1 nia cv_init(&sc->sc_task_cv, "rsutsk");
221 1.1 nia mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET);
222 1.1 nia mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE);
223 1.1 nia
224 1.1 nia usb_init_task(&sc->sc_task, rsu_task, sc, 0);
225 1.1 nia
226 1.1 nia callout_init(&sc->calib_to, 0);
227 1.1 nia callout_setfunc(&sc->calib_to, rsu_calib_to, sc);
228 1.1 nia
229 1.1 nia /* Read chip revision. */
230 1.1 nia sc->cut = MS(rsu_read_4(sc, R92S_PMC_FSM), R92S_PMC_FSM_CUT);
231 1.1 nia if (sc->cut != 3)
232 1.1 nia sc->cut = (sc->cut >> 1) + 1;
233 1.1 nia
234 1.1 nia KASSERT(sc->sc_dev != NULL);
235 1.1 nia
236 1.1 nia error = usbd_set_config_no(sc->sc_udev, 1, 0);
237 1.1 nia if (error != 0) {
238 1.1 nia aprint_error_dev(self, "failed to set configuration"
239 1.1 nia ", err=%s\n", usbd_errstr(error));
240 1.1 nia return;
241 1.1 nia }
242 1.1 nia
243 1.1 nia /* Get the first interface handle. */
244 1.1 nia error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface);
245 1.1 nia if (error != 0) {
246 1.1 nia aprint_error_dev(self, "could not get interface handle\n");
247 1.1 nia return;
248 1.1 nia }
249 1.1 nia
250 1.1 nia error = rsu_read_rom(sc);
251 1.1 nia if (error != 0) {
252 1.1 nia printf("%s: could not read ROM\n", device_xname(sc->sc_dev));
253 1.1 nia return;
254 1.1 nia }
255 1.1 nia IEEE80211_ADDR_COPY(ic->ic_myaddr, &sc->rom[0x12]);
256 1.1 nia
257 1.1 nia printf("%s: MAC/BB RTL8712 cut %d, address %s\n",
258 1.1 nia device_xname(sc->sc_dev), sc->cut, ether_sprintf(ic->ic_myaddr));
259 1.1 nia
260 1.1 nia if (rsu_open_pipes(sc) != 0)
261 1.1 nia return;
262 1.1 nia
263 1.1 nia KASSERT(ifp != NULL);
264 1.1 nia
265 1.1 nia ic->ic_ifp = ifp;
266 1.1 nia ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
267 1.1 nia ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */
268 1.1 nia ic->ic_state = IEEE80211_S_INIT;
269 1.1 nia
270 1.1 nia /* Set device capabilities. */
271 1.1 nia ic->ic_caps =
272 1.1 nia IEEE80211_C_MONITOR | /* Monitor mode. */
273 1.1 nia IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */
274 1.1 nia IEEE80211_C_SHSLOT | /* Short slot time supported. */
275 1.1 nia IEEE80211_C_WPA; /* WPA/RSN. */
276 1.1 nia
277 1.1 nia #ifdef notyet
278 1.1 nia ic->ic_caps +=
279 1.1 nia IEEE80211_C_WEP; /* WEP. */
280 1.1 nia #endif
281 1.1 nia
282 1.1 nia #ifdef notyet
283 1.1 nia /* Check if HT support is present. */
284 1.1 nia if (usb_lookup(rsu_devs_noht, uaa->uaa_vendor, uaa->uaa_product) == NULL) {
285 1.1 nia /* Set HT capabilities. */
286 1.1 nia ic->ic_htcaps =
287 1.1 nia IEEE80211_HTCAP_CBW20_40 |
288 1.1 nia IEEE80211_HTCAP_DSSSCCK40;
289 1.1 nia /* Set supported HT rates. */
290 1.1 nia for (i = 0; i < 2; i++)
291 1.1 nia ic->ic_sup_mcs[i] = 0xff;
292 1.1 nia }
293 1.1 nia #endif
294 1.1 nia
295 1.1 nia /* Set supported .11b and .11g rates. */
296 1.1 nia ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
297 1.1 nia ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
298 1.1 nia
299 1.1 nia /* Set supported .11b and .11g channels (1 through 14). */
300 1.1 nia for (i = 1; i <= 14; i++) {
301 1.1 nia ic->ic_channels[i].ic_freq =
302 1.1 nia ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
303 1.1 nia ic->ic_channels[i].ic_flags =
304 1.1 nia IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
305 1.1 nia IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
306 1.1 nia }
307 1.1 nia
308 1.1 nia ifp->if_softc = sc;
309 1.1 nia ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
310 1.1 nia ifp->if_init = rsu_init;
311 1.1 nia ifp->if_ioctl = rsu_ioctl;
312 1.1 nia ifp->if_start = rsu_start;
313 1.1 nia ifp->if_watchdog = rsu_watchdog;
314 1.1 nia memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
315 1.1 nia
316 1.1 nia if_initialize(ifp);
317 1.1 nia ieee80211_ifattach(ic);
318 1.1 nia
319 1.1 nia /* Override state transition machine. */
320 1.1 nia sc->sc_newstate = ic->ic_newstate;
321 1.1 nia ic->ic_newstate = rsu_newstate;
322 1.1 nia
323 1.1 nia /* XXX media locking needs revisiting */
324 1.1 nia mutex_init(&sc->sc_media_mtx, MUTEX_DEFAULT, IPL_SOFTUSB);
325 1.1 nia ieee80211_media_init_with_lock(ic,
326 1.1 nia rsu_media_change, ieee80211_media_status, &sc->sc_media_mtx);
327 1.1 nia
328 1.1 nia if_register(ifp);
329 1.1 nia
330 1.1 nia ieee80211_announce(ic);
331 1.1 nia
332 1.1 nia usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
333 1.1 nia }
334 1.1 nia
335 1.1 nia static int
336 1.1 nia rsu_detach(device_t self, int flags)
337 1.1 nia {
338 1.1 nia struct rsu_softc *sc = device_private(self);
339 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
340 1.1 nia struct ifnet *ifp = sc->sc_ic.ic_ifp;
341 1.1 nia int s;
342 1.1 nia
343 1.1 nia s = splusb();
344 1.1 nia
345 1.1 nia if (ifp->if_flags & IFF_RUNNING) {
346 1.1 nia rsu_stop(ifp);
347 1.1 nia callout_halt(&sc->calib_to, NULL);
348 1.1 nia usb_rem_task_wait(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER,
349 1.1 nia NULL);
350 1.1 nia }
351 1.1 nia
352 1.1 nia ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
353 1.1 nia ieee80211_ifdetach(ic);
354 1.1 nia if_detach(ifp);
355 1.1 nia
356 1.1 nia mutex_destroy(&sc->sc_media_mtx);
357 1.1 nia
358 1.1 nia /* Abort and close Tx/Rx pipes. */
359 1.1 nia rsu_close_pipes(sc);
360 1.1 nia
361 1.1 nia /* Free Tx/Rx buffers. */
362 1.1 nia rsu_free_tx_list(sc);
363 1.1 nia rsu_free_rx_list(sc);
364 1.1 nia splx(s);
365 1.1 nia
366 1.1 nia usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
367 1.1 nia
368 1.1 nia callout_destroy(&sc->calib_to);
369 1.1 nia
370 1.1 nia mutex_destroy(&sc->sc_task_mtx);
371 1.1 nia mutex_destroy(&sc->sc_tx_mtx);
372 1.1 nia
373 1.1 nia return (0);
374 1.1 nia }
375 1.1 nia
376 1.1 nia int
377 1.1 nia rsu_open_pipes(struct rsu_softc *sc)
378 1.1 nia {
379 1.1 nia usb_interface_descriptor_t *id;
380 1.1 nia int i, error;
381 1.1 nia
382 1.1 nia /*
383 1.1 nia * Determine the number of Tx/Rx endpoints (there are chips with
384 1.1 nia * 4, 6 or 11 endpoints).
385 1.1 nia */
386 1.1 nia id = usbd_get_interface_descriptor(sc->sc_iface);
387 1.1 nia sc->npipes = id->bNumEndpoints;
388 1.1 nia if (sc->npipes == 4)
389 1.1 nia sc->qid2idx = rsu_qid2idx_4ep;
390 1.1 nia else if (sc->npipes == 6)
391 1.1 nia sc->qid2idx = rsu_qid2idx_6ep;
392 1.1 nia else /* Assume npipes==11; will fail below otherwise. */
393 1.1 nia sc->qid2idx = rsu_qid2idx_11ep;
394 1.1 nia DPRINTF(("%d endpoints configuration\n", sc->npipes));
395 1.1 nia
396 1.1 nia /* Open all pipes. */
397 1.1 nia for (i = 0; i < MIN(sc->npipes, (int)__arraycount(r92s_epaddr)); i++) {
398 1.1 nia error = usbd_open_pipe(sc->sc_iface, r92s_epaddr[i], 0,
399 1.1 nia &sc->pipe[i]);
400 1.1 nia if (error != 0) {
401 1.1 nia printf("%s: could not open bulk pipe 0x%02x\n",
402 1.1 nia device_xname(sc->sc_dev), r92s_epaddr[i]);
403 1.1 nia break;
404 1.1 nia }
405 1.1 nia }
406 1.1 nia if (error != 0)
407 1.1 nia rsu_close_pipes(sc);
408 1.1 nia return (error);
409 1.1 nia }
410 1.1 nia
411 1.1 nia void
412 1.1 nia rsu_close_pipes(struct rsu_softc *sc)
413 1.1 nia {
414 1.1 nia struct usbd_pipe *pipe;
415 1.1 nia int i;
416 1.1 nia
417 1.1 nia /* Close all pipes. */
418 1.1 nia for (i = 0; i < sc->npipes; i++) {
419 1.1 nia pipe = atomic_swap_ptr(&sc->pipe[i], NULL);
420 1.1 nia if (pipe != NULL) {
421 1.1 nia usbd_close_pipe(pipe);
422 1.1 nia }
423 1.1 nia }
424 1.1 nia }
425 1.1 nia
426 1.1 nia int
427 1.1 nia rsu_alloc_rx_list(struct rsu_softc *sc)
428 1.1 nia {
429 1.1 nia struct rsu_rx_data *data;
430 1.1 nia int i, error = 0;
431 1.1 nia
432 1.1 nia for (i = 0; i < RSU_RX_LIST_COUNT; i++) {
433 1.1 nia data = &sc->rx_data[i];
434 1.1 nia
435 1.1 nia data->sc = sc; /* Backpointer for callbacks. */
436 1.1 nia
437 1.1 nia error = usbd_create_xfer(data->pipe, RSU_RXBUFSZ,
438 1.1 nia 0, 0, &data->xfer);
439 1.1 nia if (error) {
440 1.1 nia printf("%s: could not allocate xfer\n",
441 1.1 nia device_xname(sc->sc_dev));
442 1.1 nia error = ENOMEM;
443 1.1 nia break;
444 1.1 nia }
445 1.1 nia data->buf = usbd_get_buffer(data->xfer);
446 1.1 nia }
447 1.1 nia if (error != 0)
448 1.1 nia rsu_free_rx_list(sc);
449 1.1 nia return (error);
450 1.1 nia }
451 1.1 nia
452 1.1 nia void
453 1.1 nia rsu_free_rx_list(struct rsu_softc *sc)
454 1.1 nia {
455 1.1 nia int i;
456 1.1 nia
457 1.1 nia /* NB: Caller must abort pipe first. */
458 1.1 nia for (i = 0; i < RSU_RX_LIST_COUNT; i++) {
459 1.1 nia if (sc->rx_data[i].xfer != NULL)
460 1.1 nia usbd_destroy_xfer(sc->rx_data[i].xfer);
461 1.1 nia sc->rx_data[i].xfer = NULL;
462 1.1 nia }
463 1.1 nia }
464 1.1 nia
465 1.1 nia int
466 1.1 nia rsu_alloc_tx_list(struct rsu_softc *sc)
467 1.1 nia {
468 1.1 nia struct rsu_tx_data *data;
469 1.1 nia int i, error = 0;
470 1.1 nia
471 1.1 nia mutex_enter(&sc->sc_tx_mtx);
472 1.1 nia TAILQ_INIT(&sc->tx_free_list);
473 1.1 nia for (i = 0; i < RSU_TX_LIST_COUNT; i++) {
474 1.1 nia data = &sc->tx_data[i];
475 1.1 nia
476 1.1 nia data->sc = sc; /* Backpointer for callbacks. */
477 1.1 nia
478 1.1 nia error = usbd_create_xfer(data->pipe,
479 1.1 nia RSU_TXBUFSZ, USBD_FORCE_SHORT_XFER, 0,
480 1.1 nia &data->xfer);
481 1.1 nia if (error) {
482 1.1 nia printf("%s: could not allocate xfer\n",
483 1.1 nia device_xname(sc->sc_dev));
484 1.1 nia error = ENOMEM;
485 1.1 nia break;
486 1.1 nia }
487 1.1 nia data->buf = usbd_get_buffer(data->xfer);
488 1.1 nia
489 1.1 nia /* Append this Tx buffer to our free list. */
490 1.1 nia TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
491 1.1 nia }
492 1.1 nia if (error != 0)
493 1.1 nia rsu_free_tx_list(sc);
494 1.1 nia
495 1.1 nia mutex_exit(&sc->sc_tx_mtx);
496 1.1 nia return (error);
497 1.1 nia }
498 1.1 nia
499 1.1 nia void
500 1.1 nia rsu_free_tx_list(struct rsu_softc *sc)
501 1.1 nia {
502 1.1 nia struct usbd_xfer *xfer;
503 1.1 nia int i;
504 1.1 nia
505 1.1 nia /* NB: Caller must abort pipe first. */
506 1.1 nia for (i = 0; i < RSU_TX_LIST_COUNT; i++) {
507 1.1 nia xfer = atomic_swap_ptr(&sc->tx_data[i].xfer, NULL);
508 1.1 nia if (xfer != NULL)
509 1.1 nia usbd_destroy_xfer(xfer);
510 1.1 nia }
511 1.1 nia }
512 1.1 nia
513 1.1 nia void
514 1.1 nia rsu_task(void *arg)
515 1.1 nia {
516 1.1 nia struct rsu_softc *sc = arg;
517 1.1 nia struct rsu_host_cmd_ring *ring = &sc->cmdq;
518 1.1 nia struct rsu_host_cmd *cmd;
519 1.1 nia int s;
520 1.1 nia
521 1.1 nia /* Process host commands. */
522 1.1 nia s = splusb();
523 1.1 nia mutex_spin_enter(&sc->sc_task_mtx);
524 1.1 nia
525 1.1 nia while (ring->next != ring->cur) {
526 1.1 nia cmd = &ring->cmd[ring->next];
527 1.1 nia splx(s);
528 1.1 nia membar_consumer();
529 1.1 nia /* Invoke callback. */
530 1.1 nia cmd->cb(sc, cmd->data);
531 1.1 nia s = splusb();
532 1.1 nia atomic_dec_uint(&ring->queued);
533 1.1 nia ring->next = (ring->next + 1) % RSU_HOST_CMD_RING_COUNT;
534 1.1 nia }
535 1.1 nia
536 1.1 nia mutex_spin_exit(&sc->sc_task_mtx);
537 1.1 nia splx(s);
538 1.1 nia }
539 1.1 nia
540 1.1 nia void
541 1.1 nia rsu_do_async(struct rsu_softc *sc,
542 1.1 nia void (*cb)(struct rsu_softc *, void *), void *arg, int len)
543 1.1 nia {
544 1.1 nia struct rsu_host_cmd_ring *ring = &sc->cmdq;
545 1.1 nia struct rsu_host_cmd *cmd;
546 1.1 nia bool schedtask = false;
547 1.1 nia int s;
548 1.1 nia
549 1.1 nia s = splusb();
550 1.1 nia mutex_spin_enter(&sc->sc_task_mtx);
551 1.1 nia
552 1.1 nia cmd = &ring->cmd[ring->cur];
553 1.1 nia cmd->cb = cb;
554 1.1 nia KASSERT(len <= sizeof(cmd->data));
555 1.1 nia memcpy(cmd->data, arg, len);
556 1.1 nia ring->cur = (ring->cur + 1) % RSU_HOST_CMD_RING_COUNT;
557 1.1 nia
558 1.1 nia /* If there is no pending command already, schedule a task. */
559 1.1 nia if (atomic_inc_uint_nv(&ring->queued) == 1)
560 1.1 nia schedtask = true;
561 1.1 nia
562 1.1 nia mutex_spin_exit(&sc->sc_task_mtx);
563 1.1 nia splx(s);
564 1.1 nia
565 1.1 nia if (schedtask)
566 1.1 nia usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
567 1.1 nia }
568 1.1 nia
569 1.1 nia void
570 1.1 nia rsu_wait_async(struct rsu_softc *sc)
571 1.1 nia {
572 1.1 nia /* Wait for all queued asynchronous commands to complete. */
573 1.1 nia mutex_spin_enter(&sc->sc_task_mtx);
574 1.1 nia while (sc->cmdq.queued > 0)
575 1.1 nia cv_wait(&sc->sc_task_cv, &sc->sc_task_mtx);
576 1.1 nia mutex_spin_exit(&sc->sc_task_mtx);
577 1.1 nia }
578 1.1 nia
579 1.1 nia int
580 1.1 nia rsu_write_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
581 1.1 nia int len)
582 1.1 nia {
583 1.1 nia usb_device_request_t req;
584 1.1 nia
585 1.1 nia req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
586 1.1 nia req.bRequest = R92S_REQ_REGS;
587 1.1 nia USETW(req.wValue, addr);
588 1.1 nia USETW(req.wIndex, 0);
589 1.1 nia USETW(req.wLength, len);
590 1.1 nia return (usbd_do_request(sc->sc_udev, &req, buf));
591 1.1 nia }
592 1.1 nia
593 1.1 nia void
594 1.1 nia rsu_write_1(struct rsu_softc *sc, uint16_t addr, uint8_t val)
595 1.1 nia {
596 1.1 nia rsu_write_region_1(sc, addr, &val, 1);
597 1.1 nia }
598 1.1 nia
599 1.1 nia void
600 1.1 nia rsu_write_2(struct rsu_softc *sc, uint16_t addr, uint16_t val)
601 1.1 nia {
602 1.1 nia val = htole16(val);
603 1.1 nia rsu_write_region_1(sc, addr, (uint8_t *)&val, 2);
604 1.1 nia }
605 1.1 nia
606 1.1 nia void
607 1.1 nia rsu_write_4(struct rsu_softc *sc, uint16_t addr, uint32_t val)
608 1.1 nia {
609 1.1 nia val = htole32(val);
610 1.1 nia rsu_write_region_1(sc, addr, (uint8_t *)&val, 4);
611 1.1 nia }
612 1.1 nia
613 1.1 nia int
614 1.1 nia rsu_read_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
615 1.1 nia int len)
616 1.1 nia {
617 1.1 nia usb_device_request_t req;
618 1.1 nia
619 1.1 nia req.bmRequestType = UT_READ_VENDOR_DEVICE;
620 1.1 nia req.bRequest = R92S_REQ_REGS;
621 1.1 nia USETW(req.wValue, addr);
622 1.1 nia USETW(req.wIndex, 0);
623 1.1 nia USETW(req.wLength, len);
624 1.1 nia return (usbd_do_request(sc->sc_udev, &req, buf));
625 1.1 nia }
626 1.1 nia
627 1.1 nia uint8_t
628 1.1 nia rsu_read_1(struct rsu_softc *sc, uint16_t addr)
629 1.1 nia {
630 1.1 nia uint8_t val;
631 1.1 nia
632 1.1 nia if (rsu_read_region_1(sc, addr, &val, 1) != 0)
633 1.1 nia return (0xff);
634 1.1 nia return (val);
635 1.1 nia }
636 1.1 nia
637 1.1 nia uint16_t
638 1.1 nia rsu_read_2(struct rsu_softc *sc, uint16_t addr)
639 1.1 nia {
640 1.1 nia uint16_t val;
641 1.1 nia
642 1.1 nia if (rsu_read_region_1(sc, addr, (uint8_t *)&val, 2) != 0)
643 1.1 nia return (0xffff);
644 1.1 nia return (le16toh(val));
645 1.1 nia }
646 1.1 nia
647 1.1 nia uint32_t
648 1.1 nia rsu_read_4(struct rsu_softc *sc, uint16_t addr)
649 1.1 nia {
650 1.1 nia uint32_t val;
651 1.1 nia
652 1.1 nia if (rsu_read_region_1(sc, addr, (uint8_t *)&val, 4) != 0)
653 1.1 nia return (0xffffffff);
654 1.1 nia return (le32toh(val));
655 1.1 nia }
656 1.1 nia
657 1.1 nia int
658 1.1 nia rsu_fw_iocmd(struct rsu_softc *sc, uint32_t iocmd)
659 1.1 nia {
660 1.1 nia int ntries;
661 1.1 nia
662 1.1 nia rsu_write_4(sc, R92S_IOCMD_CTRL, iocmd);
663 1.1 nia DELAY(100);
664 1.1 nia for (ntries = 0; ntries < 50; ntries++) {
665 1.1 nia if (rsu_read_4(sc, R92S_IOCMD_CTRL) == 0)
666 1.1 nia return (0);
667 1.1 nia DELAY(10);
668 1.1 nia }
669 1.1 nia return (ETIMEDOUT);
670 1.1 nia }
671 1.1 nia
672 1.1 nia uint8_t
673 1.1 nia rsu_efuse_read_1(struct rsu_softc *sc, uint16_t addr)
674 1.1 nia {
675 1.1 nia uint32_t reg;
676 1.1 nia int ntries;
677 1.1 nia
678 1.1 nia reg = rsu_read_4(sc, R92S_EFUSE_CTRL);
679 1.1 nia reg = RW(reg, R92S_EFUSE_CTRL_ADDR, addr);
680 1.1 nia reg &= ~R92S_EFUSE_CTRL_VALID;
681 1.1 nia rsu_write_4(sc, R92S_EFUSE_CTRL, reg);
682 1.1 nia /* Wait for read operation to complete. */
683 1.1 nia for (ntries = 0; ntries < 100; ntries++) {
684 1.1 nia reg = rsu_read_4(sc, R92S_EFUSE_CTRL);
685 1.1 nia if (reg & R92S_EFUSE_CTRL_VALID)
686 1.1 nia return (MS(reg, R92S_EFUSE_CTRL_DATA));
687 1.1 nia DELAY(5);
688 1.1 nia }
689 1.1 nia printf("%s: could not read efuse byte at address 0x%x\n",
690 1.1 nia device_xname(sc->sc_dev), addr);
691 1.1 nia return (0xff);
692 1.1 nia }
693 1.1 nia
694 1.1 nia int
695 1.1 nia rsu_read_rom(struct rsu_softc *sc)
696 1.1 nia {
697 1.1 nia uint8_t *rom = sc->rom;
698 1.1 nia uint16_t addr = 0;
699 1.1 nia uint32_t reg;
700 1.1 nia uint8_t off, msk;
701 1.1 nia int i;
702 1.1 nia
703 1.1 nia /* Make sure that ROM type is eFuse and that autoload succeeded. */
704 1.1 nia reg = rsu_read_1(sc, R92S_EE_9346CR);
705 1.1 nia if ((reg & (R92S_9356SEL | R92S_EEPROM_EN)) != R92S_EEPROM_EN)
706 1.1 nia return (EIO);
707 1.1 nia
708 1.1 nia /* Turn on 2.5V to prevent eFuse leakage. */
709 1.1 nia reg = rsu_read_1(sc, R92S_EFUSE_TEST + 3);
710 1.1 nia rsu_write_1(sc, R92S_EFUSE_TEST + 3, reg | 0x80);
711 1.1 nia usbd_delay_ms(sc->sc_udev, 10);
712 1.1 nia rsu_write_1(sc, R92S_EFUSE_TEST + 3, reg & ~0x80);
713 1.1 nia
714 1.1 nia /* Read full ROM image. */
715 1.1 nia memset(&sc->rom, 0xff, sizeof(sc->rom));
716 1.1 nia while (addr < 512) {
717 1.1 nia reg = rsu_efuse_read_1(sc, addr);
718 1.1 nia if (reg == 0xff)
719 1.1 nia break;
720 1.1 nia addr++;
721 1.1 nia off = reg >> 4;
722 1.1 nia msk = reg & 0xf;
723 1.1 nia for (i = 0; i < 4; i++) {
724 1.1 nia if (msk & (1 << i))
725 1.1 nia continue;
726 1.1 nia rom[off * 8 + i * 2 + 0] =
727 1.1 nia rsu_efuse_read_1(sc, addr);
728 1.1 nia addr++;
729 1.1 nia rom[off * 8 + i * 2 + 1] =
730 1.1 nia rsu_efuse_read_1(sc, addr);
731 1.1 nia addr++;
732 1.1 nia }
733 1.1 nia }
734 1.1 nia
735 1.1 nia #ifdef RSU_DEBUG
736 1.1 nia if (rsu_debug >= 5) {
737 1.1 nia /* Dump ROM content. */
738 1.1 nia printf("\n");
739 1.1 nia for (i = 0; i < sizeof(sc->rom); i++)
740 1.1 nia printf("%02x:", rom[i]);
741 1.1 nia printf("\n");
742 1.1 nia }
743 1.1 nia #endif
744 1.1 nia return (0);
745 1.1 nia }
746 1.1 nia
747 1.1 nia int
748 1.1 nia rsu_fw_cmd(struct rsu_softc *sc, uint8_t code, void *buf, int len)
749 1.1 nia {
750 1.1 nia struct rsu_tx_data *data;
751 1.1 nia struct r92s_tx_desc *txd;
752 1.1 nia struct r92s_fw_cmd_hdr *cmd;
753 1.1 nia int cmdsz, xferlen;
754 1.1 nia
755 1.1 nia data = sc->fwcmd_data;
756 1.1 nia
757 1.1 nia /* Round-up command length to a multiple of 8 bytes. */
758 1.1 nia cmdsz = (len + 7) & ~7;
759 1.1 nia
760 1.1 nia xferlen = sizeof(*txd) + sizeof(*cmd) + cmdsz;
761 1.1 nia KASSERT(xferlen <= RSU_TXBUFSZ);
762 1.1 nia memset(data->buf, 0, xferlen);
763 1.1 nia
764 1.1 nia /* Setup Tx descriptor. */
765 1.1 nia txd = (struct r92s_tx_desc *)data->buf;
766 1.1 nia txd->txdw0 = htole32(
767 1.1 nia SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |
768 1.1 nia SM(R92S_TXDW0_PKTLEN, sizeof(*cmd) + cmdsz) |
769 1.1 nia R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG);
770 1.1 nia txd->txdw1 = htole32(SM(R92S_TXDW1_QSEL, R92S_TXDW1_QSEL_H2C));
771 1.1 nia
772 1.1 nia /* Setup command header. */
773 1.1 nia cmd = (struct r92s_fw_cmd_hdr *)&txd[1];
774 1.1 nia cmd->len = htole16(cmdsz);
775 1.1 nia cmd->code = code;
776 1.1 nia cmd->seq = sc->cmd_seq;
777 1.1 nia sc->cmd_seq = (sc->cmd_seq + 1) & 0x7f;
778 1.1 nia
779 1.1 nia /* Copy command payload. */
780 1.1 nia memcpy(&cmd[1], buf, len);
781 1.1 nia
782 1.1 nia DPRINTFN(2, ("Tx cmd code=%d len=%d\n", code, cmdsz));
783 1.1 nia /*pipe = sc->pipe[sc->qid2idx[RSU_QID_H2C]];*/
784 1.1 nia usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
785 1.1 nia USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS,
786 1.1 nia RSU_CMD_TIMEOUT, NULL);
787 1.1 nia return (usbd_transfer(data->xfer));
788 1.1 nia }
789 1.1 nia
790 1.1 nia int
791 1.1 nia rsu_media_change(struct ifnet *ifp)
792 1.1 nia {
793 1.1 nia int error;
794 1.1 nia
795 1.1 nia error = ieee80211_media_change(ifp);
796 1.1 nia if (error != ENETRESET)
797 1.1 nia return (error);
798 1.1 nia
799 1.1 nia if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
800 1.1 nia (IFF_UP | IFF_RUNNING)) {
801 1.1 nia rsu_stop(ifp);
802 1.1 nia error = rsu_init(ifp);
803 1.1 nia }
804 1.1 nia return (error);
805 1.1 nia }
806 1.1 nia
807 1.1 nia void
808 1.1 nia rsu_calib_to(void *arg)
809 1.1 nia {
810 1.1 nia struct rsu_softc *sc = arg;
811 1.1 nia
812 1.1 nia /* Do it in a process context. */
813 1.1 nia rsu_do_async(sc, rsu_calib_cb, NULL, 0);
814 1.1 nia }
815 1.1 nia
816 1.1 nia void
817 1.1 nia rsu_calib_cb(struct rsu_softc *sc, void *arg)
818 1.1 nia {
819 1.1 nia uint32_t reg;
820 1.1 nia
821 1.1 nia #ifdef notyet
822 1.1 nia /* Read WPS PBC status. */
823 1.1 nia rsu_write_1(sc, R92S_MAC_PINMUX_CTRL,
824 1.1 nia R92S_GPIOMUX_EN | SM(R92S_GPIOSEL_GPIO, R92S_GPIOSEL_GPIO_JTAG));
825 1.1 nia rsu_write_1(sc, R92S_GPIO_IO_SEL,
826 1.1 nia rsu_read_1(sc, R92S_GPIO_IO_SEL) & ~R92S_GPIO_WPS);
827 1.1 nia reg = rsu_read_1(sc, R92S_GPIO_CTRL);
828 1.1 nia if (reg != 0xff && (reg & R92S_GPIO_WPS))
829 1.1 nia DPRINTF(("WPS PBC is pushed\n"));
830 1.1 nia #endif
831 1.1 nia
832 1.1 nia /* Read current signal level. */
833 1.1 nia if (rsu_fw_iocmd(sc, 0xf4000001) == 0) {
834 1.1 nia reg = rsu_read_4(sc, R92S_IOCMD_DATA);
835 1.1 nia DPRINTFN(8, ("RSSI=%d%%\n", reg >> 4));
836 1.1 nia }
837 1.1 nia (void)reg;
838 1.1 nia
839 1.1 nia callout_schedule(&sc->calib_to, hz);
840 1.1 nia }
841 1.1 nia
842 1.1 nia int
843 1.1 nia rsu_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
844 1.1 nia {
845 1.1 nia struct rsu_softc *sc = ic->ic_ifp->if_softc;
846 1.1 nia struct rsu_cmd_newstate cmd;
847 1.1 nia
848 1.1 nia callout_stop(&sc->calib_to);
849 1.1 nia
850 1.1 nia /* Do it in a process context. */
851 1.1 nia cmd.state = nstate;
852 1.1 nia cmd.arg = arg;
853 1.1 nia rsu_do_async(sc, rsu_newstate_cb, &cmd, sizeof(cmd));
854 1.1 nia return (0);
855 1.1 nia }
856 1.1 nia
857 1.1 nia void
858 1.1 nia rsu_newstate_cb(struct rsu_softc *sc, void *arg)
859 1.1 nia {
860 1.1 nia struct rsu_cmd_newstate *cmd = arg;
861 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
862 1.1 nia struct ifnet *ifp = sc->sc_ic.ic_ifp;
863 1.1 nia enum ieee80211_state ostate;
864 1.1 nia int error, s;
865 1.1 nia
866 1.1 nia s = splnet();
867 1.1 nia ostate = ic->ic_state;
868 1.1 nia
869 1.1 nia if (ostate == IEEE80211_S_RUN) {
870 1.1 nia /* Stop calibration. */
871 1.1 nia callout_halt(&sc->calib_to, NULL);
872 1.1 nia /* Disassociate from our current BSS. */
873 1.1 nia (void)rsu_disconnect(sc);
874 1.1 nia }
875 1.1 nia switch (cmd->state) {
876 1.1 nia case IEEE80211_S_INIT:
877 1.1 nia break;
878 1.1 nia case IEEE80211_S_SCAN:
879 1.1 nia error = rsu_site_survey(sc);
880 1.1 nia if (error != 0) {
881 1.1 nia printf("%s: could not send site survey command\n",
882 1.1 nia device_xname(sc->sc_dev));
883 1.1 nia }
884 1.1 nia if (ifp->if_flags & IFF_DEBUG)
885 1.1 nia printf("%s: %s -> %s\n", ifp->if_xname,
886 1.1 nia ieee80211_state_name[ic->ic_state],
887 1.1 nia ieee80211_state_name[cmd->state]);
888 1.1 nia ic->ic_state = cmd->state;
889 1.1 nia splx(s);
890 1.1 nia return;
891 1.1 nia case IEEE80211_S_AUTH:
892 1.1 nia ic->ic_state = cmd->state;
893 1.1 nia splx(s);
894 1.1 nia return;
895 1.1 nia case IEEE80211_S_ASSOC:
896 1.1 nia /* No-op for this driver. See rsu_event_join_bss(). */
897 1.1 nia if (ifp->if_flags & IFF_DEBUG)
898 1.1 nia printf("%s: %s -> %s\n", ifp->if_xname,
899 1.1 nia ieee80211_state_name[ic->ic_state],
900 1.1 nia ieee80211_state_name[cmd->state]);
901 1.1 nia ic->ic_state = cmd->state;
902 1.1 nia splx(s);
903 1.1 nia return;
904 1.1 nia case IEEE80211_S_RUN:
905 1.1 nia /* Indicate highest supported rate. */
906 1.1 nia ic->ic_bss->ni_txrate = ic->ic_bss->ni_rates.rs_nrates - 1;
907 1.1 nia
908 1.1 nia /* Start periodic calibration. */
909 1.1 nia callout_schedule(&sc->calib_to, hz);
910 1.1 nia break;
911 1.1 nia }
912 1.1 nia (void)sc->sc_newstate(ic, cmd->state, cmd->arg);
913 1.1 nia splx(s);
914 1.1 nia }
915 1.1 nia
916 1.1 nia int
917 1.1 nia rsu_site_survey(struct rsu_softc *sc)
918 1.1 nia {
919 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
920 1.1 nia struct r92s_fw_cmd_sitesurvey cmd;
921 1.1 nia
922 1.1 nia memset(&cmd, 0, sizeof(cmd));
923 1.1 nia if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->scan_pass == 1)
924 1.1 nia cmd.active = htole32(1);
925 1.1 nia cmd.limit = htole32(48);
926 1.1 nia if (sc->scan_pass == 1) {
927 1.1 nia /* Do a directed scan for second pass. */
928 1.1 nia cmd.ssidlen = htole32(ic->ic_des_esslen);
929 1.1 nia memcpy(cmd.ssid, ic->ic_des_essid, ic->ic_des_esslen);
930 1.1 nia }
931 1.1 nia DPRINTF(("sending site survey command, pass=%d\n", sc->scan_pass));
932 1.1 nia return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
933 1.1 nia }
934 1.1 nia
935 1.1 nia int
936 1.1 nia rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
937 1.1 nia {
938 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
939 1.1 nia struct ndis_wlan_bssid_ex *bss;
940 1.1 nia struct ndis_802_11_fixed_ies *fixed;
941 1.1 nia struct r92s_fw_cmd_auth auth;
942 1.1 nia uint8_t buf[sizeof(*bss) + 128], *frm;
943 1.1 nia uint8_t opmode;
944 1.1 nia int error;
945 1.1 nia
946 1.1 nia /* Let the FW decide the opmode based on the capinfo field. */
947 1.1 nia opmode = NDIS802_11AUTOUNKNOWN;
948 1.1 nia DPRINTF(("setting operating mode to %d\n", opmode));
949 1.1 nia error = rsu_fw_cmd(sc, R92S_CMD_SET_OPMODE, &opmode, sizeof(opmode));
950 1.1 nia if (error != 0)
951 1.1 nia return (error);
952 1.1 nia
953 1.1 nia memset(&auth, 0, sizeof(auth));
954 1.1 nia auth.mode = R92S_AUTHMODE_OPEN;
955 1.1 nia DPRINTF(("setting auth mode to %d\n", auth.mode));
956 1.1 nia error = rsu_fw_cmd(sc, R92S_CMD_SET_AUTH, &auth, sizeof(auth));
957 1.1 nia if (error != 0)
958 1.1 nia return (error);
959 1.1 nia
960 1.1 nia memset(buf, 0, sizeof(buf));
961 1.1 nia bss = (struct ndis_wlan_bssid_ex *)buf;
962 1.1 nia IEEE80211_ADDR_COPY(bss->macaddr, ni->ni_bssid);
963 1.1 nia bss->ssid.ssidlen = htole32(ni->ni_esslen);
964 1.1 nia memcpy(bss->ssid.ssid, ni->ni_essid, ni->ni_esslen);
965 1.1 nia bss->rssi = htole32(ni->ni_rssi);
966 1.1 nia if (ic->ic_curmode == IEEE80211_MODE_11B)
967 1.1 nia bss->networktype = htole32(NDIS802_11DS);
968 1.1 nia else
969 1.1 nia bss->networktype = htole32(NDIS802_11OFDM24);
970 1.1 nia bss->config.len = htole32(sizeof(bss->config));
971 1.1 nia bss->config.bintval = htole32(ni->ni_intval);
972 1.1 nia bss->config.dsconfig = htole32(ieee80211_chan2ieee(ic, ni->ni_chan));
973 1.1 nia bss->inframode = htole32(NDIS802_11INFRASTRUCTURE);
974 1.1 nia memcpy(bss->supprates, ni->ni_rates.rs_rates,
975 1.1 nia ni->ni_rates.rs_nrates);
976 1.1 nia /* Write the fixed fields of the beacon frame. */
977 1.1 nia fixed = (struct ndis_802_11_fixed_ies *)&bss[1];
978 1.1 nia memcpy(&fixed->tstamp, ni->ni_tstamp.data, 8);
979 1.1 nia fixed->bintval = htole16(ni->ni_intval);
980 1.1 nia fixed->capabilities = htole16(ni->ni_capinfo);
981 1.1 nia /* Write IEs to be included in the association request. */
982 1.1 nia frm = (uint8_t *)&fixed[1];
983 1.1 nia bss->ieslen = htole32(frm - (uint8_t *)fixed);
984 1.1 nia bss->len = htole32(((frm - buf) + 3) & ~3);
985 1.1 nia DPRINTF(("sending join bss command to %s chan %d\n",
986 1.1 nia ether_sprintf(bss->macaddr), le32toh(bss->config.dsconfig)));
987 1.1 nia return (rsu_fw_cmd(sc, R92S_CMD_JOIN_BSS, buf, sizeof(buf)));
988 1.1 nia }
989 1.1 nia
990 1.1 nia int
991 1.1 nia rsu_disconnect(struct rsu_softc *sc)
992 1.1 nia {
993 1.1 nia uint32_t zero = 0; /* :-) */
994 1.1 nia
995 1.1 nia /* Disassociate from our current BSS. */
996 1.1 nia DPRINTF(("sending disconnect command\n"));
997 1.1 nia return (rsu_fw_cmd(sc, R92S_CMD_DISCONNECT, &zero, sizeof(zero)));
998 1.1 nia }
999 1.1 nia
1000 1.1 nia void
1001 1.1 nia rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
1002 1.1 nia {
1003 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
1004 1.1 nia struct ieee80211_node *ni;
1005 1.1 nia struct ieee80211_frame *wh;
1006 1.1 nia struct ndis_wlan_bssid_ex *bss;
1007 1.1 nia struct mbuf *m;
1008 1.1 nia uint32_t pktlen, ieslen;
1009 1.1 nia
1010 1.1 nia if (__predict_false(len < sizeof(*bss)))
1011 1.1 nia return;
1012 1.1 nia bss = (struct ndis_wlan_bssid_ex *)buf;
1013 1.1 nia ieslen = le32toh(bss->ieslen);
1014 1.1 nia if (ieslen > len - sizeof(*bss))
1015 1.1 nia return;
1016 1.1 nia
1017 1.1 nia DPRINTFN(2, ("found BSS %s: len=%d chan=%d inframode=%d "
1018 1.1 nia "networktype=%d privacy=%d\n",
1019 1.1 nia ether_sprintf(bss->macaddr), le32toh(bss->len),
1020 1.1 nia le32toh(bss->config.dsconfig), le32toh(bss->inframode),
1021 1.1 nia le32toh(bss->networktype), le32toh(bss->privacy)));
1022 1.1 nia
1023 1.1 nia /* Build a fake beacon frame to let net80211 do all the parsing. */
1024 1.1 nia pktlen = sizeof(*wh) + ieslen;
1025 1.1 nia if (__predict_false(pktlen > MCLBYTES))
1026 1.1 nia return;
1027 1.1 nia MGETHDR(m, M_DONTWAIT, MT_DATA);
1028 1.1 nia if (__predict_false(m == NULL))
1029 1.1 nia return;
1030 1.1 nia if (pktlen > MHLEN) {
1031 1.1 nia MCLGET(m, M_DONTWAIT);
1032 1.1 nia if (!(m->m_flags & M_EXT)) {
1033 1.1 nia m_free(m);
1034 1.1 nia return;
1035 1.1 nia }
1036 1.1 nia }
1037 1.1 nia wh = mtod(m, struct ieee80211_frame *);
1038 1.1 nia wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
1039 1.1 nia IEEE80211_FC0_SUBTYPE_BEACON;
1040 1.1 nia wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
1041 1.1 nia *(uint16_t *)wh->i_dur = 0;
1042 1.1 nia IEEE80211_ADDR_COPY(wh->i_addr1, etherbroadcastaddr);
1043 1.1 nia IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
1044 1.1 nia IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
1045 1.1 nia *(uint16_t *)wh->i_seq = 0;
1046 1.1 nia memcpy(&wh[1], (uint8_t *)&bss[1], ieslen);
1047 1.1 nia
1048 1.1 nia /* Finalize mbuf. */
1049 1.1 nia m->m_pkthdr.len = m->m_len = pktlen;
1050 1.1 nia
1051 1.1 nia ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
1052 1.1 nia ieee80211_input(ic, m, ni, le32toh(bss->rssi), 0);
1053 1.1 nia /* Node is no longer needed. */
1054 1.1 nia ieee80211_free_node(ni);
1055 1.1 nia }
1056 1.1 nia
1057 1.1 nia void
1058 1.1 nia rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
1059 1.1 nia {
1060 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
1061 1.1 nia struct ieee80211_node *ni = ic->ic_bss;
1062 1.1 nia struct r92s_event_join_bss *rsp;
1063 1.1 nia int res;
1064 1.1 nia
1065 1.1 nia if (__predict_false(len < sizeof(*rsp)))
1066 1.1 nia return;
1067 1.1 nia rsp = (struct r92s_event_join_bss *)buf;
1068 1.1 nia res = (int)le32toh(rsp->join_res);
1069 1.1 nia
1070 1.1 nia DPRINTF(("Rx join BSS event len=%d res=%d\n", len, res));
1071 1.1 nia if (res <= 0) {
1072 1.1 nia ic->ic_stats.is_rx_auth_fail++;
1073 1.1 nia ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1074 1.1 nia return;
1075 1.1 nia }
1076 1.1 nia DPRINTF(("associated with %s associd=%d\n",
1077 1.1 nia ether_sprintf(rsp->bss.macaddr), le32toh(rsp->associd)));
1078 1.1 nia
1079 1.1 nia ni->ni_associd = le32toh(rsp->associd) | 0xc000;
1080 1.1 nia
1081 1.1 nia /* Force an ASSOC->RUN transition. AUTH->RUN is invalid. */
1082 1.1 nia ic->ic_state = IEEE80211_S_ASSOC;
1083 1.1 nia ieee80211_new_state(ic, IEEE80211_S_RUN,
1084 1.1 nia IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
1085 1.1 nia }
1086 1.1 nia
1087 1.1 nia void
1088 1.1 nia rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
1089 1.1 nia {
1090 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
1091 1.1 nia struct ifnet *ifp = sc->sc_ic.ic_ifp;
1092 1.1 nia
1093 1.1 nia DPRINTFN(4, ("Rx event code=%d len=%d\n", code, len));
1094 1.1 nia switch (code) {
1095 1.1 nia case R92S_EVT_SURVEY:
1096 1.1 nia if (ic->ic_state == IEEE80211_S_SCAN)
1097 1.1 nia rsu_event_survey(sc, buf, len);
1098 1.1 nia break;
1099 1.1 nia case R92S_EVT_SURVEY_DONE:
1100 1.1 nia DPRINTF(("site survey pass %d done, found %d BSS\n",
1101 1.1 nia sc->scan_pass, le32toh(*(uint32_t *)buf)));
1102 1.1 nia if (ic->ic_state != IEEE80211_S_SCAN)
1103 1.1 nia break; /* Ignore if not scanning. */
1104 1.1 nia if (sc->scan_pass == 0 && ic->ic_des_esslen != 0) {
1105 1.1 nia /* Schedule a directed scan for hidden APs. */
1106 1.1 nia sc->scan_pass = 1;
1107 1.1 nia ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1108 1.1 nia break;
1109 1.1 nia }
1110 1.1 nia sc->scan_pass = 0;
1111 1.1 nia break;
1112 1.1 nia case R92S_EVT_JOIN_BSS:
1113 1.1 nia if (ic->ic_state == IEEE80211_S_AUTH)
1114 1.1 nia rsu_event_join_bss(sc, buf, len);
1115 1.1 nia break;
1116 1.1 nia case R92S_EVT_DEL_STA:
1117 1.1 nia DPRINTF(("disassociated from %s\n", ether_sprintf(buf)));
1118 1.1 nia if (ic->ic_state == IEEE80211_S_RUN &&
1119 1.1 nia IEEE80211_ADDR_EQ(ic->ic_bss->ni_bssid, buf))
1120 1.1 nia ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
1121 1.1 nia break;
1122 1.1 nia case R92S_EVT_WPS_PBC:
1123 1.1 nia DPRINTF(("WPS PBC pushed.\n"));
1124 1.1 nia break;
1125 1.1 nia case R92S_EVT_FWDBG:
1126 1.1 nia if (ifp->if_flags & IFF_DEBUG) {
1127 1.1 nia buf[60] = '\0';
1128 1.1 nia printf("FWDBG: %s\n", (char *)buf);
1129 1.1 nia }
1130 1.1 nia break;
1131 1.1 nia }
1132 1.1 nia }
1133 1.1 nia
1134 1.1 nia void
1135 1.1 nia rsu_rx_multi_event(struct rsu_softc *sc, uint8_t *buf, int len)
1136 1.1 nia {
1137 1.1 nia struct r92s_fw_cmd_hdr *cmd;
1138 1.1 nia int cmdsz;
1139 1.1 nia
1140 1.1 nia DPRINTFN(6, ("Rx events len=%d\n", len));
1141 1.1 nia
1142 1.1 nia /* Skip Rx status. */
1143 1.1 nia buf += sizeof(struct r92s_rx_stat);
1144 1.1 nia len -= sizeof(struct r92s_rx_stat);
1145 1.1 nia
1146 1.1 nia /* Process all events. */
1147 1.1 nia for (;;) {
1148 1.1 nia /* Check that command header fits. */
1149 1.1 nia if (__predict_false(len < sizeof(*cmd)))
1150 1.1 nia break;
1151 1.1 nia cmd = (struct r92s_fw_cmd_hdr *)buf;
1152 1.1 nia /* Check that command payload fits. */
1153 1.1 nia cmdsz = le16toh(cmd->len);
1154 1.1 nia if (__predict_false(len < sizeof(*cmd) + cmdsz))
1155 1.1 nia break;
1156 1.1 nia if (cmdsz > len)
1157 1.1 nia break;
1158 1.1 nia
1159 1.1 nia /* Process firmware event. */
1160 1.1 nia rsu_rx_event(sc, cmd->code, (uint8_t *)&cmd[1], cmdsz);
1161 1.1 nia
1162 1.1 nia if (!(cmd->seq & R92S_FW_CMD_MORE))
1163 1.1 nia break;
1164 1.1 nia buf += sizeof(*cmd) + cmdsz;
1165 1.1 nia len -= sizeof(*cmd) + cmdsz;
1166 1.1 nia }
1167 1.1 nia }
1168 1.1 nia
1169 1.1 nia int8_t
1170 1.1 nia rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
1171 1.1 nia {
1172 1.1 nia static const int8_t cckoff[] = { 14, -2, -20, -40 };
1173 1.1 nia struct r92s_rx_phystat *phy;
1174 1.1 nia struct r92s_rx_cck *cck;
1175 1.1 nia uint8_t rpt;
1176 1.1 nia int8_t rssi;
1177 1.1 nia
1178 1.1 nia if (rate <= 3) {
1179 1.1 nia cck = (struct r92s_rx_cck *)physt;
1180 1.1 nia rpt = (cck->agc_rpt >> 6) & 0x3;
1181 1.1 nia rssi = cck->agc_rpt & 0x3e;
1182 1.1 nia rssi = cckoff[rpt] - rssi;
1183 1.1 nia } else { /* OFDM/HT. */
1184 1.1 nia phy = (struct r92s_rx_phystat *)physt;
1185 1.1 nia rssi = ((le32toh(phy->phydw1) >> 1) & 0x7f) - 106;
1186 1.1 nia }
1187 1.1 nia return (rssi);
1188 1.1 nia }
1189 1.1 nia
1190 1.1 nia void
1191 1.1 nia rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen)
1192 1.1 nia {
1193 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
1194 1.1 nia struct ifnet *ifp = sc->sc_ic.ic_ifp;
1195 1.1 nia struct ieee80211_frame *wh;
1196 1.1 nia struct ieee80211_node *ni;
1197 1.1 nia struct r92s_rx_stat *stat;
1198 1.1 nia uint32_t rxdw0, rxdw3;
1199 1.1 nia struct mbuf *m;
1200 1.1 nia uint8_t rate;
1201 1.1 nia int8_t rssi = 0;
1202 1.1 nia int s, infosz;
1203 1.1 nia
1204 1.1 nia stat = (struct r92s_rx_stat *)buf;
1205 1.1 nia rxdw0 = le32toh(stat->rxdw0);
1206 1.1 nia rxdw3 = le32toh(stat->rxdw3);
1207 1.1 nia
1208 1.1 nia if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
1209 1.1 nia if_statinc(ifp, if_ierrors);
1210 1.1 nia return;
1211 1.1 nia }
1212 1.1 nia if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) {
1213 1.1 nia if_statinc(ifp, if_ierrors);
1214 1.1 nia return;
1215 1.1 nia }
1216 1.1 nia
1217 1.1 nia rate = MS(rxdw3, R92S_RXDW3_RATE);
1218 1.1 nia infosz = MS(rxdw0, R92S_RXDW0_INFOSZ) * 8;
1219 1.1 nia
1220 1.1 nia /* Get RSSI from PHY status descriptor if present. */
1221 1.1 nia if (infosz != 0)
1222 1.1 nia rssi = rsu_get_rssi(sc, rate, &stat[1]);
1223 1.1 nia
1224 1.1 nia DPRINTFN(5, ("Rx frame len=%d rate=%d infosz=%d rssi=%d\n",
1225 1.1 nia pktlen, rate, infosz, rssi));
1226 1.1 nia
1227 1.1 nia MGETHDR(m, M_DONTWAIT, MT_DATA);
1228 1.1 nia if (__predict_false(m == NULL)) {
1229 1.1 nia if_statinc(ifp, if_ierrors);
1230 1.1 nia return;
1231 1.1 nia }
1232 1.1 nia if (pktlen > MHLEN) {
1233 1.1 nia MCLGET(m, M_DONTWAIT);
1234 1.1 nia if (__predict_false(!(m->m_flags & M_EXT))) {
1235 1.1 nia if_statinc(ifp, if_ierrors);
1236 1.1 nia m_freem(m);
1237 1.1 nia return;
1238 1.1 nia }
1239 1.1 nia }
1240 1.1 nia /* Finalize mbuf. */
1241 1.1 nia m_set_rcvif(m, ifp);
1242 1.1 nia
1243 1.1 nia /* Hardware does Rx TCP checksum offload. */
1244 1.1 nia if (rxdw3 & R92S_RXDW3_TCPCHKVALID) {
1245 1.1 nia if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT))
1246 1.1 nia m->m_pkthdr.csum_flags |= M_CSUM_TCPv4;
1247 1.1 nia else
1248 1.1 nia m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
1249 1.1 nia }
1250 1.1 nia wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
1251 1.1 nia memcpy(mtod(m, uint8_t *), wh, pktlen);
1252 1.1 nia m->m_pkthdr.len = m->m_len = pktlen;
1253 1.1 nia
1254 1.1 nia s = splnet();
1255 1.1 nia
1256 1.1 nia ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
1257 1.1 nia ieee80211_input(ic, m, ni, rssi, 0);
1258 1.1 nia /* Node is no longer needed. */
1259 1.1 nia ieee80211_free_node(ni);
1260 1.1 nia splx(s);
1261 1.1 nia }
1262 1.1 nia
1263 1.1 nia void
1264 1.1 nia rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len)
1265 1.1 nia {
1266 1.1 nia struct r92s_rx_stat *stat;
1267 1.1 nia uint32_t rxdw0;
1268 1.1 nia int totlen, pktlen, infosz, npkts;
1269 1.1 nia
1270 1.1 nia /* Get the number of encapsulated frames. */
1271 1.1 nia stat = (struct r92s_rx_stat *)buf;
1272 1.1 nia npkts = MS(le32toh(stat->rxdw2), R92S_RXDW2_PKTCNT);
1273 1.1 nia DPRINTFN(6, ("Rx %d frames in one chunk\n", npkts));
1274 1.1 nia
1275 1.1 nia /* Process all of them. */
1276 1.1 nia while (npkts-- > 0) {
1277 1.1 nia if (__predict_false(len < sizeof(*stat)))
1278 1.1 nia break;
1279 1.1 nia stat = (struct r92s_rx_stat *)buf;
1280 1.1 nia rxdw0 = le32toh(stat->rxdw0);
1281 1.1 nia
1282 1.1 nia pktlen = MS(rxdw0, R92S_RXDW0_PKTLEN);
1283 1.1 nia if (__predict_false(pktlen == 0))
1284 1.1 nia break;
1285 1.1 nia
1286 1.1 nia infosz = MS(rxdw0, R92S_RXDW0_INFOSZ) * 8;
1287 1.1 nia
1288 1.1 nia /* Make sure everything fits in xfer. */
1289 1.1 nia totlen = sizeof(*stat) + infosz + pktlen;
1290 1.1 nia if (__predict_false(totlen > len))
1291 1.1 nia break;
1292 1.1 nia
1293 1.1 nia /* Process 802.11 frame. */
1294 1.1 nia rsu_rx_frame(sc, buf, pktlen);
1295 1.1 nia
1296 1.1 nia /* Next chunk is 128-byte aligned. */
1297 1.1 nia totlen = (totlen + 127) & ~127;
1298 1.1 nia buf += totlen;
1299 1.1 nia len -= totlen;
1300 1.1 nia }
1301 1.1 nia }
1302 1.1 nia
1303 1.1 nia void
1304 1.1 nia rsu_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1305 1.1 nia {
1306 1.1 nia struct rsu_rx_data *data = priv;
1307 1.1 nia struct rsu_softc *sc = data->sc;
1308 1.1 nia struct r92s_rx_stat *stat;
1309 1.1 nia struct ifnet *ifp = sc->sc_ic.ic_ifp;
1310 1.1 nia int len;
1311 1.1 nia
1312 1.1 nia if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1313 1.1 nia DPRINTF(("RX status=%d\n", status));
1314 1.1 nia if (status == USBD_STALLED)
1315 1.1 nia usbd_clear_endpoint_stall_async(data->pipe);
1316 1.1 nia if (status != USBD_CANCELLED)
1317 1.1 nia goto resubmit;
1318 1.1 nia return;
1319 1.1 nia }
1320 1.1 nia usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
1321 1.1 nia
1322 1.1 nia if (__predict_false(len < sizeof(*stat))) {
1323 1.1 nia DPRINTF(("xfer too short %d\n", len));
1324 1.1 nia if_statinc(ifp, if_ierrors);
1325 1.1 nia goto resubmit;
1326 1.1 nia }
1327 1.1 nia if (len > RSU_RXBUFSZ) {
1328 1.1 nia DPRINTF(("xfer too large %d\n", len));
1329 1.1 nia if_statinc(ifp, if_ierrors);
1330 1.1 nia goto resubmit;
1331 1.1 nia }
1332 1.1 nia
1333 1.1 nia /* Determine if it is a firmware C2H event or an 802.11 frame. */
1334 1.1 nia stat = (struct r92s_rx_stat *)data->buf;
1335 1.1 nia if ((le32toh(stat->rxdw1) & 0x1ff) == 0x1ff)
1336 1.1 nia rsu_rx_multi_event(sc, data->buf, len);
1337 1.1 nia else
1338 1.1 nia rsu_rx_multi_frame(sc, data->buf, len);
1339 1.1 nia
1340 1.1 nia resubmit:
1341 1.1 nia /* Setup a new transfer. */
1342 1.1 nia usbd_setup_xfer(xfer, data, data->buf, RSU_RXBUFSZ,
1343 1.1 nia USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rsu_rxeof);
1344 1.1 nia (void)usbd_transfer(xfer);
1345 1.1 nia }
1346 1.1 nia
1347 1.1 nia void
1348 1.1 nia rsu_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1349 1.1 nia {
1350 1.1 nia struct rsu_tx_data *data = priv;
1351 1.1 nia struct rsu_softc *sc = data->sc;
1352 1.1 nia struct ifnet *ifp = sc->sc_ic.ic_ifp;
1353 1.1 nia int s;
1354 1.1 nia
1355 1.1 nia s = splnet();
1356 1.1 nia
1357 1.1 nia /* Put this Tx buffer back to our free list. */
1358 1.1 nia mutex_enter(&sc->sc_tx_mtx);
1359 1.1 nia TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
1360 1.1 nia mutex_exit(&sc->sc_tx_mtx);
1361 1.1 nia
1362 1.1 nia if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
1363 1.1 nia if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1364 1.1 nia return;
1365 1.1 nia
1366 1.1 nia DPRINTF(("TX status=%d\n", status));
1367 1.1 nia if (status == USBD_STALLED)
1368 1.1 nia usbd_clear_endpoint_stall_async(data->pipe);
1369 1.1 nia if_statinc(ifp, if_oerrors);
1370 1.1 nia splx(s);
1371 1.1 nia return;
1372 1.1 nia }
1373 1.1 nia sc->sc_tx_timer = 0;
1374 1.1 nia
1375 1.1 nia /* We just released a Tx buffer, notify Tx. */
1376 1.1 nia if (ifp->if_flags & IFF_OACTIVE) {
1377 1.1 nia ifp->if_flags &= ~IFF_OACTIVE;
1378 1.1 nia rsu_start(ifp);
1379 1.1 nia }
1380 1.1 nia splx(s);
1381 1.1 nia }
1382 1.1 nia
1383 1.1 nia int
1384 1.1 nia rsu_tx(struct rsu_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
1385 1.1 nia {
1386 1.1 nia struct ieee80211_frame *wh;
1387 1.1 nia struct rsu_tx_data *data;
1388 1.1 nia struct r92s_tx_desc *txd;
1389 1.1 nia struct usbd_pipe *pipe;
1390 1.1 nia uint16_t qos;
1391 1.1 nia uint8_t qid, tid = 0;
1392 1.1 nia int hasqos, xferlen, error;
1393 1.1 nia
1394 1.1 nia wh = mtod(m, struct ieee80211_frame *);
1395 1.1 nia
1396 1.1 nia #ifdef notyet
1397 1.1 nia if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1398 1.1 nia k = ieee80211_get_txkey(ic, wh, ni);
1399 1.1 nia if ((m = ieee80211_encrypt(ic, m, k)) == NULL)
1400 1.1 nia return (ENOBUFS);
1401 1.1 nia wh = mtod(m, struct ieee80211_frame *);
1402 1.1 nia }
1403 1.1 nia #endif
1404 1.1 nia
1405 1.1 nia if ((hasqos = ieee80211_has_qos(wh))) {
1406 1.1 nia qos = ieee80211_get_qos(wh);
1407 1.1 nia tid = qos & IEEE80211_QOS_TID;
1408 1.1 nia qid = rsu_ac2qid[TID_TO_WME_AC(tid)];
1409 1.1 nia } else
1410 1.1 nia qid = RSU_QID_BE;
1411 1.1 nia
1412 1.1 nia /* Get the USB pipe to use for this queue id. */
1413 1.1 nia pipe = sc->pipe[sc->qid2idx[qid]];
1414 1.1 nia
1415 1.1 nia /* Grab a Tx buffer from our free list. */
1416 1.1 nia mutex_enter(&sc->sc_tx_mtx);
1417 1.1 nia data = TAILQ_FIRST(&sc->tx_free_list);
1418 1.1 nia TAILQ_REMOVE(&sc->tx_free_list, data, next);
1419 1.1 nia mutex_exit(&sc->sc_tx_mtx);
1420 1.1 nia
1421 1.1 nia /* Fill Tx descriptor. */
1422 1.1 nia txd = (struct r92s_tx_desc *)data->buf;
1423 1.1 nia memset(txd, 0, sizeof(*txd));
1424 1.1 nia
1425 1.1 nia txd->txdw0 |= htole32(
1426 1.1 nia SM(R92S_TXDW0_PKTLEN, m->m_pkthdr.len) |
1427 1.1 nia SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |
1428 1.1 nia R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG);
1429 1.1 nia
1430 1.1 nia txd->txdw1 |= htole32(
1431 1.1 nia SM(R92S_TXDW1_MACID, R92S_MACID_BSS) |
1432 1.1 nia SM(R92S_TXDW1_QSEL, R92S_TXDW1_QSEL_BE));
1433 1.1 nia if (!hasqos)
1434 1.1 nia txd->txdw1 |= htole32(R92S_TXDW1_NONQOS);
1435 1.1 nia #ifdef notyet
1436 1.1 nia if (k != NULL) {
1437 1.1 nia switch (k->k_cipher) {
1438 1.1 nia case IEEE80211_CIPHER_WEP:
1439 1.1 nia k->wk_flags |= IEEE80211_KEY_GROUP; /* XXX */
1440 1.1 nia if (k->wk_keylen == 5)
1441 1.1 nia mode = RT2860_MODE_WEP40;
1442 1.1 nia else
1443 1.1 nia mode = RT2860_MODE_WEP104;
1444 1.1 nia break;
1445 1.1 nia case IEEE80211_CIPHER_TKIP:
1446 1.1 nia cipher = R92S_TXDW1_CIPHER_TKIP;
1447 1.1 nia break;
1448 1.1 nia case IEEE80211_CIPHER_AES_CCM:
1449 1.1 nia cipher = R92S_TXDW1_CIPHER_AES;
1450 1.1 nia break;
1451 1.1 nia default:
1452 1.1 nia cipher = R92S_TXDW1_CIPHER_NONE;
1453 1.1 nia }
1454 1.1 nia txd->txdw1 |= htole32(
1455 1.1 nia SM(R92S_TXDW1_CIPHER, cipher) |
1456 1.1 nia SM(R92S_TXDW1_KEYIDX, k->k_id));
1457 1.1 nia }
1458 1.1 nia #endif
1459 1.1 nia txd->txdw2 |= htole32(R92S_TXDW2_BK);
1460 1.1 nia if (IEEE80211_IS_MULTICAST(wh->i_addr1))
1461 1.1 nia txd->txdw2 |= htole32(R92S_TXDW2_BMCAST);
1462 1.1 nia /*
1463 1.1 nia * Firmware will use and increment the sequence number for the
1464 1.1 nia * specified TID.
1465 1.1 nia */
1466 1.1 nia txd->txdw3 |= htole32(SM(R92S_TXDW3_SEQ, tid));
1467 1.1 nia
1468 1.1 nia xferlen = sizeof(*txd) + m->m_pkthdr.len;
1469 1.1 nia m_copydata(m, 0, m->m_pkthdr.len, &txd[1]);
1470 1.1 nia m_freem(m);
1471 1.1 nia
1472 1.1 nia data->pipe = pipe;
1473 1.1 nia usbd_setup_xfer(data->xfer, data, data->buf, xferlen,
1474 1.1 nia USBD_FORCE_SHORT_XFER, RSU_TX_TIMEOUT,
1475 1.1 nia rsu_txeof);
1476 1.1 nia error = usbd_transfer(data->xfer);
1477 1.1 nia if (__predict_false(error != USBD_IN_PROGRESS && error != 0)) {
1478 1.1 nia /* Put this Tx buffer back to our free list. */
1479 1.1 nia mutex_enter(&sc->sc_tx_mtx);
1480 1.1 nia TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
1481 1.1 nia mutex_exit(&sc->sc_tx_mtx);
1482 1.1 nia return (error);
1483 1.1 nia }
1484 1.1 nia ieee80211_free_node(ni);
1485 1.1 nia return (0);
1486 1.1 nia }
1487 1.1 nia
1488 1.1 nia void
1489 1.1 nia rsu_start(struct ifnet *ifp)
1490 1.1 nia {
1491 1.1 nia struct rsu_softc *sc = ifp->if_softc;
1492 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
1493 1.1 nia struct ether_header *eh;
1494 1.1 nia struct ieee80211_node *ni;
1495 1.1 nia struct mbuf *m;
1496 1.1 nia
1497 1.1 nia if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1498 1.1 nia return;
1499 1.1 nia
1500 1.1 nia for (;;) {
1501 1.1 nia if (TAILQ_EMPTY(&sc->tx_free_list)) {
1502 1.1 nia ifp->if_flags |= IFF_OACTIVE;
1503 1.1 nia break;
1504 1.1 nia }
1505 1.1 nia if (ic->ic_state != IEEE80211_S_RUN)
1506 1.1 nia break;
1507 1.1 nia
1508 1.1 nia /* Encapsulate and send data frames. */
1509 1.1 nia IFQ_DEQUEUE(&ifp->if_snd, m);
1510 1.1 nia if (m == NULL)
1511 1.1 nia break;
1512 1.1 nia
1513 1.1 nia eh = mtod(m, struct ether_header *);
1514 1.1 nia ni = ieee80211_find_txnode(ic, eh->ether_dhost);
1515 1.1 nia if (ni == NULL) {
1516 1.1 nia m_freem(m);
1517 1.1 nia if_statinc(ifp, if_oerrors);
1518 1.1 nia continue;
1519 1.1 nia }
1520 1.1 nia
1521 1.1 nia if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
1522 1.1 nia ieee80211_free_node(ni);
1523 1.1 nia if_statinc(ifp, if_oerrors);
1524 1.1 nia continue;
1525 1.1 nia }
1526 1.1 nia
1527 1.1 nia if (rsu_tx(sc, m, ni) != 0) {
1528 1.1 nia ieee80211_free_node(ni);
1529 1.1 nia if_statinc(ifp, if_oerrors);
1530 1.1 nia continue;
1531 1.1 nia }
1532 1.1 nia
1533 1.1 nia sc->sc_tx_timer = 5;
1534 1.1 nia ifp->if_timer = 1;
1535 1.1 nia }
1536 1.1 nia }
1537 1.1 nia
1538 1.1 nia void
1539 1.1 nia rsu_watchdog(struct ifnet *ifp)
1540 1.1 nia {
1541 1.1 nia struct rsu_softc *sc = ifp->if_softc;
1542 1.1 nia
1543 1.1 nia ifp->if_timer = 0;
1544 1.1 nia
1545 1.1 nia if (sc->sc_tx_timer > 0) {
1546 1.1 nia if (--sc->sc_tx_timer == 0) {
1547 1.1 nia printf("%s: device timeout\n",
1548 1.1 nia device_xname(sc->sc_dev));
1549 1.1 nia /* rsu_init(ifp); XXX needs a process context! */
1550 1.1 nia if_statinc(ifp, if_oerrors);
1551 1.1 nia return;
1552 1.1 nia }
1553 1.1 nia ifp->if_timer = 1;
1554 1.1 nia }
1555 1.1 nia ieee80211_watchdog(&sc->sc_ic);
1556 1.1 nia }
1557 1.1 nia
1558 1.1 nia int
1559 1.1 nia rsu_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1560 1.1 nia {
1561 1.1 nia struct rsu_softc *sc = ifp->if_softc;
1562 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
1563 1.1 nia int s, error = 0;
1564 1.1 nia
1565 1.1 nia s = splnet();
1566 1.1 nia
1567 1.1 nia switch (cmd) {
1568 1.1 nia case SIOCSIFADDR:
1569 1.1 nia ifp->if_flags |= IFF_UP;
1570 1.1 nia /* FALLTHROUGH */
1571 1.1 nia case SIOCSIFFLAGS:
1572 1.1 nia switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
1573 1.1 nia case IFF_UP|IFF_RUNNING:
1574 1.1 nia break;
1575 1.1 nia case IFF_UP:
1576 1.1 nia rsu_init(ifp);
1577 1.1 nia break;
1578 1.1 nia case IFF_RUNNING:
1579 1.1 nia rsu_stop(ifp);
1580 1.1 nia break;
1581 1.1 nia case 0:
1582 1.1 nia break;
1583 1.1 nia }
1584 1.1 nia break;
1585 1.1 nia default:
1586 1.1 nia error = ieee80211_ioctl(ic, cmd, data);
1587 1.1 nia }
1588 1.1 nia
1589 1.1 nia if (error == ENETRESET) {
1590 1.1 nia if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
1591 1.1 nia (IFF_UP | IFF_RUNNING)) {
1592 1.1 nia rsu_stop(ifp);
1593 1.1 nia rsu_init(ifp);
1594 1.1 nia }
1595 1.1 nia error = 0;
1596 1.1 nia }
1597 1.1 nia splx(s);
1598 1.1 nia
1599 1.1 nia return (error);
1600 1.1 nia }
1601 1.1 nia
1602 1.1 nia /*
1603 1.1 nia * Power on sequence for A-cut adapters.
1604 1.1 nia */
1605 1.1 nia void
1606 1.1 nia rsu_power_on_acut(struct rsu_softc *sc)
1607 1.1 nia {
1608 1.1 nia uint32_t reg;
1609 1.1 nia
1610 1.1 nia rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x53);
1611 1.1 nia rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x57);
1612 1.1 nia
1613 1.1 nia /* Enable AFE macro block's bandgap and Mbias. */
1614 1.1 nia rsu_write_1(sc, R92S_AFE_MISC,
1615 1.1 nia rsu_read_1(sc, R92S_AFE_MISC) |
1616 1.1 nia R92S_AFE_MISC_BGEN | R92S_AFE_MISC_MBEN);
1617 1.1 nia /* Enable LDOA15 block. */
1618 1.1 nia rsu_write_1(sc, R92S_LDOA15_CTRL,
1619 1.1 nia rsu_read_1(sc, R92S_LDOA15_CTRL) | R92S_LDA15_EN);
1620 1.1 nia
1621 1.1 nia rsu_write_1(sc, R92S_SPS1_CTRL,
1622 1.1 nia rsu_read_1(sc, R92S_SPS1_CTRL) | R92S_SPS1_LDEN);
1623 1.1 nia usbd_delay_ms(sc->sc_udev, 2);
1624 1.1 nia /* Enable switch regulator block. */
1625 1.1 nia rsu_write_1(sc, R92S_SPS1_CTRL,
1626 1.1 nia rsu_read_1(sc, R92S_SPS1_CTRL) | R92S_SPS1_SWEN);
1627 1.1 nia
1628 1.1 nia rsu_write_4(sc, R92S_SPS1_CTRL, 0x00a7b267);
1629 1.1 nia
1630 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
1631 1.1 nia rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) | 0x08);
1632 1.1 nia
1633 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1634 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x20);
1635 1.1 nia
1636 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
1637 1.1 nia rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) & ~0x90);
1638 1.1 nia
1639 1.1 nia /* Enable AFE clock. */
1640 1.1 nia rsu_write_1(sc, R92S_AFE_XTAL_CTRL + 1,
1641 1.1 nia rsu_read_1(sc, R92S_AFE_XTAL_CTRL + 1) & ~0x04);
1642 1.1 nia /* Enable AFE PLL macro block. */
1643 1.1 nia rsu_write_1(sc, R92S_AFE_PLL_CTRL,
1644 1.1 nia rsu_read_1(sc, R92S_AFE_PLL_CTRL) | 0x11);
1645 1.1 nia /* Attach AFE PLL to MACTOP/BB. */
1646 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL,
1647 1.1 nia rsu_read_1(sc, R92S_SYS_ISO_CTRL) & ~0x11);
1648 1.1 nia
1649 1.1 nia /* Switch to 40MHz clock instead of 80MHz. */
1650 1.1 nia rsu_write_2(sc, R92S_SYS_CLKR,
1651 1.1 nia rsu_read_2(sc, R92S_SYS_CLKR) & ~R92S_SYS_CLKSEL);
1652 1.1 nia
1653 1.1 nia /* Enable MAC clock. */
1654 1.1 nia rsu_write_2(sc, R92S_SYS_CLKR,
1655 1.1 nia rsu_read_2(sc, R92S_SYS_CLKR) |
1656 1.1 nia R92S_MAC_CLK_EN | R92S_SYS_CLK_EN);
1657 1.1 nia
1658 1.1 nia rsu_write_1(sc, R92S_PMC_FSM, 0x02);
1659 1.1 nia
1660 1.1 nia /* Enable digital core and IOREG R/W. */
1661 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1662 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x08);
1663 1.1 nia
1664 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1665 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x80);
1666 1.1 nia
1667 1.1 nia /* Switch the control path to firmware. */
1668 1.1 nia reg = rsu_read_2(sc, R92S_SYS_CLKR);
1669 1.1 nia reg = (reg & ~R92S_SWHW_SEL) | R92S_FWHW_SEL;
1670 1.1 nia rsu_write_2(sc, R92S_SYS_CLKR, reg);
1671 1.1 nia
1672 1.1 nia rsu_write_2(sc, R92S_CR, 0x37fc);
1673 1.1 nia
1674 1.1 nia /* Fix USB RX FIFO issue. */
1675 1.1 nia rsu_write_1(sc, 0xfe5c,
1676 1.1 nia rsu_read_1(sc, 0xfe5c) | 0x80);
1677 1.1 nia rsu_write_1(sc, 0x00ab,
1678 1.1 nia rsu_read_1(sc, 0x00ab) | 0xc0);
1679 1.1 nia
1680 1.1 nia rsu_write_1(sc, R92S_SYS_CLKR,
1681 1.1 nia rsu_read_1(sc, R92S_SYS_CLKR) & ~R92S_SYS_CPU_CLKSEL);
1682 1.1 nia }
1683 1.1 nia
1684 1.1 nia /*
1685 1.1 nia * Power on sequence for B-cut and C-cut adapters.
1686 1.1 nia */
1687 1.1 nia void
1688 1.1 nia rsu_power_on_bcut(struct rsu_softc *sc)
1689 1.1 nia {
1690 1.1 nia uint32_t reg;
1691 1.1 nia int ntries;
1692 1.1 nia
1693 1.1 nia /* Prevent eFuse leakage. */
1694 1.1 nia rsu_write_1(sc, 0x37, 0xb0);
1695 1.1 nia usbd_delay_ms(sc->sc_udev, 10);
1696 1.1 nia rsu_write_1(sc, 0x37, 0x30);
1697 1.1 nia
1698 1.1 nia /* Switch the control path to hardware. */
1699 1.1 nia reg = rsu_read_2(sc, R92S_SYS_CLKR);
1700 1.1 nia if (reg & R92S_FWHW_SEL) {
1701 1.1 nia rsu_write_2(sc, R92S_SYS_CLKR,
1702 1.1 nia reg & ~(R92S_SWHW_SEL | R92S_FWHW_SEL));
1703 1.1 nia }
1704 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1705 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) & ~0x8c);
1706 1.1 nia usbd_delay_ms(sc->sc_udev, 10);
1707 1.1 nia
1708 1.1 nia rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x53);
1709 1.1 nia rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x57);
1710 1.1 nia
1711 1.1 nia reg = rsu_read_1(sc, R92S_AFE_MISC);
1712 1.1 nia rsu_write_1(sc, R92S_AFE_MISC, reg | R92S_AFE_MISC_BGEN);
1713 1.1 nia rsu_write_1(sc, R92S_AFE_MISC, reg | R92S_AFE_MISC_BGEN |
1714 1.1 nia R92S_AFE_MISC_MBEN | R92S_AFE_MISC_I32_EN);
1715 1.1 nia
1716 1.1 nia /* Enable PLL. */
1717 1.1 nia rsu_write_1(sc, R92S_LDOA15_CTRL,
1718 1.1 nia rsu_read_1(sc, R92S_LDOA15_CTRL) | R92S_LDA15_EN);
1719 1.1 nia
1720 1.1 nia rsu_write_1(sc, R92S_LDOV12D_CTRL,
1721 1.1 nia rsu_read_1(sc, R92S_LDOV12D_CTRL) | R92S_LDV12_EN);
1722 1.1 nia
1723 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
1724 1.1 nia rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) | 0x08);
1725 1.1 nia
1726 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1727 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x20);
1728 1.1 nia
1729 1.1 nia /* Support 64KB IMEM. */
1730 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
1731 1.1 nia rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) & ~0x97);
1732 1.1 nia
1733 1.1 nia /* Enable AFE clock. */
1734 1.1 nia rsu_write_1(sc, R92S_AFE_XTAL_CTRL + 1,
1735 1.1 nia rsu_read_1(sc, R92S_AFE_XTAL_CTRL + 1) & ~0x04);
1736 1.1 nia /* Enable AFE PLL macro block. */
1737 1.1 nia reg = rsu_read_1(sc, R92S_AFE_PLL_CTRL);
1738 1.1 nia rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x11);
1739 1.1 nia usbd_delay_ms(sc->sc_udev, 5);
1740 1.1 nia rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x51);
1741 1.1 nia usbd_delay_ms(sc->sc_udev, 5);
1742 1.1 nia rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x11);
1743 1.1 nia usbd_delay_ms(sc->sc_udev, 5);
1744 1.1 nia
1745 1.1 nia /* Attach AFE PLL to MACTOP/BB. */
1746 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL,
1747 1.1 nia rsu_read_1(sc, R92S_SYS_ISO_CTRL) & ~0x11);
1748 1.1 nia
1749 1.1 nia /* Switch to 40MHz clock. */
1750 1.1 nia rsu_write_1(sc, R92S_SYS_CLKR, 0x00);
1751 1.1 nia /* Disable CPU clock and 80MHz SSC. */
1752 1.1 nia rsu_write_1(sc, R92S_SYS_CLKR,
1753 1.1 nia rsu_read_1(sc, R92S_SYS_CLKR) | 0xa0);
1754 1.1 nia /* Enable MAC clock. */
1755 1.1 nia rsu_write_2(sc, R92S_SYS_CLKR,
1756 1.1 nia rsu_read_2(sc, R92S_SYS_CLKR) |
1757 1.1 nia R92S_MAC_CLK_EN | R92S_SYS_CLK_EN);
1758 1.1 nia
1759 1.1 nia rsu_write_1(sc, R92S_PMC_FSM, 0x02);
1760 1.1 nia
1761 1.1 nia /* Enable digital core and IOREG R/W. */
1762 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1763 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x08);
1764 1.1 nia
1765 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
1766 1.1 nia rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x80);
1767 1.1 nia
1768 1.1 nia /* Switch the control path to firmware. */
1769 1.1 nia reg = rsu_read_2(sc, R92S_SYS_CLKR);
1770 1.1 nia reg = (reg & ~R92S_SWHW_SEL) | R92S_FWHW_SEL;
1771 1.1 nia rsu_write_2(sc, R92S_SYS_CLKR, reg);
1772 1.1 nia
1773 1.1 nia rsu_write_2(sc, R92S_CR, 0x37fc);
1774 1.1 nia
1775 1.1 nia /* Fix USB RX FIFO issue. */
1776 1.1 nia rsu_write_1(sc, 0xfe5c,
1777 1.1 nia rsu_read_1(sc, 0xfe5c) | 0x80);
1778 1.1 nia
1779 1.1 nia rsu_write_1(sc, R92S_SYS_CLKR,
1780 1.1 nia rsu_read_1(sc, R92S_SYS_CLKR) & ~R92S_SYS_CPU_CLKSEL);
1781 1.1 nia
1782 1.1 nia rsu_write_1(sc, 0xfe1c, 0x80);
1783 1.1 nia
1784 1.1 nia /* Make sure TxDMA is ready to download firmware. */
1785 1.1 nia for (ntries = 0; ntries < 20; ntries++) {
1786 1.1 nia reg = rsu_read_1(sc, R92S_TCR);
1787 1.1 nia if ((reg & (R92S_TCR_IMEM_CHK_RPT | R92S_TCR_EMEM_CHK_RPT)) ==
1788 1.1 nia (R92S_TCR_IMEM_CHK_RPT | R92S_TCR_EMEM_CHK_RPT))
1789 1.1 nia break;
1790 1.1 nia DELAY(5);
1791 1.1 nia }
1792 1.1 nia if (ntries == 20) {
1793 1.1 nia /* Reset TxDMA. */
1794 1.1 nia reg = rsu_read_1(sc, R92S_CR);
1795 1.1 nia rsu_write_1(sc, R92S_CR, reg & ~R92S_CR_TXDMA_EN);
1796 1.1 nia DELAY(2);
1797 1.1 nia rsu_write_1(sc, R92S_CR, reg | R92S_CR_TXDMA_EN);
1798 1.1 nia }
1799 1.1 nia }
1800 1.1 nia
1801 1.1 nia void
1802 1.1 nia rsu_power_off(struct rsu_softc *sc)
1803 1.1 nia {
1804 1.1 nia /* Turn RF off. */
1805 1.1 nia rsu_write_1(sc, R92S_RF_CTRL, 0x00);
1806 1.1 nia usbd_delay_ms(sc->sc_udev, 5);
1807 1.1 nia
1808 1.1 nia /* Turn MAC off. */
1809 1.1 nia /* Switch control path. */
1810 1.1 nia rsu_write_1(sc, R92S_SYS_CLKR + 1, 0x38);
1811 1.1 nia /* Reset MACTOP. */
1812 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1, 0x70);
1813 1.1 nia rsu_write_1(sc, R92S_PMC_FSM, 0x06);
1814 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL + 0, 0xf9);
1815 1.1 nia rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1, 0xe8);
1816 1.1 nia
1817 1.1 nia /* Disable AFE PLL. */
1818 1.1 nia rsu_write_1(sc, R92S_AFE_PLL_CTRL, 0x00);
1819 1.1 nia /* Disable A15V. */
1820 1.1 nia rsu_write_1(sc, R92S_LDOA15_CTRL, 0x54);
1821 1.1 nia /* Disable eFuse 1.2V. */
1822 1.1 nia rsu_write_1(sc, R92S_SYS_FUNC_EN + 1, 0x50);
1823 1.1 nia rsu_write_1(sc, R92S_LDOV12D_CTRL, 0x24);
1824 1.1 nia /* Enable AFE macro block's bandgap and Mbias. */
1825 1.1 nia rsu_write_1(sc, R92S_AFE_MISC, 0x30);
1826 1.1 nia /* Disable 1.6V LDO. */
1827 1.1 nia rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x56);
1828 1.1 nia rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x43);
1829 1.1 nia }
1830 1.1 nia
1831 1.1 nia int
1832 1.1 nia rsu_fw_loadsection(struct rsu_softc *sc, uint8_t *buf, int len)
1833 1.1 nia {
1834 1.1 nia struct rsu_tx_data *data;
1835 1.1 nia struct r92s_tx_desc *txd;
1836 1.1 nia /*struct usbd_pipe *pipe;*/
1837 1.1 nia int mlen, error;
1838 1.1 nia
1839 1.1 nia data = sc->fwcmd_data;
1840 1.1 nia /*pipe = sc->pipe[sc->qid2idx[RSU_QID_VO]];*/
1841 1.1 nia txd = (struct r92s_tx_desc *)data->buf;
1842 1.1 nia while (len > 0) {
1843 1.1 nia memset(txd, 0, sizeof(*txd));
1844 1.1 nia if (len <= RSU_TXBUFSZ - sizeof(*txd)) {
1845 1.1 nia /* Last chunk. */
1846 1.1 nia txd->txdw0 |= htole32(R92S_TXDW0_LINIP);
1847 1.1 nia mlen = len;
1848 1.1 nia } else
1849 1.1 nia mlen = RSU_TXBUFSZ - sizeof(*txd);
1850 1.1 nia txd->txdw0 |= htole32(SM(R92S_TXDW0_PKTLEN, mlen));
1851 1.1 nia memcpy(&txd[1], buf, mlen);
1852 1.1 nia
1853 1.1 nia usbd_setup_xfer(data->xfer, data, data->buf,
1854 1.1 nia sizeof(*txd) + mlen,
1855 1.1 nia USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS,
1856 1.1 nia RSU_TX_TIMEOUT, NULL);
1857 1.1 nia error = usbd_transfer(data->xfer);
1858 1.1 nia if (error != 0)
1859 1.1 nia return (error);
1860 1.1 nia buf += mlen;
1861 1.1 nia len -= mlen;
1862 1.1 nia }
1863 1.1 nia return (0);
1864 1.1 nia }
1865 1.1 nia
1866 1.1 nia int
1867 1.1 nia rsu_load_firmware(struct rsu_softc *sc)
1868 1.1 nia {
1869 1.1 nia struct r92s_fw_hdr *hdr;
1870 1.1 nia struct r92s_fw_priv *dmem;
1871 1.1 nia uint8_t *imem, *emem;
1872 1.1 nia int imemsz, ememsz;
1873 1.1 nia u_char *fw;
1874 1.1 nia size_t size;
1875 1.1 nia uint32_t reg;
1876 1.1 nia int ntries, error;
1877 1.1 nia firmware_handle_t fh;
1878 1.1 nia
1879 1.1 nia if ((error = firmware_open("rsu", "rsu-rtl8712", &fh)) != 0) {
1880 1.1 nia printf("%s: failed firmware_open of file %s (error %d)\n",
1881 1.1 nia device_xname(sc->sc_dev), "rsu-rtl8712", error);
1882 1.1 nia return error;
1883 1.1 nia }
1884 1.1 nia
1885 1.1 nia size = firmware_get_size(fh);
1886 1.1 nia if ((fw = firmware_malloc(size)) == NULL) {
1887 1.1 nia firmware_close(fh);
1888 1.1 nia return ENOMEM;
1889 1.1 nia }
1890 1.1 nia
1891 1.1 nia if ((error = firmware_read(fh, 0, fw, size)) != 0) {
1892 1.1 nia firmware_close(fh);
1893 1.1 nia goto fail;
1894 1.1 nia }
1895 1.1 nia
1896 1.1 nia firmware_close(fh);
1897 1.1 nia
1898 1.1 nia if (size < sizeof(*hdr)) {
1899 1.1 nia printf("%s: firmware too short\n", device_xname(sc->sc_dev));
1900 1.1 nia error = EINVAL;
1901 1.1 nia goto fail;
1902 1.1 nia }
1903 1.1 nia
1904 1.1 nia hdr = (struct r92s_fw_hdr *)fw;
1905 1.1 nia if (hdr->signature != htole16(0x8712) &&
1906 1.1 nia hdr->signature != htole16(0x8192)) {
1907 1.1 nia printf("%s: invalid firmware signature 0x%x\n",
1908 1.1 nia device_xname(sc->sc_dev), le16toh(hdr->signature));
1909 1.1 nia error = EINVAL;
1910 1.1 nia goto fail;
1911 1.1 nia }
1912 1.1 nia DPRINTF(("FW V%d %02x-%02x %02x:%02x\n", le16toh(hdr->version),
1913 1.1 nia hdr->month, hdr->day, hdr->hour, hdr->minute));
1914 1.1 nia
1915 1.1 nia /* Make sure that driver and firmware are in sync. */
1916 1.1 nia if (hdr->privsz != htole32(sizeof(*dmem))) {
1917 1.1 nia printf("%s: unsupported firmware image\n",
1918 1.1 nia device_xname(sc->sc_dev));
1919 1.1 nia error = EINVAL;
1920 1.1 nia goto fail;
1921 1.1 nia }
1922 1.1 nia /* Get FW sections sizes. */
1923 1.1 nia imemsz = le32toh(hdr->imemsz);
1924 1.1 nia ememsz = le32toh(hdr->sramsz);
1925 1.1 nia /* Check that all FW sections fit in image. */
1926 1.1 nia if (size < sizeof(*hdr) + imemsz + ememsz) {
1927 1.1 nia printf("%s: firmware too short\n", device_xname(sc->sc_dev));
1928 1.1 nia error = EINVAL;
1929 1.1 nia goto fail;
1930 1.1 nia }
1931 1.1 nia imem = (uint8_t *)&hdr[1];
1932 1.1 nia emem = imem + imemsz;
1933 1.1 nia
1934 1.1 nia /* Load IMEM section. */
1935 1.1 nia error = rsu_fw_loadsection(sc, imem, imemsz);
1936 1.1 nia if (error != 0) {
1937 1.1 nia printf("%s: could not load firmware section %s\n",
1938 1.1 nia device_xname(sc->sc_dev), "IMEM");
1939 1.1 nia goto fail;
1940 1.1 nia }
1941 1.1 nia /* Wait for load to complete. */
1942 1.1 nia for (ntries = 0; ntries < 10; ntries++) {
1943 1.1 nia reg = rsu_read_2(sc, R92S_TCR);
1944 1.1 nia if (reg & R92S_TCR_IMEM_CODE_DONE)
1945 1.1 nia break;
1946 1.1 nia DELAY(10);
1947 1.1 nia }
1948 1.1 nia if (ntries == 10 || !(reg & R92S_TCR_IMEM_CHK_RPT)) {
1949 1.1 nia printf("%s: timeout waiting for %s transfer\n",
1950 1.1 nia device_xname(sc->sc_dev), "IMEM");
1951 1.1 nia error = ETIMEDOUT;
1952 1.1 nia goto fail;
1953 1.1 nia }
1954 1.1 nia
1955 1.1 nia /* Load EMEM section. */
1956 1.1 nia error = rsu_fw_loadsection(sc, emem, ememsz);
1957 1.1 nia if (error != 0) {
1958 1.1 nia printf("%s: could not load firmware section %s\n",
1959 1.1 nia device_xname(sc->sc_dev), "EMEM");
1960 1.1 nia goto fail;
1961 1.1 nia }
1962 1.1 nia /* Wait for load to complete. */
1963 1.1 nia for (ntries = 0; ntries < 10; ntries++) {
1964 1.1 nia reg = rsu_read_2(sc, R92S_TCR);
1965 1.1 nia if (reg & R92S_TCR_EMEM_CODE_DONE)
1966 1.1 nia break;
1967 1.1 nia DELAY(10);
1968 1.1 nia }
1969 1.1 nia if (ntries == 10 || !(reg & R92S_TCR_EMEM_CHK_RPT)) {
1970 1.1 nia printf("%s: timeout waiting for %s transfer\n",
1971 1.1 nia device_xname(sc->sc_dev), "EMEM");
1972 1.1 nia error = ETIMEDOUT;
1973 1.1 nia goto fail;
1974 1.1 nia }
1975 1.1 nia
1976 1.1 nia /* Enable CPU. */
1977 1.1 nia rsu_write_1(sc, R92S_SYS_CLKR,
1978 1.1 nia rsu_read_1(sc, R92S_SYS_CLKR) | R92S_SYS_CPU_CLKSEL);
1979 1.1 nia if (!(rsu_read_1(sc, R92S_SYS_CLKR) & R92S_SYS_CPU_CLKSEL)) {
1980 1.1 nia printf("%s: could not enable system clock\n",
1981 1.1 nia device_xname(sc->sc_dev));
1982 1.1 nia error = EIO;
1983 1.1 nia goto fail;
1984 1.1 nia }
1985 1.1 nia rsu_write_2(sc, R92S_SYS_FUNC_EN,
1986 1.1 nia rsu_read_2(sc, R92S_SYS_FUNC_EN) | R92S_FEN_CPUEN);
1987 1.1 nia if (!(rsu_read_2(sc, R92S_SYS_FUNC_EN) & R92S_FEN_CPUEN)) {
1988 1.1 nia printf("%s: could not enable microcontroller\n",
1989 1.1 nia device_xname(sc->sc_dev));
1990 1.1 nia error = EIO;
1991 1.1 nia goto fail;
1992 1.1 nia }
1993 1.1 nia
1994 1.1 nia /* Wait for CPU to initialize. */
1995 1.1 nia for (ntries = 0; ntries < 100; ntries++) {
1996 1.1 nia if (rsu_read_2(sc, R92S_TCR) & R92S_TCR_IMEM_RDY)
1997 1.1 nia break;
1998 1.1 nia usbd_delay_ms(sc->sc_udev, 10);
1999 1.1 nia }
2000 1.1 nia if (ntries == 100) {
2001 1.1 nia printf("%s: timeout waiting for microcontroller\n",
2002 1.1 nia device_xname(sc->sc_dev));
2003 1.1 nia error = ETIMEDOUT;
2004 1.1 nia goto fail;
2005 1.1 nia }
2006 1.1 nia
2007 1.1 nia /* Update DMEM section before loading. */
2008 1.1 nia dmem = &hdr->priv;
2009 1.1 nia memset(dmem, 0, sizeof(*dmem));
2010 1.1 nia dmem->hci_sel = R92S_HCI_SEL_USB | R92S_HCI_SEL_8172;
2011 1.1 nia dmem->nendpoints = sc->npipes;
2012 1.1 nia dmem->rf_config = 0x12; /* 1T2R */
2013 1.1 nia dmem->vcs_type = R92S_VCS_TYPE_AUTO;
2014 1.1 nia dmem->vcs_mode = R92S_VCS_MODE_RTS_CTS;
2015 1.1 nia #ifdef notyet
2016 1.1 nia dmem->bw40_en = (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_40) != 0;
2017 1.1 nia #else
2018 1.1 nia dmem->bw40_en = 0;
2019 1.1 nia #endif
2020 1.1 nia dmem->turbo_mode = 1;
2021 1.1 nia /* Load DMEM section. */
2022 1.1 nia error = rsu_fw_loadsection(sc, (uint8_t *)dmem, sizeof(*dmem));
2023 1.1 nia if (error != 0) {
2024 1.1 nia printf("%s: could not load firmware section %s\n",
2025 1.1 nia device_xname(sc->sc_dev), "DMEM");
2026 1.1 nia goto fail;
2027 1.1 nia }
2028 1.1 nia /* Wait for load to complete. */
2029 1.1 nia for (ntries = 0; ntries < 100; ntries++) {
2030 1.1 nia if (rsu_read_2(sc, R92S_TCR) & R92S_TCR_DMEM_CODE_DONE)
2031 1.1 nia break;
2032 1.1 nia DELAY(1000);
2033 1.1 nia }
2034 1.1 nia if (ntries == 100) {
2035 1.1 nia printf("%s: timeout waiting for %s transfer\n",
2036 1.1 nia device_xname(sc->sc_dev), "DMEM");
2037 1.1 nia error = ETIMEDOUT;
2038 1.1 nia goto fail;
2039 1.1 nia }
2040 1.1 nia /* Wait for firmware readiness. */
2041 1.1 nia for (ntries = 0; ntries < 60; ntries++) {
2042 1.1 nia if (!(rsu_read_2(sc, R92S_TCR) & R92S_TCR_FWRDY))
2043 1.1 nia break;
2044 1.1 nia usbd_delay_ms(sc->sc_udev, 10);
2045 1.1 nia }
2046 1.1 nia if (ntries == 60) {
2047 1.1 nia printf("%s: timeout waiting for firmware readiness\n",
2048 1.1 nia device_xname(sc->sc_dev));
2049 1.1 nia error = ETIMEDOUT;
2050 1.1 nia goto fail;
2051 1.1 nia }
2052 1.1 nia fail:
2053 1.1 nia firmware_free(fw, size);
2054 1.1 nia return (error);
2055 1.1 nia }
2056 1.1 nia
2057 1.1 nia int
2058 1.1 nia rsu_init(struct ifnet *ifp)
2059 1.1 nia {
2060 1.1 nia struct rsu_softc *sc = ifp->if_softc;
2061 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
2062 1.1 nia struct r92s_set_pwr_mode cmd;
2063 1.1 nia struct rsu_rx_data *data;
2064 1.1 nia int i, error;
2065 1.1 nia
2066 1.1 nia /* Init host async commands ring. */
2067 1.1 nia
2068 1.1 nia mutex_enter(&sc->sc_task_mtx);
2069 1.1 nia sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
2070 1.1 nia mutex_exit(&sc->sc_task_mtx);
2071 1.1 nia
2072 1.1 nia /* Allocate Tx/Rx buffers. */
2073 1.1 nia error = rsu_alloc_rx_list(sc);
2074 1.1 nia if (error != 0) {
2075 1.1 nia printf("%s: could not allocate Rx buffers\n",
2076 1.1 nia device_xname(sc->sc_dev));
2077 1.1 nia goto fail;
2078 1.1 nia }
2079 1.1 nia error = rsu_alloc_tx_list(sc);
2080 1.1 nia if (error != 0) {
2081 1.1 nia printf("%s: could not allocate Tx buffers\n",
2082 1.1 nia device_xname(sc->sc_dev));
2083 1.1 nia goto fail;
2084 1.1 nia }
2085 1.1 nia
2086 1.1 nia /* Reserve one Tx buffer for firmware commands. */
2087 1.1 nia mutex_enter(&sc->sc_tx_mtx);
2088 1.1 nia sc->fwcmd_data = TAILQ_FIRST(&sc->tx_free_list);
2089 1.1 nia TAILQ_REMOVE(&sc->tx_free_list, sc->fwcmd_data, next);
2090 1.1 nia mutex_exit(&sc->sc_tx_mtx);
2091 1.1 nia
2092 1.1 nia /* Power on adapter. */
2093 1.1 nia if (sc->cut == 1)
2094 1.1 nia rsu_power_on_acut(sc);
2095 1.1 nia else
2096 1.1 nia rsu_power_on_bcut(sc);
2097 1.1 nia /* Load firmware. */
2098 1.1 nia error = rsu_load_firmware(sc);
2099 1.1 nia if (error != 0)
2100 1.1 nia goto fail;
2101 1.1 nia
2102 1.1 nia /* Enable Rx TCP checksum offload. */
2103 1.1 nia rsu_write_4(sc, R92S_RCR,
2104 1.1 nia rsu_read_4(sc, R92S_RCR) | 0x04000000);
2105 1.1 nia /* Append PHY status. */
2106 1.1 nia rsu_write_4(sc, R92S_RCR,
2107 1.1 nia rsu_read_4(sc, R92S_RCR) | 0x02000000);
2108 1.1 nia
2109 1.1 nia rsu_write_4(sc, R92S_CR,
2110 1.1 nia rsu_read_4(sc, R92S_CR) & ~0xff000000);
2111 1.1 nia
2112 1.1 nia /* Use 128 bytes pages. */
2113 1.1 nia rsu_write_1(sc, 0x00b5,
2114 1.1 nia rsu_read_1(sc, 0x00b5) | 0x01);
2115 1.1 nia /* Enable USB Rx aggregation. */
2116 1.1 nia rsu_write_1(sc, 0x00bd,
2117 1.1 nia rsu_read_1(sc, 0x00bd) | 0x80);
2118 1.1 nia /* Set USB Rx aggregation threshold. */
2119 1.1 nia rsu_write_1(sc, 0x00d9, 0x01);
2120 1.1 nia /* Set USB Rx aggregation timeout (1.7ms/4). */
2121 1.1 nia rsu_write_1(sc, 0xfe5b, 0x04);
2122 1.1 nia /* Fix USB Rx FIFO issue. */
2123 1.1 nia rsu_write_1(sc, 0xfe5c,
2124 1.1 nia rsu_read_1(sc, 0xfe5c) | 0x80);
2125 1.1 nia
2126 1.1 nia /* Set MAC address. */
2127 1.1 nia IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
2128 1.1 nia rsu_write_region_1(sc, R92S_MACID, ic->ic_myaddr, IEEE80211_ADDR_LEN);
2129 1.1 nia
2130 1.1 nia /* Queue Rx xfers (XXX C2H pipe for 11-pipe configurations?) */
2131 1.1 nia for (i = 0; i < RSU_RX_LIST_COUNT; i++) {
2132 1.1 nia data = &sc->rx_data[i];
2133 1.1 nia
2134 1.1 nia data->pipe = sc->pipe[sc->qid2idx[RSU_QID_RXOFF]];
2135 1.1 nia usbd_setup_xfer(data->xfer, data, data->buf,
2136 1.1 nia RSU_RXBUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
2137 1.1 nia rsu_rxeof);
2138 1.1 nia error = usbd_transfer(data->xfer);
2139 1.1 nia if (error != 0 && error != USBD_IN_PROGRESS)
2140 1.1 nia goto fail;
2141 1.1 nia }
2142 1.1 nia
2143 1.1 nia /* NB: it really takes that long for firmware to boot. */
2144 1.1 nia usbd_delay_ms(sc->sc_udev, 1500);
2145 1.1 nia
2146 1.1 nia DPRINTF(("setting MAC address to %s\n", ether_sprintf(ic->ic_myaddr)));
2147 1.1 nia error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, ic->ic_myaddr,
2148 1.1 nia IEEE80211_ADDR_LEN);
2149 1.1 nia if (error != 0) {
2150 1.1 nia printf("%s: could not set MAC address\n",
2151 1.1 nia device_xname(sc->sc_dev));
2152 1.1 nia goto fail;
2153 1.1 nia }
2154 1.1 nia
2155 1.1 nia rsu_write_1(sc, R92S_USB_HRPWM,
2156 1.1 nia R92S_USB_HRPWM_PS_ST_ACTIVE | R92S_USB_HRPWM_PS_ALL_ON);
2157 1.1 nia
2158 1.1 nia memset(&cmd, 0, sizeof(cmd));
2159 1.1 nia cmd.mode = R92S_PS_MODE_ACTIVE;
2160 1.1 nia DPRINTF(("setting ps mode to %d\n", cmd.mode));
2161 1.1 nia error = rsu_fw_cmd(sc, R92S_CMD_SET_PWR_MODE, &cmd, sizeof(cmd));
2162 1.1 nia if (error != 0) {
2163 1.1 nia printf("%s: could not set PS mode\n",
2164 1.1 nia device_xname(sc->sc_dev));
2165 1.1 nia goto fail;
2166 1.1 nia }
2167 1.1 nia
2168 1.1 nia #ifdef notyet
2169 1.1 nia if (ic->ic_htcaps & IEEE80211_HTCAP_CBW20_40) {
2170 1.1 nia /* Enable 40MHz mode. */
2171 1.1 nia error = rsu_fw_iocmd(sc,
2172 1.1 nia SM(R92S_IOCMD_CLASS, 0xf4) |
2173 1.1 nia SM(R92S_IOCMD_INDEX, 0x00) |
2174 1.1 nia SM(R92S_IOCMD_VALUE, 0x0007));
2175 1.1 nia if (error != 0) {
2176 1.1 nia printf("%s: could not enable 40MHz mode\n",
2177 1.1 nia device_xname(sc->sc_dev));
2178 1.1 nia goto fail;
2179 1.1 nia }
2180 1.1 nia }
2181 1.1 nia #endif
2182 1.1 nia
2183 1.1 nia /* Set default channel. */
2184 1.1 nia ic->ic_bss->ni_chan = ic->ic_ibss_chan;
2185 1.1 nia
2186 1.1 nia /* We're ready to go. */
2187 1.1 nia ifp->if_flags &= ~IFF_OACTIVE;
2188 1.1 nia ifp->if_flags |= IFF_RUNNING;
2189 1.1 nia
2190 1.1 nia sc->scan_pass = 0;
2191 1.1 nia if (ic->ic_opmode == IEEE80211_M_MONITOR)
2192 1.1 nia ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
2193 1.1 nia else
2194 1.1 nia ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2195 1.1 nia return (0);
2196 1.1 nia fail:
2197 1.1 nia rsu_stop(ifp);
2198 1.1 nia return (error);
2199 1.1 nia }
2200 1.1 nia
2201 1.1 nia void
2202 1.1 nia rsu_stop(struct ifnet *ifp)
2203 1.1 nia {
2204 1.1 nia struct rsu_softc *sc = ifp->if_softc;
2205 1.1 nia struct ieee80211com *ic = &sc->sc_ic;
2206 1.1 nia int i, s;
2207 1.1 nia
2208 1.1 nia sc->sc_tx_timer = 0;
2209 1.1 nia ifp->if_timer = 0;
2210 1.1 nia ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2211 1.1 nia
2212 1.1 nia s = splusb();
2213 1.1 nia ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2214 1.1 nia /* Wait for all async commands to complete. */
2215 1.1 nia rsu_wait_async(sc);
2216 1.1 nia splx(s);
2217 1.1 nia
2218 1.1 nia callout_destroy(&sc->calib_to);
2219 1.1 nia
2220 1.1 nia /* Power off adapter. */
2221 1.1 nia rsu_power_off(sc);
2222 1.1 nia
2223 1.1 nia /* Abort Tx/Rx. */
2224 1.1 nia for (i = 0; i < sc->npipes; i++)
2225 1.1 nia usbd_abort_pipe(sc->pipe[i]);
2226 1.1 nia
2227 1.1 nia /* Free Tx/Rx buffers. */
2228 1.1 nia rsu_free_tx_list(sc);
2229 1.1 nia rsu_free_rx_list(sc);
2230 1.1 nia }
2231 1.1 nia
2232 1.1 nia MODULE(MODULE_CLASS_DRIVER, if_rsu, NULL);
2233 1.1 nia
2234 1.1 nia #ifdef _MODULE
2235 1.1 nia #include "ioconf.c"
2236 1.1 nia #endif
2237 1.1 nia
2238 1.1 nia static int
2239 1.1 nia if_rsu_modcmd(modcmd_t cmd, void *arg)
2240 1.1 nia {
2241 1.1 nia int error = 0;
2242 1.1 nia
2243 1.1 nia switch (cmd) {
2244 1.1 nia case MODULE_CMD_INIT:
2245 1.1 nia #ifdef _MODULE
2246 1.1 nia error = config_init_component(cfdriver_ioconf_rsu,
2247 1.1 nia cfattach_ioconf_rsu, cfdata_ioconf_rsu);
2248 1.1 nia #endif
2249 1.1 nia return error;
2250 1.1 nia case MODULE_CMD_FINI:
2251 1.1 nia #ifdef _MODULE
2252 1.1 nia error = config_fini_component(cfdriver_ioconf_rsu,
2253 1.1 nia cfattach_ioconf_rsu, cfdata_ioconf_rsu);
2254 1.1 nia #endif
2255 1.1 nia return error;
2256 1.1 nia default:
2257 1.1 nia return ENOTTY;
2258 1.1 nia }
2259 1.1 nia }
2260