| @@ -1,39 +1,41 @@ | | | @@ -1,39 +1,41 @@ |
1 | /* $NetBSD: if_urtwn.c,v 1.48 2016/10/12 02:56:45 nat Exp $ */ | | 1 | /* $NetBSD: if_urtwn.c,v 1.49 2016/10/12 03:23:29 nat Exp $ */ |
2 | /* $OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $ */ | | 2 | /* $OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $ */ |
3 | | | 3 | |
4 | /*- | | 4 | /*- |
5 | * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> | | 5 | * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> |
6 | * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> | | 6 | * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> |
| | | 7 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> |
7 | * | | 8 | * |
8 | * Permission to use, copy, modify, and distribute this software for any | | 9 | * Permission to use, copy, modify, and distribute this software for any |
9 | * purpose with or without fee is hereby granted, provided that the above | | 10 | * purpose with or without fee is hereby granted, provided that the above |
10 | * copyright notice and this permission notice appear in all copies. | | 11 | * copyright notice and this permission notice appear in all copies. |
11 | * | | 12 | * |
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | | 18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | | 19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
19 | */ | | 20 | */ |
20 | | | 21 | |
21 | /*- | | 22 | /*- |
22 | * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU. | | 23 | * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU |
| | | 24 | * RTL8192EU. |
23 | */ | | 25 | */ |
24 | | | 26 | |
25 | #include <sys/cdefs.h> | | 27 | #include <sys/cdefs.h> |
26 | __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.48 2016/10/12 02:56:45 nat Exp $"); | | 28 | __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.49 2016/10/12 03:23:29 nat Exp $"); |
27 | | | 29 | |
28 | #ifdef _KERNEL_OPT | | 30 | #ifdef _KERNEL_OPT |
29 | #include "opt_inet.h" | | 31 | #include "opt_inet.h" |
30 | #endif | | 32 | #endif |
31 | | | 33 | |
32 | #include <sys/param.h> | | 34 | #include <sys/param.h> |
33 | #include <sys/sockio.h> | | 35 | #include <sys/sockio.h> |
34 | #include <sys/sysctl.h> | | 36 | #include <sys/sysctl.h> |
35 | #include <sys/mbuf.h> | | 37 | #include <sys/mbuf.h> |
36 | #include <sys/kernel.h> | | 38 | #include <sys/kernel.h> |
37 | #include <sys/socket.h> | | 39 | #include <sys/socket.h> |
38 | #include <sys/systm.h> | | 40 | #include <sys/systm.h> |
39 | #include <sys/module.h> | | 41 | #include <sys/module.h> |
| @@ -89,30 +91,33 @@ __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v | | | @@ -89,30 +91,33 @@ __KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v |
89 | #define DBG_RF __BIT(5) | | 91 | #define DBG_RF __BIT(5) |
90 | #define DBG_REG __BIT(6) | | 92 | #define DBG_REG __BIT(6) |
91 | #define DBG_ALL 0xffffffffU | | 93 | #define DBG_ALL 0xffffffffU |
92 | u_int urtwn_debug = 0; | | 94 | u_int urtwn_debug = 0; |
93 | #define DPRINTFN(n, s) \ | | 95 | #define DPRINTFN(n, s) \ |
94 | do { if (urtwn_debug & (n)) printf s; } while (/*CONSTCOND*/0) | | 96 | do { if (urtwn_debug & (n)) printf s; } while (/*CONSTCOND*/0) |
95 | #else | | 97 | #else |
96 | #define DPRINTFN(n, s) | | 98 | #define DPRINTFN(n, s) |
97 | #endif | | 99 | #endif |
98 | | | 100 | |
99 | #define URTWN_DEV(v,p) { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, 0 } | | 101 | #define URTWN_DEV(v,p) { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, 0 } |
100 | #define URTWN_RTL8188E_DEV(v,p) \ | | 102 | #define URTWN_RTL8188E_DEV(v,p) \ |
101 | { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, FLAG_RTL8188E } | | 103 | { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, FLAG_RTL8188E } |
| | | 104 | #define URTWN_RTL8192EU_DEV(v,p) \ |
| | | 105 | { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, FLAG_RTL8192E } |
102 | static const struct urtwn_dev { | | 106 | static const struct urtwn_dev { |
103 | struct usb_devno dev; | | 107 | struct usb_devno dev; |
104 | uint32_t flags; | | 108 | uint32_t flags; |
105 | #define FLAG_RTL8188E __BIT(0) | | 109 | #define FLAG_RTL8188E __BIT(0) |
| | | 110 | #define FLAG_RTL8192E __BIT(1) |
106 | } urtwn_devs[] = { | | 111 | } urtwn_devs[] = { |
107 | URTWN_DEV(ABOCOM, RTL8188CU_1), | | 112 | URTWN_DEV(ABOCOM, RTL8188CU_1), |
108 | URTWN_DEV(ABOCOM, RTL8188CU_2), | | 113 | URTWN_DEV(ABOCOM, RTL8188CU_2), |
109 | URTWN_DEV(ABOCOM, RTL8192CU), | | 114 | URTWN_DEV(ABOCOM, RTL8192CU), |
110 | URTWN_DEV(ASUSTEK, RTL8192CU), | | 115 | URTWN_DEV(ASUSTEK, RTL8192CU), |
111 | URTWN_DEV(ASUSTEK, RTL8192CU_3), | | 116 | URTWN_DEV(ASUSTEK, RTL8192CU_3), |
112 | URTWN_DEV(ASUSTEK, USBN10NANO), | | 117 | URTWN_DEV(ASUSTEK, USBN10NANO), |
113 | URTWN_DEV(ASUSTEK, RTL8192CU_3), | | 118 | URTWN_DEV(ASUSTEK, RTL8192CU_3), |
114 | URTWN_DEV(AZUREWAVE, RTL8188CE_1), | | 119 | URTWN_DEV(AZUREWAVE, RTL8188CE_1), |
115 | URTWN_DEV(AZUREWAVE, RTL8188CE_2), | | 120 | URTWN_DEV(AZUREWAVE, RTL8188CE_2), |
116 | URTWN_DEV(AZUREWAVE, RTL8188CU), | | 121 | URTWN_DEV(AZUREWAVE, RTL8188CU), |
117 | URTWN_DEV(BELKIN, F7D2102), | | 122 | URTWN_DEV(BELKIN, F7D2102), |
118 | URTWN_DEV(BELKIN, RTL8188CU), | | 123 | URTWN_DEV(BELKIN, RTL8188CU), |
| @@ -174,29 +179,33 @@ static const struct urtwn_dev { | | | @@ -174,29 +179,33 @@ static const struct urtwn_dev { |
174 | URTWN_DEV(SITECOMEU, RTL8188CU_2), | | 179 | URTWN_DEV(SITECOMEU, RTL8188CU_2), |
175 | URTWN_DEV(SITECOMEU, RTL8192CU), | | 180 | URTWN_DEV(SITECOMEU, RTL8192CU), |
176 | URTWN_DEV(SITECOMEU, RTL8192CUR2), | | 181 | URTWN_DEV(SITECOMEU, RTL8192CUR2), |
177 | URTWN_DEV(TPLINK, RTL8192CU), | | 182 | URTWN_DEV(TPLINK, RTL8192CU), |
178 | URTWN_DEV(TRENDNET, RTL8188CU), | | 183 | URTWN_DEV(TRENDNET, RTL8188CU), |
179 | URTWN_DEV(TRENDNET, RTL8192CU), | | 184 | URTWN_DEV(TRENDNET, RTL8192CU), |
180 | URTWN_DEV(ZYXEL, RTL8192CU), | | 185 | URTWN_DEV(ZYXEL, RTL8192CU), |
181 | | | 186 | |
182 | /* URTWN_RTL8188E */ | | 187 | /* URTWN_RTL8188E */ |
183 | URTWN_RTL8188E_DEV(DLINK, DWA125D1), | | 188 | URTWN_RTL8188E_DEV(DLINK, DWA125D1), |
184 | URTWN_RTL8188E_DEV(ELECOM, WDC150SU2M), | | 189 | URTWN_RTL8188E_DEV(ELECOM, WDC150SU2M), |
185 | URTWN_RTL8188E_DEV(REALTEK, RTL8188ETV), | | 190 | URTWN_RTL8188E_DEV(REALTEK, RTL8188ETV), |
186 | URTWN_RTL8188E_DEV(REALTEK, RTL8188EU), | | 191 | URTWN_RTL8188E_DEV(REALTEK, RTL8188EU), |
| | | 192 | |
| | | 193 | /* URTWN_RTL8192EU */ |
| | | 194 | URTWN_RTL8192EU_DEV(REALTEK, RTL8192EU), |
187 | }; | | 195 | }; |
188 | #undef URTWN_DEV | | 196 | #undef URTWN_DEV |
189 | #undef URTWN_RTL8188E_DEV | | 197 | #undef URTWN_RTL8188E_DEV |
| | | 198 | #undef URTWN_RTL8192EU_DEV |
190 | | | 199 | |
191 | static int urtwn_match(device_t, cfdata_t, void *); | | 200 | static int urtwn_match(device_t, cfdata_t, void *); |
192 | static void urtwn_attach(device_t, device_t, void *); | | 201 | static void urtwn_attach(device_t, device_t, void *); |
193 | static int urtwn_detach(device_t, int); | | 202 | static int urtwn_detach(device_t, int); |
194 | static int urtwn_activate(device_t, enum devact); | | 203 | static int urtwn_activate(device_t, enum devact); |
195 | | | 204 | |
196 | CFATTACH_DECL_NEW(urtwn, sizeof(struct urtwn_softc), urtwn_match, | | 205 | CFATTACH_DECL_NEW(urtwn, sizeof(struct urtwn_softc), urtwn_match, |
197 | urtwn_attach, urtwn_detach, urtwn_activate); | | 206 | urtwn_attach, urtwn_detach, urtwn_activate); |
198 | | | 207 | |
199 | static int urtwn_open_pipes(struct urtwn_softc *); | | 208 | static int urtwn_open_pipes(struct urtwn_softc *); |
200 | static void urtwn_close_pipes(struct urtwn_softc *); | | 209 | static void urtwn_close_pipes(struct urtwn_softc *); |
201 | static int urtwn_alloc_rx_list(struct urtwn_softc *); | | 210 | static int urtwn_alloc_rx_list(struct urtwn_softc *); |
202 | static void urtwn_free_rx_list(struct urtwn_softc *); | | 211 | static void urtwn_free_rx_list(struct urtwn_softc *); |
| @@ -213,26 +222,28 @@ static void urtwn_write_2(struct urtwn_s | | | @@ -213,26 +222,28 @@ static void urtwn_write_2(struct urtwn_s |
213 | static void urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t); | | 222 | static void urtwn_write_4(struct urtwn_softc *, uint16_t, uint32_t); |
214 | static int urtwn_write_region(struct urtwn_softc *, uint16_t, uint8_t *, | | 223 | static int urtwn_write_region(struct urtwn_softc *, uint16_t, uint8_t *, |
215 | int); | | 224 | int); |
216 | static int urtwn_read_region_1(struct urtwn_softc *, uint16_t, uint8_t *, | | 225 | static int urtwn_read_region_1(struct urtwn_softc *, uint16_t, uint8_t *, |
217 | int); | | 226 | int); |
218 | static uint8_t urtwn_read_1(struct urtwn_softc *, uint16_t); | | 227 | static uint8_t urtwn_read_1(struct urtwn_softc *, uint16_t); |
219 | static uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t); | | 228 | static uint16_t urtwn_read_2(struct urtwn_softc *, uint16_t); |
220 | static uint32_t urtwn_read_4(struct urtwn_softc *, uint16_t); | | 229 | static uint32_t urtwn_read_4(struct urtwn_softc *, uint16_t); |
221 | static int urtwn_fw_cmd(struct urtwn_softc *, uint8_t, const void *, int); | | 230 | static int urtwn_fw_cmd(struct urtwn_softc *, uint8_t, const void *, int); |
222 | static void urtwn_r92c_rf_write(struct urtwn_softc *, int, uint8_t, | | 231 | static void urtwn_r92c_rf_write(struct urtwn_softc *, int, uint8_t, |
223 | uint32_t); | | 232 | uint32_t); |
224 | static void urtwn_r88e_rf_write(struct urtwn_softc *, int, uint8_t, | | 233 | static void urtwn_r88e_rf_write(struct urtwn_softc *, int, uint8_t, |
225 | uint32_t); | | 234 | uint32_t); |
| | | 235 | static void urtwn_r92e_rf_write(struct urtwn_softc *, int, uint8_t, |
| | | 236 | uint32_t); |
226 | static uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t); | | 237 | static uint32_t urtwn_rf_read(struct urtwn_softc *, int, uint8_t); |
227 | static int urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t); | | 238 | static int urtwn_llt_write(struct urtwn_softc *, uint32_t, uint32_t); |
228 | static uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t); | | 239 | static uint8_t urtwn_efuse_read_1(struct urtwn_softc *, uint16_t); |
229 | static void urtwn_efuse_read(struct urtwn_softc *); | | 240 | static void urtwn_efuse_read(struct urtwn_softc *); |
230 | static void urtwn_efuse_switch_power(struct urtwn_softc *); | | 241 | static void urtwn_efuse_switch_power(struct urtwn_softc *); |
231 | static int urtwn_read_chipid(struct urtwn_softc *); | | 242 | static int urtwn_read_chipid(struct urtwn_softc *); |
232 | #ifdef URTWN_DEBUG | | 243 | #ifdef URTWN_DEBUG |
233 | static void urtwn_dump_rom(struct urtwn_softc *, struct r92c_rom *); | | 244 | static void urtwn_dump_rom(struct urtwn_softc *, struct r92c_rom *); |
234 | #endif | | 245 | #endif |
235 | static void urtwn_read_rom(struct urtwn_softc *); | | 246 | static void urtwn_read_rom(struct urtwn_softc *); |
236 | static void urtwn_r88e_read_rom(struct urtwn_softc *); | | 247 | static void urtwn_r88e_read_rom(struct urtwn_softc *); |
237 | static int urtwn_media_change(struct ifnet *); | | 248 | static int urtwn_media_change(struct ifnet *); |
238 | static int urtwn_ra_init(struct urtwn_softc *); | | 249 | static int urtwn_ra_init(struct urtwn_softc *); |
| @@ -252,26 +263,27 @@ static void urtwn_update_avgrssi(struct | | | @@ -252,26 +263,27 @@ static void urtwn_update_avgrssi(struct |
252 | static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *); | | 263 | static int8_t urtwn_get_rssi(struct urtwn_softc *, int, void *); |
253 | static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *); | | 264 | static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *); |
254 | static void urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int); | | 265 | static void urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int); |
255 | static void urtwn_rxeof(struct usbd_xfer *, void *, usbd_status); | | 266 | static void urtwn_rxeof(struct usbd_xfer *, void *, usbd_status); |
256 | static void urtwn_txeof(struct usbd_xfer *, void *, usbd_status); | | 267 | static void urtwn_txeof(struct usbd_xfer *, void *, usbd_status); |
257 | static int urtwn_tx(struct urtwn_softc *, struct mbuf *, | | 268 | static int urtwn_tx(struct urtwn_softc *, struct mbuf *, |
258 | struct ieee80211_node *, struct urtwn_tx_data *); | | 269 | struct ieee80211_node *, struct urtwn_tx_data *); |
259 | static struct urtwn_tx_data * | | 270 | static struct urtwn_tx_data * |
260 | urtwn_get_tx_data(struct urtwn_softc *, size_t); | | 271 | urtwn_get_tx_data(struct urtwn_softc *, size_t); |
261 | static void urtwn_start(struct ifnet *); | | 272 | static void urtwn_start(struct ifnet *); |
262 | static void urtwn_watchdog(struct ifnet *); | | 273 | static void urtwn_watchdog(struct ifnet *); |
263 | static int urtwn_ioctl(struct ifnet *, u_long, void *); | | 274 | static int urtwn_ioctl(struct ifnet *, u_long, void *); |
264 | static int urtwn_r92c_power_on(struct urtwn_softc *); | | 275 | static int urtwn_r92c_power_on(struct urtwn_softc *); |
| | | 276 | static int urtwn_r92e_power_on(struct urtwn_softc *); |
265 | static int urtwn_r88e_power_on(struct urtwn_softc *); | | 277 | static int urtwn_r88e_power_on(struct urtwn_softc *); |
266 | static int urtwn_llt_init(struct urtwn_softc *); | | 278 | static int urtwn_llt_init(struct urtwn_softc *); |
267 | static void urtwn_fw_reset(struct urtwn_softc *); | | 279 | static void urtwn_fw_reset(struct urtwn_softc *); |
268 | static void urtwn_r88e_fw_reset(struct urtwn_softc *); | | 280 | static void urtwn_r88e_fw_reset(struct urtwn_softc *); |
269 | static int urtwn_fw_loadpage(struct urtwn_softc *, int, uint8_t *, int); | | 281 | static int urtwn_fw_loadpage(struct urtwn_softc *, int, uint8_t *, int); |
270 | static int urtwn_load_firmware(struct urtwn_softc *); | | 282 | static int urtwn_load_firmware(struct urtwn_softc *); |
271 | static int urtwn_r92c_dma_init(struct urtwn_softc *); | | 283 | static int urtwn_r92c_dma_init(struct urtwn_softc *); |
272 | static int urtwn_r88e_dma_init(struct urtwn_softc *); | | 284 | static int urtwn_r88e_dma_init(struct urtwn_softc *); |
273 | static void urtwn_mac_init(struct urtwn_softc *); | | 285 | static void urtwn_mac_init(struct urtwn_softc *); |
274 | static void urtwn_bb_init(struct urtwn_softc *); | | 286 | static void urtwn_bb_init(struct urtwn_softc *); |
275 | static void urtwn_rf_init(struct urtwn_softc *); | | 287 | static void urtwn_rf_init(struct urtwn_softc *); |
276 | static void urtwn_cam_init(struct urtwn_softc *); | | 288 | static void urtwn_cam_init(struct urtwn_softc *); |
277 | static void urtwn_pa_bias_init(struct urtwn_softc *); | | 289 | static void urtwn_pa_bias_init(struct urtwn_softc *); |
| @@ -283,90 +295,94 @@ static void urtwn_get_txpower(struct urt | | | @@ -283,90 +295,94 @@ static void urtwn_get_txpower(struct urt |
283 | static void urtwn_r88e_get_txpower(struct urtwn_softc *, size_t, u_int, | | 295 | static void urtwn_r88e_get_txpower(struct urtwn_softc *, size_t, u_int, |
284 | u_int, uint16_t[]); | | 296 | u_int, uint16_t[]); |
285 | static void urtwn_set_txpower(struct urtwn_softc *, u_int, u_int); | | 297 | static void urtwn_set_txpower(struct urtwn_softc *, u_int, u_int); |
286 | static void urtwn_set_chan(struct urtwn_softc *, struct ieee80211_channel *, | | 298 | static void urtwn_set_chan(struct urtwn_softc *, struct ieee80211_channel *, |
287 | u_int); | | 299 | u_int); |
288 | static void urtwn_iq_calib(struct urtwn_softc *, bool); | | 300 | static void urtwn_iq_calib(struct urtwn_softc *, bool); |
289 | static void urtwn_lc_calib(struct urtwn_softc *); | | 301 | static void urtwn_lc_calib(struct urtwn_softc *); |
290 | static void urtwn_temp_calib(struct urtwn_softc *); | | 302 | static void urtwn_temp_calib(struct urtwn_softc *); |
291 | static int urtwn_init(struct ifnet *); | | 303 | static int urtwn_init(struct ifnet *); |
292 | static void urtwn_stop(struct ifnet *, int); | | 304 | static void urtwn_stop(struct ifnet *, int); |
293 | static int urtwn_reset(struct ifnet *); | | 305 | static int urtwn_reset(struct ifnet *); |
294 | static void urtwn_chip_stop(struct urtwn_softc *); | | 306 | static void urtwn_chip_stop(struct urtwn_softc *); |
295 | static void urtwn_newassoc(struct ieee80211_node *, int); | | 307 | static void urtwn_newassoc(struct ieee80211_node *, int); |
| | | 308 | static void urtwn_delay_ms(struct urtwn_softc *, int ms); |
296 | | | 309 | |
297 | /* Aliases. */ | | 310 | /* Aliases. */ |
298 | #define urtwn_bb_write urtwn_write_4 | | 311 | #define urtwn_bb_write urtwn_write_4 |
299 | #define urtwn_bb_read urtwn_read_4 | | 312 | #define urtwn_bb_read urtwn_read_4 |
300 | | | 313 | |
301 | #define urtwn_lookup(d,v,p) ((const struct urtwn_dev *)usb_lookup(d,v,p)) | | 314 | #define urtwn_lookup(d,v,p) ((const struct urtwn_dev *)usb_lookup(d,v,p)) |
302 | | | 315 | |
303 | static const uint16_t addaReg[] = { | | 316 | static const uint16_t addaReg[] = { |
304 | R92C_FPGA0_XCD_SWITCHCTL, R92C_BLUETOOTH, R92C_RX_WAIT_CCA, | | 317 | R92C_FPGA0_XCD_SWITCHCTL, R92C_BLUETOOTH, R92C_RX_WAIT_CCA, |
305 | R92C_TX_CCK_RFON, R92C_TX_CCK_BBON, R92C_TX_OFDM_RFON, | | 318 | R92C_TX_CCK_RFON, R92C_TX_CCK_BBON, R92C_TX_OFDM_RFON, |
306 | R92C_TX_OFDM_BBON, R92C_TX_TO_RX, R92C_TX_TO_TX, R92C_RX_CCK, | | 319 | R92C_TX_OFDM_BBON, R92C_TX_TO_RX, R92C_TX_TO_TX, R92C_RX_CCK, |
307 | R92C_RX_OFDM, R92C_RX_WAIT_RIFS, R92C_RX_TO_RX, | | 320 | R92C_RX_OFDM, R92C_RX_WAIT_RIFS, R92C_RX_TO_RX, |
308 | R92C_STANDBY, R92C_SLEEP, R92C_PMPD_ANAEN | | 321 | R92C_STANDBY, R92C_SLEEP, R92C_PMPD_ANAEN |
309 | }; | | 322 | }; |
310 | | | 323 | |
311 | static int | | 324 | static int |
312 | urtwn_match(device_t parent, cfdata_t match, void *aux) | | 325 | urtwn_match(device_t parent, cfdata_t match, void *aux) |
313 | { | | 326 | { |
314 | struct usb_attach_arg *uaa = aux; | | 327 | struct usb_attach_arg *uaa = aux; |
315 | | | 328 | |
316 | return urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ? | | 329 | return urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product) != |
317 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; | | 330 | NULL ? UMATCH_VENDOR_PRODUCT : UMATCH_NONE; |
318 | } | | 331 | } |
319 | | | 332 | |
320 | static void | | 333 | static void |
321 | urtwn_attach(device_t parent, device_t self, void *aux) | | 334 | urtwn_attach(device_t parent, device_t self, void *aux) |
322 | { | | 335 | { |
323 | struct urtwn_softc *sc = device_private(self); | | 336 | struct urtwn_softc *sc = device_private(self); |
324 | struct ieee80211com *ic = &sc->sc_ic; | | 337 | struct ieee80211com *ic = &sc->sc_ic; |
325 | struct ifnet *ifp = &sc->sc_if; | | 338 | struct ifnet *ifp = &sc->sc_if; |
326 | struct usb_attach_arg *uaa = aux; | | 339 | struct usb_attach_arg *uaa = aux; |
327 | char *devinfop; | | 340 | char *devinfop; |
328 | const struct urtwn_dev *dev; | | 341 | const struct urtwn_dev *dev; |
329 | usb_device_request_t req; | | 342 | usb_device_request_t req; |
330 | size_t i; | | 343 | size_t i; |
331 | int error; | | 344 | int error; |
332 | | | 345 | |
333 | sc->sc_dev = self; | | 346 | sc->sc_dev = self; |
334 | sc->sc_udev = uaa->uaa_device; | | 347 | sc->sc_udev = uaa->uaa_device; |
335 | | | 348 | |
336 | sc->chip = 0; | | 349 | sc->chip = 0; |
337 | dev = urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product); | | 350 | dev = urtwn_lookup(urtwn_devs, uaa->uaa_vendor, uaa->uaa_product); |
338 | if (dev != NULL && ISSET(dev->flags, FLAG_RTL8188E)) | | 351 | if (dev != NULL && ISSET(dev->flags, FLAG_RTL8188E)) |
339 | SET(sc->chip, URTWN_CHIP_88E); | | 352 | SET(sc->chip, URTWN_CHIP_88E); |
| | | 353 | if (dev != NULL && ISSET(dev->flags, FLAG_RTL8192E)) |
| | | 354 | SET(sc->chip, URTWN_CHIP_92EU); |
340 | | | 355 | |
341 | aprint_naive("\n"); | | 356 | aprint_naive("\n"); |
342 | aprint_normal("\n"); | | 357 | aprint_normal("\n"); |
343 | | | 358 | |
344 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 359 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
345 | | | 360 | |
346 | devinfop = usbd_devinfo_alloc(sc->sc_udev, 0); | | 361 | devinfop = usbd_devinfo_alloc(sc->sc_udev, 0); |
347 | aprint_normal_dev(self, "%s\n", devinfop); | | 362 | aprint_normal_dev(self, "%s\n", devinfop); |
348 | usbd_devinfo_free(devinfop); | | 363 | usbd_devinfo_free(devinfop); |
349 | | | 364 | |
350 | req.bmRequestType = UT_WRITE_DEVICE; | | 365 | req.bmRequestType = UT_WRITE_DEVICE; |
351 | req.bRequest = UR_SET_FEATURE; | | 366 | req.bRequest = UR_SET_FEATURE; |
352 | USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); | | 367 | USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); |
353 | USETW(req.wIndex, UHF_PORT_SUSPEND); | | 368 | USETW(req.wIndex, UHF_PORT_SUSPEND); |
354 | USETW(req.wLength, 0); | | 369 | USETW(req.wLength, 0); |
355 | | | 370 | |
356 | (void) usbd_do_request(sc->sc_udev, &req, 0); | | 371 | (void) usbd_do_request(sc->sc_udev, &req, 0); |
357 | | | 372 | |
358 | mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET); | | 373 | mutex_init(&sc->sc_task_mtx, MUTEX_DEFAULT, IPL_NET); |
359 | mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE); | | 374 | mutex_init(&sc->sc_tx_mtx, MUTEX_DEFAULT, IPL_NONE); |
| | | 375 | mutex_init(&sc->sc_rx_mtx, MUTEX_DEFAULT, IPL_NONE); |
360 | mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE); | | 376 | mutex_init(&sc->sc_fwcmd_mtx, MUTEX_DEFAULT, IPL_NONE); |
361 | mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE); | | 377 | mutex_init(&sc->sc_write_mtx, MUTEX_DEFAULT, IPL_NONE); |
362 | | | 378 | |
363 | usb_init_task(&sc->sc_task, urtwn_task, sc, 0); | | 379 | usb_init_task(&sc->sc_task, urtwn_task, sc, 0); |
364 | | | 380 | |
365 | callout_init(&sc->sc_scan_to, 0); | | 381 | callout_init(&sc->sc_scan_to, 0); |
366 | callout_setfunc(&sc->sc_scan_to, urtwn_next_scan, sc); | | 382 | callout_setfunc(&sc->sc_scan_to, urtwn_next_scan, sc); |
367 | callout_init(&sc->sc_calib_to, 0); | | 383 | callout_init(&sc->sc_calib_to, 0); |
368 | callout_setfunc(&sc->sc_calib_to, urtwn_calib_to, sc); | | 384 | callout_setfunc(&sc->sc_calib_to, urtwn_calib_to, sc); |
369 | | | 385 | |
370 | error = usbd_set_config_no(sc->sc_udev, 1, 0); | | 386 | error = usbd_set_config_no(sc->sc_udev, 1, 0); |
371 | if (error != 0) { | | 387 | if (error != 0) { |
372 | aprint_error_dev(self, "failed to set configuration" | | 388 | aprint_error_dev(self, "failed to set configuration" |
| @@ -381,37 +397,42 @@ urtwn_attach(device_t parent, device_t s | | | @@ -381,37 +397,42 @@ urtwn_attach(device_t parent, device_t s |
381 | goto fail; | | 397 | goto fail; |
382 | } | | 398 | } |
383 | | | 399 | |
384 | error = urtwn_read_chipid(sc); | | 400 | error = urtwn_read_chipid(sc); |
385 | if (error != 0) { | | 401 | if (error != 0) { |
386 | aprint_error_dev(self, "unsupported test chip\n"); | | 402 | aprint_error_dev(self, "unsupported test chip\n"); |
387 | goto fail; | | 403 | goto fail; |
388 | } | | 404 | } |
389 | | | 405 | |
390 | /* Determine number of Tx/Rx chains. */ | | 406 | /* Determine number of Tx/Rx chains. */ |
391 | if (sc->chip & URTWN_CHIP_92C) { | | 407 | if (sc->chip & URTWN_CHIP_92C) { |
392 | sc->ntxchains = (sc->chip & URTWN_CHIP_92C_1T2R) ? 1 : 2; | | 408 | sc->ntxchains = (sc->chip & URTWN_CHIP_92C_1T2R) ? 1 : 2; |
393 | sc->nrxchains = 2; | | 409 | sc->nrxchains = 2; |
| | | 410 | } else if (sc->chip & URTWN_CHIP_92EU) { |
| | | 411 | sc->ntxchains = 2; |
| | | 412 | sc->nrxchains = 2; |
394 | } else { | | 413 | } else { |
395 | sc->ntxchains = 1; | | 414 | sc->ntxchains = 1; |
396 | sc->nrxchains = 1; | | 415 | sc->nrxchains = 1; |
397 | } | | 416 | } |
398 | | | 417 | |
399 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 418 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 419 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
400 | urtwn_r88e_read_rom(sc); | | 420 | urtwn_r88e_read_rom(sc); |
401 | else | | 421 | else |
402 | urtwn_read_rom(sc); | | 422 | urtwn_read_rom(sc); |
403 | | | 423 | |
404 | aprint_normal_dev(self, "MAC/BB RTL%s, RF 6052 %zdT%zdR, address %s\n", | | 424 | aprint_normal_dev(self, "MAC/BB RTL%s, RF 6052 %zdT%zdR, address %s\n", |
| | | 425 | (sc->chip & URTWN_CHIP_92EU) ? "8192EU" : |
405 | (sc->chip & URTWN_CHIP_92C) ? "8192CU" : | | 426 | (sc->chip & URTWN_CHIP_92C) ? "8192CU" : |
406 | (sc->chip & URTWN_CHIP_88E) ? "8188EU" : | | 427 | (sc->chip & URTWN_CHIP_88E) ? "8188EU" : |
407 | (sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" : | | 428 | (sc->board_type == R92C_BOARD_TYPE_HIGHPA) ? "8188RU" : |
408 | (sc->board_type == R92C_BOARD_TYPE_MINICARD) ? "8188CE-VAU" : | | 429 | (sc->board_type == R92C_BOARD_TYPE_MINICARD) ? "8188CE-VAU" : |
409 | "8188CUS", sc->ntxchains, sc->nrxchains, | | 430 | "8188CUS", sc->ntxchains, sc->nrxchains, |
410 | ether_sprintf(ic->ic_myaddr)); | | 431 | ether_sprintf(ic->ic_myaddr)); |
411 | | | 432 | |
412 | error = urtwn_open_pipes(sc); | | 433 | error = urtwn_open_pipes(sc); |
413 | if (error != 0) { | | 434 | if (error != 0) { |
414 | aprint_error_dev(sc->sc_dev, "could not open pipes\n"); | | 435 | aprint_error_dev(sc->sc_dev, "could not open pipes\n"); |
415 | goto fail; | | 436 | goto fail; |
416 | } | | 437 | } |
417 | aprint_normal_dev(self, "%d rx pipe%s, %d tx pipe%s\n", | | 438 | aprint_normal_dev(self, "%d rx pipe%s, %d tx pipe%s\n", |
| @@ -529,85 +550,98 @@ urtwn_detach(device_t self, int flags) | | | @@ -529,85 +550,98 @@ urtwn_detach(device_t self, int flags) |
529 | urtwn_close_pipes(sc); | | 550 | urtwn_close_pipes(sc); |
530 | } | | 551 | } |
531 | | | 552 | |
532 | splx(s); | | 553 | splx(s); |
533 | | | 554 | |
534 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); | | 555 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); |
535 | | | 556 | |
536 | callout_destroy(&sc->sc_scan_to); | | 557 | callout_destroy(&sc->sc_scan_to); |
537 | callout_destroy(&sc->sc_calib_to); | | 558 | callout_destroy(&sc->sc_calib_to); |
538 | | | 559 | |
539 | mutex_destroy(&sc->sc_write_mtx); | | 560 | mutex_destroy(&sc->sc_write_mtx); |
540 | mutex_destroy(&sc->sc_fwcmd_mtx); | | 561 | mutex_destroy(&sc->sc_fwcmd_mtx); |
541 | mutex_destroy(&sc->sc_tx_mtx); | | 562 | mutex_destroy(&sc->sc_tx_mtx); |
| | | 563 | mutex_destroy(&sc->sc_rx_mtx); |
542 | mutex_destroy(&sc->sc_task_mtx); | | 564 | mutex_destroy(&sc->sc_task_mtx); |
543 | | | 565 | |
544 | return 0; | | 566 | return 0; |
545 | } | | 567 | } |
546 | | | 568 | |
547 | static int | | 569 | static int |
548 | urtwn_activate(device_t self, enum devact act) | | 570 | urtwn_activate(device_t self, enum devact act) |
549 | { | | 571 | { |
550 | struct urtwn_softc *sc = device_private(self); | | 572 | struct urtwn_softc *sc = device_private(self); |
551 | | | 573 | |
552 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 574 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
553 | | | 575 | |
554 | switch (act) { | | 576 | switch (act) { |
555 | case DVACT_DEACTIVATE: | | 577 | case DVACT_DEACTIVATE: |
556 | if_deactivate(sc->sc_ic.ic_ifp); | | 578 | if_deactivate(sc->sc_ic.ic_ifp); |
557 | return 0; | | 579 | return 0; |
558 | default: | | 580 | default: |
559 | return EOPNOTSUPP; | | 581 | return EOPNOTSUPP; |
560 | } | | 582 | } |
561 | } | | 583 | } |
562 | | | 584 | |
563 | static int | | 585 | static int |
564 | urtwn_open_pipes(struct urtwn_softc *sc) | | 586 | urtwn_open_pipes(struct urtwn_softc *sc) |
565 | { | | 587 | { |
566 | /* Bulk-out endpoints addresses (from highest to lowest prio). */ | | 588 | /* Bulk-out endpoints addresses (from highest to lowest prio). */ |
567 | static const uint8_t epaddr[] = { 0x02, 0x03, 0x05 }; | | 589 | static uint8_t epaddr[3]; |
| | | 590 | static uint8_t rxepaddr[3]; |
568 | usb_interface_descriptor_t *id; | | 591 | usb_interface_descriptor_t *id; |
569 | usb_endpoint_descriptor_t *ed; | | 592 | usb_endpoint_descriptor_t *ed; |
570 | size_t i, ntx = 0; | | 593 | size_t i, ntx = 0, nrx = 0; |
571 | int error; | | 594 | int error; |
572 | | | 595 | |
573 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 596 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
574 | | | 597 | |
575 | /* Determine the number of bulk-out pipes. */ | | 598 | /* Determine the number of bulk-out pipes. */ |
576 | id = usbd_get_interface_descriptor(sc->sc_iface); | | 599 | id = usbd_get_interface_descriptor(sc->sc_iface); |
577 | for (i = 0; i < id->bNumEndpoints; i++) { | | 600 | for (i = 0; i < id->bNumEndpoints; i++) { |
578 | ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); | | 601 | ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); |
579 | if (ed != NULL && | | 602 | if (ed != NULL && |
580 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && | | 603 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && |
581 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) | | 604 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) { |
| | | 605 | epaddr[ntx] = ed->bEndpointAddress; |
582 | ntx++; | | 606 | ntx++; |
| | | 607 | } |
| | | 608 | if (ed != NULL && |
| | | 609 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK && |
| | | 610 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) { |
| | | 611 | rxepaddr[nrx] = ed->bEndpointAddress; |
| | | 612 | nrx++; |
| | | 613 | } |
583 | } | | 614 | } |
584 | DPRINTFN(DBG_INIT, ("%s: %s: found %zd bulk-out pipes\n", | | 615 | DPRINTFN(DBG_INIT, ("%s: %s: found %zd bulk-out pipes\n", |
585 | device_xname(sc->sc_dev), __func__, ntx)); | | 616 | device_xname(sc->sc_dev), __func__, ntx)); |
586 | if (ntx == 0 || ntx > R92C_MAX_EPOUT) { | | 617 | if (ntx == 0 || ntx > R92C_MAX_EPOUT) { |
587 | aprint_error_dev(sc->sc_dev, | | 618 | aprint_error_dev(sc->sc_dev, |
588 | "%zd: invalid number of Tx bulk pipes\n", ntx); | | 619 | "%zd: invalid number of Tx bulk pipes\n", ntx); |
589 | return EIO; | | 620 | return EIO; |
590 | } | | 621 | } |
591 | sc->rx_npipe = 1; | | 622 | sc->rx_npipe = nrx; |
592 | sc->tx_npipe = ntx; | | 623 | sc->tx_npipe = ntx; |
593 | | | 624 | |
594 | /* Open bulk-in pipe at address 0x81. */ | | 625 | /* Open bulk-in pipe at address 0x81. */ |
595 | error = usbd_open_pipe(sc->sc_iface, 0x81, USBD_EXCLUSIVE_USE, | | 626 | for (i = 0; i < nrx; i++) { |
596 | &sc->rx_pipe); | | 627 | error = usbd_open_pipe(sc->sc_iface, rxepaddr[i], |
597 | if (error != 0) { | | 628 | USBD_EXCLUSIVE_USE, &sc->rx_pipe[i]); |
598 | aprint_error_dev(sc->sc_dev, "could not open Rx bulk pipe" | | 629 | if (error != 0) { |
599 | ": %d\n", error); | | 630 | aprint_error_dev(sc->sc_dev, |
600 | goto fail; | | 631 | "could not open Rx bulk pipe 0x%02x: %d\n", |
| | | 632 | rxepaddr[i], error); |
| | | 633 | goto fail; |
| | | 634 | } |
601 | } | | 635 | } |
602 | | | 636 | |
603 | /* Open bulk-out pipes (up to 3). */ | | 637 | /* Open bulk-out pipes (up to 3). */ |
604 | for (i = 0; i < ntx; i++) { | | 638 | for (i = 0; i < ntx; i++) { |
605 | error = usbd_open_pipe(sc->sc_iface, epaddr[i], | | 639 | error = usbd_open_pipe(sc->sc_iface, epaddr[i], |
606 | USBD_EXCLUSIVE_USE, &sc->tx_pipe[i]); | | 640 | USBD_EXCLUSIVE_USE, &sc->tx_pipe[i]); |
607 | if (error != 0) { | | 641 | if (error != 0) { |
608 | aprint_error_dev(sc->sc_dev, | | 642 | aprint_error_dev(sc->sc_dev, |
609 | "could not open Tx bulk pipe 0x%02x: %d\n", | | 643 | "could not open Tx bulk pipe 0x%02x: %d\n", |
610 | epaddr[i], error); | | 644 | epaddr[i], error); |
611 | goto fail; | | 645 | goto fail; |
612 | } | | 646 | } |
613 | } | | 647 | } |
| @@ -622,84 +656,93 @@ urtwn_open_pipes(struct urtwn_softc *sc) | | | @@ -622,84 +656,93 @@ urtwn_open_pipes(struct urtwn_softc *sc) |
622 | if (error != 0) | | 656 | if (error != 0) |
623 | urtwn_close_pipes(sc); | | 657 | urtwn_close_pipes(sc); |
624 | return error; | | 658 | return error; |
625 | } | | 659 | } |
626 | | | 660 | |
627 | static void | | 661 | static void |
628 | urtwn_close_pipes(struct urtwn_softc *sc) | | 662 | urtwn_close_pipes(struct urtwn_softc *sc) |
629 | { | | 663 | { |
630 | struct usbd_pipe *pipe; | | 664 | struct usbd_pipe *pipe; |
631 | size_t i; | | 665 | size_t i; |
632 | | | 666 | |
633 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 667 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
634 | | | 668 | |
635 | /* Close Rx pipe. */ | | 669 | /* Close Rx pipes. */ |
636 | CTASSERT(sizeof(pipe) == sizeof(void *)); | | 670 | CTASSERT(sizeof(pipe) == sizeof(void *)); |
637 | pipe = atomic_swap_ptr(&sc->rx_pipe, NULL); | | 671 | for (i = 0; i < sc->rx_npipe; i++) { |
638 | if (pipe != NULL) { | | 672 | pipe = atomic_swap_ptr(&sc->rx_pipe[i], NULL); |
639 | usbd_close_pipe(pipe); | | 673 | if (pipe != NULL) { |
| | | 674 | usbd_close_pipe(pipe); |
| | | 675 | } |
640 | } | | 676 | } |
| | | 677 | |
641 | /* Close Tx pipes. */ | | 678 | /* Close Tx pipes. */ |
642 | for (i = 0; i < R92C_MAX_EPOUT; i++) { | | 679 | for (i = 0; i < sc->tx_npipe; i++) { |
643 | pipe = atomic_swap_ptr(&sc->tx_pipe[i], NULL); | | 680 | pipe = atomic_swap_ptr(&sc->tx_pipe[i], NULL); |
644 | if (pipe != NULL) { | | 681 | if (pipe != NULL) { |
645 | usbd_close_pipe(pipe); | | 682 | usbd_close_pipe(pipe); |
646 | } | | 683 | } |
647 | } | | 684 | } |
648 | } | | 685 | } |
649 | | | 686 | |
650 | static int | | 687 | static int |
651 | urtwn_alloc_rx_list(struct urtwn_softc *sc) | | 688 | urtwn_alloc_rx_list(struct urtwn_softc *sc) |
652 | { | | 689 | { |
653 | struct urtwn_rx_data *data; | | 690 | struct urtwn_rx_data *data; |
654 | size_t i; | | 691 | size_t i; |
655 | int error = 0; | | 692 | int error = 0; |
656 | | | 693 | |
657 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 694 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
658 | | | 695 | |
659 | for (i = 0; i < URTWN_RX_LIST_COUNT; i++) { | | 696 | for (size_t j = 0; j < sc->rx_npipe; j++) { |
660 | data = &sc->rx_data[i]; | | 697 | TAILQ_INIT(&sc->rx_free_list[j]); |
| | | 698 | for (i = 0; i < URTWN_RX_LIST_COUNT; i++) { |
| | | 699 | data = &sc->rx_data[j][i]; |
661 | | | 700 | |
662 | data->sc = sc; /* Backpointer for callbacks. */ | | 701 | data->sc = sc; /* Backpointer for callbacks. */ |
663 | | | 702 | |
664 | error = usbd_create_xfer(sc->rx_pipe, URTWN_RXBUFSZ, | | 703 | error = usbd_create_xfer(sc->rx_pipe[j], URTWN_RXBUFSZ, |
665 | USBD_SHORT_XFER_OK, 0, &data->xfer); | | 704 | USBD_SHORT_XFER_OK, 0, &data->xfer); |
666 | if (error) { | | 705 | if (error) { |
667 | aprint_error_dev(sc->sc_dev, | | 706 | aprint_error_dev(sc->sc_dev, |
668 | "could not allocate xfer\n"); | | 707 | "could not allocate xfer\n"); |
669 | break; | | 708 | break; |
670 | } | | 709 | } |
671 | | | 710 | |
672 | data->buf = usbd_get_buffer(data->xfer); | | 711 | data->buf = usbd_get_buffer(data->xfer); |
| | | 712 | TAILQ_INSERT_TAIL(&sc->rx_free_list[j], data, next); |
| | | 713 | } |
673 | } | | 714 | } |
674 | if (error != 0) | | 715 | if (error != 0) |
675 | urtwn_free_rx_list(sc); | | 716 | urtwn_free_rx_list(sc); |
676 | return error; | | 717 | return error; |
677 | } | | 718 | } |
678 | | | 719 | |
679 | static void | | 720 | static void |
680 | urtwn_free_rx_list(struct urtwn_softc *sc) | | 721 | urtwn_free_rx_list(struct urtwn_softc *sc) |
681 | { | | 722 | { |
682 | struct usbd_xfer *xfer; | | 723 | struct usbd_xfer *xfer; |
683 | size_t i; | | 724 | size_t i; |
684 | | | 725 | |
685 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 726 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
686 | | | 727 | |
687 | /* NB: Caller must abort pipe first. */ | | 728 | /* NB: Caller must abort pipe first. */ |
688 | for (i = 0; i < URTWN_RX_LIST_COUNT; i++) { | | 729 | for (size_t j = 0; j < sc->rx_npipe; j++) { |
689 | CTASSERT(sizeof(xfer) == sizeof(void *)); | | 730 | for (i = 0; i < URTWN_RX_LIST_COUNT; i++) { |
690 | xfer = atomic_swap_ptr(&sc->rx_data[i].xfer, NULL); | | 731 | CTASSERT(sizeof(xfer) == sizeof(void *)); |
691 | if (xfer != NULL) | | 732 | xfer = atomic_swap_ptr(&sc->rx_data[j][i].xfer, NULL); |
692 | usbd_destroy_xfer(xfer); | | 733 | if (xfer != NULL) |
| | | 734 | usbd_destroy_xfer(xfer); |
| | | 735 | } |
693 | } | | 736 | } |
694 | } | | 737 | } |
695 | | | 738 | |
696 | static int | | 739 | static int |
697 | urtwn_alloc_tx_list(struct urtwn_softc *sc) | | 740 | urtwn_alloc_tx_list(struct urtwn_softc *sc) |
698 | { | | 741 | { |
699 | struct urtwn_tx_data *data; | | 742 | struct urtwn_tx_data *data; |
700 | size_t i; | | 743 | size_t i; |
701 | int error = 0; | | 744 | int error = 0; |
702 | | | 745 | |
703 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 746 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
704 | | | 747 | |
705 | mutex_enter(&sc->sc_tx_mtx); | | 748 | mutex_enter(&sc->sc_tx_mtx); |
| @@ -967,47 +1010,57 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uin | | | @@ -967,47 +1010,57 @@ urtwn_fw_cmd(struct urtwn_softc *sc, uin |
967 | device_xname(sc->sc_dev), __func__, id, buf, len)); | | 1010 | device_xname(sc->sc_dev), __func__, id, buf, len)); |
968 | | | 1011 | |
969 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 1012 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
970 | | | 1013 | |
971 | mutex_enter(&sc->sc_fwcmd_mtx); | | 1014 | mutex_enter(&sc->sc_fwcmd_mtx); |
972 | fwcur = sc->fwcur; | | 1015 | fwcur = sc->fwcur; |
973 | sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; | | 1016 | sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; |
974 | mutex_exit(&sc->sc_fwcmd_mtx); | | 1017 | mutex_exit(&sc->sc_fwcmd_mtx); |
975 | | | 1018 | |
976 | /* Wait for current FW box to be empty. */ | | 1019 | /* Wait for current FW box to be empty. */ |
977 | for (ntries = 0; ntries < 100; ntries++) { | | 1020 | for (ntries = 0; ntries < 100; ntries++) { |
978 | if (!(urtwn_read_1(sc, R92C_HMETFR) & (1 << fwcur))) | | 1021 | if (!(urtwn_read_1(sc, R92C_HMETFR) & (1 << fwcur))) |
979 | break; | | 1022 | break; |
980 | DELAY(1); | | 1023 | DELAY(10); |
981 | } | | 1024 | } |
982 | if (ntries == 100) { | | 1025 | if (ntries == 100) { |
983 | aprint_error_dev(sc->sc_dev, | | 1026 | aprint_error_dev(sc->sc_dev, |
984 | "could not send firmware command %d\n", id); | | 1027 | "could not send firmware command %d\n", id); |
985 | return ETIMEDOUT; | | 1028 | return ETIMEDOUT; |
986 | } | | 1029 | } |
987 | | | 1030 | |
988 | memset(&cmd, 0, sizeof(cmd)); | | 1031 | memset(&cmd, 0, sizeof(cmd)); |
989 | KASSERT(len <= sizeof(cmd.msg)); | | 1032 | KASSERT(len <= sizeof(cmd.msg)); |
990 | memcpy(cmd.msg, buf, len); | | 1033 | memcpy(cmd.msg, buf, len); |
991 | | | 1034 | |
992 | /* Write the first word last since that will trigger the FW. */ | | 1035 | /* Write the first word last since that will trigger the FW. */ |
993 | cp = (uint8_t *)&cmd; | | 1036 | cp = (uint8_t *)&cmd; |
| | | 1037 | cmd.id = id; |
994 | if (len >= 4) { | | 1038 | if (len >= 4) { |
995 | cmd.id = id | R92C_CMD_FLAG_EXT; | | 1039 | if (!ISSET(sc->chip, URTWN_CHIP_92EU)) { |
996 | urtwn_write_region(sc, R92C_HMEBOX_EXT(fwcur), &cp[1], 2); | | 1040 | cmd.id |= R92C_CMD_FLAG_EXT; |
997 | urtwn_write_4(sc, R92C_HMEBOX(fwcur), | | 1041 | urtwn_write_region(sc, R92C_HMEBOX_EXT(fwcur), |
998 | cp[0] + (cp[3] << 8) + (cp[4] << 16) + (cp[5] << 24)); | | 1042 | &cp[1], 2); |
| | | 1043 | urtwn_write_4(sc, R92C_HMEBOX(fwcur), |
| | | 1044 | cp[0] + (cp[3] << 8) + (cp[4] << 16) + |
| | | 1045 | (cp[5] << 24)); |
| | | 1046 | } else { |
| | | 1047 | urtwn_write_region(sc, R92E_HMEBOX_EXT(fwcur), |
| | | 1048 | &cp[4], 2); |
| | | 1049 | urtwn_write_4(sc, R92C_HMEBOX(fwcur), |
| | | 1050 | cp[0] + (cp[1] << 8) + (cp[2] << 16) + |
| | | 1051 | (cp[3] << 24)); |
| | | 1052 | } |
999 | } else { | | 1053 | } else { |
1000 | cmd.id = id; | | | |
1001 | urtwn_write_region(sc, R92C_HMEBOX(fwcur), cp, len); | | 1054 | urtwn_write_region(sc, R92C_HMEBOX(fwcur), cp, len); |
1002 | } | | 1055 | } |
1003 | | | 1056 | |
1004 | return 0; | | 1057 | return 0; |
1005 | } | | 1058 | } |
1006 | | | 1059 | |
1007 | static __inline void | | 1060 | static __inline void |
1008 | urtwn_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, uint32_t val) | | 1061 | urtwn_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, uint32_t val) |
1009 | { | | 1062 | { |
1010 | | | 1063 | |
1011 | sc->sc_rf_write(sc, chain, addr, val); | | 1064 | sc->sc_rf_write(sc, chain, addr, val); |
1012 | } | | 1065 | } |
1013 | | | 1066 | |
| @@ -1019,26 +1072,35 @@ urtwn_r92c_rf_write(struct urtwn_softc * | | | @@ -1019,26 +1072,35 @@ urtwn_r92c_rf_write(struct urtwn_softc * |
1019 | urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), | | 1072 | urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), |
1020 | SM(R92C_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); | | 1073 | SM(R92C_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); |
1021 | } | | 1074 | } |
1022 | | | 1075 | |
1023 | static void | | 1076 | static void |
1024 | urtwn_r88e_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, | | 1077 | urtwn_r88e_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, |
1025 | uint32_t val) | | 1078 | uint32_t val) |
1026 | { | | 1079 | { |
1027 | | | 1080 | |
1028 | urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), | | 1081 | urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), |
1029 | SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); | | 1082 | SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); |
1030 | } | | 1083 | } |
1031 | | | 1084 | |
| | | 1085 | static void |
| | | 1086 | urtwn_r92e_rf_write(struct urtwn_softc *sc, int chain, uint8_t addr, |
| | | 1087 | uint32_t val) |
| | | 1088 | { |
| | | 1089 | |
| | | 1090 | urtwn_bb_write(sc, R92C_LSSI_PARAM(chain), |
| | | 1091 | SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); |
| | | 1092 | } |
| | | 1093 | |
1032 | static uint32_t | | 1094 | static uint32_t |
1033 | urtwn_rf_read(struct urtwn_softc *sc, int chain, uint8_t addr) | | 1095 | urtwn_rf_read(struct urtwn_softc *sc, int chain, uint8_t addr) |
1034 | { | | 1096 | { |
1035 | uint32_t reg[R92C_MAX_CHAINS], val; | | 1097 | uint32_t reg[R92C_MAX_CHAINS], val; |
1036 | | | 1098 | |
1037 | reg[0] = urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)); | | 1099 | reg[0] = urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)); |
1038 | if (chain != 0) { | | 1100 | if (chain != 0) { |
1039 | reg[chain] = urtwn_bb_read(sc, R92C_HSSI_PARAM2(chain)); | | 1101 | reg[chain] = urtwn_bb_read(sc, R92C_HSSI_PARAM2(chain)); |
1040 | } | | 1102 | } |
1041 | | | 1103 | |
1042 | urtwn_bb_write(sc, R92C_HSSI_PARAM2(0), | | 1104 | urtwn_bb_write(sc, R92C_HSSI_PARAM2(0), |
1043 | reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE); | | 1105 | reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE); |
1044 | DELAY(1000); | | 1106 | DELAY(1000); |
| @@ -1174,27 +1236,28 @@ urtwn_efuse_switch_power(struct urtwn_so | | | @@ -1174,27 +1236,28 @@ urtwn_efuse_switch_power(struct urtwn_so |
1174 | (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { | | 1236 | (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { |
1175 | urtwn_write_2(sc, R92C_SYS_CLKR, | | 1237 | urtwn_write_2(sc, R92C_SYS_CLKR, |
1176 | reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); | | 1238 | reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); |
1177 | } | | 1239 | } |
1178 | } | | 1240 | } |
1179 | | | 1241 | |
1180 | static int | | 1242 | static int |
1181 | urtwn_read_chipid(struct urtwn_softc *sc) | | 1243 | urtwn_read_chipid(struct urtwn_softc *sc) |
1182 | { | | 1244 | { |
1183 | uint32_t reg; | | 1245 | uint32_t reg; |
1184 | | | 1246 | |
1185 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 1247 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
1186 | | | 1248 | |
1187 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 1249 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 1250 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
1188 | return 0; | | 1251 | return 0; |
1189 | | | 1252 | |
1190 | reg = urtwn_read_4(sc, R92C_SYS_CFG); | | 1253 | reg = urtwn_read_4(sc, R92C_SYS_CFG); |
1191 | if (reg & R92C_SYS_CFG_TRP_VAUX_EN) { | | 1254 | if (reg & R92C_SYS_CFG_TRP_VAUX_EN) { |
1192 | /* test chip, not supported */ | | 1255 | /* test chip, not supported */ |
1193 | return EIO; | | 1256 | return EIO; |
1194 | } | | 1257 | } |
1195 | if (reg & R92C_SYS_CFG_TYPE_92C) { | | 1258 | if (reg & R92C_SYS_CFG_TYPE_92C) { |
1196 | sc->chip |= URTWN_CHIP_92C; | | 1259 | sc->chip |= URTWN_CHIP_92C; |
1197 | /* Check if it is a castrated 8192C. */ | | 1260 | /* Check if it is a castrated 8192C. */ |
1198 | if (MS(urtwn_read_4(sc, R92C_HPON_FSM), | | 1261 | if (MS(urtwn_read_4(sc, R92C_HPON_FSM), |
1199 | R92C_HPON_FSM_CHIP_BONDING_ID) == | | 1262 | R92C_HPON_FSM_CHIP_BONDING_ID) == |
1200 | R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R) { | | 1263 | R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R) { |
| @@ -1339,27 +1402,27 @@ urtwn_r88e_read_rom(struct urtwn_softc * | | | @@ -1339,27 +1402,27 @@ urtwn_r88e_read_rom(struct urtwn_softc * |
1339 | uint16_t addr = 0; | | 1402 | uint16_t addr = 0; |
1340 | uint8_t off, msk, tmp; | | 1403 | uint8_t off, msk, tmp; |
1341 | int i; | | 1404 | int i; |
1342 | | | 1405 | |
1343 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 1406 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
1344 | | | 1407 | |
1345 | mutex_enter(&sc->sc_write_mtx); | | 1408 | mutex_enter(&sc->sc_write_mtx); |
1346 | | | 1409 | |
1347 | off = 0; | | 1410 | off = 0; |
1348 | urtwn_efuse_switch_power(sc); | | 1411 | urtwn_efuse_switch_power(sc); |
1349 | | | 1412 | |
1350 | /* Read full ROM image. */ | | 1413 | /* Read full ROM image. */ |
1351 | memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom)); | | 1414 | memset(&sc->r88e_rom, 0xff, sizeof(sc->r88e_rom)); |
1352 | while (addr < 1024) { | | 1415 | while (addr < 4096) { |
1353 | reg = urtwn_efuse_read_1(sc, addr); | | 1416 | reg = urtwn_efuse_read_1(sc, addr); |
1354 | if (reg == 0xff) | | 1417 | if (reg == 0xff) |
1355 | break; | | 1418 | break; |
1356 | addr++; | | 1419 | addr++; |
1357 | if ((reg & 0x1f) == 0x0f) { | | 1420 | if ((reg & 0x1f) == 0x0f) { |
1358 | tmp = (reg & 0xe0) >> 5; | | 1421 | tmp = (reg & 0xe0) >> 5; |
1359 | reg = urtwn_efuse_read_1(sc, addr); | | 1422 | reg = urtwn_efuse_read_1(sc, addr); |
1360 | if ((reg & 0x0f) != 0x0f) | | 1423 | if ((reg & 0x0f) != 0x0f) |
1361 | off = ((reg & 0xf0) >> 1) | tmp; | | 1424 | off = ((reg & 0xf0) >> 1) | tmp; |
1362 | addr++; | | 1425 | addr++; |
1363 | } else | | 1426 | } else |
1364 | off = reg >> 4; | | 1427 | off = reg >> 4; |
1365 | msk = reg & 0xf; | | 1428 | msk = reg & 0xf; |
| @@ -1382,28 +1445,33 @@ urtwn_r88e_read_rom(struct urtwn_softc * | | | @@ -1382,28 +1445,33 @@ urtwn_r88e_read_rom(struct urtwn_softc * |
1382 | sc->cck_tx_pwr[i] = sc->r88e_rom[addr++]; | | 1445 | sc->cck_tx_pwr[i] = sc->r88e_rom[addr++]; |
1383 | for (i = 0; i < 5; i++) | | 1446 | for (i = 0; i < 5; i++) |
1384 | sc->ht40_tx_pwr[i] = sc->r88e_rom[addr++]; | | 1447 | sc->ht40_tx_pwr[i] = sc->r88e_rom[addr++]; |
1385 | sc->bw20_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf0) >> 4; | | 1448 | sc->bw20_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf0) >> 4; |
1386 | if (sc->bw20_tx_pwr_diff & 0x08) | | 1449 | if (sc->bw20_tx_pwr_diff & 0x08) |
1387 | sc->bw20_tx_pwr_diff |= 0xf0; | | 1450 | sc->bw20_tx_pwr_diff |= 0xf0; |
1388 | sc->ofdm_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf); | | 1451 | sc->ofdm_tx_pwr_diff = (sc->r88e_rom[addr] & 0xf); |
1389 | if (sc->ofdm_tx_pwr_diff & 0x08) | | 1452 | if (sc->ofdm_tx_pwr_diff & 0x08) |
1390 | sc->ofdm_tx_pwr_diff |= 0xf0; | | 1453 | sc->ofdm_tx_pwr_diff |= 0xf0; |
1391 | sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY); | | 1454 | sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY); |
1392 | | | 1455 | |
1393 | IEEE80211_ADDR_COPY(ic->ic_myaddr, &sc->r88e_rom[0xd7]); | | 1456 | IEEE80211_ADDR_COPY(ic->ic_myaddr, &sc->r88e_rom[0xd7]); |
1394 | | | 1457 | |
1395 | sc->sc_rf_write = urtwn_r88e_rf_write; | | 1458 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) { |
1396 | sc->sc_power_on = urtwn_r88e_power_on; | | 1459 | sc->sc_power_on = urtwn_r92e_power_on; |
| | | 1460 | sc->sc_rf_write = urtwn_r92e_rf_write; |
| | | 1461 | } else { |
| | | 1462 | sc->sc_power_on = urtwn_r88e_power_on; |
| | | 1463 | sc->sc_rf_write = urtwn_r88e_rf_write; |
| | | 1464 | } |
1397 | sc->sc_dma_init = urtwn_r88e_dma_init; | | 1465 | sc->sc_dma_init = urtwn_r88e_dma_init; |
1398 | | | 1466 | |
1399 | mutex_exit(&sc->sc_write_mtx); | | 1467 | mutex_exit(&sc->sc_write_mtx); |
1400 | } | | 1468 | } |
1401 | | | 1469 | |
1402 | static int | | 1470 | static int |
1403 | urtwn_media_change(struct ifnet *ifp) | | 1471 | urtwn_media_change(struct ifnet *ifp) |
1404 | { | | 1472 | { |
1405 | #ifdef URTWN_DEBUG | | 1473 | #ifdef URTWN_DEBUG |
1406 | struct urtwn_softc *sc = ifp->if_softc; | | 1474 | struct urtwn_softc *sc = ifp->if_softc; |
1407 | #endif | | 1475 | #endif |
1408 | int error; | | 1476 | int error; |
1409 | | | 1477 | |
| @@ -1423,37 +1491,37 @@ urtwn_media_change(struct ifnet *ifp) | | | @@ -1423,37 +1491,37 @@ urtwn_media_change(struct ifnet *ifp) |
1423 | * Initialize rate adaptation in firmware. | | 1491 | * Initialize rate adaptation in firmware. |
1424 | */ | | 1492 | */ |
1425 | static int | | 1493 | static int |
1426 | urtwn_ra_init(struct urtwn_softc *sc) | | 1494 | urtwn_ra_init(struct urtwn_softc *sc) |
1427 | { | | 1495 | { |
1428 | static const uint8_t map[] = { | | 1496 | static const uint8_t map[] = { |
1429 | 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 | | 1497 | 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 |
1430 | }; | | 1498 | }; |
1431 | struct ieee80211com *ic = &sc->sc_ic; | | 1499 | struct ieee80211com *ic = &sc->sc_ic; |
1432 | struct ieee80211_node *ni = ic->ic_bss; | | 1500 | struct ieee80211_node *ni = ic->ic_bss; |
1433 | struct ieee80211_rateset *rs = &ni->ni_rates; | | 1501 | struct ieee80211_rateset *rs = &ni->ni_rates; |
1434 | struct r92c_fw_cmd_macid_cfg cmd; | | 1502 | struct r92c_fw_cmd_macid_cfg cmd; |
1435 | uint32_t rates, basicrates; | | 1503 | uint32_t rates, basicrates; |
1436 | uint32_t mask; | | 1504 | uint32_t mask, rrsr_mask, rrsr_rate; |
1437 | uint8_t mode; | | 1505 | uint8_t mode; |
1438 | size_t maxrate, maxbasicrate, i, j; | | 1506 | size_t maxrate, maxbasicrate, i, j; |
1439 | int error; | | 1507 | int error; |
1440 | | | 1508 | |
1441 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 1509 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
1442 | | | 1510 | |
1443 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 1511 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
1444 | | | 1512 | |
1445 | /* Get normal and basic rates mask. */ | | 1513 | /* Get normal and basic rates mask. */ |
1446 | rates = basicrates = 0; | | 1514 | rates = basicrates = 1; |
1447 | maxrate = maxbasicrate = 0; | | 1515 | maxrate = maxbasicrate = 0; |
1448 | for (i = 0; i < rs->rs_nrates; i++) { | | 1516 | for (i = 0; i < rs->rs_nrates; i++) { |
1449 | /* Convert 802.11 rate to HW rate index. */ | | 1517 | /* Convert 802.11 rate to HW rate index. */ |
1450 | for (j = 0; j < __arraycount(map); j++) { | | 1518 | for (j = 0; j < __arraycount(map); j++) { |
1451 | if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == map[j]) { | | 1519 | if ((rs->rs_rates[i] & IEEE80211_RATE_VAL) == map[j]) { |
1452 | break; | | 1520 | break; |
1453 | } | | 1521 | } |
1454 | } | | 1522 | } |
1455 | if (j == __arraycount(map)) { | | 1523 | if (j == __arraycount(map)) { |
1456 | /* Unknown rate, skip. */ | | 1524 | /* Unknown rate, skip. */ |
1457 | continue; | | 1525 | continue; |
1458 | } | | 1526 | } |
1459 | | | 1527 | |
| @@ -1468,65 +1536,80 @@ urtwn_ra_init(struct urtwn_softc *sc) | | | @@ -1468,65 +1536,80 @@ urtwn_ra_init(struct urtwn_softc *sc) |
1468 | maxbasicrate = j; | | 1536 | maxbasicrate = j; |
1469 | } | | 1537 | } |
1470 | } | | 1538 | } |
1471 | } | | 1539 | } |
1472 | if (ic->ic_curmode == IEEE80211_MODE_11B) { | | 1540 | if (ic->ic_curmode == IEEE80211_MODE_11B) { |
1473 | mode = R92C_RAID_11B; | | 1541 | mode = R92C_RAID_11B; |
1474 | } else { | | 1542 | } else { |
1475 | mode = R92C_RAID_11BG; | | 1543 | mode = R92C_RAID_11BG; |
1476 | } | | 1544 | } |
1477 | DPRINTFN(DBG_INIT, ("%s: %s: mode=0x%x rates=0x%x, basicrates=0x%x, " | | 1545 | DPRINTFN(DBG_INIT, ("%s: %s: mode=0x%x rates=0x%x, basicrates=0x%x, " |
1478 | "maxrate=%zx, maxbasicrate=%zx\n", | | 1546 | "maxrate=%zx, maxbasicrate=%zx\n", |
1479 | device_xname(sc->sc_dev), __func__, mode, rates, basicrates, | | 1547 | device_xname(sc->sc_dev), __func__, mode, rates, basicrates, |
1480 | maxrate, maxbasicrate)); | | 1548 | maxrate, maxbasicrate)); |
1481 | if (basicrates == 0) { | | 1549 | |
1482 | basicrates |= 1; /* add 1Mbps */ | | 1550 | if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) { |
| | | 1551 | maxbasicrate |= R92C_RATE_SHORTGI; |
| | | 1552 | maxrate |= R92C_RATE_SHORTGI; |
1483 | } | | 1553 | } |
1484 | | | 1554 | |
1485 | /* Set rates mask for group addressed frames. */ | | 1555 | /* Set rates mask for group addressed frames. */ |
1486 | cmd.macid = URTWN_MACID_BC | URTWN_MACID_VALID; | | 1556 | cmd.macid = URTWN_MACID_BC | URTWN_MACID_VALID; |
| | | 1557 | if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) |
| | | 1558 | cmd.macid |= URTWN_MACID_SHORTGI; |
| | | 1559 | |
1487 | mask = (mode << 28) | basicrates; | | 1560 | mask = (mode << 28) | basicrates; |
1488 | cmd.mask[0] = (uint8_t)mask; | | 1561 | cmd.mask[0] = (uint8_t)mask; |
1489 | cmd.mask[1] = (uint8_t)(mask >> 8); | | 1562 | cmd.mask[1] = (uint8_t)(mask >> 8); |
1490 | cmd.mask[2] = (uint8_t)(mask >> 16); | | 1563 | cmd.mask[2] = (uint8_t)(mask >> 16); |
1491 | cmd.mask[3] = (uint8_t)(mask >> 24); | | 1564 | cmd.mask[3] = (uint8_t)(mask >> 24); |
1492 | error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); | | 1565 | error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); |
1493 | if (error != 0) { | | 1566 | if (error != 0) { |
1494 | aprint_error_dev(sc->sc_dev, | | 1567 | aprint_error_dev(sc->sc_dev, |
1495 | "could not add broadcast station\n"); | | 1568 | "could not add broadcast station\n"); |
1496 | return error; | | 1569 | return error; |
1497 | } | | 1570 | } |
1498 | /* Set initial MRR rate. */ | | 1571 | /* Set initial MRR rate. */ |
1499 | DPRINTFN(DBG_INIT, ("%s: %s: maxbasicrate=%zd\n", | | 1572 | DPRINTFN(DBG_INIT, ("%s: %s: maxbasicrate=%zd\n", |
1500 | device_xname(sc->sc_dev), __func__, maxbasicrate)); | | 1573 | device_xname(sc->sc_dev), __func__, maxbasicrate)); |
1501 | urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BC), maxbasicrate); | | 1574 | urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BC), maxbasicrate); |
1502 | | | 1575 | |
1503 | /* Set rates mask for unicast frames. */ | | 1576 | /* Set rates mask for unicast frames. */ |
1504 | cmd.macid = URTWN_MACID_BSS | URTWN_MACID_VALID; | | 1577 | cmd.macid = URTWN_MACID_BSS | URTWN_MACID_VALID; |
| | | 1578 | if (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) |
| | | 1579 | cmd.macid |= URTWN_MACID_SHORTGI; |
| | | 1580 | |
1505 | mask = (mode << 28) | rates; | | 1581 | mask = (mode << 28) | rates; |
1506 | cmd.mask[0] = (uint8_t)mask; | | 1582 | cmd.mask[0] = (uint8_t)mask; |
1507 | cmd.mask[1] = (uint8_t)(mask >> 8); | | 1583 | cmd.mask[1] = (uint8_t)(mask >> 8); |
1508 | cmd.mask[2] = (uint8_t)(mask >> 16); | | 1584 | cmd.mask[2] = (uint8_t)(mask >> 16); |
1509 | cmd.mask[3] = (uint8_t)(mask >> 24); | | 1585 | cmd.mask[3] = (uint8_t)(mask >> 24); |
1510 | error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); | | 1586 | error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); |
1511 | if (error != 0) { | | 1587 | if (error != 0) { |
1512 | aprint_error_dev(sc->sc_dev, "could not add BSS station\n"); | | 1588 | aprint_error_dev(sc->sc_dev, "could not add BSS station\n"); |
1513 | return error; | | 1589 | return error; |
1514 | } | | 1590 | } |
1515 | /* Set initial MRR rate. */ | | 1591 | /* Set initial MRR rate. */ |
1516 | DPRINTFN(DBG_INIT, ("%s: %s: maxrate=%zd\n", device_xname(sc->sc_dev), | | 1592 | DPRINTFN(DBG_INIT, ("%s: %s: maxrate=%zd\n", device_xname(sc->sc_dev), |
1517 | __func__, maxrate)); | | 1593 | __func__, maxrate)); |
1518 | urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BSS), maxrate); | | 1594 | urtwn_write_1(sc, R92C_INIDATA_RATE_SEL(URTWN_MACID_BSS), maxrate); |
1519 | | | 1595 | |
| | | 1596 | rrsr_rate = ic->ic_fixed_rate; |
| | | 1597 | if (rrsr_rate == -1) |
| | | 1598 | rrsr_rate = 11; |
| | | 1599 | |
| | | 1600 | rrsr_mask = 0xffff >> (15 - rrsr_rate); |
| | | 1601 | urtwn_write_2(sc, R92C_RRSR, rrsr_mask); |
| | | 1602 | |
1520 | /* Indicate highest supported rate. */ | | 1603 | /* Indicate highest supported rate. */ |
1521 | ni->ni_txrate = rs->rs_nrates - 1; | | 1604 | ni->ni_txrate = rs->rs_nrates - 1; |
1522 | | | 1605 | |
1523 | return 0; | | 1606 | return 0; |
1524 | } | | 1607 | } |
1525 | | | 1608 | |
1526 | static int | | 1609 | static int |
1527 | urtwn_get_nettype(struct urtwn_softc *sc) | | 1610 | urtwn_get_nettype(struct urtwn_softc *sc) |
1528 | { | | 1611 | { |
1529 | struct ieee80211com *ic = &sc->sc_ic; | | 1612 | struct ieee80211com *ic = &sc->sc_ic; |
1530 | int type; | | 1613 | int type; |
1531 | | | 1614 | |
1532 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 1615 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
| @@ -1593,27 +1676,37 @@ urtwn_tsf_sync_enable(struct urtwn_softc | | | @@ -1593,27 +1676,37 @@ urtwn_tsf_sync_enable(struct urtwn_softc |
1593 | } | | 1676 | } |
1594 | | | 1677 | |
1595 | static void | | 1678 | static void |
1596 | urtwn_set_led(struct urtwn_softc *sc, int led, int on) | | 1679 | urtwn_set_led(struct urtwn_softc *sc, int led, int on) |
1597 | { | | 1680 | { |
1598 | uint8_t reg; | | 1681 | uint8_t reg; |
1599 | | | 1682 | |
1600 | DPRINTFN(DBG_FN, ("%s: %s: led=%d, on=%d\n", device_xname(sc->sc_dev), | | 1683 | DPRINTFN(DBG_FN, ("%s: %s: led=%d, on=%d\n", device_xname(sc->sc_dev), |
1601 | __func__, led, on)); | | 1684 | __func__, led, on)); |
1602 | | | 1685 | |
1603 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 1686 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
1604 | | | 1687 | |
1605 | if (led == URTWN_LED_LINK) { | | 1688 | if (led == URTWN_LED_LINK) { |
1606 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { | | 1689 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 1690 | urtwn_write_1(sc, 0x64, urtwn_read_1(sc, 0x64) & 0xfe); |
| | | 1691 | reg = urtwn_read_1(sc, R92C_LEDCFG1) & R92E_LEDSON; |
| | | 1692 | urtwn_write_1(sc, R92C_LEDCFG1, reg | |
| | | 1693 | (R92C_LEDCFG0_DIS << 1)); |
| | | 1694 | if (on) { |
| | | 1695 | reg = urtwn_read_1(sc, R92C_LEDCFG1) & |
| | | 1696 | R92E_LEDSON; |
| | | 1697 | urtwn_write_1(sc, R92C_LEDCFG1, reg); |
| | | 1698 | } |
| | | 1699 | } else if (ISSET(sc->chip, URTWN_CHIP_88E)) { |
1607 | reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0xf0; | | 1700 | reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0xf0; |
1608 | urtwn_write_1(sc, R92C_LEDCFG2, reg | 0x60); | | 1701 | urtwn_write_1(sc, R92C_LEDCFG2, reg | 0x60); |
1609 | if (!on) { | | 1702 | if (!on) { |
1610 | reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0x90; | | 1703 | reg = urtwn_read_1(sc, R92C_LEDCFG2) & 0x90; |
1611 | urtwn_write_1(sc, R92C_LEDCFG2, | | 1704 | urtwn_write_1(sc, R92C_LEDCFG2, |
1612 | reg | R92C_LEDCFG0_DIS); | | 1705 | reg | R92C_LEDCFG0_DIS); |
1613 | reg = urtwn_read_1(sc, R92C_MAC_PINMUX_CFG); | | 1706 | reg = urtwn_read_1(sc, R92C_MAC_PINMUX_CFG); |
1614 | urtwn_write_1(sc, R92C_MAC_PINMUX_CFG, | | 1707 | urtwn_write_1(sc, R92C_MAC_PINMUX_CFG, |
1615 | reg & 0xfe); | | 1708 | reg & 0xfe); |
1616 | } | | 1709 | } |
1617 | } else { | | 1710 | } else { |
1618 | reg = urtwn_read_1(sc, R92C_LEDCFG0) & 0x70; | | 1711 | reg = urtwn_read_1(sc, R92C_LEDCFG0) & 0x70; |
1619 | if (!on) { | | 1712 | if (!on) { |
| @@ -1634,41 +1727,51 @@ urtwn_calib_to(void *arg) | | | @@ -1634,41 +1727,51 @@ urtwn_calib_to(void *arg) |
1634 | | | 1727 | |
1635 | if (sc->sc_dying) | | 1728 | if (sc->sc_dying) |
1636 | return; | | 1729 | return; |
1637 | | | 1730 | |
1638 | /* Do it in a process context. */ | | 1731 | /* Do it in a process context. */ |
1639 | urtwn_do_async(sc, urtwn_calib_to_cb, NULL, 0); | | 1732 | urtwn_do_async(sc, urtwn_calib_to_cb, NULL, 0); |
1640 | } | | 1733 | } |
1641 | | | 1734 | |
1642 | /* ARGSUSED */ | | 1735 | /* ARGSUSED */ |
1643 | static void | | 1736 | static void |
1644 | urtwn_calib_to_cb(struct urtwn_softc *sc, void *arg) | | 1737 | urtwn_calib_to_cb(struct urtwn_softc *sc, void *arg) |
1645 | { | | 1738 | { |
1646 | struct r92c_fw_cmd_rssi cmd; | | 1739 | struct r92c_fw_cmd_rssi cmd; |
| | | 1740 | struct r92e_fw_cmd_rssi cmde; |
1647 | | | 1741 | |
1648 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 1742 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
1649 | | | 1743 | |
1650 | if (sc->sc_ic.ic_state != IEEE80211_S_RUN) | | 1744 | if (sc->sc_ic.ic_state != IEEE80211_S_RUN) |
1651 | goto restart_timer; | | 1745 | goto restart_timer; |
1652 | | | 1746 | |
1653 | mutex_enter(&sc->sc_write_mtx); | | 1747 | mutex_enter(&sc->sc_write_mtx); |
1654 | if (sc->avg_pwdb != -1) { | | 1748 | if (sc->avg_pwdb != -1) { |
1655 | /* Indicate Rx signal strength to FW for rate adaptation. */ | | 1749 | /* Indicate Rx signal strength to FW for rate adaptation. */ |
1656 | memset(&cmd, 0, sizeof(cmd)); | | 1750 | memset(&cmd, 0, sizeof(cmd)); |
| | | 1751 | memset(&cmde, 0, sizeof(cmde)); |
1657 | cmd.macid = 0; /* BSS. */ | | 1752 | cmd.macid = 0; /* BSS. */ |
| | | 1753 | cmde.macid = 0; /* BSS. */ |
1658 | cmd.pwdb = sc->avg_pwdb; | | 1754 | cmd.pwdb = sc->avg_pwdb; |
| | | 1755 | cmde.pwdb = sc->avg_pwdb; |
1659 | DPRINTFN(DBG_RF, ("%s: %s: sending RSSI command avg=%d\n", | | 1756 | DPRINTFN(DBG_RF, ("%s: %s: sending RSSI command avg=%d\n", |
1660 | device_xname(sc->sc_dev), __func__, sc->avg_pwdb)); | | 1757 | device_xname(sc->sc_dev), __func__, sc->avg_pwdb)); |
1661 | urtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd)); | | 1758 | if (!ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 1759 | urtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, |
| | | 1760 | sizeof(cmd)); |
| | | 1761 | } else { |
| | | 1762 | urtwn_fw_cmd(sc, R92E_CMD_RSSI_REPORT, &cmde, |
| | | 1763 | sizeof(cmde)); |
| | | 1764 | } |
1662 | } | | 1765 | } |
1663 | | | 1766 | |
1664 | /* Do temperature compensation. */ | | 1767 | /* Do temperature compensation. */ |
1665 | urtwn_temp_calib(sc); | | 1768 | urtwn_temp_calib(sc); |
1666 | mutex_exit(&sc->sc_write_mtx); | | 1769 | mutex_exit(&sc->sc_write_mtx); |
1667 | | | 1770 | |
1668 | restart_timer: | | 1771 | restart_timer: |
1669 | if (!sc->sc_dying) { | | 1772 | if (!sc->sc_dying) { |
1670 | /* Restart calibration timer. */ | | 1773 | /* Restart calibration timer. */ |
1671 | callout_schedule(&sc->sc_calib_to, hz); | | 1774 | callout_schedule(&sc->sc_calib_to, hz); |
1672 | } | | 1775 | } |
1673 | } | | 1776 | } |
1674 | | | 1777 | |
| @@ -1853,40 +1956,32 @@ urtwn_newstate_cb(struct urtwn_softc *sc | | | @@ -1853,40 +1956,32 @@ urtwn_newstate_cb(struct urtwn_softc *sc |
1853 | urtwn_read_1(sc, R92C_TXPAUSE) | 0x0f); | | 1956 | urtwn_read_1(sc, R92C_TXPAUSE) | 0x0f); |
1854 | | | 1957 | |
1855 | urtwn_set_chan(sc, ic->ic_curchan, | | 1958 | urtwn_set_chan(sc, ic->ic_curchan, |
1856 | IEEE80211_HTINFO_2NDCHAN_NONE); | | 1959 | IEEE80211_HTINFO_2NDCHAN_NONE); |
1857 | | | 1960 | |
1858 | /* Start periodic scan. */ | | 1961 | /* Start periodic scan. */ |
1859 | if (!sc->sc_dying) | | 1962 | if (!sc->sc_dying) |
1860 | callout_schedule(&sc->sc_scan_to, hz / 5); | | 1963 | callout_schedule(&sc->sc_scan_to, hz / 5); |
1861 | break; | | 1964 | break; |
1862 | | | 1965 | |
1863 | case IEEE80211_S_AUTH: | | 1966 | case IEEE80211_S_AUTH: |
1864 | /* Set initial gain under link. */ | | 1967 | /* Set initial gain under link. */ |
1865 | reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0)); | | 1968 | reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0)); |
1866 | #ifdef doaslinux | | | |
1867 | reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); | | 1969 | reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); |
1868 | #else | | | |
1869 | reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); | | | |
1870 | #endif | | | |
1871 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); | | 1970 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); |
1872 | | | 1971 | |
1873 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 1972 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { |
1874 | reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); | | 1973 | reg = urtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); |
1875 | #ifdef doaslinux | | | |
1876 | reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); | | 1974 | reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x32); |
1877 | #else | | | |
1878 | reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, 0x20); | | | |
1879 | #endif | | | |
1880 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); | | 1975 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); |
1881 | } | | 1976 | } |
1882 | | | 1977 | |
1883 | /* Set media status to 'No Link'. */ | | 1978 | /* Set media status to 'No Link'. */ |
1884 | urtwn_set_nettype0_msr(sc, R92C_CR_NETTYPE_NOLINK); | | 1979 | urtwn_set_nettype0_msr(sc, R92C_CR_NETTYPE_NOLINK); |
1885 | | | 1980 | |
1886 | /* Allow Rx from any BSSID. */ | | 1981 | /* Allow Rx from any BSSID. */ |
1887 | urtwn_write_4(sc, R92C_RCR, | | 1982 | urtwn_write_4(sc, R92C_RCR, |
1888 | urtwn_read_4(sc, R92C_RCR) & | | 1983 | urtwn_read_4(sc, R92C_RCR) & |
1889 | ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN)); | | 1984 | ~(R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN)); |
1890 | | | 1985 | |
1891 | urtwn_set_chan(sc, ic->ic_curchan, | | 1986 | urtwn_set_chan(sc, ic->ic_curchan, |
1892 | IEEE80211_HTINFO_2NDCHAN_NONE); | | 1987 | IEEE80211_HTINFO_2NDCHAN_NONE); |
| @@ -1984,27 +2079,28 @@ urtwn_newstate_cb(struct urtwn_softc *sc | | | @@ -1984,27 +2079,28 @@ urtwn_newstate_cb(struct urtwn_softc *sc |
1984 | break; | | 2079 | break; |
1985 | } | | 2080 | } |
1986 | urtwn_write_1(sc, R92C_MSR, msr); | | 2081 | urtwn_write_1(sc, R92C_MSR, msr); |
1987 | | | 2082 | |
1988 | sifs_time = 10; | | 2083 | sifs_time = 10; |
1989 | urtwn_write_1(sc, R92C_SIFS_CCK + 1, sifs_time); | | 2084 | urtwn_write_1(sc, R92C_SIFS_CCK + 1, sifs_time); |
1990 | urtwn_write_1(sc, R92C_SIFS_OFDM + 1, sifs_time); | | 2085 | urtwn_write_1(sc, R92C_SIFS_OFDM + 1, sifs_time); |
1991 | urtwn_write_1(sc, R92C_SPEC_SIFS + 1, sifs_time); | | 2086 | urtwn_write_1(sc, R92C_SPEC_SIFS + 1, sifs_time); |
1992 | urtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, sifs_time); | | 2087 | urtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, sifs_time); |
1993 | urtwn_write_1(sc, R92C_R2T_SIFS + 1, sifs_time); | | 2088 | urtwn_write_1(sc, R92C_R2T_SIFS + 1, sifs_time); |
1994 | urtwn_write_1(sc, R92C_T2T_SIFS + 1, sifs_time); | | 2089 | urtwn_write_1(sc, R92C_T2T_SIFS + 1, sifs_time); |
1995 | | | 2090 | |
1996 | /* Intialize rate adaptation. */ | | 2091 | /* Intialize rate adaptation. */ |
1997 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 2092 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 2093 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
1998 | ni->ni_txrate = ni->ni_rates.rs_nrates - 1; | | 2094 | ni->ni_txrate = ni->ni_rates.rs_nrates - 1; |
1999 | else | | 2095 | else |
2000 | urtwn_ra_init(sc); | | 2096 | urtwn_ra_init(sc); |
2001 | | | 2097 | |
2002 | /* Turn link LED on. */ | | 2098 | /* Turn link LED on. */ |
2003 | urtwn_set_led(sc, URTWN_LED_LINK, 1); | | 2099 | urtwn_set_led(sc, URTWN_LED_LINK, 1); |
2004 | | | 2100 | |
2005 | /* Reset average RSSI. */ | | 2101 | /* Reset average RSSI. */ |
2006 | sc->avg_pwdb = -1; | | 2102 | sc->avg_pwdb = -1; |
2007 | | | 2103 | |
2008 | /* Reset temperature calibration state machine. */ | | 2104 | /* Reset temperature calibration state machine. */ |
2009 | sc->thcal_state = 0; | | 2105 | sc->thcal_state = 0; |
2010 | sc->thcal_lctemp = 0; | | 2106 | sc->thcal_lctemp = 0; |
| @@ -2242,27 +2338,27 @@ urtwn_rx_frame(struct urtwn_softc *sc, u | | | @@ -2242,27 +2338,27 @@ urtwn_rx_frame(struct urtwn_softc *sc, u |
2242 | } | | 2338 | } |
2243 | if (__predict_false(pktlen > MCLBYTES)) { | | 2339 | if (__predict_false(pktlen > MCLBYTES)) { |
2244 | DPRINTFN(DBG_RX, ("%s: %s: packet too big %d\n", | | 2340 | DPRINTFN(DBG_RX, ("%s: %s: packet too big %d\n", |
2245 | device_xname(sc->sc_dev), __func__, pktlen)); | | 2341 | device_xname(sc->sc_dev), __func__, pktlen)); |
2246 | ifp->if_ierrors++; | | 2342 | ifp->if_ierrors++; |
2247 | return; | | 2343 | return; |
2248 | } | | 2344 | } |
2249 | | | 2345 | |
2250 | rate = MS(rxdw3, R92C_RXDW3_RATE); | | 2346 | rate = MS(rxdw3, R92C_RXDW3_RATE); |
2251 | infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8; | | 2347 | infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8; |
2252 | | | 2348 | |
2253 | /* Get RSSI from PHY status descriptor if present. */ | | 2349 | /* Get RSSI from PHY status descriptor if present. */ |
2254 | if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { | | 2350 | if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { |
2255 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 2351 | if (!ISSET(sc->chip, URTWN_CHIP_92C)) |
2256 | rssi = urtwn_r88e_get_rssi(sc, rate, &stat[1]); | | 2352 | rssi = urtwn_r88e_get_rssi(sc, rate, &stat[1]); |
2257 | else | | 2353 | else |
2258 | rssi = urtwn_get_rssi(sc, rate, &stat[1]); | | 2354 | rssi = urtwn_get_rssi(sc, rate, &stat[1]); |
2259 | /* Update our average RSSI. */ | | 2355 | /* Update our average RSSI. */ |
2260 | urtwn_update_avgrssi(sc, rate, rssi); | | 2356 | urtwn_update_avgrssi(sc, rate, rssi); |
2261 | } | | 2357 | } |
2262 | | | 2358 | |
2263 | DPRINTFN(DBG_RX, ("%s: %s: Rx frame len=%d rate=%d infosz=%d rssi=%d\n", | | 2359 | DPRINTFN(DBG_RX, ("%s: %s: Rx frame len=%d rate=%d infosz=%d rssi=%d\n", |
2264 | device_xname(sc->sc_dev), __func__, pktlen, rate, infosz, rssi)); | | 2360 | device_xname(sc->sc_dev), __func__, pktlen, rate, infosz, rssi)); |
2265 | | | 2361 | |
2266 | MGETHDR(m, M_DONTWAIT, MT_DATA); | | 2362 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
2267 | if (__predict_false(m == NULL)) { | | 2363 | if (__predict_false(m == NULL)) { |
2268 | aprint_error_dev(sc->sc_dev, "couldn't allocate rx mbuf\n"); | | 2364 | aprint_error_dev(sc->sc_dev, "couldn't allocate rx mbuf\n"); |
| @@ -2328,36 +2424,43 @@ urtwn_rx_frame(struct urtwn_softc *sc, u | | | @@ -2328,36 +2424,43 @@ urtwn_rx_frame(struct urtwn_softc *sc, u |
2328 | | | 2424 | |
2329 | /* Node is no longer needed. */ | | 2425 | /* Node is no longer needed. */ |
2330 | ieee80211_free_node(ni); | | 2426 | ieee80211_free_node(ni); |
2331 | | | 2427 | |
2332 | splx(s); | | 2428 | splx(s); |
2333 | } | | 2429 | } |
2334 | | | 2430 | |
2335 | static void | | 2431 | static void |
2336 | urtwn_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) | | 2432 | urtwn_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) |
2337 | { | | 2433 | { |
2338 | struct urtwn_rx_data *data = priv; | | 2434 | struct urtwn_rx_data *data = priv; |
2339 | struct urtwn_softc *sc = data->sc; | | 2435 | struct urtwn_softc *sc = data->sc; |
2340 | struct r92c_rx_stat *stat; | | 2436 | struct r92c_rx_stat *stat; |
| | | 2437 | size_t pidx = data->pidx; |
2341 | uint32_t rxdw0; | | 2438 | uint32_t rxdw0; |
2342 | uint8_t *buf; | | 2439 | uint8_t *buf; |
2343 | int len, totlen, pktlen, infosz, npkts; | | 2440 | int len, totlen, pktlen, infosz, npkts; |
2344 | | | 2441 | |
2345 | DPRINTFN(DBG_FN|DBG_RX, ("%s: %s: status=%d\n", | | 2442 | DPRINTFN(DBG_FN|DBG_RX, ("%s: %s: status=%d\n", |
2346 | device_xname(sc->sc_dev), __func__, status)); | | 2443 | device_xname(sc->sc_dev), __func__, status)); |
2347 | | | 2444 | |
| | | 2445 | mutex_enter(&sc->sc_rx_mtx); |
| | | 2446 | TAILQ_REMOVE(&sc->rx_free_list[pidx], data, next); |
| | | 2447 | TAILQ_INSERT_TAIL(&sc->rx_free_list[pidx], data, next); |
| | | 2448 | /* Put this Rx buffer back to our free list. */ |
| | | 2449 | mutex_exit(&sc->sc_rx_mtx); |
| | | 2450 | |
2348 | if (__predict_false(status != USBD_NORMAL_COMPLETION)) { | | 2451 | if (__predict_false(status != USBD_NORMAL_COMPLETION)) { |
2349 | if (status == USBD_STALLED) | | 2452 | if (status == USBD_STALLED) |
2350 | usbd_clear_endpoint_stall_async(sc->rx_pipe); | | 2453 | usbd_clear_endpoint_stall_async(sc->rx_pipe[pidx]); |
2351 | else if (status != USBD_CANCELLED) | | 2454 | else if (status != USBD_CANCELLED) |
2352 | goto resubmit; | | 2455 | goto resubmit; |
2353 | return; | | 2456 | return; |
2354 | } | | 2457 | } |
2355 | usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); | | 2458 | usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); |
2356 | | | 2459 | |
2357 | if (__predict_false(len < (int)sizeof(*stat))) { | | 2460 | if (__predict_false(len < (int)sizeof(*stat))) { |
2358 | DPRINTFN(DBG_RX, ("%s: %s: xfer too short %d\n", | | 2461 | DPRINTFN(DBG_RX, ("%s: %s: xfer too short %d\n", |
2359 | device_xname(sc->sc_dev), __func__, len)); | | 2462 | device_xname(sc->sc_dev), __func__, len)); |
2360 | goto resubmit; | | 2463 | goto resubmit; |
2361 | } | | 2464 | } |
2362 | buf = data->buf; | | 2465 | buf = data->buf; |
2363 | | | 2466 | |
| @@ -2429,55 +2532,60 @@ urtwn_txeof(struct usbd_xfer *xfer, void | | | @@ -2429,55 +2532,60 @@ urtwn_txeof(struct usbd_xfer *xfer, void |
2429 | TAILQ_INSERT_TAIL(&sc->tx_free_list[pidx], data, next); | | 2532 | TAILQ_INSERT_TAIL(&sc->tx_free_list[pidx], data, next); |
2430 | mutex_exit(&sc->sc_tx_mtx); | | 2533 | mutex_exit(&sc->sc_tx_mtx); |
2431 | | | 2534 | |
2432 | s = splnet(); | | 2535 | s = splnet(); |
2433 | sc->tx_timer = 0; | | 2536 | sc->tx_timer = 0; |
2434 | ifp->if_flags &= ~IFF_OACTIVE; | | 2537 | ifp->if_flags &= ~IFF_OACTIVE; |
2435 | | | 2538 | |
2436 | if (__predict_false(status != USBD_NORMAL_COMPLETION)) { | | 2539 | if (__predict_false(status != USBD_NORMAL_COMPLETION)) { |
2437 | if (status != USBD_NOT_STARTED && status != USBD_CANCELLED) { | | 2540 | if (status != USBD_NOT_STARTED && status != USBD_CANCELLED) { |
2438 | if (status == USBD_STALLED) { | | 2541 | if (status == USBD_STALLED) { |
2439 | struct usbd_pipe *pipe = sc->tx_pipe[pidx]; | | 2542 | struct usbd_pipe *pipe = sc->tx_pipe[pidx]; |
2440 | usbd_clear_endpoint_stall_async(pipe); | | 2543 | usbd_clear_endpoint_stall_async(pipe); |
2441 | } | | 2544 | } |
| | | 2545 | printf("ERROR1\n"); |
2442 | ifp->if_oerrors++; | | 2546 | ifp->if_oerrors++; |
2443 | } | | 2547 | } |
2444 | splx(s); | | 2548 | splx(s); |
2445 | return; | | 2549 | return; |
2446 | } | | 2550 | } |
2447 | | | 2551 | |
2448 | ifp->if_opackets++; | | 2552 | ifp->if_opackets++; |
2449 | urtwn_start(ifp); | | 2553 | urtwn_start(ifp); |
2450 | | | | |
2451 | splx(s); | | 2554 | splx(s); |
| | | 2555 | |
2452 | } | | 2556 | } |
2453 | | | 2557 | |
2454 | static int | | 2558 | static int |
2455 | urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, | | 2559 | urtwn_tx(struct urtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, |
2456 | struct urtwn_tx_data *data) | | 2560 | struct urtwn_tx_data *data) |
2457 | { | | 2561 | { |
2458 | struct ieee80211com *ic = &sc->sc_ic; | | 2562 | struct ieee80211com *ic = &sc->sc_ic; |
2459 | struct ieee80211_frame *wh; | | 2563 | struct ieee80211_frame *wh; |
2460 | struct ieee80211_key *k = NULL; | | 2564 | struct ieee80211_key *k = NULL; |
2461 | struct r92c_tx_desc *txd; | | 2565 | struct r92c_tx_desc *txd; |
2462 | size_t i, padsize, xferlen; | | 2566 | size_t i, padsize, xferlen, txd_len; |
2463 | uint16_t seq, sum; | | 2567 | uint16_t seq, sum; |
2464 | uint8_t raid, type, tid; | | 2568 | uint8_t raid, type, tid; |
2465 | int s, hasqos, error; | | 2569 | int s, hasqos, error; |
2466 | | | 2570 | |
2467 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 2571 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
2468 | | | 2572 | |
2469 | wh = mtod(m, struct ieee80211_frame *); | | 2573 | wh = mtod(m, struct ieee80211_frame *); |
2470 | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | | 2574 | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; |
| | | 2575 | txd_len = sizeof(*txd); |
| | | 2576 | |
| | | 2577 | if (!ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 2578 | txd_len = 32; |
2471 | | | 2579 | |
2472 | if (wh->i_fc[1] & IEEE80211_FC1_WEP) { | | 2580 | if (wh->i_fc[1] & IEEE80211_FC1_WEP) { |
2473 | k = ieee80211_crypto_encap(ic, ni, m); | | 2581 | k = ieee80211_crypto_encap(ic, ni, m); |
2474 | if (k == NULL) | | 2582 | if (k == NULL) |
2475 | return ENOBUFS; | | 2583 | return ENOBUFS; |
2476 | | | 2584 | |
2477 | /* packet header may have moved, reset our local pointer */ | | 2585 | /* packet header may have moved, reset our local pointer */ |
2478 | wh = mtod(m, struct ieee80211_frame *); | | 2586 | wh = mtod(m, struct ieee80211_frame *); |
2479 | } | | 2587 | } |
2480 | | | 2588 | |
2481 | if (__predict_false(sc->sc_drvbpf != NULL)) { | | 2589 | if (__predict_false(sc->sc_drvbpf != NULL)) { |
2482 | struct urtwn_tx_radiotap_header *tap = &sc->sc_txtap; | | 2590 | struct urtwn_tx_radiotap_header *tap = &sc->sc_txtap; |
2483 | | | 2591 | |
| @@ -2492,74 +2600,84 @@ urtwn_tx(struct urtwn_softc *sc, struct | | | @@ -2492,74 +2600,84 @@ urtwn_tx(struct urtwn_softc *sc, struct |
2492 | bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m); | | 2600 | bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m); |
2493 | } | | 2601 | } |
2494 | | | 2602 | |
2495 | /* non-qos data frames */ | | 2603 | /* non-qos data frames */ |
2496 | tid = R92C_TXDW1_QSEL_BE; | | 2604 | tid = R92C_TXDW1_QSEL_BE; |
2497 | if ((hasqos = ieee80211_has_qos(wh))) { | | 2605 | if ((hasqos = ieee80211_has_qos(wh))) { |
2498 | /* data frames in 11n mode */ | | 2606 | /* data frames in 11n mode */ |
2499 | struct ieee80211_qosframe *qwh = (void *)wh; | | 2607 | struct ieee80211_qosframe *qwh = (void *)wh; |
2500 | tid = qwh->i_qos[0] & IEEE80211_QOS_TID; | | 2608 | tid = qwh->i_qos[0] & IEEE80211_QOS_TID; |
2501 | } else if (type != IEEE80211_FC0_TYPE_DATA) { | | 2609 | } else if (type != IEEE80211_FC0_TYPE_DATA) { |
2502 | tid = R92C_TXDW1_QSEL_MGNT; | | 2610 | tid = R92C_TXDW1_QSEL_MGNT; |
2503 | } | | 2611 | } |
2504 | | | 2612 | |
2505 | if (((sizeof(*txd) + m->m_pkthdr.len) % 64) == 0) /* XXX: 64 */ | | 2613 | if (((txd_len + m->m_pkthdr.len) % 64) == 0) /* XXX: 64 */ |
2506 | padsize = 8; | | 2614 | padsize = 8; |
2507 | else | | 2615 | else |
2508 | padsize = 0; | | 2616 | padsize = 0; |
2509 | | | 2617 | |
| | | 2618 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 2619 | padsize = 0; |
| | | 2620 | |
2510 | /* Fill Tx descriptor. */ | | 2621 | /* Fill Tx descriptor. */ |
2511 | txd = (struct r92c_tx_desc *)data->buf; | | 2622 | txd = (struct r92c_tx_desc *)data->buf; |
2512 | memset(txd, 0, sizeof(*txd) + padsize); | | 2623 | memset(txd, 0, txd_len + padsize); |
2513 | | | 2624 | |
2514 | txd->txdw0 |= htole32( | | 2625 | txd->txdw0 |= htole32( |
2515 | SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) | | | 2626 | SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) | |
2516 | SM(R92C_TXDW0_OFFSET, sizeof(*txd)) | | | 2627 | SM(R92C_TXDW0_OFFSET, txd_len)); |
2517 | R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG); | | 2628 | if (!ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 2629 | txd->txdw0 |= htole32( |
| | | 2630 | R92C_TXDW0_OWN | R92C_TXDW0_FSG | R92C_TXDW0_LSG); |
| | | 2631 | } |
2518 | | | 2632 | |
2519 | if (IEEE80211_IS_MULTICAST(wh->i_addr1)) | | 2633 | if (IEEE80211_IS_MULTICAST(wh->i_addr1)) |
2520 | txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); | | 2634 | txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); |
2521 | | | 2635 | |
2522 | /* fix pad field */ | | 2636 | /* fix pad field */ |
2523 | if (padsize > 0) { | | 2637 | if (padsize > 0) { |
2524 | DPRINTFN(DBG_TX, ("%s: %s: padding: size=%zd\n", | | 2638 | DPRINTFN(DBG_TX, ("%s: %s: padding: size=%zd\n", |
2525 | device_xname(sc->sc_dev), __func__, padsize)); | | 2639 | device_xname(sc->sc_dev), __func__, padsize)); |
2526 | txd->txdw1 |= htole32(SM(R92C_TXDW1_PKTOFF, (padsize / 8))); | | 2640 | txd->txdw1 |= htole32(SM(R92C_TXDW1_PKTOFF, (padsize / 8))); |
2527 | } | | 2641 | } |
2528 | | | 2642 | |
2529 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && | | 2643 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && |
2530 | type == IEEE80211_FC0_TYPE_DATA) { | | 2644 | type == IEEE80211_FC0_TYPE_DATA) { |
2531 | if (ic->ic_curmode == IEEE80211_MODE_11B) | | 2645 | if (ic->ic_curmode == IEEE80211_MODE_11B) |
2532 | raid = R92C_RAID_11B; | | 2646 | raid = R92C_RAID_11B; |
2533 | else | | 2647 | else |
2534 | raid = R92C_RAID_11BG; | | 2648 | raid = R92C_RAID_11BG; |
2535 | DPRINTFN(DBG_TX, | | 2649 | DPRINTFN(DBG_TX, |
2536 | ("%s: %s: data packet: tid=%d, raid=%d\n", | | 2650 | ("%s: %s: data packet: tid=%d, raid=%d\n", |
2537 | device_xname(sc->sc_dev), __func__, tid, raid)); | | 2651 | device_xname(sc->sc_dev), __func__, tid, raid)); |
2538 | | | 2652 | |
2539 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { | | 2653 | if (!ISSET(sc->chip, URTWN_CHIP_92C)) { |
2540 | txd->txdw1 |= htole32( | | 2654 | txd->txdw1 |= htole32( |
2541 | SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) | | | 2655 | SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) | |
2542 | SM(R92C_TXDW1_QSEL, tid) | | | 2656 | SM(R92C_TXDW1_QSEL, tid) | |
2543 | SM(R92C_TXDW1_RAID, raid) | | | 2657 | SM(R92C_TXDW1_RAID, raid) | |
2544 | R92C_TXDW1_AGGBK); | | 2658 | R92C_TXDW1_AGGBK); |
2545 | txd->txdw2 |= htole32(R88E_TXDW2_AGGBK); | | | |
2546 | } else | | 2659 | } else |
2547 | txd->txdw1 |= htole32( | | 2660 | txd->txdw1 |= htole32( |
2548 | SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) | | | 2661 | SM(R92C_TXDW1_MACID, URTWN_MACID_BSS) | |
2549 | SM(R92C_TXDW1_QSEL, tid) | | | 2662 | SM(R92C_TXDW1_QSEL, tid) | |
2550 | SM(R92C_TXDW1_RAID, raid) | | | 2663 | SM(R92C_TXDW1_RAID, raid) | |
2551 | R92C_TXDW1_AGGBK); | | 2664 | R92C_TXDW1_AGGBK); |
2552 | | | 2665 | |
| | | 2666 | if (ISSET(sc->chip, URTWN_CHIP_88E)) |
| | | 2667 | txd->txdw2 |= htole32(R88E_TXDW2_AGGBK); |
| | | 2668 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 2669 | txd->txdw3 |= htole32(R92E_TXDW3_AGGBK); |
| | | 2670 | |
2553 | if (hasqos) { | | 2671 | if (hasqos) { |
2554 | txd->txdw4 |= htole32(R92C_TXDW4_QOS); | | 2672 | txd->txdw4 |= htole32(R92C_TXDW4_QOS); |
2555 | } | | 2673 | } |
2556 | | | 2674 | |
2557 | if (ic->ic_flags & IEEE80211_F_USEPROT) { | | 2675 | if (ic->ic_flags & IEEE80211_F_USEPROT) { |
2558 | /* for 11g */ | | 2676 | /* for 11g */ |
2559 | if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { | | 2677 | if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { |
2560 | txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF | | | 2678 | txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF | |
2561 | R92C_TXDW4_HWRTSEN); | | 2679 | R92C_TXDW4_HWRTSEN); |
2562 | } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) { | | 2680 | } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) { |
2563 | txd->txdw4 |= htole32(R92C_TXDW4_RTSEN | | | 2681 | txd->txdw4 |= htole32(R92C_TXDW4_RTSEN | |
2564 | R92C_TXDW4_HWRTSEN); | | 2682 | R92C_TXDW4_HWRTSEN); |
2565 | } | | 2683 | } |
| @@ -2587,45 +2705,54 @@ urtwn_tx(struct urtwn_softc *sc, struct | | | @@ -2587,45 +2705,54 @@ urtwn_tx(struct urtwn_softc *sc, struct |
2587 | } else { | | 2705 | } else { |
2588 | /* broadcast or multicast packets */ | | 2706 | /* broadcast or multicast packets */ |
2589 | DPRINTFN(DBG_TX, ("%s: %s: bc or mc packet\n", | | 2707 | DPRINTFN(DBG_TX, ("%s: %s: bc or mc packet\n", |
2590 | device_xname(sc->sc_dev), __func__)); | | 2708 | device_xname(sc->sc_dev), __func__)); |
2591 | txd->txdw1 |= htole32( | | 2709 | txd->txdw1 |= htole32( |
2592 | SM(R92C_TXDW1_MACID, URTWN_MACID_BC) | | | 2710 | SM(R92C_TXDW1_MACID, URTWN_MACID_BC) | |
2593 | SM(R92C_TXDW1_RAID, R92C_RAID_11B)); | | 2711 | SM(R92C_TXDW1_RAID, R92C_RAID_11B)); |
2594 | | | 2712 | |
2595 | /* Force CCK1. */ | | 2713 | /* Force CCK1. */ |
2596 | txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); | | 2714 | txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); |
2597 | /* Use 1Mbps */ | | 2715 | /* Use 1Mbps */ |
2598 | txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0)); | | 2716 | txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 0)); |
2599 | } | | 2717 | } |
2600 | | | | |
2601 | /* Set sequence number */ | | 2718 | /* Set sequence number */ |
2602 | seq = LE_READ_2(&wh->i_seq[0]) >> IEEE80211_SEQ_SEQ_SHIFT; | | 2719 | seq = LE_READ_2(&wh->i_seq[0]) >> IEEE80211_SEQ_SEQ_SHIFT; |
2603 | txd->txdseq |= htole16(seq); | | 2720 | if (!ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 2721 | txd->txdseq |= htole16(seq); |
2604 | | | 2722 | |
2605 | if (!hasqos) { | | 2723 | if (!hasqos) { |
2606 | /* Use HW sequence numbering for non-QoS frames. */ | | 2724 | /* Use HW sequence numbering for non-QoS frames. */ |
2607 | txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ); | | 2725 | txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ); |
2608 | txd->txdseq |= htole16(0x8000); /* WTF? */ | | 2726 | txd->txdseq |= htole16(R92C_HWSEQ_EN); |
| | | 2727 | } |
| | | 2728 | } else { |
| | | 2729 | txd->txdseq2 |= htole16((seq & R92E_HWSEQ_MASK) << |
| | | 2730 | R92E_HWSEQ_SHIFT); |
| | | 2731 | if (!hasqos) { |
| | | 2732 | /* Use HW sequence numbering for non-QoS frames. */ |
| | | 2733 | txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ); |
| | | 2734 | txd->txdw7 |= htole16(R92C_HWSEQ_EN); |
| | | 2735 | } |
2609 | } | | 2736 | } |
2610 | | | 2737 | |
2611 | /* Compute Tx descriptor checksum. */ | | 2738 | /* Compute Tx descriptor checksum. */ |
2612 | sum = 0; | | 2739 | sum = 0; |
2613 | for (i = 0; i < sizeof(*txd) / 2; i++) | | 2740 | for (i = 0; i < R92C_TXDESC_SUMSIZE / 2; i++) |
2614 | sum ^= ((uint16_t *)txd)[i]; | | 2741 | sum ^= ((uint16_t *)txd)[i]; |
2615 | txd->txdsum = sum; /* NB: already little endian. */ | | 2742 | txd->txdsum = sum; /* NB: already little endian. */ |
2616 | | | 2743 | |
2617 | xferlen = sizeof(*txd) + m->m_pkthdr.len + padsize; | | 2744 | xferlen = txd_len + m->m_pkthdr.len + padsize; |
2618 | m_copydata(m, 0, m->m_pkthdr.len, (char *)&txd[1] + padsize); | | 2745 | m_copydata(m, 0, m->m_pkthdr.len, (char *)&txd[0] + txd_len + padsize); |
2619 | | | 2746 | |
2620 | s = splnet(); | | 2747 | s = splnet(); |
2621 | usbd_setup_xfer(data->xfer, data, data->buf, xferlen, | | 2748 | usbd_setup_xfer(data->xfer, data, data->buf, xferlen, |
2622 | USBD_FORCE_SHORT_XFER, URTWN_TX_TIMEOUT, | | 2749 | USBD_FORCE_SHORT_XFER, URTWN_TX_TIMEOUT, |
2623 | urtwn_txeof); | | 2750 | urtwn_txeof); |
2624 | error = usbd_transfer(data->xfer); | | 2751 | error = usbd_transfer(data->xfer); |
2625 | if (__predict_false(error != USBD_NORMAL_COMPLETION && | | 2752 | if (__predict_false(error != USBD_NORMAL_COMPLETION && |
2626 | error != USBD_IN_PROGRESS)) { | | 2753 | error != USBD_IN_PROGRESS)) { |
2627 | splx(s); | | 2754 | splx(s); |
2628 | DPRINTFN(DBG_TX, ("%s: %s: transfer failed %d\n", | | 2755 | DPRINTFN(DBG_TX, ("%s: %s: transfer failed %d\n", |
2629 | device_xname(sc->sc_dev), __func__, error)); | | 2756 | device_xname(sc->sc_dev), __func__, error)); |
2630 | return error; | | 2757 | return error; |
2631 | } | | 2758 | } |
| @@ -2704,73 +2831,78 @@ urtwn_start(struct ifnet *ifp) | | | @@ -2704,73 +2831,78 @@ urtwn_start(struct ifnet *ifp) |
2704 | } | | 2831 | } |
2705 | data = urtwn_get_tx_data(sc, sc->ac2idx[qid]); | | 2832 | data = urtwn_get_tx_data(sc, sc->ac2idx[qid]); |
2706 | | | 2833 | |
2707 | if (data == NULL) { | | 2834 | if (data == NULL) { |
2708 | ifp->if_flags |= IFF_OACTIVE; | | 2835 | ifp->if_flags |= IFF_OACTIVE; |
2709 | DPRINTFN(DBG_TX, ("%s: empty tx_free_list\n", | | 2836 | DPRINTFN(DBG_TX, ("%s: empty tx_free_list\n", |
2710 | device_xname(sc->sc_dev))); | | 2837 | device_xname(sc->sc_dev))); |
2711 | return; | | 2838 | return; |
2712 | } | | 2839 | } |
2713 | IFQ_DEQUEUE(&ifp->if_snd, m); | | 2840 | IFQ_DEQUEUE(&ifp->if_snd, m); |
2714 | | | 2841 | |
2715 | if (m->m_len < (int)sizeof(*eh) && | | 2842 | if (m->m_len < (int)sizeof(*eh) && |
2716 | (m = m_pullup(m, sizeof(*eh))) == NULL) { | | 2843 | (m = m_pullup(m, sizeof(*eh))) == NULL) { |
| | | 2844 | printf("ERROR6\n"); |
2717 | ifp->if_oerrors++; | | 2845 | ifp->if_oerrors++; |
2718 | continue; | | 2846 | continue; |
2719 | } | | 2847 | } |
2720 | eh = mtod(m, struct ether_header *); | | 2848 | eh = mtod(m, struct ether_header *); |
2721 | ni = ieee80211_find_txnode(ic, eh->ether_dhost); | | 2849 | ni = ieee80211_find_txnode(ic, eh->ether_dhost); |
2722 | if (ni == NULL) { | | 2850 | if (ni == NULL) { |
2723 | m_freem(m); | | 2851 | m_freem(m); |
| | | 2852 | printf("ERROR5\n"); |
2724 | ifp->if_oerrors++; | | 2853 | ifp->if_oerrors++; |
2725 | continue; | | 2854 | continue; |
2726 | } | | 2855 | } |
2727 | | | 2856 | |
2728 | bpf_mtap(ifp, m); | | 2857 | bpf_mtap(ifp, m); |
2729 | | | 2858 | |
2730 | if ((m = ieee80211_encap(ic, m, ni)) == NULL) { | | 2859 | if ((m = ieee80211_encap(ic, m, ni)) == NULL) { |
2731 | ieee80211_free_node(ni); | | 2860 | ieee80211_free_node(ni); |
| | | 2861 | printf("ERROR4\n"); |
2732 | ifp->if_oerrors++; | | 2862 | ifp->if_oerrors++; |
2733 | continue; | | 2863 | continue; |
2734 | } | | 2864 | } |
2735 | sendit: | | 2865 | sendit: |
2736 | bpf_mtap3(ic->ic_rawbpf, m); | | 2866 | bpf_mtap3(ic->ic_rawbpf, m); |
2737 | | | 2867 | |
2738 | if (urtwn_tx(sc, m, ni, data) != 0) { | | 2868 | if (urtwn_tx(sc, m, ni, data) != 0) { |
2739 | m_freem(m); | | 2869 | m_freem(m); |
2740 | ieee80211_free_node(ni); | | 2870 | ieee80211_free_node(ni); |
| | | 2871 | printf("ERROR3\n"); |
2741 | ifp->if_oerrors++; | | 2872 | ifp->if_oerrors++; |
2742 | continue; | | 2873 | continue; |
2743 | } | | 2874 | } |
2744 | m_freem(m); | | 2875 | m_freem(m); |
2745 | ieee80211_free_node(ni); | | 2876 | ieee80211_free_node(ni); |
2746 | sc->tx_timer = 5; | | 2877 | sc->tx_timer = 5; |
2747 | ifp->if_timer = 1; | | 2878 | ifp->if_timer = 1; |
2748 | } | | 2879 | } |
2749 | } | | 2880 | } |
2750 | | | 2881 | |
2751 | static void | | 2882 | static void |
2752 | urtwn_watchdog(struct ifnet *ifp) | | 2883 | urtwn_watchdog(struct ifnet *ifp) |
2753 | { | | 2884 | { |
2754 | struct urtwn_softc *sc = ifp->if_softc; | | 2885 | struct urtwn_softc *sc = ifp->if_softc; |
2755 | | | 2886 | |
2756 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 2887 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
2757 | | | 2888 | |
2758 | ifp->if_timer = 0; | | 2889 | ifp->if_timer = 0; |
2759 | | | 2890 | |
2760 | if (sc->tx_timer > 0) { | | 2891 | if (sc->tx_timer > 0) { |
2761 | if (--sc->tx_timer == 0) { | | 2892 | if (--sc->tx_timer == 0) { |
2762 | aprint_error_dev(sc->sc_dev, "device timeout\n"); | | 2893 | aprint_error_dev(sc->sc_dev, "device timeout\n"); |
2763 | /* urtwn_init(ifp); XXX needs a process context! */ | | 2894 | /* urtwn_init(ifp); XXX needs a process context! */ |
| | | 2895 | printf("ERROR2\n"); |
2764 | ifp->if_oerrors++; | | 2896 | ifp->if_oerrors++; |
2765 | return; | | 2897 | return; |
2766 | } | | 2898 | } |
2767 | ifp->if_timer = 1; | | 2899 | ifp->if_timer = 1; |
2768 | } | | 2900 | } |
2769 | ieee80211_watchdog(&sc->sc_ic); | | 2901 | ieee80211_watchdog(&sc->sc_ic); |
2770 | } | | 2902 | } |
2771 | | | 2903 | |
2772 | static int | | 2904 | static int |
2773 | urtwn_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 2905 | urtwn_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
2774 | { | | 2906 | { |
2775 | struct urtwn_softc *sc = ifp->if_softc; | | 2907 | struct urtwn_softc *sc = ifp->if_softc; |
2776 | struct ieee80211com *ic = &sc->sc_ic; | | 2908 | struct ieee80211com *ic = &sc->sc_ic; |
| @@ -2848,46 +2980,46 @@ urtwn_r92c_power_on(struct urtwn_softc * | | | @@ -2848,46 +2980,46 @@ urtwn_r92c_power_on(struct urtwn_softc * |
2848 | break; | | 2980 | break; |
2849 | DELAY(5); | | 2981 | DELAY(5); |
2850 | } | | 2982 | } |
2851 | if (ntries == 1000) { | | 2983 | if (ntries == 1000) { |
2852 | aprint_error_dev(sc->sc_dev, | | 2984 | aprint_error_dev(sc->sc_dev, |
2853 | "timeout waiting for chip autoload\n"); | | 2985 | "timeout waiting for chip autoload\n"); |
2854 | return ETIMEDOUT; | | 2986 | return ETIMEDOUT; |
2855 | } | | 2987 | } |
2856 | | | 2988 | |
2857 | /* Unlock ISO/CLK/Power control register. */ | | 2989 | /* Unlock ISO/CLK/Power control register. */ |
2858 | urtwn_write_1(sc, R92C_RSV_CTRL, 0); | | 2990 | urtwn_write_1(sc, R92C_RSV_CTRL, 0); |
2859 | /* Move SPS into PWM mode. */ | | 2991 | /* Move SPS into PWM mode. */ |
2860 | urtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); | | 2992 | urtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); |
2861 | DELAY(100); | | 2993 | DELAY(5); |
2862 | | | 2994 | |
2863 | reg = urtwn_read_1(sc, R92C_LDOV12D_CTRL); | | 2995 | reg = urtwn_read_1(sc, R92C_LDOV12D_CTRL); |
2864 | if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) { | | 2996 | if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) { |
2865 | urtwn_write_1(sc, R92C_LDOV12D_CTRL, | | 2997 | urtwn_write_1(sc, R92C_LDOV12D_CTRL, |
2866 | reg | R92C_LDOV12D_CTRL_LDV12_EN); | | 2998 | reg | R92C_LDOV12D_CTRL_LDV12_EN); |
2867 | DELAY(100); | | 2999 | DELAY(100); |
2868 | urtwn_write_1(sc, R92C_SYS_ISO_CTRL, | | 3000 | urtwn_write_1(sc, R92C_SYS_ISO_CTRL, |
2869 | urtwn_read_1(sc, R92C_SYS_ISO_CTRL) & | | 3001 | urtwn_read_1(sc, R92C_SYS_ISO_CTRL) & |
2870 | ~R92C_SYS_ISO_CTRL_MD2PP); | | 3002 | ~R92C_SYS_ISO_CTRL_MD2PP); |
2871 | } | | 3003 | } |
2872 | | | 3004 | |
2873 | /* Auto enable WLAN. */ | | 3005 | /* Auto enable WLAN. */ |
2874 | urtwn_write_2(sc, R92C_APS_FSMCO, | | 3006 | urtwn_write_2(sc, R92C_APS_FSMCO, |
2875 | urtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); | | 3007 | urtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); |
2876 | for (ntries = 0; ntries < 1000; ntries++) { | | 3008 | for (ntries = 0; ntries < 1000; ntries++) { |
2877 | if (!(urtwn_read_2(sc, R92C_APS_FSMCO) & | | 3009 | if (!(urtwn_read_2(sc, R92C_APS_FSMCO) & |
2878 | R92C_APS_FSMCO_APFM_ONMAC)) | | 3010 | R92C_APS_FSMCO_APFM_ONMAC)) |
2879 | break; | | 3011 | break; |
2880 | DELAY(5); | | 3012 | DELAY(100); |
2881 | } | | 3013 | } |
2882 | if (ntries == 1000) { | | 3014 | if (ntries == 1000) { |
2883 | aprint_error_dev(sc->sc_dev, | | 3015 | aprint_error_dev(sc->sc_dev, |
2884 | "timeout waiting for MAC auto ON\n"); | | 3016 | "timeout waiting for MAC auto ON\n"); |
2885 | return ETIMEDOUT; | | 3017 | return ETIMEDOUT; |
2886 | } | | 3018 | } |
2887 | | | 3019 | |
2888 | /* Enable radio, GPIO and LED functions. */ | | 3020 | /* Enable radio, GPIO and LED functions. */ |
2889 | KASSERT((R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_PDN_EN | | | 3021 | KASSERT((R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_PDN_EN | |
2890 | R92C_APS_FSMCO_PFM_ALDN) == 0x0812); | | 3022 | R92C_APS_FSMCO_PFM_ALDN) == 0x0812); |
2891 | urtwn_write_2(sc, R92C_APS_FSMCO, | | 3023 | urtwn_write_2(sc, R92C_APS_FSMCO, |
2892 | R92C_APS_FSMCO_AFSM_HSUS | | | 3024 | R92C_APS_FSMCO_AFSM_HSUS | |
2893 | R92C_APS_FSMCO_PDN_EN | | | 3025 | R92C_APS_FSMCO_PDN_EN | |
| @@ -2915,26 +3047,106 @@ urtwn_r92c_power_on(struct urtwn_softc * | | | @@ -2915,26 +3047,106 @@ urtwn_r92c_power_on(struct urtwn_softc * |
2915 | /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ | | 3047 | /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ |
2916 | reg = urtwn_read_2(sc, R92C_CR); | | 3048 | reg = urtwn_read_2(sc, R92C_CR); |
2917 | reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | | | 3049 | reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | |
2918 | R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | | | 3050 | R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | |
2919 | R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | | | 3051 | R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | |
2920 | R92C_CR_ENSEC; | | 3052 | R92C_CR_ENSEC; |
2921 | urtwn_write_2(sc, R92C_CR, reg); | | 3053 | urtwn_write_2(sc, R92C_CR, reg); |
2922 | | | 3054 | |
2923 | urtwn_write_1(sc, 0xfe10, 0x19); | | 3055 | urtwn_write_1(sc, 0xfe10, 0x19); |
2924 | return 0; | | 3056 | return 0; |
2925 | } | | 3057 | } |
2926 | | | 3058 | |
2927 | static int | | 3059 | static int |
| | | 3060 | urtwn_r92e_power_on(struct urtwn_softc *sc) |
| | | 3061 | { |
| | | 3062 | uint32_t reg; |
| | | 3063 | uint32_t val; |
| | | 3064 | int ntries; |
| | | 3065 | |
| | | 3066 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
| | | 3067 | |
| | | 3068 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
| | | 3069 | |
| | | 3070 | /* Enable radio, GPIO and LED functions. */ |
| | | 3071 | KASSERT((R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_PDN_EN | |
| | | 3072 | R92C_APS_FSMCO_PFM_ALDN) == 0x0812); |
| | | 3073 | urtwn_write_2(sc, R92C_APS_FSMCO, |
| | | 3074 | R92C_APS_FSMCO_AFSM_HSUS | |
| | | 3075 | R92C_APS_FSMCO_PDN_EN | |
| | | 3076 | R92C_APS_FSMCO_PFM_ALDN); |
| | | 3077 | |
| | | 3078 | if (urtwn_read_4(sc, R92E_SYS_CFG1_8192E) & R92E_SPSLDO_SEL){ |
| | | 3079 | /* LDO. */ |
| | | 3080 | urtwn_write_1(sc, R92E_LDO_SWR_CTRL, 0xc3); |
| | | 3081 | } |
| | | 3082 | else { |
| | | 3083 | urtwn_write_2(sc, R92C_SYS_SWR_CTRL2, urtwn_read_2(sc, |
| | | 3084 | R92C_SYS_SWR_CTRL2) & 0xffff); |
| | | 3085 | urtwn_write_1(sc, R92E_LDO_SWR_CTRL, 0x83); |
| | | 3086 | } |
| | | 3087 | |
| | | 3088 | for (ntries = 0; ntries < 2; ntries++) { |
| | | 3089 | urtwn_write_1(sc, R92C_AFE_PLL_CTRL, |
| | | 3090 | urtwn_read_1(sc, R92C_AFE_PLL_CTRL)); |
| | | 3091 | urtwn_write_2(sc, R92C_AFE_CTRL4, urtwn_read_2(sc, |
| | | 3092 | R92C_AFE_CTRL4)); |
| | | 3093 | } |
| | | 3094 | |
| | | 3095 | /* Reset BB. */ |
| | | 3096 | urtwn_write_1(sc, R92C_SYS_FUNC_EN, |
| | | 3097 | urtwn_read_1(sc, R92C_SYS_FUNC_EN) & ~(R92C_SYS_FUNC_EN_BBRSTB | |
| | | 3098 | R92C_SYS_FUNC_EN_BB_GLB_RST)); |
| | | 3099 | |
| | | 3100 | urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 2, urtwn_read_1(sc, |
| | | 3101 | R92C_AFE_XTAL_CTRL + 2) | 0x80); |
| | | 3102 | |
| | | 3103 | /* Disable HWPDN. */ |
| | | 3104 | urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, |
| | | 3105 | R92C_APS_FSMCO) & ~R92C_APS_FSMCO_APDM_HPDN); |
| | | 3106 | |
| | | 3107 | /* Disable WL suspend. */ |
| | | 3108 | urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, |
| | | 3109 | R92C_APS_FSMCO) & ~(R92C_APS_FSMCO_AFSM_PCIE | |
| | | 3110 | R92C_APS_FSMCO_AFSM_HSUS)); |
| | | 3111 | |
| | | 3112 | urtwn_write_4(sc, R92C_APS_FSMCO, urtwn_read_4(sc, |
| | | 3113 | R92C_APS_FSMCO) | R92C_APS_FSMCO_RDY_MACON); |
| | | 3114 | urtwn_write_2(sc, R92C_APS_FSMCO, urtwn_read_2(sc, |
| | | 3115 | R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); |
| | | 3116 | for (ntries = 0; ntries < 10000; ntries++) { |
| | | 3117 | val = urtwn_read_2(sc, R92C_APS_FSMCO) & |
| | | 3118 | R92C_APS_FSMCO_APFM_ONMAC; |
| | | 3119 | if (val == 0x0) |
| | | 3120 | break; |
| | | 3121 | DELAY(10); |
| | | 3122 | } |
| | | 3123 | if (ntries == 10000) { |
| | | 3124 | aprint_error_dev(sc->sc_dev, |
| | | 3125 | "timeout waiting for chip power up\n"); |
| | | 3126 | return ETIMEDOUT; |
| | | 3127 | } |
| | | 3128 | |
| | | 3129 | urtwn_write_2(sc, R92C_CR, 0x00); |
| | | 3130 | reg = urtwn_read_2(sc, R92C_CR); |
| | | 3131 | reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | |
| | | 3132 | R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | |
| | | 3133 | R92C_CR_SCHEDULE_EN | R92C_CR_ENSEC; |
| | | 3134 | urtwn_write_2(sc, R92C_CR, reg); |
| | | 3135 | |
| | | 3136 | return 0; |
| | | 3137 | } |
| | | 3138 | |
| | | 3139 | static int |
2928 | urtwn_r88e_power_on(struct urtwn_softc *sc) | | 3140 | urtwn_r88e_power_on(struct urtwn_softc *sc) |
2929 | { | | 3141 | { |
2930 | uint32_t reg; | | 3142 | uint32_t reg; |
2931 | uint8_t val; | | 3143 | uint8_t val; |
2932 | int ntries; | | 3144 | int ntries; |
2933 | | | 3145 | |
2934 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3146 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
2935 | | | 3147 | |
2936 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3148 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
2937 | | | 3149 | |
2938 | /* Wait for power ready bit. */ | | 3150 | /* Wait for power ready bit. */ |
2939 | for (ntries = 0; ntries < 5000; ntries++) { | | 3151 | for (ntries = 0; ntries < 5000; ntries++) { |
2940 | val = urtwn_read_1(sc, 0x6) & 0x2; | | 3152 | val = urtwn_read_1(sc, 0x6) & 0x2; |
| @@ -2978,36 +3190,55 @@ urtwn_r88e_power_on(struct urtwn_softc * | | | @@ -2978,36 +3190,55 @@ urtwn_r88e_power_on(struct urtwn_softc * |
2978 | reg = urtwn_read_2(sc, R92C_CR); | | 3190 | reg = urtwn_read_2(sc, R92C_CR); |
2979 | reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | | | 3191 | reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | |
2980 | R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | | | 3192 | R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | |
2981 | R92C_CR_SCHEDULE_EN | R92C_CR_ENSEC | R92C_CR_CALTMR_EN; | | 3193 | R92C_CR_SCHEDULE_EN | R92C_CR_ENSEC | R92C_CR_CALTMR_EN; |
2982 | urtwn_write_2(sc, R92C_CR, reg); | | 3194 | urtwn_write_2(sc, R92C_CR, reg); |
2983 | | | 3195 | |
2984 | return 0; | | 3196 | return 0; |
2985 | } | | 3197 | } |
2986 | | | 3198 | |
2987 | static int | | 3199 | static int |
2988 | urtwn_llt_init(struct urtwn_softc *sc) | | 3200 | urtwn_llt_init(struct urtwn_softc *sc) |
2989 | { | | 3201 | { |
2990 | size_t i, page_count, pktbuf_count; | | 3202 | size_t i, page_count, pktbuf_count; |
| | | 3203 | uint32_t val; |
2991 | int error; | | 3204 | int error; |
2992 | | | 3205 | |
2993 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3206 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
2994 | | | 3207 | |
2995 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3208 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
2996 | | | 3209 | |
2997 | page_count = (sc->chip & URTWN_CHIP_88E) ? | | 3210 | if (sc->chip & URTWN_CHIP_88E) |
2998 | R88E_TX_PAGE_COUNT : R92C_TX_PAGE_COUNT; | | 3211 | page_count = R88E_TX_PAGE_COUNT; |
2999 | pktbuf_count = (sc->chip & URTWN_CHIP_88E) ? | | 3212 | else if (sc->chip & URTWN_CHIP_92EU) |
3000 | R88E_TXPKTBUF_COUNT : R92C_TXPKTBUF_COUNT; | | 3213 | page_count = R92E_TX_PAGE_COUNT; |
| | | 3214 | else |
| | | 3215 | page_count = R92C_TX_PAGE_COUNT; |
| | | 3216 | if (sc->chip & URTWN_CHIP_88E) |
| | | 3217 | pktbuf_count = R88E_TXPKTBUF_COUNT; |
| | | 3218 | else if (sc->chip & URTWN_CHIP_92EU) |
| | | 3219 | pktbuf_count = R88E_TXPKTBUF_COUNT; |
| | | 3220 | else |
| | | 3221 | pktbuf_count = R92C_TXPKTBUF_COUNT; |
| | | 3222 | |
| | | 3223 | if (sc->chip & URTWN_CHIP_92EU) { |
| | | 3224 | val = urtwn_read_4(sc, R92E_AUTO_LLT) | R92E_AUTO_LLT_EN; |
| | | 3225 | urtwn_write_4(sc, R92E_AUTO_LLT, val); |
| | | 3226 | DELAY(100); |
| | | 3227 | val = urtwn_read_4(sc, R92E_AUTO_LLT); |
| | | 3228 | if (val & R92E_AUTO_LLT_EN) |
| | | 3229 | return EIO; |
| | | 3230 | return 0; |
| | | 3231 | } |
3001 | | | 3232 | |
3002 | /* Reserve pages [0; page_count]. */ | | 3233 | /* Reserve pages [0; page_count]. */ |
3003 | for (i = 0; i < page_count; i++) { | | 3234 | for (i = 0; i < page_count; i++) { |
3004 | if ((error = urtwn_llt_write(sc, i, i + 1)) != 0) | | 3235 | if ((error = urtwn_llt_write(sc, i, i + 1)) != 0) |
3005 | return error; | | 3236 | return error; |
3006 | } | | 3237 | } |
3007 | /* NB: 0xff indicates end-of-list. */ | | 3238 | /* NB: 0xff indicates end-of-list. */ |
3008 | if ((error = urtwn_llt_write(sc, i, 0xff)) != 0) | | 3239 | if ((error = urtwn_llt_write(sc, i, 0xff)) != 0) |
3009 | return error; | | 3240 | return error; |
3010 | /* | | 3241 | /* |
3011 | * Use pages [page_count + 1; pktbuf_count - 1] | | 3242 | * Use pages [page_count + 1; pktbuf_count - 1] |
3012 | * as ring buffer. | | 3243 | * as ring buffer. |
3013 | */ | | 3244 | */ |
| @@ -3044,29 +3275,45 @@ urtwn_fw_reset(struct urtwn_softc *sc) | | | @@ -3044,29 +3275,45 @@ urtwn_fw_reset(struct urtwn_softc *sc) |
3044 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, | | 3275 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, |
3045 | urtwn_read_2(sc, R92C_SYS_FUNC_EN) & ~R92C_SYS_FUNC_EN_CPUEN); | | 3276 | urtwn_read_2(sc, R92C_SYS_FUNC_EN) & ~R92C_SYS_FUNC_EN_CPUEN); |
3046 | } | | 3277 | } |
3047 | | | 3278 | |
3048 | static void | | 3279 | static void |
3049 | urtwn_r88e_fw_reset(struct urtwn_softc *sc) | | 3280 | urtwn_r88e_fw_reset(struct urtwn_softc *sc) |
3050 | { | | 3281 | { |
3051 | uint16_t reg; | | 3282 | uint16_t reg; |
3052 | | | 3283 | |
3053 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3284 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
3054 | | | 3285 | |
3055 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3286 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
3056 | | | 3287 | |
| | | 3288 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 3289 | reg = urtwn_read_2(sc, R92C_RSV_CTRL) & ~R92E_RSV_MIO_EN; |
| | | 3290 | urtwn_write_2(sc,R92C_RSV_CTRL, reg); |
| | | 3291 | } |
| | | 3292 | DELAY(50); |
| | | 3293 | |
3057 | reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN); | | 3294 | reg = urtwn_read_2(sc, R92C_SYS_FUNC_EN); |
3058 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); | | 3295 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); |
| | | 3296 | DELAY(50); |
| | | 3297 | |
3059 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN); | | 3298 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN); |
| | | 3299 | DELAY(50); |
| | | 3300 | |
| | | 3301 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 3302 | reg = urtwn_read_2(sc, R92C_RSV_CTRL) | R92E_RSV_MIO_EN; |
| | | 3303 | urtwn_write_2(sc,R92C_RSV_CTRL, reg); |
| | | 3304 | } |
| | | 3305 | DELAY(50); |
| | | 3306 | |
3060 | } | | 3307 | } |
3061 | | | 3308 | |
3062 | static int | | 3309 | static int |
3063 | urtwn_fw_loadpage(struct urtwn_softc *sc, int page, uint8_t *buf, int len) | | 3310 | urtwn_fw_loadpage(struct urtwn_softc *sc, int page, uint8_t *buf, int len) |
3064 | { | | 3311 | { |
3065 | uint32_t reg; | | 3312 | uint32_t reg; |
3066 | int off, mlen, error = 0; | | 3313 | int off, mlen, error = 0; |
3067 | | | 3314 | |
3068 | DPRINTFN(DBG_FN, ("%s: %s: page=%d, buf=%p, len=%d\n", | | 3315 | DPRINTFN(DBG_FN, ("%s: %s: page=%d, buf=%p, len=%d\n", |
3069 | device_xname(sc->sc_dev), __func__, page, buf, len)); | | 3316 | device_xname(sc->sc_dev), __func__, page, buf, len)); |
3070 | | | 3317 | |
3071 | reg = urtwn_read_4(sc, R92C_MCUFWDL); | | 3318 | reg = urtwn_read_4(sc, R92C_MCUFWDL); |
3072 | reg = RW(reg, R92C_MCUFWDL_PAGE, page); | | 3319 | reg = RW(reg, R92C_MCUFWDL_PAGE, page); |
| @@ -3098,26 +3345,28 @@ urtwn_load_firmware(struct urtwn_softc * | | | @@ -3098,26 +3345,28 @@ urtwn_load_firmware(struct urtwn_softc * |
3098 | const char *name; | | 3345 | const char *name; |
3099 | u_char *fw, *ptr; | | 3346 | u_char *fw, *ptr; |
3100 | size_t len; | | 3347 | size_t len; |
3101 | uint32_t reg; | | 3348 | uint32_t reg; |
3102 | int mlen, ntries, page, error; | | 3349 | int mlen, ntries, page, error; |
3103 | | | 3350 | |
3104 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3351 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
3105 | | | 3352 | |
3106 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3353 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
3107 | | | 3354 | |
3108 | /* Read firmware image from the filesystem. */ | | 3355 | /* Read firmware image from the filesystem. */ |
3109 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 3356 | if (ISSET(sc->chip, URTWN_CHIP_88E)) |
3110 | name = "rtl8188eufw.bin"; | | 3357 | name = "rtl8188eufw.bin"; |
| | | 3358 | else if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 3359 | name = "rtl8192eefw.bin"; |
3111 | else if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) == | | 3360 | else if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) == |
3112 | URTWN_CHIP_UMC_A_CUT) | | 3361 | URTWN_CHIP_UMC_A_CUT) |
3113 | name = "rtl8192cfwU.bin"; | | 3362 | name = "rtl8192cfwU.bin"; |
3114 | else | | 3363 | else |
3115 | name = "rtl8192cfw.bin"; | | 3364 | name = "rtl8192cfw.bin"; |
3116 | if ((error = firmware_open("if_urtwn", name, &fwh)) != 0) { | | 3365 | if ((error = firmware_open("if_urtwn", name, &fwh)) != 0) { |
3117 | aprint_error_dev(sc->sc_dev, | | 3366 | aprint_error_dev(sc->sc_dev, |
3118 | "failed load firmware of file %s (error %d)\n", name, | | 3367 | "failed load firmware of file %s (error %d)\n", name, |
3119 | error); | | 3368 | error); |
3120 | return error; | | 3369 | return error; |
3121 | } | | 3370 | } |
3122 | const size_t fwlen = len = firmware_get_size(fwh); | | 3371 | const size_t fwlen = len = firmware_get_size(fwh); |
3123 | fw = firmware_malloc(len); | | 3372 | fw = firmware_malloc(len); |
| @@ -3126,63 +3375,67 @@ urtwn_load_firmware(struct urtwn_softc * | | | @@ -3126,63 +3375,67 @@ urtwn_load_firmware(struct urtwn_softc * |
3126 | "failed to allocate firmware memory\n"); | | 3375 | "failed to allocate firmware memory\n"); |
3127 | firmware_close(fwh); | | 3376 | firmware_close(fwh); |
3128 | return ENOMEM; | | 3377 | return ENOMEM; |
3129 | } | | 3378 | } |
3130 | error = firmware_read(fwh, 0, fw, len); | | 3379 | error = firmware_read(fwh, 0, fw, len); |
3131 | firmware_close(fwh); | | 3380 | firmware_close(fwh); |
3132 | if (error != 0) { | | 3381 | if (error != 0) { |
3133 | aprint_error_dev(sc->sc_dev, | | 3382 | aprint_error_dev(sc->sc_dev, |
3134 | "failed to read firmware (error %d)\n", error); | | 3383 | "failed to read firmware (error %d)\n", error); |
3135 | firmware_free(fw, fwlen); | | 3384 | firmware_free(fw, fwlen); |
3136 | return error; | | 3385 | return error; |
3137 | } | | 3386 | } |
3138 | | | 3387 | |
| | | 3388 | len = fwlen; |
3139 | ptr = fw; | | 3389 | ptr = fw; |
3140 | hdr = (const struct r92c_fw_hdr *)ptr; | | 3390 | hdr = (const struct r92c_fw_hdr *)ptr; |
3141 | /* Check if there is a valid FW header and skip it. */ | | 3391 | /* Check if there is a valid FW header and skip it. */ |
3142 | if ((le16toh(hdr->signature) >> 4) == 0x88c || | | 3392 | if ((le16toh(hdr->signature) >> 4) == 0x88c || |
3143 | (le16toh(hdr->signature) >> 4) == 0x88e || | | 3393 | (le16toh(hdr->signature) >> 4) == 0x88e || |
| | | 3394 | (le16toh(hdr->signature) >> 4) == 0x92e || |
3144 | (le16toh(hdr->signature) >> 4) == 0x92c) { | | 3395 | (le16toh(hdr->signature) >> 4) == 0x92c) { |
3145 | DPRINTFN(DBG_INIT, ("%s: %s: FW V%d.%d %02d-%02d %02d:%02d\n", | | 3396 | DPRINTFN(DBG_INIT, ("%s: %s: FW V%d.%d %02d-%02d %02d:%02d\n", |
3146 | device_xname(sc->sc_dev), __func__, | | 3397 | device_xname(sc->sc_dev), __func__, |
3147 | le16toh(hdr->version), le16toh(hdr->subversion), | | 3398 | le16toh(hdr->version), le16toh(hdr->subversion), |
3148 | hdr->month, hdr->date, hdr->hour, hdr->minute)); | | 3399 | hdr->month, hdr->date, hdr->hour, hdr->minute)); |
3149 | ptr += sizeof(*hdr); | | 3400 | ptr += sizeof(*hdr); |
3150 | len -= sizeof(*hdr); | | 3401 | len -= sizeof(*hdr); |
3151 | } | | 3402 | } |
3152 | | | 3403 | |
3153 | if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) { | | 3404 | if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) { |
3154 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 3405 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 3406 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
3155 | urtwn_r88e_fw_reset(sc); | | 3407 | urtwn_r88e_fw_reset(sc); |
3156 | else | | 3408 | else |
3157 | urtwn_fw_reset(sc); | | 3409 | urtwn_fw_reset(sc); |
3158 | urtwn_write_1(sc, R92C_MCUFWDL, 0); | | | |
3159 | } | | 3410 | } |
3160 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 3411 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 3412 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
3161 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, | | 3413 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, |
3162 | urtwn_read_2(sc, R92C_SYS_FUNC_EN) | | | 3414 | urtwn_read_2(sc, R92C_SYS_FUNC_EN) | |
3163 | R92C_SYS_FUNC_EN_CPUEN); | | 3415 | R92C_SYS_FUNC_EN_CPUEN); |
3164 | } | | 3416 | } |
3165 | | | 3417 | |
3166 | /* download enabled */ | | 3418 | /* download enabled */ |
3167 | urtwn_write_1(sc, R92C_MCUFWDL, | | 3419 | urtwn_write_1(sc, R92C_MCUFWDL, |
3168 | urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN); | | 3420 | urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN); |
3169 | urtwn_write_1(sc, R92C_MCUFWDL + 2, | | 3421 | urtwn_write_1(sc, R92C_MCUFWDL + 2, |
3170 | urtwn_read_1(sc, R92C_MCUFWDL + 2) & ~0x08); | | 3422 | urtwn_read_1(sc, R92C_MCUFWDL + 2) & ~0x08); |
3171 | | | 3423 | |
3172 | /* Reset the FWDL checksum. */ | | 3424 | /* Reset the FWDL checksum. */ |
3173 | urtwn_write_1(sc, R92C_MCUFWDL, | | 3425 | urtwn_write_1(sc, R92C_MCUFWDL, |
3174 | urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT); | | 3426 | urtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT); |
3175 | | | 3427 | |
| | | 3428 | DELAY(50); |
3176 | /* download firmware */ | | 3429 | /* download firmware */ |
3177 | for (page = 0; len > 0; page++) { | | 3430 | for (page = 0; len > 0; page++) { |
3178 | mlen = MIN(len, R92C_FW_PAGE_SIZE); | | 3431 | mlen = MIN(len, R92C_FW_PAGE_SIZE); |
3179 | error = urtwn_fw_loadpage(sc, page, ptr, mlen); | | 3432 | error = urtwn_fw_loadpage(sc, page, ptr, mlen); |
3180 | if (error != 0) { | | 3433 | if (error != 0) { |
3181 | aprint_error_dev(sc->sc_dev, | | 3434 | aprint_error_dev(sc->sc_dev, |
3182 | "could not load firmware page %d\n", page); | | 3435 | "could not load firmware page %d\n", page); |
3183 | goto fail; | | 3436 | goto fail; |
3184 | } | | 3437 | } |
3185 | ptr += mlen; | | 3438 | ptr += mlen; |
3186 | len -= mlen; | | 3439 | len -= mlen; |
3187 | } | | 3440 | } |
3188 | | | 3441 | |
| @@ -3198,27 +3451,28 @@ urtwn_load_firmware(struct urtwn_softc * | | | @@ -3198,27 +3451,28 @@ urtwn_load_firmware(struct urtwn_softc * |
3198 | DELAY(5); | | 3451 | DELAY(5); |
3199 | } | | 3452 | } |
3200 | if (ntries == 1000) { | | 3453 | if (ntries == 1000) { |
3201 | aprint_error_dev(sc->sc_dev, | | 3454 | aprint_error_dev(sc->sc_dev, |
3202 | "timeout waiting for checksum report\n"); | | 3455 | "timeout waiting for checksum report\n"); |
3203 | error = ETIMEDOUT; | | 3456 | error = ETIMEDOUT; |
3204 | goto fail; | | 3457 | goto fail; |
3205 | } | | 3458 | } |
3206 | | | 3459 | |
3207 | /* Wait for firmware readiness. */ | | 3460 | /* Wait for firmware readiness. */ |
3208 | reg = urtwn_read_4(sc, R92C_MCUFWDL); | | 3461 | reg = urtwn_read_4(sc, R92C_MCUFWDL); |
3209 | reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY; | | 3462 | reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY; |
3210 | urtwn_write_4(sc, R92C_MCUFWDL, reg); | | 3463 | urtwn_write_4(sc, R92C_MCUFWDL, reg); |
3211 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 3464 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 3465 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
3212 | urtwn_r88e_fw_reset(sc); | | 3466 | urtwn_r88e_fw_reset(sc); |
3213 | for (ntries = 0; ntries < 1000; ntries++) { | | 3467 | for (ntries = 0; ntries < 1000; ntries++) { |
3214 | if (urtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY) | | 3468 | if (urtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY) |
3215 | break; | | 3469 | break; |
3216 | DELAY(5); | | 3470 | DELAY(5); |
3217 | } | | 3471 | } |
3218 | if (ntries == 1000) { | | 3472 | if (ntries == 1000) { |
3219 | aprint_error_dev(sc->sc_dev, | | 3473 | aprint_error_dev(sc->sc_dev, |
3220 | "timeout waiting for firmware readiness\n"); | | 3474 | "timeout waiting for firmware readiness\n"); |
3221 | error = ETIMEDOUT; | | 3475 | error = ETIMEDOUT; |
3222 | goto fail; | | 3476 | goto fail; |
3223 | } | | 3477 | } |
3224 | fail: | | 3478 | fail: |
| @@ -3380,98 +3634,106 @@ static void | | | @@ -3380,98 +3634,106 @@ static void |
3380 | urtwn_mac_init(struct urtwn_softc *sc) | | 3634 | urtwn_mac_init(struct urtwn_softc *sc) |
3381 | { | | 3635 | { |
3382 | size_t i; | | 3636 | size_t i; |
3383 | | | 3637 | |
3384 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3638 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
3385 | | | 3639 | |
3386 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3640 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
3387 | | | 3641 | |
3388 | /* Write MAC initialization values. */ | | 3642 | /* Write MAC initialization values. */ |
3389 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { | | 3643 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { |
3390 | for (i = 0; i < __arraycount(rtl8188eu_mac); i++) | | 3644 | for (i = 0; i < __arraycount(rtl8188eu_mac); i++) |
3391 | urtwn_write_1(sc, rtl8188eu_mac[i].reg, | | 3645 | urtwn_write_1(sc, rtl8188eu_mac[i].reg, |
3392 | rtl8188eu_mac[i].val); | | 3646 | rtl8188eu_mac[i].val); |
| | | 3647 | } else if (ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 3648 | for (i = 0; i < __arraycount(rtl8192eu_mac); i++) |
| | | 3649 | urtwn_write_1(sc, rtl8192eu_mac[i].reg, |
| | | 3650 | rtl8192eu_mac[i].val); |
3393 | } else { | | 3651 | } else { |
3394 | for (i = 0; i < __arraycount(rtl8192cu_mac); i++) | | 3652 | for (i = 0; i < __arraycount(rtl8192cu_mac); i++) |
3395 | urtwn_write_1(sc, rtl8192cu_mac[i].reg, | | 3653 | urtwn_write_1(sc, rtl8192cu_mac[i].reg, |
3396 | rtl8192cu_mac[i].val); | | 3654 | rtl8192cu_mac[i].val); |
3397 | } | | 3655 | } |
3398 | } | | 3656 | } |
3399 | | | 3657 | |
3400 | static void | | 3658 | static void |
3401 | urtwn_bb_init(struct urtwn_softc *sc) | | 3659 | urtwn_bb_init(struct urtwn_softc *sc) |
3402 | { | | 3660 | { |
3403 | const struct urtwn_bb_prog *prog; | | 3661 | const struct urtwn_bb_prog *prog; |
3404 | uint32_t reg; | | 3662 | uint32_t reg; |
3405 | uint8_t crystalcap; | | 3663 | uint8_t crystalcap; |
3406 | size_t i; | | 3664 | size_t i; |
3407 | | | 3665 | |
3408 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3666 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
3409 | | | 3667 | |
3410 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3668 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
3411 | | | 3669 | |
3412 | /* Enable BB and RF. */ | | 3670 | /* Enable BB and RF. */ |
3413 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, | | 3671 | urtwn_write_2(sc, R92C_SYS_FUNC_EN, |
3414 | urtwn_read_2(sc, R92C_SYS_FUNC_EN) | | | 3672 | urtwn_read_2(sc, R92C_SYS_FUNC_EN) | |
3415 | R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | | | 3673 | R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | |
3416 | R92C_SYS_FUNC_EN_DIO_RF); | | 3674 | R92C_SYS_FUNC_EN_DIO_RF); |
3417 | | | 3675 | |
3418 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 3676 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 3677 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
3419 | urtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x83); | | 3678 | urtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x83); |
3420 | urtwn_write_1(sc, R92C_AFE_PLL_CTRL + 1, 0xdb); | | 3679 | urtwn_write_1(sc, R92C_AFE_PLL_CTRL + 1, 0xdb); |
3421 | } | | 3680 | } |
3422 | | | 3681 | |
3423 | urtwn_write_1(sc, R92C_RF_CTRL, | | 3682 | urtwn_write_1(sc, R92C_RF_CTRL, |
3424 | R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); | | 3683 | R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); |
3425 | urtwn_write_1(sc, R92C_SYS_FUNC_EN, | | 3684 | urtwn_write_1(sc, R92C_SYS_FUNC_EN, |
3426 | R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | | | 3685 | R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | |
3427 | R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); | | 3686 | R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); |
3428 | | | 3687 | |
3429 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 3688 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 3689 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
3430 | urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f); | | 3690 | urtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f); |
3431 | urtwn_write_1(sc, 0x15, 0xe9); | | 3691 | urtwn_write_1(sc, 0x15, 0xe9); |
3432 | urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); | | 3692 | urtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); |
3433 | } | | 3693 | } |
3434 | | | 3694 | |
3435 | /* Select BB programming based on board type. */ | | 3695 | /* Select BB programming based on board type. */ |
3436 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 3696 | if (ISSET(sc->chip, URTWN_CHIP_88E)) |
3437 | prog = &rtl8188eu_bb_prog; | | 3697 | prog = &rtl8188eu_bb_prog; |
| | | 3698 | else if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 3699 | prog = &rtl8192eu_bb_prog; |
3438 | else if (!(sc->chip & URTWN_CHIP_92C)) { | | 3700 | else if (!(sc->chip & URTWN_CHIP_92C)) { |
3439 | if (sc->board_type == R92C_BOARD_TYPE_MINICARD) { | | 3701 | if (sc->board_type == R92C_BOARD_TYPE_MINICARD) { |
3440 | prog = &rtl8188ce_bb_prog; | | 3702 | prog = &rtl8188ce_bb_prog; |
3441 | } else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) { | | 3703 | } else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) { |
3442 | prog = &rtl8188ru_bb_prog; | | 3704 | prog = &rtl8188ru_bb_prog; |
3443 | } else { | | 3705 | } else { |
3444 | prog = &rtl8188cu_bb_prog; | | 3706 | prog = &rtl8188cu_bb_prog; |
3445 | } | | 3707 | } |
3446 | } else { | | 3708 | } else { |
3447 | if (sc->board_type == R92C_BOARD_TYPE_MINICARD) { | | 3709 | if (sc->board_type == R92C_BOARD_TYPE_MINICARD) { |
3448 | prog = &rtl8192ce_bb_prog; | | 3710 | prog = &rtl8192ce_bb_prog; |
3449 | } else { | | 3711 | } else { |
3450 | prog = &rtl8192cu_bb_prog; | | 3712 | prog = &rtl8192cu_bb_prog; |
3451 | } | | 3713 | } |
3452 | } | | 3714 | } |
3453 | /* Write BB initialization values. */ | | 3715 | /* Write BB initialization values. */ |
3454 | for (i = 0; i < prog->count; i++) { | | 3716 | for (i = 0; i < prog->count; i++) { |
3455 | /* additional delay depend on registers */ | | 3717 | /* additional delay depend on registers */ |
3456 | switch (prog->regs[i]) { | | 3718 | switch (prog->regs[i]) { |
3457 | case 0xfe: | | 3719 | case 0xfe: |
3458 | usbd_delay_ms(sc->sc_udev, 50); | | 3720 | urtwn_delay_ms(sc, 50); |
3459 | break; | | 3721 | break; |
3460 | case 0xfd: | | 3722 | case 0xfd: |
3461 | usbd_delay_ms(sc->sc_udev, 5); | | 3723 | urtwn_delay_ms(sc, 5); |
3462 | break; | | 3724 | break; |
3463 | case 0xfc: | | 3725 | case 0xfc: |
3464 | usbd_delay_ms(sc->sc_udev, 1); | | 3726 | urtwn_delay_ms(sc, 1); |
3465 | break; | | 3727 | break; |
3466 | case 0xfb: | | 3728 | case 0xfb: |
3467 | DELAY(50); | | 3729 | DELAY(50); |
3468 | break; | | 3730 | break; |
3469 | case 0xfa: | | 3731 | case 0xfa: |
3470 | DELAY(5); | | 3732 | DELAY(5); |
3471 | break; | | 3733 | break; |
3472 | case 0xf9: | | 3734 | case 0xf9: |
3473 | DELAY(1); | | 3735 | DELAY(1); |
3474 | break; | | 3736 | break; |
3475 | } | | 3737 | } |
3476 | urtwn_bb_write(sc, prog->regs[i], prog->vals[i]); | | 3738 | urtwn_bb_write(sc, prog->regs[i], prog->vals[i]); |
3477 | DELAY(1); | | 3739 | DELAY(1); |
| @@ -3512,32 +3774,38 @@ urtwn_bb_init(struct urtwn_softc *sc) | | | @@ -3512,32 +3774,38 @@ urtwn_bb_init(struct urtwn_softc *sc) |
3512 | reg = (reg & ~0x0c000000) | (2 << 26); | | 3774 | reg = (reg & ~0x0c000000) | (2 << 26); |
3513 | urtwn_bb_write(sc, 0xe80, reg); | | 3775 | urtwn_bb_write(sc, 0xe80, reg); |
3514 | reg = urtwn_bb_read(sc, 0xe88); | | 3776 | reg = urtwn_bb_read(sc, 0xe88); |
3515 | reg = (reg & ~0x0c000000) | (2 << 26); | | 3777 | reg = (reg & ~0x0c000000) | (2 << 26); |
3516 | urtwn_bb_write(sc, 0xe88, reg); | | 3778 | urtwn_bb_write(sc, 0xe88, reg); |
3517 | } | | 3779 | } |
3518 | | | 3780 | |
3519 | /* Write AGC values. */ | | 3781 | /* Write AGC values. */ |
3520 | for (i = 0; i < prog->agccount; i++) { | | 3782 | for (i = 0; i < prog->agccount; i++) { |
3521 | urtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, prog->agcvals[i]); | | 3783 | urtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, prog->agcvals[i]); |
3522 | DELAY(1); | | 3784 | DELAY(1); |
3523 | } | | 3785 | } |
3524 | | | 3786 | |
3525 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { | | 3787 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 3788 | ISSET(sc->chip, URTWN_CHIP_92EU)) { |
3526 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); | | 3789 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); |
3527 | DELAY(1); | | 3790 | DELAY(1); |
3528 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420); | | 3791 | urtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420); |
3529 | DELAY(1); | | 3792 | DELAY(1); |
3530 | | | 3793 | |
| | | 3794 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) { |
| | | 3795 | urtwn_write_2(sc, R92C_AFE_CTRL3, urtwn_read_2(sc, |
| | | 3796 | R92C_AFE_CTRL3)); |
| | | 3797 | } |
| | | 3798 | |
3531 | crystalcap = sc->r88e_rom[0xb9]; | | 3799 | crystalcap = sc->r88e_rom[0xb9]; |
3532 | if (crystalcap == 0xff) | | 3800 | if (crystalcap == 0xff) |
3533 | crystalcap = 0x20; | | 3801 | crystalcap = 0x20; |
3534 | crystalcap &= 0x3f; | | 3802 | crystalcap &= 0x3f; |
3535 | reg = urtwn_bb_read(sc, R92C_AFE_XTAL_CTRL); | | 3803 | reg = urtwn_bb_read(sc, R92C_AFE_XTAL_CTRL); |
3536 | urtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, | | 3804 | urtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, |
3537 | RW(reg, R92C_AFE_XTAL_CTRL_ADDR, | | 3805 | RW(reg, R92C_AFE_XTAL_CTRL_ADDR, |
3538 | crystalcap | crystalcap << 6)); | | 3806 | crystalcap | crystalcap << 6)); |
3539 | } else { | | 3807 | } else { |
3540 | if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & | | 3808 | if (urtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & |
3541 | R92C_HSSI_PARAM2_CCK_HIPWR) { | | 3809 | R92C_HSSI_PARAM2_CCK_HIPWR) { |
3542 | SET(sc->sc_flags, URTWN_FLAG_CCK_HIPWR); | | 3810 | SET(sc->sc_flags, URTWN_FLAG_CCK_HIPWR); |
3543 | } | | 3811 | } |
| @@ -3546,79 +3814,81 @@ urtwn_bb_init(struct urtwn_softc *sc) | | | @@ -3546,79 +3814,81 @@ urtwn_bb_init(struct urtwn_softc *sc) |
3546 | | | 3814 | |
3547 | static void | | 3815 | static void |
3548 | urtwn_rf_init(struct urtwn_softc *sc) | | 3816 | urtwn_rf_init(struct urtwn_softc *sc) |
3549 | { | | 3817 | { |
3550 | const struct urtwn_rf_prog *prog; | | 3818 | const struct urtwn_rf_prog *prog; |
3551 | uint32_t reg, mask, saved; | | 3819 | uint32_t reg, mask, saved; |
3552 | size_t i, j, idx; | | 3820 | size_t i, j, idx; |
3553 | | | 3821 | |
3554 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3822 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
3555 | | | 3823 | |
3556 | /* Select RF programming based on board type. */ | | 3824 | /* Select RF programming based on board type. */ |
3557 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 3825 | if (ISSET(sc->chip, URTWN_CHIP_88E)) |
3558 | prog = rtl8188eu_rf_prog; | | 3826 | prog = rtl8188eu_rf_prog; |
| | | 3827 | else if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 3828 | prog = rtl8192eu_rf_prog; |
3559 | else if (!(sc->chip & URTWN_CHIP_92C)) { | | 3829 | else if (!(sc->chip & URTWN_CHIP_92C)) { |
3560 | if (sc->board_type == R92C_BOARD_TYPE_MINICARD) { | | 3830 | if (sc->board_type == R92C_BOARD_TYPE_MINICARD) { |
3561 | prog = rtl8188ce_rf_prog; | | 3831 | prog = rtl8188ce_rf_prog; |
3562 | } else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) { | | 3832 | } else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) { |
3563 | prog = rtl8188ru_rf_prog; | | 3833 | prog = rtl8188ru_rf_prog; |
3564 | } else { | | 3834 | } else { |
3565 | prog = rtl8188cu_rf_prog; | | 3835 | prog = rtl8188cu_rf_prog; |
3566 | } | | 3836 | } |
3567 | } else { | | 3837 | } else { |
3568 | prog = rtl8192ce_rf_prog; | | 3838 | prog = rtl8192ce_rf_prog; |
3569 | } | | 3839 | } |
3570 | | | 3840 | |
3571 | for (i = 0; i < sc->nrxchains; i++) { | | 3841 | for (i = 0; i < sc->nrxchains; i++) { |
3572 | /* Save RF_ENV control type. */ | | 3842 | /* Save RF_ENV control type. */ |
3573 | idx = i / 2; | | 3843 | idx = i / 2; |
3574 | mask = 0xffffU << ((i % 2) * 16); | | 3844 | mask = 0xffffU << ((i % 2) * 16); |
3575 | saved = urtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)) & mask; | | 3845 | saved = urtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)) & mask; |
3576 | | | 3846 | |
3577 | /* Set RF_ENV enable. */ | | 3847 | /* Set RF_ENV enable. */ |
3578 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); | | 3848 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); |
3579 | reg |= 0x100000; | | 3849 | reg |= 0x100000; |
3580 | urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); | | 3850 | urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); |
3581 | DELAY(1); | | 3851 | DELAY(50); |
3582 | | | 3852 | |
3583 | /* Set RF_ENV output high. */ | | 3853 | /* Set RF_ENV output high. */ |
3584 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); | | 3854 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); |
3585 | reg |= 0x10; | | 3855 | reg |= 0x10; |
3586 | urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); | | 3856 | urtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); |
3587 | DELAY(1); | | 3857 | DELAY(50); |
3588 | | | 3858 | |
3589 | /* Set address and data lengths of RF registers. */ | | 3859 | /* Set address and data lengths of RF registers. */ |
3590 | reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); | | 3860 | reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); |
3591 | reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH; | | 3861 | reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH; |
3592 | urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); | | 3862 | urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); |
3593 | DELAY(1); | | 3863 | DELAY(50); |
3594 | reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); | | 3864 | reg = urtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); |
3595 | reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH; | | 3865 | reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH; |
3596 | urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); | | 3866 | urtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); |
3597 | DELAY(1); | | 3867 | DELAY(50); |
3598 | | | 3868 | |
3599 | /* Write RF initialization values for this chain. */ | | 3869 | /* Write RF initialization values for this chain. */ |
3600 | for (j = 0; j < prog[i].count; j++) { | | 3870 | for (j = 0; j < prog[i].count; j++) { |
3601 | if (prog[i].regs[j] >= 0xf9 && | | 3871 | if (prog[i].regs[j] >= 0xf9 && |
3602 | prog[i].regs[j] <= 0xfe) { | | 3872 | prog[i].regs[j] <= 0xfe) { |
3603 | /* | | 3873 | /* |
3604 | * These are fake RF registers offsets that | | 3874 | * These are fake RF registers offsets that |
3605 | * indicate a delay is required. | | 3875 | * indicate a delay is required. |
3606 | */ | | 3876 | */ |
3607 | usbd_delay_ms(sc->sc_udev, 50); | | 3877 | urtwn_delay_ms(sc, 50); |
3608 | continue; | | 3878 | continue; |
3609 | } | | 3879 | } |
3610 | urtwn_rf_write(sc, i, prog[i].regs[j], prog[i].vals[j]); | | 3880 | urtwn_rf_write(sc, i, prog[i].regs[j], prog[i].vals[j]); |
3611 | DELAY(1); | | 3881 | DELAY(5); |
3612 | } | | 3882 | } |
3613 | | | 3883 | |
3614 | /* Restore RF_ENV control type. */ | | 3884 | /* Restore RF_ENV control type. */ |
3615 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)) & ~mask; | | 3885 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)) & ~mask; |
3616 | urtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg | saved); | | 3886 | urtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg | saved); |
3617 | } | | 3887 | } |
3618 | | | 3888 | |
3619 | if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) == | | 3889 | if ((sc->chip & (URTWN_CHIP_UMC_A_CUT | URTWN_CHIP_92C)) == |
3620 | URTWN_CHIP_UMC_A_CUT) { | | 3890 | URTWN_CHIP_UMC_A_CUT) { |
3621 | urtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255); | | 3891 | urtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255); |
3622 | urtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00); | | 3892 | urtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00); |
3623 | } | | 3893 | } |
3624 | | | 3894 | |
| @@ -3628,26 +3898,28 @@ urtwn_rf_init(struct urtwn_softc *sc) | | | @@ -3628,26 +3898,28 @@ urtwn_rf_init(struct urtwn_softc *sc) |
3628 | } | | 3898 | } |
3629 | } | | 3899 | } |
3630 | | | 3900 | |
3631 | static void | | 3901 | static void |
3632 | urtwn_cam_init(struct urtwn_softc *sc) | | 3902 | urtwn_cam_init(struct urtwn_softc *sc) |
3633 | { | | 3903 | { |
3634 | uint32_t content, command; | | 3904 | uint32_t content, command; |
3635 | uint8_t idx; | | 3905 | uint8_t idx; |
3636 | size_t i; | | 3906 | size_t i; |
3637 | | | 3907 | |
3638 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 3908 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
3639 | | | 3909 | |
3640 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 3910 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
| | | 3911 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 3912 | return; |
3641 | | | 3913 | |
3642 | for (idx = 0; idx < R92C_CAM_ENTRY_COUNT; idx++) { | | 3914 | for (idx = 0; idx < R92C_CAM_ENTRY_COUNT; idx++) { |
3643 | content = (idx & 3) | | 3915 | content = (idx & 3) |
3644 | | (R92C_CAM_ALGO_AES << R92C_CAM_ALGO_S) | | 3916 | | (R92C_CAM_ALGO_AES << R92C_CAM_ALGO_S) |
3645 | | R92C_CAM_VALID; | | 3917 | | R92C_CAM_VALID; |
3646 | | | 3918 | |
3647 | command = R92C_CAMCMD_POLLING | | 3919 | command = R92C_CAMCMD_POLLING |
3648 | | R92C_CAMCMD_WRITE | | 3920 | | R92C_CAMCMD_WRITE |
3649 | | R92C_CAM_CTL0(idx); | | 3921 | | R92C_CAM_CTL0(idx); |
3650 | | | 3922 | |
3651 | urtwn_write_4(sc, R92C_CAMWRITE, content); | | 3923 | urtwn_write_4(sc, R92C_CAMWRITE, content); |
3652 | urtwn_write_4(sc, R92C_CAMCMD, command); | | 3924 | urtwn_write_4(sc, R92C_CAMCMD, command); |
3653 | } | | 3925 | } |
| @@ -3998,27 +4270,28 @@ urtwn_r88e_get_txpower(struct urtwn_soft | | | @@ -3998,27 +4270,28 @@ urtwn_r88e_get_txpower(struct urtwn_soft |
3998 | } | | 4270 | } |
3999 | } | | 4271 | } |
4000 | | | 4272 | |
4001 | static void | | 4273 | static void |
4002 | urtwn_set_txpower(struct urtwn_softc *sc, u_int chan, u_int ht40m) | | 4274 | urtwn_set_txpower(struct urtwn_softc *sc, u_int chan, u_int ht40m) |
4003 | { | | 4275 | { |
4004 | uint16_t power[URTWN_RIDX_COUNT]; | | 4276 | uint16_t power[URTWN_RIDX_COUNT]; |
4005 | size_t i; | | 4277 | size_t i; |
4006 | | | 4278 | |
4007 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 4279 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
4008 | | | 4280 | |
4009 | for (i = 0; i < sc->ntxchains; i++) { | | 4281 | for (i = 0; i < sc->ntxchains; i++) { |
4010 | /* Compute per-rate Tx power values. */ | | 4282 | /* Compute per-rate Tx power values. */ |
4011 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 4283 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 4284 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
4012 | urtwn_r88e_get_txpower(sc, i, chan, ht40m, power); | | 4285 | urtwn_r88e_get_txpower(sc, i, chan, ht40m, power); |
4013 | else | | 4286 | else |
4014 | urtwn_get_txpower(sc, i, chan, ht40m, power); | | 4287 | urtwn_get_txpower(sc, i, chan, ht40m, power); |
4015 | /* Write per-rate Tx power values to hardware. */ | | 4288 | /* Write per-rate Tx power values to hardware. */ |
4016 | urtwn_write_txpower(sc, i, power); | | 4289 | urtwn_write_txpower(sc, i, power); |
4017 | } | | 4290 | } |
4018 | } | | 4291 | } |
4019 | | | 4292 | |
4020 | static void | | 4293 | static void |
4021 | urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c, u_int ht40m) | | 4294 | urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c, u_int ht40m) |
4022 | { | | 4295 | { |
4023 | struct ieee80211com *ic = &sc->sc_ic; | | 4296 | struct ieee80211com *ic = &sc->sc_ic; |
4024 | u_int chan; | | 4297 | u_int chan; |
| @@ -4081,36 +4354,38 @@ urtwn_set_chan(struct urtwn_softc *sc, s | | | @@ -4081,36 +4354,38 @@ urtwn_set_chan(struct urtwn_softc *sc, s |
4081 | | | 4354 | |
4082 | /* Select 40MHz bandwidth. */ | | 4355 | /* Select 40MHz bandwidth. */ |
4083 | urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, | | 4356 | urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, |
4084 | (sc->rf_chnlbw[0] & ~0xfff) | chan); | | 4357 | (sc->rf_chnlbw[0] & ~0xfff) | chan); |
4085 | } else { | | 4358 | } else { |
4086 | urtwn_write_1(sc, R92C_BWOPMODE, | | 4359 | urtwn_write_1(sc, R92C_BWOPMODE, |
4087 | urtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ); | | 4360 | urtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ); |
4088 | | | 4361 | |
4089 | urtwn_bb_write(sc, R92C_FPGA0_RFMOD, | | 4362 | urtwn_bb_write(sc, R92C_FPGA0_RFMOD, |
4090 | urtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ); | | 4363 | urtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ); |
4091 | urtwn_bb_write(sc, R92C_FPGA1_RFMOD, | | 4364 | urtwn_bb_write(sc, R92C_FPGA1_RFMOD, |
4092 | urtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ); | | 4365 | urtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ); |
4093 | | | 4366 | |
4094 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 4367 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 4368 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
4095 | urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, | | 4369 | urtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, |
4096 | urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | | | 4370 | urtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | |
4097 | R92C_FPGA0_ANAPARAM2_CBW20); | | 4371 | R92C_FPGA0_ANAPARAM2_CBW20); |
4098 | } | | 4372 | } |
4099 | | | 4373 | |
4100 | /* Select 20MHz bandwidth. */ | | 4374 | /* Select 20MHz bandwidth. */ |
4101 | urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, | | 4375 | urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, |
4102 | (sc->rf_chnlbw[0] & ~0xfff) | chan | | | 4376 | (sc->rf_chnlbw[0] & ~0xfff) | chan | |
4103 | (ISSET(sc->chip, URTWN_CHIP_88E) ? | | 4377 | (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 4378 | ISSET(sc->chip, URTWN_CHIP_92EU) ? |
4104 | R88E_RF_CHNLBW_BW20 : R92C_RF_CHNLBW_BW20)); | | 4379 | R88E_RF_CHNLBW_BW20 : R92C_RF_CHNLBW_BW20)); |
4105 | } | | 4380 | } |
4106 | } | | 4381 | } |
4107 | | | 4382 | |
4108 | static void | | 4383 | static void |
4109 | urtwn_iq_calib(struct urtwn_softc *sc, bool inited) | | 4384 | urtwn_iq_calib(struct urtwn_softc *sc, bool inited) |
4110 | { | | 4385 | { |
4111 | | | 4386 | |
4112 | DPRINTFN(DBG_FN, ("%s: %s: inited=%d\n", device_xname(sc->sc_dev), | | 4387 | DPRINTFN(DBG_FN, ("%s: %s: inited=%d\n", device_xname(sc->sc_dev), |
4113 | __func__, inited)); | | 4388 | __func__, inited)); |
4114 | | | 4389 | |
4115 | uint32_t addaBackup[16], iqkBackup[4], piMode; | | 4390 | uint32_t addaBackup[16], iqkBackup[4], piMode; |
4116 | | | 4391 | |
| @@ -4274,66 +4549,71 @@ urtwn_lc_calib(struct urtwn_softc *sc) | | | @@ -4274,66 +4549,71 @@ urtwn_lc_calib(struct urtwn_softc *sc) |
4274 | urtwn_rf_write(sc, i, R92C_RF_AC, | | 4549 | urtwn_rf_write(sc, i, R92C_RF_AC, |
4275 | RW(rf_ac[i], R92C_RF_AC_MODE, | | 4550 | RW(rf_ac[i], R92C_RF_AC_MODE, |
4276 | R92C_RF_AC_MODE_STANDBY)); | | 4551 | R92C_RF_AC_MODE_STANDBY)); |
4277 | } | | 4552 | } |
4278 | } else { | | 4553 | } else { |
4279 | /* Block all Tx queues. */ | | 4554 | /* Block all Tx queues. */ |
4280 | urtwn_write_1(sc, R92C_TXPAUSE, 0xff); | | 4555 | urtwn_write_1(sc, R92C_TXPAUSE, 0xff); |
4281 | } | | 4556 | } |
4282 | /* Start calibration. */ | | 4557 | /* Start calibration. */ |
4283 | urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, | | 4558 | urtwn_rf_write(sc, 0, R92C_RF_CHNLBW, |
4284 | urtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART); | | 4559 | urtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART); |
4285 | | | 4560 | |
4286 | /* Give calibration the time to complete. */ | | 4561 | /* Give calibration the time to complete. */ |
4287 | usbd_delay_ms(sc->sc_udev, 100); | | 4562 | urtwn_delay_ms(sc, 100); |
4288 | | | 4563 | |
4289 | /* Restore configuration. */ | | 4564 | /* Restore configuration. */ |
4290 | if ((txmode & 0x70) != 0) { | | 4565 | if ((txmode & 0x70) != 0) { |
4291 | /* Restore Tx mode. */ | | 4566 | /* Restore Tx mode. */ |
4292 | urtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode); | | 4567 | urtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode); |
4293 | /* Restore RF mode. */ | | 4568 | /* Restore RF mode. */ |
4294 | for (i = 0; i < sc->nrxchains; i++) { | | 4569 | for (i = 0; i < sc->nrxchains; i++) { |
4295 | urtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]); | | 4570 | urtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]); |
4296 | } | | 4571 | } |
4297 | } else { | | 4572 | } else { |
4298 | /* Unblock all Tx queues. */ | | 4573 | /* Unblock all Tx queues. */ |
4299 | urtwn_write_1(sc, R92C_TXPAUSE, 0x00); | | 4574 | urtwn_write_1(sc, R92C_TXPAUSE, 0x00); |
4300 | } | | 4575 | } |
4301 | } | | 4576 | } |
4302 | | | 4577 | |
4303 | static void | | 4578 | static void |
4304 | urtwn_temp_calib(struct urtwn_softc *sc) | | 4579 | urtwn_temp_calib(struct urtwn_softc *sc) |
4305 | { | | 4580 | { |
4306 | int temp; | | 4581 | int temp, t_meter_reg; |
4307 | | | 4582 | |
4308 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 4583 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
4309 | | | 4584 | |
4310 | KASSERT(mutex_owned(&sc->sc_write_mtx)); | | 4585 | KASSERT(mutex_owned(&sc->sc_write_mtx)); |
4311 | | | 4586 | |
| | | 4587 | if (!ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 4588 | t_meter_reg = R92C_RF_T_METER; |
| | | 4589 | else |
| | | 4590 | t_meter_reg = R92E_RF_T_METER; |
| | | 4591 | |
4312 | if (sc->thcal_state == 0) { | | 4592 | if (sc->thcal_state == 0) { |
4313 | /* Start measuring temperature. */ | | 4593 | /* Start measuring temperature. */ |
4314 | DPRINTFN(DBG_RF, ("%s: %s: start measuring temperature\n", | | 4594 | DPRINTFN(DBG_RF, ("%s: %s: start measuring temperature\n", |
4315 | device_xname(sc->sc_dev), __func__)); | | 4595 | device_xname(sc->sc_dev), __func__)); |
4316 | urtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60); | | 4596 | urtwn_rf_write(sc, 0, t_meter_reg, 0x60); |
4317 | sc->thcal_state = 1; | | 4597 | sc->thcal_state = 1; |
4318 | return; | | 4598 | return; |
4319 | } | | 4599 | } |
4320 | sc->thcal_state = 0; | | 4600 | sc->thcal_state = 0; |
4321 | | | 4601 | |
4322 | /* Read measured temperature. */ | | 4602 | /* Read measured temperature. */ |
4323 | temp = urtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f; | | 4603 | temp = urtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f; |
4324 | DPRINTFN(DBG_RF, ("%s: %s: temperature=%d\n", device_xname(sc->sc_dev), | | 4604 | DPRINTFN(DBG_RF, ("%s: %s: temperature=%d\n", device_xname(sc->sc_dev), |
4325 | __func__, temp)); | | 4605 | __func__, temp)); |
4326 | if (temp == 0) /* Read failed, skip. */ | | 4606 | if (temp == 0) /* Read failed, skip. */ |
4327 | return; | | 4607 | return; |
4328 | | | 4608 | |
4329 | /* | | 4609 | /* |
4330 | * Redo LC calibration if temperature changed significantly since | | 4610 | * Redo LC calibration if temperature changed significantly since |
4331 | * last calibration. | | 4611 | * last calibration. |
4332 | */ | | 4612 | */ |
4333 | if (sc->thcal_lctemp == 0) { | | 4613 | if (sc->thcal_lctemp == 0) { |
4334 | /* First LC calibration is performed in urtwn_init(). */ | | 4614 | /* First LC calibration is performed in urtwn_init(). */ |
4335 | sc->thcal_lctemp = temp; | | 4615 | sc->thcal_lctemp = temp; |
4336 | } else if (abs(temp - sc->thcal_lctemp) > 1) { | | 4616 | } else if (abs(temp - sc->thcal_lctemp) > 1) { |
4337 | DPRINTFN(DBG_RF, | | 4617 | DPRINTFN(DBG_RF, |
4338 | ("%s: %s: LC calib triggered by temp: %d -> %d\n", | | 4618 | ("%s: %s: LC calib triggered by temp: %d -> %d\n", |
4339 | device_xname(sc->sc_dev), __func__, sc->thcal_lctemp, | | 4619 | device_xname(sc->sc_dev), __func__, sc->thcal_lctemp, |
| @@ -4388,35 +4668,40 @@ urtwn_init(struct ifnet *ifp) | | | @@ -4388,35 +4668,40 @@ urtwn_init(struct ifnet *ifp) |
4388 | error = urtwn_power_on(sc); | | 4668 | error = urtwn_power_on(sc); |
4389 | if (error != 0) | | 4669 | if (error != 0) |
4390 | goto fail; | | 4670 | goto fail; |
4391 | | | 4671 | |
4392 | /* Initialize DMA. */ | | 4672 | /* Initialize DMA. */ |
4393 | error = urtwn_dma_init(sc); | | 4673 | error = urtwn_dma_init(sc); |
4394 | if (error != 0) | | 4674 | if (error != 0) |
4395 | goto fail; | | 4675 | goto fail; |
4396 | | | 4676 | |
4397 | /* Set info size in Rx descriptors (in 64-bit words). */ | | 4677 | /* Set info size in Rx descriptors (in 64-bit words). */ |
4398 | urtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4); | | 4678 | urtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4); |
4399 | | | 4679 | |
4400 | /* Init interrupts. */ | | 4680 | /* Init interrupts. */ |
4401 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { | | 4681 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 4682 | ISSET(sc->chip, URTWN_CHIP_92EU)) { |
4402 | urtwn_write_4(sc, R88E_HISR, 0xffffffff); | | 4683 | urtwn_write_4(sc, R88E_HISR, 0xffffffff); |
4403 | urtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 | | | 4684 | urtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 | |
4404 | R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT); | | 4685 | R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT); |
4405 | urtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW | | | 4686 | urtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW | |
4406 | R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR); | | 4687 | R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR); |
4407 | urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, | | 4688 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { |
4408 | urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) | | | 4689 | urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, |
4409 | R92C_USB_SPECIAL_OPTION_INT_BULK_SEL); | | 4690 | urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) | |
| | | 4691 | R92C_USB_SPECIAL_OPTION_INT_BULK_SEL); |
| | | 4692 | } |
| | | 4693 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 4694 | urtwn_write_1(sc, R92C_USB_HRPWM, 0); |
4410 | } else { | | 4695 | } else { |
4411 | urtwn_write_4(sc, R92C_HISR, 0xffffffff); | | 4696 | urtwn_write_4(sc, R92C_HISR, 0xffffffff); |
4412 | urtwn_write_4(sc, R92C_HIMR, 0xffffffff); | | 4697 | urtwn_write_4(sc, R92C_HIMR, 0xffffffff); |
4413 | } | | 4698 | } |
4414 | | | 4699 | |
4415 | /* Set MAC address. */ | | 4700 | /* Set MAC address. */ |
4416 | IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl)); | | 4701 | IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl)); |
4417 | urtwn_write_region(sc, R92C_MACID, ic->ic_myaddr, IEEE80211_ADDR_LEN); | | 4702 | urtwn_write_region(sc, R92C_MACID, ic->ic_myaddr, IEEE80211_ADDR_LEN); |
4418 | | | 4703 | |
4419 | /* Set initial network type. */ | | 4704 | /* Set initial network type. */ |
4420 | reg = urtwn_read_4(sc, R92C_CR); | | 4705 | reg = urtwn_read_4(sc, R92C_CR); |
4421 | switch (ic->ic_opmode) { | | 4706 | switch (ic->ic_opmode) { |
4422 | case IEEE80211_M_STA: | | 4707 | case IEEE80211_M_STA: |
| @@ -4437,159 +4722,170 @@ urtwn_init(struct ifnet *ifp) | | | @@ -4437,159 +4722,170 @@ urtwn_init(struct ifnet *ifp) |
4437 | | | 4722 | |
4438 | /* SIFS (used in NAV) */ | | 4723 | /* SIFS (used in NAV) */ |
4439 | urtwn_write_2(sc, R92C_SPEC_SIFS, | | 4724 | urtwn_write_2(sc, R92C_SPEC_SIFS, |
4440 | SM(R92C_SPEC_SIFS_CCK, 0x10) | SM(R92C_SPEC_SIFS_OFDM, 0x10)); | | 4725 | SM(R92C_SPEC_SIFS_CCK, 0x10) | SM(R92C_SPEC_SIFS_OFDM, 0x10)); |
4441 | | | 4726 | |
4442 | /* Set short/long retry limits. */ | | 4727 | /* Set short/long retry limits. */ |
4443 | urtwn_write_2(sc, R92C_RL, | | 4728 | urtwn_write_2(sc, R92C_RL, |
4444 | SM(R92C_RL_SRL, 0x30) | SM(R92C_RL_LRL, 0x30)); | | 4729 | SM(R92C_RL_SRL, 0x30) | SM(R92C_RL_LRL, 0x30)); |
4445 | | | 4730 | |
4446 | /* Initialize EDCA parameters. */ | | 4731 | /* Initialize EDCA parameters. */ |
4447 | urtwn_edca_init(sc); | | 4732 | urtwn_edca_init(sc); |
4448 | | | 4733 | |
4449 | /* Setup rate fallback. */ | | 4734 | /* Setup rate fallback. */ |
4450 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 4735 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 4736 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
4451 | urtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000); | | 4737 | urtwn_write_4(sc, R92C_DARFRC + 0, 0x00000000); |
4452 | urtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404); | | 4738 | urtwn_write_4(sc, R92C_DARFRC + 4, 0x10080404); |
4453 | urtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201); | | 4739 | urtwn_write_4(sc, R92C_RARFRC + 0, 0x04030201); |
4454 | urtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605); | | 4740 | urtwn_write_4(sc, R92C_RARFRC + 4, 0x08070605); |
4455 | } | | 4741 | } |
4456 | | | 4742 | |
4457 | urtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, | | 4743 | urtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, |
4458 | urtwn_read_1(sc, R92C_FWHW_TXQ_CTRL) | | | 4744 | urtwn_read_1(sc, R92C_FWHW_TXQ_CTRL) | |
4459 | R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW); | | 4745 | R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW); |
4460 | /* Set ACK timeout. */ | | 4746 | /* Set ACK timeout. */ |
4461 | urtwn_write_1(sc, R92C_ACKTO, 0x40); | | 4747 | urtwn_write_1(sc, R92C_ACKTO, 0x40); |
4462 | | | 4748 | |
4463 | /* Setup USB aggregation. */ | | 4749 | /* Setup USB aggregation. */ |
4464 | /* Tx */ | | 4750 | /* Tx */ |
4465 | reg = urtwn_read_4(sc, R92C_TDECTRL); | | 4751 | reg = urtwn_read_4(sc, R92C_TDECTRL); |
4466 | reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, 6); | | 4752 | reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, 6); |
4467 | urtwn_write_4(sc, R92C_TDECTRL, reg); | | 4753 | urtwn_write_4(sc, R92C_TDECTRL, reg); |
4468 | /* Rx */ | | 4754 | /* Rx */ |
4469 | urtwn_write_1(sc, R92C_TRXDMA_CTRL, | | 4755 | urtwn_write_1(sc, R92C_TRXDMA_CTRL, |
4470 | urtwn_read_1(sc, R92C_TRXDMA_CTRL) | | | 4756 | urtwn_read_1(sc, R92C_TRXDMA_CTRL) | |
4471 | R92C_TRXDMA_CTRL_RXDMA_AGG_EN); | | 4757 | R92C_TRXDMA_CTRL_RXDMA_AGG_EN); |
4472 | urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, | | 4758 | urtwn_write_1(sc, R92C_USB_SPECIAL_OPTION, |
4473 | urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) & | | 4759 | urtwn_read_1(sc, R92C_USB_SPECIAL_OPTION) & |
4474 | ~R92C_USB_SPECIAL_OPTION_AGG_EN); | | 4760 | ~R92C_USB_SPECIAL_OPTION_AGG_EN); |
4475 | urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48); | | 4761 | urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48); |
4476 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 4762 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 4763 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
4477 | urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4); | | 4764 | urtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4); |
4478 | else | | 4765 | else |
4479 | urtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4); | | 4766 | urtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4); |
4480 | | | 4767 | |
4481 | /* Initialize beacon parameters. */ | | 4768 | /* Initialize beacon parameters. */ |
4482 | urtwn_write_2(sc, R92C_BCN_CTRL, 0x1010); | | 4769 | urtwn_write_2(sc, R92C_BCN_CTRL, 0x1010); |
4483 | urtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404); | | 4770 | urtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404); |
4484 | urtwn_write_1(sc, R92C_DRVERLYINT, R92C_DRIVER_EARLY_INT_TIME); | | 4771 | urtwn_write_1(sc, R92C_DRVERLYINT, R92C_DRIVER_EARLY_INT_TIME); |
4485 | urtwn_write_1(sc, R92C_BCNDMATIM, R92C_DMA_ATIME_INT_TIME); | | 4772 | urtwn_write_1(sc, R92C_BCNDMATIM, R92C_DMA_ATIME_INT_TIME); |
4486 | urtwn_write_2(sc, R92C_BCNTCFG, 0x660f); | | 4773 | urtwn_write_2(sc, R92C_BCNTCFG, 0x660f); |
4487 | | | 4774 | |
4488 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 4775 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 4776 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
4489 | /* Setup AMPDU aggregation. */ | | 4777 | /* Setup AMPDU aggregation. */ |
4490 | urtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ | | 4778 | urtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ |
4491 | urtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); | | 4779 | urtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); |
4492 | urtwn_write_2(sc, 0x4ca, 0x0708); | | 4780 | urtwn_write_2(sc, 0x4ca, 0x0708); |
4493 | | | 4781 | |
4494 | urtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); | | 4782 | urtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); |
4495 | urtwn_write_1(sc, R92C_BCN_CTRL, R92C_BCN_CTRL_DIS_TSF_UDT0); | | 4783 | urtwn_write_1(sc, R92C_BCN_CTRL, R92C_BCN_CTRL_DIS_TSF_UDT0); |
4496 | } | | 4784 | } |
4497 | | | 4785 | |
4498 | /* Load 8051 microcode. */ | | 4786 | /* Load 8051 microcode. */ |
4499 | error = urtwn_load_firmware(sc); | | 4787 | error = urtwn_load_firmware(sc); |
4500 | if (error != 0) | | 4788 | if (error != 0) |
4501 | goto fail; | | 4789 | goto fail; |
4502 | SET(sc->sc_flags, URTWN_FLAG_FWREADY); | | 4790 | SET(sc->sc_flags, URTWN_FLAG_FWREADY); |
4503 | | | 4791 | |
4504 | /* Initialize MAC/BB/RF blocks. */ | | 4792 | /* Initialize MAC/BB/RF blocks. */ |
4505 | /* | | 4793 | /* |
4506 | * XXX: urtwn_mac_init() sets R92C_RCR[0:15] = R92C_RCR_APM | | | 4794 | * XXX: urtwn_mac_init() sets R92C_RCR[0:15] = R92C_RCR_APM | |
4507 | * R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_AICV | R92C_RCR_AMF. | | 4795 | * R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_AICV | R92C_RCR_AMF. |
4508 | * XXX: This setting should be removed from rtl8192cu_mac[]. | | 4796 | * XXX: This setting should be removed from rtl8192cu_mac[]. |
4509 | */ | | 4797 | */ |
4510 | urtwn_mac_init(sc); // sets R92C_RCR[0:15] | | 4798 | urtwn_mac_init(sc); // sets R92C_RCR[0:15] |
4511 | urtwn_rxfilter_init(sc); // reset R92C_RCR | | 4799 | urtwn_rxfilter_init(sc); // reset R92C_RCR |
4512 | urtwn_bb_init(sc); | | 4800 | urtwn_bb_init(sc); |
4513 | urtwn_rf_init(sc); | | 4801 | urtwn_rf_init(sc); |
4514 | | | 4802 | |
4515 | if (ISSET(sc->chip, URTWN_CHIP_88E)) { | | 4803 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 4804 | ISSET(sc->chip, URTWN_CHIP_92EU)) { |
4516 | urtwn_write_2(sc, R92C_CR, | | 4805 | urtwn_write_2(sc, R92C_CR, |
4517 | urtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN | | | 4806 | urtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN | |
4518 | R92C_CR_MACRXEN); | | 4807 | R92C_CR_MACRXEN); |
4519 | } | | 4808 | } |
4520 | | | 4809 | |
4521 | /* Turn CCK and OFDM blocks on. */ | | 4810 | /* Turn CCK and OFDM blocks on. */ |
4522 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); | | 4811 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); |
4523 | reg |= R92C_RFMOD_CCK_EN; | | 4812 | reg |= R92C_RFMOD_CCK_EN; |
4524 | urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); | | 4813 | urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); |
4525 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); | | 4814 | reg = urtwn_bb_read(sc, R92C_FPGA0_RFMOD); |
4526 | reg |= R92C_RFMOD_OFDM_EN; | | 4815 | reg |= R92C_RFMOD_OFDM_EN; |
4527 | urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); | | 4816 | urtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); |
4528 | | | 4817 | |
4529 | /* Clear per-station keys table. */ | | 4818 | /* Clear per-station keys table. */ |
4530 | urtwn_cam_init(sc); | | 4819 | urtwn_cam_init(sc); |
4531 | | | 4820 | |
4532 | /* Enable hardware sequence numbering. */ | | 4821 | /* Enable hardware sequence numbering. */ |
4533 | urtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff); | | 4822 | urtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff); |
4534 | | | 4823 | |
4535 | /* Perform LO and IQ calibrations. */ | | 4824 | /* Perform LO and IQ calibrations. */ |
4536 | urtwn_iq_calib(sc, sc->iqk_inited); | | 4825 | urtwn_iq_calib(sc, sc->iqk_inited); |
4537 | sc->iqk_inited = true; | | 4826 | sc->iqk_inited = true; |
4538 | | | 4827 | |
4539 | /* Perform LC calibration. */ | | 4828 | /* Perform LC calibration. */ |
4540 | urtwn_lc_calib(sc); | | 4829 | urtwn_lc_calib(sc); |
4541 | | | 4830 | |
4542 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) { | | 4831 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 4832 | !ISSET(sc->chip, URTWN_CHIP_92EU)) { |
4543 | /* Fix USB interference issue. */ | | 4833 | /* Fix USB interference issue. */ |
4544 | urtwn_write_1(sc, 0xfe40, 0xe0); | | 4834 | urtwn_write_1(sc, 0xfe40, 0xe0); |
4545 | urtwn_write_1(sc, 0xfe41, 0x8d); | | 4835 | urtwn_write_1(sc, 0xfe41, 0x8d); |
4546 | urtwn_write_1(sc, 0xfe42, 0x80); | | 4836 | urtwn_write_1(sc, 0xfe42, 0x80); |
4547 | urtwn_write_4(sc, 0x20c, 0xfd0320); | | 4837 | urtwn_write_4(sc, 0x20c, 0xfd0320); |
4548 | | | 4838 | |
4549 | urtwn_pa_bias_init(sc); | | 4839 | urtwn_pa_bias_init(sc); |
4550 | } | | 4840 | } |
4551 | | | 4841 | |
4552 | if (!(sc->chip & (URTWN_CHIP_92C | URTWN_CHIP_92C_1T2R))) { | | 4842 | if (!(sc->chip & (URTWN_CHIP_92C | URTWN_CHIP_92C_1T2R)) || |
| | | 4843 | !(sc->chip & URTWN_CHIP_92EU)) { |
4553 | /* 1T1R */ | | 4844 | /* 1T1R */ |
4554 | urtwn_bb_write(sc, R92C_FPGA0_RFPARAM(0), | | 4845 | urtwn_bb_write(sc, R92C_FPGA0_RFPARAM(0), |
4555 | urtwn_bb_read(sc, R92C_FPGA0_RFPARAM(0)) | __BIT(13)); | | 4846 | urtwn_bb_read(sc, R92C_FPGA0_RFPARAM(0)) | __BIT(13)); |
4556 | } | | 4847 | } |
4557 | | | 4848 | |
4558 | /* Initialize GPIO setting. */ | | 4849 | /* Initialize GPIO setting. */ |
4559 | urtwn_write_1(sc, R92C_GPIO_MUXCFG, | | 4850 | urtwn_write_1(sc, R92C_GPIO_MUXCFG, |
4560 | urtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT); | | 4851 | urtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT); |
4561 | | | 4852 | |
4562 | /* Fix for lower temperature. */ | | 4853 | /* Fix for lower temperature. */ |
4563 | if (!ISSET(sc->chip, URTWN_CHIP_88E)) | | 4854 | if (!ISSET(sc->chip, URTWN_CHIP_88E) && |
| | | 4855 | !ISSET(sc->chip, URTWN_CHIP_92EU)) |
4564 | urtwn_write_1(sc, 0x15, 0xe9); | | 4856 | urtwn_write_1(sc, 0x15, 0xe9); |
4565 | | | 4857 | |
4566 | /* Set default channel. */ | | 4858 | /* Set default channel. */ |
4567 | urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE); | | 4859 | urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE); |
4568 | | | 4860 | |
4569 | /* Queue Rx xfers. */ | | 4861 | /* Queue Rx xfers. */ |
4570 | for (i = 0; i < URTWN_RX_LIST_COUNT; i++) { | | 4862 | for (size_t j = 0; j < sc->rx_npipe; j++) { |
4571 | data = &sc->rx_data[i]; | | 4863 | for (i = 0; i < URTWN_RX_LIST_COUNT; i++) { |
4572 | usbd_setup_xfer(data->xfer, data, data->buf, URTWN_RXBUFSZ, | | 4864 | data = &sc->rx_data[j][i]; |
4573 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urtwn_rxeof); | | 4865 | usbd_setup_xfer(data->xfer, data, data->buf, |
4574 | error = usbd_transfer(data->xfer); | | 4866 | URTWN_RXBUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, |
4575 | if (__predict_false(error != USBD_NORMAL_COMPLETION && | | 4867 | urtwn_rxeof); |
4576 | error != USBD_IN_PROGRESS)) | | 4868 | error = usbd_transfer(data->xfer); |
4577 | goto fail; | | 4869 | if (__predict_false(error != USBD_NORMAL_COMPLETION && |
| | | 4870 | error != USBD_IN_PROGRESS)) |
| | | 4871 | goto fail; |
| | | 4872 | } |
4578 | } | | 4873 | } |
4579 | | | 4874 | |
4580 | /* We're ready to go. */ | | 4875 | /* We're ready to go. */ |
4581 | ifp->if_flags &= ~IFF_OACTIVE; | | 4876 | ifp->if_flags &= ~IFF_OACTIVE; |
4582 | ifp->if_flags |= IFF_RUNNING; | | 4877 | ifp->if_flags |= IFF_RUNNING; |
| | | 4878 | sc->sc_running = true; |
4583 | | | 4879 | |
4584 | mutex_exit(&sc->sc_write_mtx); | | 4880 | mutex_exit(&sc->sc_write_mtx); |
4585 | | | 4881 | |
4586 | if (ic->ic_opmode == IEEE80211_M_MONITOR) | | 4882 | if (ic->ic_opmode == IEEE80211_M_MONITOR) |
4587 | ieee80211_new_state(ic, IEEE80211_S_RUN, -1); | | 4883 | ieee80211_new_state(ic, IEEE80211_S_RUN, -1); |
4588 | else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) | | 4884 | else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) |
4589 | ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); | | 4885 | ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); |
4590 | urtwn_wait_async(sc); | | 4886 | urtwn_wait_async(sc); |
4591 | | | 4887 | |
4592 | return 0; | | 4888 | return 0; |
4593 | | | 4889 | |
4594 | fail: | | 4890 | fail: |
4595 | mutex_exit(&sc->sc_write_mtx); | | 4891 | mutex_exit(&sc->sc_write_mtx); |
| @@ -4611,64 +4907,71 @@ urtwn_stop(struct ifnet *ifp, int disabl | | | @@ -4611,64 +4907,71 @@ urtwn_stop(struct ifnet *ifp, int disabl |
4611 | s = splusb(); | | 4907 | s = splusb(); |
4612 | ieee80211_new_state(ic, IEEE80211_S_INIT, -1); | | 4908 | ieee80211_new_state(ic, IEEE80211_S_INIT, -1); |
4613 | urtwn_wait_async(sc); | | 4909 | urtwn_wait_async(sc); |
4614 | splx(s); | | 4910 | splx(s); |
4615 | | | 4911 | |
4616 | sc->tx_timer = 0; | | 4912 | sc->tx_timer = 0; |
4617 | ifp->if_timer = 0; | | 4913 | ifp->if_timer = 0; |
4618 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | | 4914 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
4619 | | | 4915 | |
4620 | callout_stop(&sc->sc_scan_to); | | 4916 | callout_stop(&sc->sc_scan_to); |
4621 | callout_stop(&sc->sc_calib_to); | | 4917 | callout_stop(&sc->sc_calib_to); |
4622 | | | 4918 | |
4623 | /* Abort Tx. */ | | 4919 | /* Abort Tx. */ |
4624 | for (i = 0; i < R92C_MAX_EPOUT; i++) { | | 4920 | for (i = 0; i < sc->tx_npipe; i++) { |
4625 | if (sc->tx_pipe[i] != NULL) | | 4921 | if (sc->tx_pipe[i] != NULL) |
4626 | usbd_abort_pipe(sc->tx_pipe[i]); | | 4922 | usbd_abort_pipe(sc->tx_pipe[i]); |
4627 | } | | 4923 | } |
4628 | | | 4924 | |
4629 | /* Stop Rx pipe. */ | | 4925 | /* Stop Rx pipe. */ |
4630 | usbd_abort_pipe(sc->rx_pipe); | | 4926 | for (i = 0; i < sc->rx_npipe; i++) { |
| | | 4927 | if (sc->rx_pipe[i] != NULL) |
| | | 4928 | usbd_abort_pipe(sc->rx_pipe[i]); |
| | | 4929 | } |
4631 | | | 4930 | |
4632 | /* Free Tx/Rx buffers. */ | | 4931 | /* Free Tx/Rx buffers. */ |
4633 | urtwn_free_tx_list(sc); | | 4932 | urtwn_free_tx_list(sc); |
4634 | urtwn_free_rx_list(sc); | | 4933 | urtwn_free_rx_list(sc); |
4635 | | | 4934 | |
| | | 4935 | sc->sc_running = false; |
4636 | if (disable) | | 4936 | if (disable) |
4637 | urtwn_chip_stop(sc); | | 4937 | urtwn_chip_stop(sc); |
4638 | } | | 4938 | } |
4639 | | | 4939 | |
4640 | static int | | 4940 | static int |
4641 | urtwn_reset(struct ifnet *ifp) | | 4941 | urtwn_reset(struct ifnet *ifp) |
4642 | { | | 4942 | { |
4643 | struct urtwn_softc *sc = ifp->if_softc; | | 4943 | struct urtwn_softc *sc = ifp->if_softc; |
4644 | struct ieee80211com *ic = &sc->sc_ic; | | 4944 | struct ieee80211com *ic = &sc->sc_ic; |
4645 | | | 4945 | |
4646 | if (ic->ic_opmode != IEEE80211_M_MONITOR) | | 4946 | if (ic->ic_opmode != IEEE80211_M_MONITOR) |
4647 | return ENETRESET; | | 4947 | return ENETRESET; |
4648 | | | 4948 | |
4649 | urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE); | | 4949 | urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE); |
4650 | | | 4950 | |
4651 | return 0; | | 4951 | return 0; |
4652 | } | | 4952 | } |
4653 | | | 4953 | |
4654 | static void | | 4954 | static void |
4655 | urtwn_chip_stop(struct urtwn_softc *sc) | | 4955 | urtwn_chip_stop(struct urtwn_softc *sc) |
4656 | { | | 4956 | { |
4657 | uint32_t reg; | | 4957 | uint32_t reg; |
4658 | bool disabled = true; | | 4958 | bool disabled = true; |
4659 | | | 4959 | |
4660 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); | | 4960 | DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__)); |
4661 | | | 4961 | |
| | | 4962 | if (ISSET(sc->chip, URTWN_CHIP_92EU)) |
| | | 4963 | return; |
| | | 4964 | |
4662 | mutex_enter(&sc->sc_write_mtx); | | 4965 | mutex_enter(&sc->sc_write_mtx); |
4663 | | | 4966 | |
4664 | /* | | 4967 | /* |
4665 | * RF Off Sequence | | 4968 | * RF Off Sequence |
4666 | */ | | 4969 | */ |
4667 | /* Pause MAC TX queue */ | | 4970 | /* Pause MAC TX queue */ |
4668 | urtwn_write_1(sc, R92C_TXPAUSE, 0xFF); | | 4971 | urtwn_write_1(sc, R92C_TXPAUSE, 0xFF); |
4669 | | | 4972 | |
4670 | /* Disable RF */ | | 4973 | /* Disable RF */ |
4671 | urtwn_rf_write(sc, 0, 0, 0); | | 4974 | urtwn_rf_write(sc, 0, 0, 0); |
4672 | | | 4975 | |
4673 | urtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF); | | 4976 | urtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF); |
4674 | | | 4977 | |
| @@ -4678,27 +4981,28 @@ urtwn_chip_stop(struct urtwn_softc *sc) | | | @@ -4678,27 +4981,28 @@ urtwn_chip_stop(struct urtwn_softc *sc) |
4678 | R92C_SYS_FUNC_EN_USBA | | | 4981 | R92C_SYS_FUNC_EN_USBA | |
4679 | R92C_SYS_FUNC_EN_BB_GLB_RST); | | 4982 | R92C_SYS_FUNC_EN_BB_GLB_RST); |
4680 | urtwn_write_1(sc, R92C_SYS_FUNC_EN, | | 4983 | urtwn_write_1(sc, R92C_SYS_FUNC_EN, |
4681 | R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA); | | 4984 | R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA); |
4682 | | | 4985 | |
4683 | /* | | 4986 | /* |
4684 | * Reset digital sequence | | 4987 | * Reset digital sequence |
4685 | */ | | 4988 | */ |
4686 | if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) { | | 4989 | if (urtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) { |
4687 | /* Reset MCU ready status */ | | 4990 | /* Reset MCU ready status */ |
4688 | urtwn_write_1(sc, R92C_MCUFWDL, 0); | | 4991 | urtwn_write_1(sc, R92C_MCUFWDL, 0); |
4689 | /* If firmware in ram code, do reset */ | | 4992 | /* If firmware in ram code, do reset */ |
4690 | if (ISSET(sc->sc_flags, URTWN_FLAG_FWREADY)) { | | 4993 | if (ISSET(sc->sc_flags, URTWN_FLAG_FWREADY)) { |
4691 | if (ISSET(sc->chip, URTWN_CHIP_88E)) | | 4994 | if (ISSET(sc->chip, URTWN_CHIP_88E) || |
| | | 4995 | ISSET(sc->chip, URTWN_CHIP_92EU)) |
4692 | urtwn_r88e_fw_reset(sc); | | 4996 | urtwn_r88e_fw_reset(sc); |
4693 | else | | 4997 | else |
4694 | urtwn_fw_reset(sc); | | 4998 | urtwn_fw_reset(sc); |
4695 | CLR(sc->sc_flags, URTWN_FLAG_FWREADY); | | 4999 | CLR(sc->sc_flags, URTWN_FLAG_FWREADY); |
4696 | } | | 5000 | } |
4697 | } | | 5001 | } |
4698 | | | 5002 | |
4699 | /* Reset MAC and Enable 8051 */ | | 5003 | /* Reset MAC and Enable 8051 */ |
4700 | urtwn_write_1(sc, R92C_SYS_FUNC_EN + 1, 0x54); | | 5004 | urtwn_write_1(sc, R92C_SYS_FUNC_EN + 1, 0x54); |
4701 | | | 5005 | |
4702 | /* Reset MCU ready status */ | | 5006 | /* Reset MCU ready status */ |
4703 | urtwn_write_1(sc, R92C_MCUFWDL, 0); | | 5007 | urtwn_write_1(sc, R92C_MCUFWDL, 0); |
4704 | | | 5008 | |
| @@ -4759,26 +5063,35 @@ urtwn_chip_stop(struct urtwn_softc *sc) | | | @@ -4759,26 +5063,35 @@ urtwn_chip_stop(struct urtwn_softc *sc) |
4759 | urtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); | | 5063 | urtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); |
4760 | | | 5064 | |
4761 | /* Set USB suspend */ | | 5065 | /* Set USB suspend */ |
4762 | urtwn_write_2(sc, R92C_APS_FSMCO, | | 5066 | urtwn_write_2(sc, R92C_APS_FSMCO, |
4763 | R92C_APS_FSMCO_APDM_HOST | | | 5067 | R92C_APS_FSMCO_APDM_HOST | |
4764 | R92C_APS_FSMCO_AFSM_HSUS | | | 5068 | R92C_APS_FSMCO_AFSM_HSUS | |
4765 | R92C_APS_FSMCO_PFM_ALDN); | | 5069 | R92C_APS_FSMCO_PFM_ALDN); |
4766 | | | 5070 | |
4767 | urtwn_write_1(sc, R92C_RSV_CTRL, 0x0E); | | 5071 | urtwn_write_1(sc, R92C_RSV_CTRL, 0x0E); |
4768 | | | 5072 | |
4769 | mutex_exit(&sc->sc_write_mtx); | | 5073 | mutex_exit(&sc->sc_write_mtx); |
4770 | } | | 5074 | } |
4771 | | | 5075 | |
| | | 5076 | static void |
| | | 5077 | urtwn_delay_ms(struct urtwn_softc *sc, int ms) |
| | | 5078 | { |
| | | 5079 | if (sc->sc_running == false) |
| | | 5080 | DELAY(ms * 1000); |
| | | 5081 | else |
| | | 5082 | usbd_delay_ms(sc->sc_udev, ms); |
| | | 5083 | } |
| | | 5084 | |
4772 | MODULE(MODULE_CLASS_DRIVER, if_urtwn, "bpf"); | | 5085 | MODULE(MODULE_CLASS_DRIVER, if_urtwn, "bpf"); |
4773 | | | 5086 | |
4774 | #ifdef _MODULE | | 5087 | #ifdef _MODULE |
4775 | #include "ioconf.c" | | 5088 | #include "ioconf.c" |
4776 | #endif | | 5089 | #endif |
4777 | | | 5090 | |
4778 | static int | | 5091 | static int |
4779 | if_urtwn_modcmd(modcmd_t cmd, void *aux) | | 5092 | if_urtwn_modcmd(modcmd_t cmd, void *aux) |
4780 | { | | 5093 | { |
4781 | int error = 0; | | 5094 | int error = 0; |
4782 | | | 5095 | |
4783 | switch (cmd) { | | 5096 | switch (cmd) { |
4784 | case MODULE_CMD_INIT: | | 5097 | case MODULE_CMD_INIT: |