if_ural.c revision 184610
1184610Salfred/*	$FreeBSD: head/sys/dev/usb2/wlan/if_ural2.c 184610 2008-11-04 02:31:03Z alfred $	*/
2184610Salfred
3184610Salfred/*-
4184610Salfred * Copyright (c) 2005, 2006
5184610Salfred *	Damien Bergamini <damien.bergamini@free.fr>
6184610Salfred *
7184610Salfred * Copyright (c) 2006, 2008
8184610Salfred *	Hans Petter Selasky <hselasky@freebsd.org>
9184610Salfred *
10184610Salfred * Permission to use, copy, modify, and distribute this software for any
11184610Salfred * purpose with or without fee is hereby granted, provided that the above
12184610Salfred * copyright notice and this permission notice appear in all copies.
13184610Salfred *
14184610Salfred * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15184610Salfred * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16184610Salfred * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17184610Salfred * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18184610Salfred * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19184610Salfred * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20184610Salfred * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21184610Salfred *
22184610Salfred */
23184610Salfred
24184610Salfred/*
25184610Salfred *
26184610Salfred * NOTE: all function names beginning like "ural_cfg_" can only
27184610Salfred * be called from within the config thread function !
28184610Salfred */
29184610Salfred
30184610Salfred#include <sys/cdefs.h>
31184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb2/wlan/if_ural2.c 184610 2008-11-04 02:31:03Z alfred $");
32184610Salfred
33184610Salfred/*-
34184610Salfred * Ralink Technology RT2500USB chipset driver
35184610Salfred * http://www.ralinktech.com/
36184610Salfred */
37184610Salfred
38184610Salfred#include <dev/usb2/include/usb2_devid.h>
39184610Salfred#include <dev/usb2/include/usb2_standard.h>
40184610Salfred#include <dev/usb2/include/usb2_mfunc.h>
41184610Salfred#include <dev/usb2/include/usb2_error.h>
42184610Salfred
43184610Salfred#define	usb2_config_td_cc ural_config_copy
44184610Salfred#define	usb2_config_td_softc ural_softc
45184610Salfred
46184610Salfred#define	USB_DEBUG_VAR ural_debug
47184610Salfred
48184610Salfred#include <dev/usb2/core/usb2_core.h>
49184610Salfred#include <dev/usb2/core/usb2_lookup.h>
50184610Salfred#include <dev/usb2/core/usb2_process.h>
51184610Salfred#include <dev/usb2/core/usb2_config_td.h>
52184610Salfred#include <dev/usb2/core/usb2_debug.h>
53184610Salfred#include <dev/usb2/core/usb2_request.h>
54184610Salfred#include <dev/usb2/core/usb2_busdma.h>
55184610Salfred#include <dev/usb2/core/usb2_util.h>
56184610Salfred
57184610Salfred#include <dev/usb2/wlan/usb2_wlan.h>
58184610Salfred#include <dev/usb2/wlan/if_ural2_reg.h>
59184610Salfred#include <dev/usb2/wlan/if_ural2_var.h>
60184610Salfred
61184610Salfred#if USB_DEBUG
62184610Salfredstatic int ural_debug = 0;
63184610Salfred
64184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural");
65184610SalfredSYSCTL_INT(_hw_usb2_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0,
66184610Salfred    "Debug level");
67184610Salfred#endif
68184610Salfred
69184610Salfred#define	URAL_RSSI(rssi)	\
70184610Salfred  ((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ? \
71184610Salfred   ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0)
72184610Salfred
73184610Salfred/* prototypes */
74184610Salfred
75184610Salfredstatic device_probe_t ural_probe;
76184610Salfredstatic device_attach_t ural_attach;
77184610Salfredstatic device_detach_t ural_detach;
78184610Salfred
79184610Salfredstatic usb2_callback_t ural_bulk_read_callback;
80184610Salfredstatic usb2_callback_t ural_bulk_read_clear_stall_callback;
81184610Salfredstatic usb2_callback_t ural_bulk_write_callback;
82184610Salfredstatic usb2_callback_t ural_bulk_write_clear_stall_callback;
83184610Salfred
84184610Salfredstatic usb2_config_td_command_t ural_cfg_first_time_setup;
85184610Salfredstatic usb2_config_td_command_t ural_config_copy;
86184610Salfredstatic usb2_config_td_command_t ural_cfg_scan_start;
87184610Salfredstatic usb2_config_td_command_t ural_cfg_scan_end;
88184610Salfredstatic usb2_config_td_command_t ural_cfg_set_chan;
89184610Salfredstatic usb2_config_td_command_t ural_cfg_enable_tsf_sync;
90184610Salfredstatic usb2_config_td_command_t ural_cfg_update_slot;
91184610Salfredstatic usb2_config_td_command_t ural_cfg_set_txpreamble;
92184610Salfredstatic usb2_config_td_command_t ural_cfg_update_promisc;
93184610Salfredstatic usb2_config_td_command_t ural_cfg_pre_init;
94184610Salfredstatic usb2_config_td_command_t ural_cfg_init;
95184610Salfredstatic usb2_config_td_command_t ural_cfg_pre_stop;
96184610Salfredstatic usb2_config_td_command_t ural_cfg_stop;
97184610Salfredstatic usb2_config_td_command_t ural_cfg_amrr_timeout;
98184610Salfredstatic usb2_config_td_command_t ural_cfg_newstate;
99184610Salfred
100184610Salfredstatic void ural_cfg_do_request(struct ural_softc *sc, struct usb2_device_request *req, void *data);
101184610Salfredstatic void ural_cfg_set_testmode(struct ural_softc *sc);
102184610Salfredstatic void ural_cfg_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, uint16_t len);
103184610Salfredstatic uint16_t ural_cfg_read(struct ural_softc *sc, uint16_t reg);
104184610Salfredstatic void ural_cfg_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, uint16_t len);
105184610Salfredstatic void ural_cfg_write(struct ural_softc *sc, uint16_t reg, uint16_t val);
106184610Salfredstatic void ural_cfg_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, uint16_t len);
107184610Salfredstatic void ural_cfg_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val);
108184610Salfredstatic uint8_t ural_cfg_bbp_read(struct ural_softc *sc, uint8_t reg);
109184610Salfredstatic void ural_cfg_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val);
110184610Salfredstatic void ural_end_of_commands(struct ural_softc *sc);
111184610Salfredstatic const char *ural_get_rf(int rev);
112184610Salfredstatic void ural_watchdog(void *arg);
113184610Salfredstatic void ural_init_cb(void *arg);
114184610Salfredstatic int ural_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data);
115184610Salfredstatic void ural_start_cb(struct ifnet *ifp);
116184610Salfredstatic int ural_newstate_cb(struct ieee80211vap *ic, enum ieee80211_state nstate, int arg);
117184610Salfredstatic void ural_std_command(struct ieee80211com *ic, usb2_config_td_command_t *func);
118184610Salfredstatic void ural_scan_start_cb(struct ieee80211com *);
119184610Salfredstatic void ural_scan_end_cb(struct ieee80211com *);
120184610Salfredstatic void ural_set_channel_cb(struct ieee80211com *);
121184610Salfredstatic void ural_cfg_disable_rf_tune(struct ural_softc *sc);
122184610Salfredstatic void ural_cfg_set_bssid(struct ural_softc *sc, uint8_t *bssid);
123184610Salfredstatic void ural_cfg_set_macaddr(struct ural_softc *sc, uint8_t *addr);
124184610Salfredstatic void ural_cfg_set_txantenna(struct ural_softc *sc, uint8_t antenna);
125184610Salfredstatic void ural_cfg_set_rxantenna(struct ural_softc *sc, uint8_t antenna);
126184610Salfredstatic void ural_cfg_read_eeprom(struct ural_softc *sc);
127184610Salfredstatic uint8_t ural_cfg_bbp_init(struct ural_softc *sc);
128184610Salfredstatic void ural_cfg_amrr_start(struct ural_softc *sc);
129184610Salfredstatic struct ieee80211vap *ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]);
130184610Salfredstatic void ural_vap_delete(struct ieee80211vap *);
131184610Salfredstatic struct ieee80211_node *ural_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]);
132184610Salfredstatic void ural_newassoc(struct ieee80211_node *, int);
133184610Salfredstatic void ural_cfg_disable_tsf_sync(struct ural_softc *sc);
134184610Salfredstatic void ural_cfg_set_run(struct ural_softc *sc, struct usb2_config_td_cc *cc);
135184610Salfredstatic void ural_fill_write_queue(struct ural_softc *sc);
136184610Salfredstatic void ural_tx_clean_queue(struct ural_softc *sc);
137184610Salfredstatic void ural_tx_freem(struct mbuf *m);
138184610Salfredstatic void ural_tx_mgt(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
139184610Salfredstatic struct ieee80211vap *ural_get_vap(struct ural_softc *sc);
140184610Salfredstatic void ural_tx_bcn(struct ural_softc *sc);
141184610Salfredstatic void ural_tx_data(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni);
142184610Salfredstatic void ural_tx_prot(struct ural_softc *sc, const struct mbuf *m, struct ieee80211_node *ni, uint8_t prot, uint16_t rate);
143184610Salfredstatic void ural_tx_raw(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params);
144184610Salfredstatic int ural_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params);
145184610Salfredstatic void ural_setup_desc_and_tx(struct ural_softc *sc, struct mbuf *m, uint32_t flags, uint16_t rate);
146184610Salfredstatic void ural_update_mcast_cb(struct ifnet *ifp);
147184610Salfredstatic void ural_update_promisc_cb(struct ifnet *ifp);
148184610Salfred
149184610Salfred/* various supported device vendors/products */
150184610Salfredstatic const struct usb2_device_id ural_devs[] = {
151184610Salfred	{USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL167G, 0)},
152184610Salfred	{USB_VPI(USB_VENDOR_ASUS, USB_PRODUCT_RALINK_RT2570, 0)},
153184610Salfred	{USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050, 0)},
154184610Salfred	{USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7051, 0)},
155184610Salfred	{USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_HU200TS, 0)},
156184610Salfred	{USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54G, 0)},
157184610Salfred	{USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GP, 0)},
158184610Salfred	{USB_VPI(USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU, 0)},
159184610Salfred	{USB_VPI(USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG122, 0)},
160184610Salfred	{USB_VPI(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GN54G, 0)},
161184610Salfred	{USB_VPI(USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWBKG, 0)},
162184610Salfred	{USB_VPI(USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254, 0)},
163184610Salfred	{USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54, 0)},
164184610Salfred	{USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54AI, 0)},
165184610Salfred	{USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54YB, 0)},
166184610Salfred	{USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_NINWIFI, 0)},
167184610Salfred	{USB_VPI(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570, 0)},
168184610Salfred	{USB_VPI(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_2, 0)},
169184610Salfred	{USB_VPI(USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_3, 0)},
170184610Salfred	{USB_VPI(USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_NV902, 0)},
171184610Salfred	{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570, 0)},
172184610Salfred	{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_2, 0)},
173184610Salfred	{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_3, 0)},
174184610Salfred	{USB_VPI(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573, 0)},
175184610Salfred	{USB_VPI(USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WL54G, 0)},
176184610Salfred	{USB_VPI(USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG, 0)},
177184610Salfred	{USB_VPI(USB_VENDOR_SPHAIRON, USB_PRODUCT_SPHAIRON_UB801R, 0)},
178184610Salfred	{USB_VPI(USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2570, 0)},
179184610Salfred	{USB_VPI(USB_VENDOR_VTECH, USB_PRODUCT_VTECH_RT2570, 0)},
180184610Salfred	{USB_VPI(USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570, 0)},
181184610Salfred};
182184610Salfred
183184610Salfred/*
184184610Salfred * Default values for MAC registers; values taken from
185184610Salfred * the reference driver:
186184610Salfred */
187184610Salfredstruct ural_def_mac {
188184610Salfred	uint16_t reg;
189184610Salfred	uint16_t val;
190184610Salfred};
191184610Salfred
192184610Salfredstatic const struct ural_def_mac ural_def_mac[] = {
193184610Salfred	{RAL_TXRX_CSR5, 0x8c8d},
194184610Salfred	{RAL_TXRX_CSR6, 0x8b8a},
195184610Salfred	{RAL_TXRX_CSR7, 0x8687},
196184610Salfred	{RAL_TXRX_CSR8, 0x0085},
197184610Salfred	{RAL_MAC_CSR13, 0x1111},
198184610Salfred	{RAL_MAC_CSR14, 0x1e11},
199184610Salfred	{RAL_TXRX_CSR21, 0xe78f},
200184610Salfred	{RAL_MAC_CSR9, 0xff1d},
201184610Salfred	{RAL_MAC_CSR11, 0x0002},
202184610Salfred	{RAL_MAC_CSR22, 0x0053},
203184610Salfred	{RAL_MAC_CSR15, 0x0000},
204184610Salfred	{RAL_MAC_CSR8, RAL_FRAME_SIZE},
205184610Salfred	{RAL_TXRX_CSR19, 0x0000},
206184610Salfred	{RAL_TXRX_CSR18, 0x005a},
207184610Salfred	{RAL_PHY_CSR2, 0x0000},
208184610Salfred	{RAL_TXRX_CSR0, 0x1ec0},
209184610Salfred	{RAL_PHY_CSR4, 0x000f}
210184610Salfred};
211184610Salfred
212184610Salfred/*
213184610Salfred * Default values for BBP registers; values taken from the reference driver.
214184610Salfred */
215184610Salfredstruct ural_def_bbp {
216184610Salfred	uint8_t	reg;
217184610Salfred	uint8_t	val;
218184610Salfred};
219184610Salfred
220184610Salfredstatic const struct ural_def_bbp ural_def_bbp[] = {
221184610Salfred	{3, 0x02},
222184610Salfred	{4, 0x19},
223184610Salfred	{14, 0x1c},
224184610Salfred	{15, 0x30},
225184610Salfred	{16, 0xac},
226184610Salfred	{17, 0x48},
227184610Salfred	{18, 0x18},
228184610Salfred	{19, 0xff},
229184610Salfred	{20, 0x1e},
230184610Salfred	{21, 0x08},
231184610Salfred	{22, 0x08},
232184610Salfred	{23, 0x08},
233184610Salfred	{24, 0x80},
234184610Salfred	{25, 0x50},
235184610Salfred	{26, 0x08},
236184610Salfred	{27, 0x23},
237184610Salfred	{30, 0x10},
238184610Salfred	{31, 0x2b},
239184610Salfred	{32, 0xb9},
240184610Salfred	{34, 0x12},
241184610Salfred	{35, 0x50},
242184610Salfred	{39, 0xc4},
243184610Salfred	{40, 0x02},
244184610Salfred	{41, 0x60},
245184610Salfred	{53, 0x10},
246184610Salfred	{54, 0x18},
247184610Salfred	{56, 0x08},
248184610Salfred	{57, 0x10},
249184610Salfred	{58, 0x08},
250184610Salfred	{61, 0x60},
251184610Salfred	{62, 0x10},
252184610Salfred	{75, 0xff}
253184610Salfred};
254184610Salfred
255184610Salfred/*
256184610Salfred * Default values for RF register R2 indexed by channel numbers.
257184610Salfred */
258184610Salfredstatic const uint32_t ural_rf2522_r2[] = {
259184610Salfred	0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814,
260184610Salfred	0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e
261184610Salfred};
262184610Salfred
263184610Salfredstatic const uint32_t ural_rf2523_r2[] = {
264184610Salfred	0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
265184610Salfred	0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
266184610Salfred};
267184610Salfred
268184610Salfredstatic const uint32_t ural_rf2524_r2[] = {
269184610Salfred	0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
270184610Salfred	0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
271184610Salfred};
272184610Salfred
273184610Salfredstatic const uint32_t ural_rf2525_r2[] = {
274184610Salfred	0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d,
275184610Salfred	0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346
276184610Salfred};
277184610Salfred
278184610Salfredstatic const uint32_t ural_rf2525_hi_r2[] = {
279184610Salfred	0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345,
280184610Salfred	0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e
281184610Salfred};
282184610Salfred
283184610Salfredstatic const uint32_t ural_rf2525e_r2[] = {
284184610Salfred	0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463,
285184610Salfred	0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b
286184610Salfred};
287184610Salfred
288184610Salfredstatic const uint32_t ural_rf2526_hi_r2[] = {
289184610Salfred	0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d,
290184610Salfred	0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241
291184610Salfred};
292184610Salfred
293184610Salfredstatic const uint32_t ural_rf2526_r2[] = {
294184610Salfred	0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229,
295184610Salfred	0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d
296184610Salfred};
297184610Salfred
298184610Salfred/*
299184610Salfred * For dual-band RF, RF registers R1 and R4 also depend on channel number;
300184610Salfred * values taken from the reference driver.
301184610Salfred */
302184610Salfredstruct ural_rf5222 {
303184610Salfred	uint8_t	chan;
304184610Salfred	uint32_t r1;
305184610Salfred	uint32_t r2;
306184610Salfred	uint32_t r4;
307184610Salfred};
308184610Salfred
309184610Salfredstatic const struct ural_rf5222 ural_rf5222[] = {
310184610Salfred	{1, 0x08808, 0x0044d, 0x00282},
311184610Salfred	{2, 0x08808, 0x0044e, 0x00282},
312184610Salfred	{3, 0x08808, 0x0044f, 0x00282},
313184610Salfred	{4, 0x08808, 0x00460, 0x00282},
314184610Salfred	{5, 0x08808, 0x00461, 0x00282},
315184610Salfred	{6, 0x08808, 0x00462, 0x00282},
316184610Salfred	{7, 0x08808, 0x00463, 0x00282},
317184610Salfred	{8, 0x08808, 0x00464, 0x00282},
318184610Salfred	{9, 0x08808, 0x00465, 0x00282},
319184610Salfred	{10, 0x08808, 0x00466, 0x00282},
320184610Salfred	{11, 0x08808, 0x00467, 0x00282},
321184610Salfred	{12, 0x08808, 0x00468, 0x00282},
322184610Salfred	{13, 0x08808, 0x00469, 0x00282},
323184610Salfred	{14, 0x08808, 0x0046b, 0x00286},
324184610Salfred
325184610Salfred	{36, 0x08804, 0x06225, 0x00287},
326184610Salfred	{40, 0x08804, 0x06226, 0x00287},
327184610Salfred	{44, 0x08804, 0x06227, 0x00287},
328184610Salfred	{48, 0x08804, 0x06228, 0x00287},
329184610Salfred	{52, 0x08804, 0x06229, 0x00287},
330184610Salfred	{56, 0x08804, 0x0622a, 0x00287},
331184610Salfred	{60, 0x08804, 0x0622b, 0x00287},
332184610Salfred	{64, 0x08804, 0x0622c, 0x00287},
333184610Salfred
334184610Salfred	{100, 0x08804, 0x02200, 0x00283},
335184610Salfred	{104, 0x08804, 0x02201, 0x00283},
336184610Salfred	{108, 0x08804, 0x02202, 0x00283},
337184610Salfred	{112, 0x08804, 0x02203, 0x00283},
338184610Salfred	{116, 0x08804, 0x02204, 0x00283},
339184610Salfred	{120, 0x08804, 0x02205, 0x00283},
340184610Salfred	{124, 0x08804, 0x02206, 0x00283},
341184610Salfred	{128, 0x08804, 0x02207, 0x00283},
342184610Salfred	{132, 0x08804, 0x02208, 0x00283},
343184610Salfred	{136, 0x08804, 0x02209, 0x00283},
344184610Salfred	{140, 0x08804, 0x0220a, 0x00283},
345184610Salfred
346184610Salfred	{149, 0x08808, 0x02429, 0x00281},
347184610Salfred	{153, 0x08808, 0x0242b, 0x00281},
348184610Salfred	{157, 0x08808, 0x0242d, 0x00281},
349184610Salfred	{161, 0x08808, 0x0242f, 0x00281}
350184610Salfred};
351184610Salfred
352184610Salfredstatic const struct usb2_config ural_config[URAL_N_TRANSFER] = {
353184610Salfred	[0] = {
354184610Salfred		.type = UE_BULK,
355184610Salfred		.endpoint = UE_ADDR_ANY,
356184610Salfred		.direction = UE_DIR_OUT,
357184610Salfred		.mh.bufsize = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE + 4),
358184610Salfred		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
359184610Salfred		.mh.callback = &ural_bulk_write_callback,
360184610Salfred		.mh.timeout = 5000,	/* ms */
361184610Salfred	},
362184610Salfred
363184610Salfred	[1] = {
364184610Salfred		.type = UE_BULK,
365184610Salfred		.endpoint = UE_ADDR_ANY,
366184610Salfred		.direction = UE_DIR_IN,
367184610Salfred		.mh.bufsize = (RAL_FRAME_SIZE + RAL_RX_DESC_SIZE),
368184610Salfred		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
369184610Salfred		.mh.callback = &ural_bulk_read_callback,
370184610Salfred	},
371184610Salfred
372184610Salfred	[2] = {
373184610Salfred		.type = UE_CONTROL,
374184610Salfred		.endpoint = 0x00,	/* Control pipe */
375184610Salfred		.direction = UE_DIR_ANY,
376184610Salfred		.mh.bufsize = sizeof(struct usb2_device_request),
377184610Salfred		.mh.callback = &ural_bulk_write_clear_stall_callback,
378184610Salfred		.mh.timeout = 1000,	/* 1 second */
379184610Salfred		.mh.interval = 50,	/* 50ms */
380184610Salfred	},
381184610Salfred
382184610Salfred	[3] = {
383184610Salfred		.type = UE_CONTROL,
384184610Salfred		.endpoint = 0x00,	/* Control pipe */
385184610Salfred		.direction = UE_DIR_ANY,
386184610Salfred		.mh.bufsize = sizeof(struct usb2_device_request),
387184610Salfred		.mh.callback = &ural_bulk_read_clear_stall_callback,
388184610Salfred		.mh.timeout = 1000,	/* 1 second */
389184610Salfred		.mh.interval = 50,	/* 50ms */
390184610Salfred	},
391184610Salfred};
392184610Salfred
393184610Salfredstatic devclass_t ural_devclass;
394184610Salfred
395184610Salfredstatic device_method_t ural_methods[] = {
396184610Salfred	DEVMETHOD(device_probe, ural_probe),
397184610Salfred	DEVMETHOD(device_attach, ural_attach),
398184610Salfred	DEVMETHOD(device_detach, ural_detach),
399184610Salfred	{0, 0}
400184610Salfred};
401184610Salfred
402184610Salfredstatic driver_t ural_driver = {
403184610Salfred	.name = "ural",
404184610Salfred	.methods = ural_methods,
405184610Salfred	.size = sizeof(struct ural_softc),
406184610Salfred};
407184610Salfred
408184610SalfredDRIVER_MODULE(ural, ushub, ural_driver, ural_devclass, NULL, 0);
409184610SalfredMODULE_DEPEND(ural, usb2_wlan, 1, 1, 1);
410184610SalfredMODULE_DEPEND(ural, usb2_core, 1, 1, 1);
411184610SalfredMODULE_DEPEND(ural, wlan, 1, 1, 1);
412184610SalfredMODULE_DEPEND(ural, wlan_amrr, 1, 1, 1);
413184610Salfred
414184610Salfredstatic int
415184610Salfredural_probe(device_t dev)
416184610Salfred{
417184610Salfred	struct usb2_attach_arg *uaa = device_get_ivars(dev);
418184610Salfred
419184610Salfred	if (uaa->usb2_mode != USB_MODE_HOST) {
420184610Salfred		return (ENXIO);
421184610Salfred	}
422184610Salfred	if (uaa->info.bConfigIndex != 0) {
423184610Salfred		return (ENXIO);
424184610Salfred	}
425184610Salfred	if (uaa->info.bIfaceIndex != RAL_IFACE_INDEX) {
426184610Salfred		return (ENXIO);
427184610Salfred	}
428184610Salfred	return (usb2_lookup_id_by_uaa(ural_devs, sizeof(ural_devs), uaa));
429184610Salfred}
430184610Salfred
431184610Salfredstatic int
432184610Salfredural_attach(device_t dev)
433184610Salfred{
434184610Salfred	struct usb2_attach_arg *uaa = device_get_ivars(dev);
435184610Salfred	struct ural_softc *sc = device_get_softc(dev);
436184610Salfred	int error;
437184610Salfred	uint8_t iface_index;
438184610Salfred
439184610Salfred	if (sc == NULL) {
440184610Salfred		return (ENOMEM);
441184610Salfred	}
442184610Salfred	device_set_usb2_desc(dev);
443184610Salfred
444184610Salfred	mtx_init(&sc->sc_mtx, "ural lock", MTX_NETWORK_LOCK,
445184610Salfred	    MTX_DEF | MTX_RECURSE);
446184610Salfred
447184610Salfred	snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
448184610Salfred	    device_get_nameunit(dev));
449184610Salfred
450184610Salfred	sc->sc_udev = uaa->device;
451184610Salfred	sc->sc_unit = device_get_unit(dev);
452184610Salfred
453184610Salfred	usb2_callout_init_mtx(&sc->sc_watchdog,
454184610Salfred	    &sc->sc_mtx, CALLOUT_RETURNUNLOCKED);
455184610Salfred
456184610Salfred	iface_index = RAL_IFACE_INDEX;
457184610Salfred	error = usb2_transfer_setup(uaa->device,
458184610Salfred	    &iface_index, sc->sc_xfer, ural_config,
459184610Salfred	    URAL_N_TRANSFER, sc, &sc->sc_mtx);
460184610Salfred
461184610Salfred	if (error) {
462184610Salfred		device_printf(dev, "could not allocate USB transfers, "
463184610Salfred		    "err=%s\n", usb2_errstr(error));
464184610Salfred		goto detach;
465184610Salfred	}
466184610Salfred	error = usb2_config_td_setup(&sc->sc_config_td, sc, &sc->sc_mtx,
467184610Salfred	    &ural_end_of_commands,
468184610Salfred	    sizeof(struct usb2_config_td_cc), 24);
469184610Salfred	if (error) {
470184610Salfred		device_printf(dev, "could not setup config "
471184610Salfred		    "thread!\n");
472184610Salfred		goto detach;
473184610Salfred	}
474184610Salfred	mtx_lock(&sc->sc_mtx);
475184610Salfred
476184610Salfred	/* start setup */
477184610Salfred
478184610Salfred	usb2_config_td_queue_command
479184610Salfred	    (&sc->sc_config_td, NULL, &ural_cfg_first_time_setup, 0, 0);
480184610Salfred
481184610Salfred	/* start watchdog (will exit mutex) */
482184610Salfred
483184610Salfred	ural_watchdog(sc);
484184610Salfred
485184610Salfred	return (0);			/* success */
486184610Salfred
487184610Salfreddetach:
488184610Salfred	ural_detach(dev);
489184610Salfred	return (ENXIO);			/* failure */
490184610Salfred}
491184610Salfred
492184610Salfredstatic int
493184610Salfredural_detach(device_t dev)
494184610Salfred{
495184610Salfred	struct ural_softc *sc = device_get_softc(dev);
496184610Salfred	struct ieee80211com *ic;
497184610Salfred	struct ifnet *ifp;
498184610Salfred
499184610Salfred	usb2_config_td_drain(&sc->sc_config_td);
500184610Salfred
501184610Salfred	mtx_lock(&sc->sc_mtx);
502184610Salfred
503184610Salfred	usb2_callout_stop(&sc->sc_watchdog);
504184610Salfred
505184610Salfred	ural_cfg_pre_stop(sc, NULL, 0);
506184610Salfred
507184610Salfred	ifp = sc->sc_ifp;
508184610Salfred	ic = ifp->if_l2com;
509184610Salfred
510184610Salfred	mtx_unlock(&sc->sc_mtx);
511184610Salfred
512184610Salfred	/* stop all USB transfers first */
513184610Salfred	usb2_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
514184610Salfred
515184610Salfred	/* get rid of any late children */
516184610Salfred	bus_generic_detach(dev);
517184610Salfred
518184610Salfred	if (ifp) {
519184610Salfred		bpfdetach(ifp);
520184610Salfred		ieee80211_ifdetach(ic);
521184610Salfred		if_free(ifp);
522184610Salfred	}
523184610Salfred	usb2_config_td_unsetup(&sc->sc_config_td);
524184610Salfred
525184610Salfred	usb2_callout_drain(&sc->sc_watchdog);
526184610Salfred
527184610Salfred	mtx_destroy(&sc->sc_mtx);
528184610Salfred
529184610Salfred	return (0);
530184610Salfred}
531184610Salfred
532184610Salfred/*========================================================================*
533184610Salfred * REGISTER READ / WRITE WRAPPER ROUTINES
534184610Salfred *========================================================================*/
535184610Salfred
536184610Salfredstatic void
537184610Salfredural_cfg_do_request(struct ural_softc *sc, struct usb2_device_request *req,
538184610Salfred    void *data)
539184610Salfred{
540184610Salfred	uint16_t length;
541184610Salfred	usb2_error_t err;
542184610Salfred
543184610Salfredrepeat:
544184610Salfred
545184610Salfred	if (usb2_config_td_is_gone(&sc->sc_config_td)) {
546184610Salfred		goto error;
547184610Salfred	}
548184610Salfred	err = usb2_do_request_flags
549184610Salfred	    (sc->sc_udev, &sc->sc_mtx, req, data, 0, NULL, 1000);
550184610Salfred
551184610Salfred	if (err) {
552184610Salfred
553184610Salfred		DPRINTF("device request failed, err=%s "
554184610Salfred		    "(ignored)\n", usb2_errstr(err));
555184610Salfred
556184610Salfred		/* wait a little before next try */
557184610Salfred		if (usb2_config_td_sleep(&sc->sc_config_td, hz / 4)) {
558184610Salfred			goto error;
559184610Salfred		}
560184610Salfred		/* try until we are detached */
561184610Salfred		goto repeat;
562184610Salfred
563184610Salfrederror:
564184610Salfred		/* the device has been detached */
565184610Salfred		length = UGETW(req->wLength);
566184610Salfred
567184610Salfred		if ((req->bmRequestType & UT_READ) && length) {
568184610Salfred			bzero(data, length);
569184610Salfred		}
570184610Salfred	}
571184610Salfred	return;
572184610Salfred}
573184610Salfred
574184610Salfredstatic void
575184610Salfredural_cfg_set_testmode(struct ural_softc *sc)
576184610Salfred{
577184610Salfred	struct usb2_device_request req;
578184610Salfred
579184610Salfred	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
580184610Salfred	req.bRequest = RAL_VENDOR_REQUEST;
581184610Salfred	USETW(req.wValue, 4);
582184610Salfred	USETW(req.wIndex, 1);
583184610Salfred	USETW(req.wLength, 0);
584184610Salfred
585184610Salfred	ural_cfg_do_request(sc, &req, NULL);
586184610Salfred	return;
587184610Salfred}
588184610Salfred
589184610Salfredstatic void
590184610Salfredural_cfg_eeprom_read(struct ural_softc *sc, uint16_t addr,
591184610Salfred    void *buf, uint16_t len)
592184610Salfred{
593184610Salfred	struct usb2_device_request req;
594184610Salfred
595184610Salfred	req.bmRequestType = UT_READ_VENDOR_DEVICE;
596184610Salfred	req.bRequest = RAL_READ_EEPROM;
597184610Salfred	USETW(req.wValue, 0);
598184610Salfred	USETW(req.wIndex, addr);
599184610Salfred	USETW(req.wLength, len);
600184610Salfred
601184610Salfred	ural_cfg_do_request(sc, &req, buf);
602184610Salfred	return;
603184610Salfred}
604184610Salfred
605184610Salfredstatic uint16_t
606184610Salfredural_cfg_read(struct ural_softc *sc, uint16_t reg)
607184610Salfred{
608184610Salfred	struct usb2_device_request req;
609184610Salfred	uint16_t val;
610184610Salfred
611184610Salfred	req.bmRequestType = UT_READ_VENDOR_DEVICE;
612184610Salfred	req.bRequest = RAL_READ_MAC;
613184610Salfred	USETW(req.wValue, 0);
614184610Salfred	USETW(req.wIndex, reg);
615184610Salfred	USETW(req.wLength, sizeof(val));
616184610Salfred
617184610Salfred	ural_cfg_do_request(sc, &req, &val);
618184610Salfred
619184610Salfred	return (le16toh(val));
620184610Salfred}
621184610Salfred
622184610Salfredstatic void
623184610Salfredural_cfg_read_multi(struct ural_softc *sc, uint16_t reg,
624184610Salfred    void *buf, uint16_t len)
625184610Salfred{
626184610Salfred	struct usb2_device_request req;
627184610Salfred
628184610Salfred	req.bmRequestType = UT_READ_VENDOR_DEVICE;
629184610Salfred	req.bRequest = RAL_READ_MULTI_MAC;
630184610Salfred	USETW(req.wValue, 0);
631184610Salfred	USETW(req.wIndex, reg);
632184610Salfred	USETW(req.wLength, len);
633184610Salfred
634184610Salfred	ural_cfg_do_request(sc, &req, buf);
635184610Salfred	return;
636184610Salfred}
637184610Salfred
638184610Salfredstatic void
639184610Salfredural_cfg_write(struct ural_softc *sc, uint16_t reg, uint16_t val)
640184610Salfred{
641184610Salfred	struct usb2_device_request req;
642184610Salfred
643184610Salfred	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
644184610Salfred	req.bRequest = RAL_WRITE_MAC;
645184610Salfred	USETW(req.wValue, val);
646184610Salfred	USETW(req.wIndex, reg);
647184610Salfred	USETW(req.wLength, 0);
648184610Salfred
649184610Salfred	ural_cfg_do_request(sc, &req, NULL);
650184610Salfred	return;
651184610Salfred}
652184610Salfred
653184610Salfredstatic void
654184610Salfredural_cfg_write_multi(struct ural_softc *sc, uint16_t reg,
655184610Salfred    void *buf, uint16_t len)
656184610Salfred{
657184610Salfred	struct usb2_device_request req;
658184610Salfred
659184610Salfred	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
660184610Salfred	req.bRequest = RAL_WRITE_MULTI_MAC;
661184610Salfred	USETW(req.wValue, 0);
662184610Salfred	USETW(req.wIndex, reg);
663184610Salfred	USETW(req.wLength, len);
664184610Salfred
665184610Salfred	ural_cfg_do_request(sc, &req, buf);
666184610Salfred	return;
667184610Salfred}
668184610Salfred
669184610Salfredstatic uint8_t
670184610Salfredural_cfg_bbp_disbusy(struct ural_softc *sc)
671184610Salfred{
672184610Salfred	uint16_t tmp;
673184610Salfred	uint8_t to;
674184610Salfred
675184610Salfred	for (to = 0;; to++) {
676184610Salfred		if (to < 100) {
677184610Salfred			tmp = ural_cfg_read(sc, RAL_PHY_CSR8);
678184610Salfred			tmp &= RAL_BBP_BUSY;
679184610Salfred
680184610Salfred			if (tmp == 0) {
681184610Salfred				return (0);
682184610Salfred			}
683184610Salfred			if (usb2_config_td_sleep(&sc->sc_config_td, hz / 100)) {
684184610Salfred				break;
685184610Salfred			}
686184610Salfred		} else {
687184610Salfred			break;
688184610Salfred		}
689184610Salfred	}
690184610Salfred	DPRINTF("could not disbusy BBP\n");
691184610Salfred	return (1);			/* failure */
692184610Salfred}
693184610Salfred
694184610Salfredstatic void
695184610Salfredural_cfg_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val)
696184610Salfred{
697184610Salfred	uint16_t tmp;
698184610Salfred
699184610Salfred	if (ural_cfg_bbp_disbusy(sc)) {
700184610Salfred		return;
701184610Salfred	}
702184610Salfred	tmp = (reg << 8) | val;
703184610Salfred	ural_cfg_write(sc, RAL_PHY_CSR7, tmp);
704184610Salfred	return;
705184610Salfred}
706184610Salfred
707184610Salfredstatic uint8_t
708184610Salfredural_cfg_bbp_read(struct ural_softc *sc, uint8_t reg)
709184610Salfred{
710184610Salfred	uint16_t val;
711184610Salfred
712184610Salfred	if (ural_cfg_bbp_disbusy(sc)) {
713184610Salfred		return (0);
714184610Salfred	}
715184610Salfred	val = RAL_BBP_WRITE | (reg << 8);
716184610Salfred	ural_cfg_write(sc, RAL_PHY_CSR7, val);
717184610Salfred
718184610Salfred	if (ural_cfg_bbp_disbusy(sc)) {
719184610Salfred		return (0);
720184610Salfred	}
721184610Salfred	return (ural_cfg_read(sc, RAL_PHY_CSR7) & 0xff);
722184610Salfred}
723184610Salfred
724184610Salfredstatic void
725184610Salfredural_cfg_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
726184610Salfred{
727184610Salfred	uint32_t tmp;
728184610Salfred	uint8_t to;
729184610Salfred
730184610Salfred	reg &= 3;
731184610Salfred
732184610Salfred	/* remember last written value */
733184610Salfred	sc->sc_rf_regs[reg] = val;
734184610Salfred
735184610Salfred	for (to = 0;; to++) {
736184610Salfred		if (to < 100) {
737184610Salfred			tmp = ural_cfg_read(sc, RAL_PHY_CSR10);
738184610Salfred
739184610Salfred			if (!(tmp & RAL_RF_LOBUSY)) {
740184610Salfred				break;
741184610Salfred			}
742184610Salfred			if (usb2_config_td_sleep(&sc->sc_config_td, hz / 100)) {
743184610Salfred				return;
744184610Salfred			}
745184610Salfred		} else {
746184610Salfred			DPRINTF("could not write to RF\n");
747184610Salfred			return;
748184610Salfred		}
749184610Salfred	}
750184610Salfred
751184610Salfred	tmp = RAL_RF_BUSY | RAL_RF_20BIT | ((val & 0xfffff) << 2) | reg;
752184610Salfred	ural_cfg_write(sc, RAL_PHY_CSR9, tmp & 0xffff);
753184610Salfred	ural_cfg_write(sc, RAL_PHY_CSR10, tmp >> 16);
754184610Salfred
755184610Salfred	DPRINTFN(16, "RF R[%u] <- 0x%05x\n", reg, val & 0xfffff);
756184610Salfred	return;
757184610Salfred}
758184610Salfred
759184610Salfredstatic void
760184610Salfredural_cfg_first_time_setup(struct ural_softc *sc,
761184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
762184610Salfred{
763184610Salfred	struct ieee80211com *ic;
764184610Salfred	struct ifnet *ifp;
765184610Salfred	uint8_t bands;
766184610Salfred
767184610Salfred	/* setup RX tap header */
768184610Salfred	sc->sc_rxtap_len = sizeof(sc->sc_rxtap);
769184610Salfred	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
770184610Salfred	sc->sc_rxtap.wr_ihdr.it_present = htole32(RAL_RX_RADIOTAP_PRESENT);
771184610Salfred
772184610Salfred	/* setup TX tap header */
773184610Salfred	sc->sc_txtap_len = sizeof(sc->sc_txtap);
774184610Salfred	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
775184610Salfred	sc->sc_txtap.wt_ihdr.it_present = htole32(RAL_TX_RADIOTAP_PRESENT);
776184610Salfred
777184610Salfred	/* retrieve RT2570 rev. no */
778184610Salfred	sc->sc_asic_rev = ural_cfg_read(sc, RAL_MAC_CSR0);
779184610Salfred
780184610Salfred	/* retrieve MAC address and various other things from EEPROM */
781184610Salfred	ural_cfg_read_eeprom(sc);
782184610Salfred
783184610Salfred	printf("%s: MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
784184610Salfred	    sc->sc_name, sc->sc_asic_rev, ural_get_rf(sc->sc_rf_rev));
785184610Salfred
786184610Salfred	mtx_unlock(&sc->sc_mtx);
787184610Salfred
788184610Salfred	ifp = if_alloc(IFT_IEEE80211);
789184610Salfred
790184610Salfred	mtx_lock(&sc->sc_mtx);
791184610Salfred
792184610Salfred	if (ifp == NULL) {
793184610Salfred		DPRINTFN(0, "could not if_alloc()!\n");
794184610Salfred		goto done;
795184610Salfred	}
796184610Salfred	sc->sc_evilhack = ifp;
797184610Salfred	sc->sc_ifp = ifp;
798184610Salfred	ic = ifp->if_l2com;
799184610Salfred
800184610Salfred	ifp->if_softc = sc;
801184610Salfred	if_initname(ifp, "ural", sc->sc_unit);
802184610Salfred	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
803184610Salfred	ifp->if_init = &ural_init_cb;
804184610Salfred	ifp->if_ioctl = &ural_ioctl_cb;
805184610Salfred	ifp->if_start = &ural_start_cb;
806184610Salfred	ifp->if_watchdog = NULL;
807184610Salfred	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
808184610Salfred	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
809184610Salfred	IFQ_SET_READY(&ifp->if_snd);
810184610Salfred
811184610Salfred	bcopy(sc->sc_myaddr, ic->ic_myaddr, sizeof(ic->ic_myaddr));
812184610Salfred
813184610Salfred	ic->ic_ifp = ifp;
814184610Salfred	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
815184610Salfred	ic->ic_opmode = IEEE80211_M_STA;
816184610Salfred
817184610Salfred	/* set device capabilities */
818184610Salfred	ic->ic_caps =
819184610Salfred	    IEEE80211_C_STA		/* station mode supported */
820184610Salfred	    | IEEE80211_C_IBSS		/* IBSS mode supported */
821184610Salfred	    | IEEE80211_C_MONITOR	/* monitor mode supported */
822184610Salfred	    | IEEE80211_C_HOSTAP	/* HostAp mode supported */
823184610Salfred	    | IEEE80211_C_TXPMGT	/* tx power management */
824184610Salfred	    | IEEE80211_C_SHPREAMBLE	/* short preamble supported */
825184610Salfred	    | IEEE80211_C_SHSLOT	/* short slot time supported */
826184610Salfred	    | IEEE80211_C_BGSCAN	/* bg scanning supported */
827184610Salfred	    | IEEE80211_C_WPA		/* 802.11i */
828184610Salfred	    ;
829184610Salfred
830184610Salfred	bands = 0;
831184610Salfred	setbit(&bands, IEEE80211_MODE_11B);
832184610Salfred	setbit(&bands, IEEE80211_MODE_11G);
833184610Salfred
834184610Salfred	if (sc->sc_rf_rev == RAL_RF_5222) {
835184610Salfred		setbit(&bands, IEEE80211_MODE_11A);
836184610Salfred	}
837184610Salfred	ieee80211_init_channels(ic, NULL, &bands);
838184610Salfred
839184610Salfred	mtx_unlock(&sc->sc_mtx);
840184610Salfred
841184610Salfred	ieee80211_ifattach(ic);
842184610Salfred
843184610Salfred	mtx_lock(&sc->sc_mtx);
844184610Salfred
845184610Salfred	ic->ic_newassoc = &ural_newassoc;
846184610Salfred	ic->ic_raw_xmit = &ural_raw_xmit_cb;
847184610Salfred	ic->ic_node_alloc = &ural_node_alloc;
848184610Salfred	ic->ic_update_mcast = &ural_update_mcast_cb;
849184610Salfred	ic->ic_update_promisc = &ural_update_promisc_cb;
850184610Salfred	ic->ic_scan_start = &ural_scan_start_cb;
851184610Salfred	ic->ic_scan_end = &ural_scan_end_cb;
852184610Salfred	ic->ic_set_channel = &ural_set_channel_cb;
853184610Salfred	ic->ic_vap_create = &ural_vap_create;
854184610Salfred	ic->ic_vap_delete = &ural_vap_delete;
855184610Salfred
856184610Salfred	sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
857184610Salfred
858184610Salfred	mtx_unlock(&sc->sc_mtx);
859184610Salfred
860184610Salfred	bpfattach(ifp, DLT_IEEE802_11_RADIO,
861184610Salfred	    sizeof(struct ieee80211_frame) + sizeof(sc->sc_txtap));
862184610Salfred
863184610Salfred	if (bootverbose) {
864184610Salfred		ieee80211_announce(ic);
865184610Salfred	}
866184610Salfred	mtx_lock(&sc->sc_mtx);
867184610Salfreddone:
868184610Salfred	return;
869184610Salfred}
870184610Salfred
871184610Salfredstatic void
872184610Salfredural_end_of_commands(struct ural_softc *sc)
873184610Salfred{
874184610Salfred	sc->sc_flags &= ~URAL_FLAG_WAIT_COMMAND;
875184610Salfred
876184610Salfred	/* start write transfer, if not started */
877184610Salfred	usb2_transfer_start(sc->sc_xfer[0]);
878184610Salfred	return;
879184610Salfred}
880184610Salfred
881184610Salfredstatic void
882184610Salfredural_config_copy_chan(struct ural_config_copy_chan *cc,
883184610Salfred    struct ieee80211com *ic, struct ieee80211_channel *c)
884184610Salfred{
885184610Salfred	if (!c)
886184610Salfred		return;
887184610Salfred	cc->chan_to_ieee =
888184610Salfred	    ieee80211_chan2ieee(ic, c);
889184610Salfred	if (c != IEEE80211_CHAN_ANYC) {
890184610Salfred		cc->chan_to_mode =
891184610Salfred		    ieee80211_chan2mode(c);
892184610Salfred		if (IEEE80211_IS_CHAN_B(c))
893184610Salfred			cc->chan_is_b = 1;
894184610Salfred		if (IEEE80211_IS_CHAN_A(c))
895184610Salfred			cc->chan_is_a = 1;
896184610Salfred		if (IEEE80211_IS_CHAN_2GHZ(c))
897184610Salfred			cc->chan_is_2ghz = 1;
898184610Salfred		if (IEEE80211_IS_CHAN_5GHZ(c))
899184610Salfred			cc->chan_is_5ghz = 1;
900184610Salfred		if (IEEE80211_IS_CHAN_ANYG(c))
901184610Salfred			cc->chan_is_g = 1;
902184610Salfred	}
903184610Salfred	return;
904184610Salfred}
905184610Salfred
906184610Salfredstatic void
907184610Salfredural_config_copy(struct ural_softc *sc,
908184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
909184610Salfred{
910184610Salfred	struct ifnet *ifp;
911184610Salfred	struct ieee80211com *ic;
912184610Salfred	struct ieee80211_node *ni;
913184610Salfred	struct ieee80211vap *vap;
914184610Salfred	const struct ieee80211_txparam *tp;
915184610Salfred
916184610Salfred	bzero(cc, sizeof(*cc));
917184610Salfred
918184610Salfred	ifp = sc->sc_ifp;
919184610Salfred	if (ifp) {
920184610Salfred		cc->if_flags = ifp->if_flags;
921184610Salfred		bcopy(ifp->if_broadcastaddr, cc->if_broadcastaddr,
922184610Salfred		    sizeof(cc->if_broadcastaddr));
923184610Salfred
924184610Salfred		ic = ifp->if_l2com;
925184610Salfred		if (ic) {
926184610Salfred			ural_config_copy_chan(&cc->ic_curchan, ic, ic->ic_curchan);
927184610Salfred			ural_config_copy_chan(&cc->ic_bsschan, ic, ic->ic_bsschan);
928184610Salfred			vap = TAILQ_FIRST(&ic->ic_vaps);
929184610Salfred			if (vap) {
930184610Salfred				ni = vap->iv_bss;
931184610Salfred				if (ni) {
932184610Salfred					cc->iv_bss.ni_intval = ni->ni_intval;
933184610Salfred					bcopy(ni->ni_bssid, cc->iv_bss.ni_bssid,
934184610Salfred					    sizeof(cc->iv_bss.ni_bssid));
935184610Salfred				}
936184610Salfred				tp = vap->iv_txparms + cc->ic_bsschan.chan_to_mode;
937184610Salfred				if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) {
938184610Salfred					cc->iv_bss.fixed_rate_none = 1;
939184610Salfred				}
940184610Salfred			}
941184610Salfred			cc->ic_opmode = ic->ic_opmode;
942184610Salfred			cc->ic_flags = ic->ic_flags;
943184610Salfred			cc->ic_txpowlimit = ic->ic_txpowlimit;
944184610Salfred			cc->ic_curmode = ic->ic_curmode;
945184610Salfred
946184610Salfred			bcopy(ic->ic_myaddr, cc->ic_myaddr,
947184610Salfred			    sizeof(cc->ic_myaddr));
948184610Salfred		}
949184610Salfred	}
950184610Salfred	sc->sc_flags |= URAL_FLAG_WAIT_COMMAND;
951184610Salfred	return;
952184610Salfred}
953184610Salfred
954184610Salfredstatic const char *
955184610Salfredural_get_rf(int rev)
956184610Salfred{
957184610Salfred	switch (rev) {
958184610Salfred		case RAL_RF_2522:return "RT2522";
959184610Salfred	case RAL_RF_2523:
960184610Salfred		return "RT2523";
961184610Salfred	case RAL_RF_2524:
962184610Salfred		return "RT2524";
963184610Salfred	case RAL_RF_2525:
964184610Salfred		return "RT2525";
965184610Salfred	case RAL_RF_2525E:
966184610Salfred		return "RT2525e";
967184610Salfred	case RAL_RF_2526:
968184610Salfred		return "RT2526";
969184610Salfred	case RAL_RF_5222:
970184610Salfred		return "RT5222";
971184610Salfred	default:
972184610Salfred		return "unknown";
973184610Salfred	}
974184610Salfred}
975184610Salfred
976184610Salfred/*------------------------------------------------------------------------*
977184610Salfred * ural_bulk_read_callback - data read "thread"
978184610Salfred *------------------------------------------------------------------------*/
979184610Salfredstatic void
980184610Salfredural_bulk_read_callback(struct usb2_xfer *xfer)
981184610Salfred{
982184610Salfred	struct ural_softc *sc = xfer->priv_sc;
983184610Salfred	struct ifnet *ifp = sc->sc_ifp;
984184610Salfred	struct ieee80211com *ic = ifp->if_l2com;
985184610Salfred	struct ieee80211_node *ni;
986184610Salfred	struct mbuf *m = NULL;
987184610Salfred	uint32_t flags;
988184610Salfred	uint32_t max_len;
989184610Salfred	uint32_t real_len;
990184610Salfred	uint8_t rssi = 0;
991184610Salfred
992184610Salfred	switch (USB_GET_STATE(xfer)) {
993184610Salfred	case USB_ST_TRANSFERRED:
994184610Salfred
995184610Salfred		DPRINTFN(15, "rx done, actlen=%d\n", xfer->actlen);
996184610Salfred
997184610Salfred		if (xfer->actlen < RAL_RX_DESC_SIZE) {
998184610Salfred			DPRINTF("too short transfer, "
999184610Salfred			    "%d bytes\n", xfer->actlen);
1000184610Salfred			ifp->if_ierrors++;
1001184610Salfred			goto tr_setup;
1002184610Salfred		}
1003184610Salfred		max_len = (xfer->actlen - RAL_RX_DESC_SIZE);
1004184610Salfred
1005184610Salfred		usb2_copy_out(xfer->frbuffers, max_len,
1006184610Salfred		    &sc->sc_rx_desc, RAL_RX_DESC_SIZE);
1007184610Salfred
1008184610Salfred		flags = le32toh(sc->sc_rx_desc.flags);
1009184610Salfred
1010184610Salfred		if (flags & (RAL_RX_PHY_ERROR | RAL_RX_CRC_ERROR)) {
1011184610Salfred			/*
1012184610Salfred		         * This should not happen since we did not
1013184610Salfred		         * request to receive those frames when we
1014184610Salfred		         * filled RAL_TXRX_CSR2:
1015184610Salfred		         */
1016184610Salfred			DPRINTFN(6, "PHY or CRC error\n");
1017184610Salfred			ifp->if_ierrors++;
1018184610Salfred			goto tr_setup;
1019184610Salfred		}
1020184610Salfred		if (max_len > MCLBYTES) {
1021184610Salfred			max_len = MCLBYTES;
1022184610Salfred		}
1023184610Salfred		real_len = (flags >> 16) & 0xfff;
1024184610Salfred
1025184610Salfred		if (real_len > max_len) {
1026184610Salfred			DPRINTF("invalid length in RX "
1027184610Salfred			    "descriptor, %u bytes, received %u bytes\n",
1028184610Salfred			    real_len, max_len);
1029184610Salfred			ifp->if_ierrors++;
1030184610Salfred			goto tr_setup;
1031184610Salfred		}
1032184610Salfred		/* ieee80211_input() will check if the mbuf is too short */
1033184610Salfred
1034184610Salfred		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1035184610Salfred
1036184610Salfred		if (m == NULL) {
1037184610Salfred			DPRINTF("could not allocate mbuf\n");
1038184610Salfred			ifp->if_ierrors++;
1039184610Salfred			goto tr_setup;
1040184610Salfred		}
1041184610Salfred		usb2_copy_out(xfer->frbuffers, 0, m->m_data, max_len);
1042184610Salfred
1043184610Salfred		/* finalize mbuf */
1044184610Salfred		m->m_pkthdr.rcvif = ifp;
1045184610Salfred		m->m_pkthdr.len = m->m_len = real_len;
1046184610Salfred
1047184610Salfred		DPRINTF("real length=%d bytes\n", real_len);
1048184610Salfred
1049184610Salfred		rssi = URAL_RSSI(sc->sc_rx_desc.rssi);
1050184610Salfred
1051184610Salfred		if (bpf_peers_present(ifp->if_bpf)) {
1052184610Salfred			struct ural_rx_radiotap_header *tap = &sc->sc_rxtap;
1053184610Salfred
1054184610Salfred			tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;
1055184610Salfred			tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate,
1056184610Salfred			    (sc->sc_rx_desc.flags & htole32(RAL_RX_OFDM)) ?
1057184610Salfred			    IEEE80211_T_OFDM : IEEE80211_T_CCK);
1058184610Salfred
1059184610Salfred			tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
1060184610Salfred			tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
1061184610Salfred			tap->wr_antenna = sc->sc_rx_ant;
1062184610Salfred			tap->wr_antsignal = rssi;
1063184610Salfred
1064184610Salfred			bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m);
1065184610Salfred		}
1066184610Salfred		/* Strip trailing 802.11 MAC FCS. */
1067184610Salfred		m_adj(m, -IEEE80211_CRC_LEN);
1068184610Salfred
1069184610Salfred	case USB_ST_SETUP:
1070184610Salfredtr_setup:
1071184610Salfred
1072184610Salfred		if (sc->sc_flags & URAL_FLAG_READ_STALL) {
1073184610Salfred			usb2_transfer_start(sc->sc_xfer[3]);
1074184610Salfred		} else {
1075184610Salfred			xfer->frlengths[0] = xfer->max_data_length;
1076184610Salfred			usb2_start_hardware(xfer);
1077184610Salfred		}
1078184610Salfred
1079184610Salfred		/*
1080184610Salfred		 * At the end of a USB callback it is always safe to unlock
1081184610Salfred		 * the private mutex of a device! That is why we do the
1082184610Salfred		 * "ieee80211_input" here, and not some lines up!
1083184610Salfred		 */
1084184610Salfred		if (m) {
1085184610Salfred			mtx_unlock(&sc->sc_mtx);
1086184610Salfred
1087184610Salfred			ni = ieee80211_find_rxnode(ic, (void *)(m->m_data));
1088184610Salfred
1089184610Salfred			if (ni) {
1090184610Salfred				/* send the frame to the 802.11 layer */
1091184610Salfred				if (ieee80211_input(ni, m, rssi, RAL_NOISE_FLOOR, 0)) {
1092184610Salfred					/* ignore */
1093184610Salfred				}
1094184610Salfred				/* node is no longer needed */
1095184610Salfred				ieee80211_free_node(ni);
1096184610Salfred			} else {
1097184610Salfred				/* broadcast */
1098184610Salfred				if (ieee80211_input_all(ic, m, rssi, RAL_NOISE_FLOOR, 0)) {
1099184610Salfred					/* ignore */
1100184610Salfred				}
1101184610Salfred			}
1102184610Salfred
1103184610Salfred			mtx_lock(&sc->sc_mtx);
1104184610Salfred		}
1105184610Salfred		return;
1106184610Salfred
1107184610Salfred	default:			/* Error */
1108184610Salfred		if (xfer->error != USB_ERR_CANCELLED) {
1109184610Salfred			/* try to clear stall first */
1110184610Salfred			sc->sc_flags |= URAL_FLAG_READ_STALL;
1111184610Salfred			usb2_transfer_start(sc->sc_xfer[3]);
1112184610Salfred		}
1113184610Salfred		return;
1114184610Salfred
1115184610Salfred	}
1116184610Salfred}
1117184610Salfred
1118184610Salfredstatic void
1119184610Salfredural_bulk_read_clear_stall_callback(struct usb2_xfer *xfer)
1120184610Salfred{
1121184610Salfred	struct ural_softc *sc = xfer->priv_sc;
1122184610Salfred	struct usb2_xfer *xfer_other = sc->sc_xfer[1];
1123184610Salfred
1124184610Salfred	if (usb2_clear_stall_callback(xfer, xfer_other)) {
1125184610Salfred		DPRINTF("stall cleared\n");
1126184610Salfred		sc->sc_flags &= ~URAL_FLAG_READ_STALL;
1127184610Salfred		usb2_transfer_start(xfer_other);
1128184610Salfred	}
1129184610Salfred	return;
1130184610Salfred}
1131184610Salfred
1132184610Salfredstatic uint8_t
1133184610Salfredural_plcp_signal(uint16_t rate)
1134184610Salfred{
1135184610Salfred	;				/* indent fix */
1136184610Salfred	switch (rate) {
1137184610Salfred		/* CCK rates (NB: not IEEE std, device-specific) */
1138184610Salfred	case 2:
1139184610Salfred		return (0x0);
1140184610Salfred	case 4:
1141184610Salfred		return (0x1);
1142184610Salfred	case 11:
1143184610Salfred		return (0x2);
1144184610Salfred	case 22:
1145184610Salfred		return (0x3);
1146184610Salfred
1147184610Salfred		/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
1148184610Salfred	case 12:
1149184610Salfred		return (0xb);
1150184610Salfred	case 18:
1151184610Salfred		return (0xf);
1152184610Salfred	case 24:
1153184610Salfred		return (0xa);
1154184610Salfred	case 36:
1155184610Salfred		return (0xe);
1156184610Salfred	case 48:
1157184610Salfred		return (0x9);
1158184610Salfred	case 72:
1159184610Salfred		return (0xd);
1160184610Salfred	case 96:
1161184610Salfred		return (0x8);
1162184610Salfred	case 108:
1163184610Salfred		return (0xc);
1164184610Salfred
1165184610Salfred		/* XXX unsupported/unknown rate */
1166184610Salfred	default:
1167184610Salfred		return (0xff);
1168184610Salfred	}
1169184610Salfred}
1170184610Salfred
1171184610Salfred/*
1172184610Salfred * We assume that "m->m_pkthdr.rcvif" is pointing to the "ni" that
1173184610Salfred * should be freed, when "ural_setup_desc_and_tx" is called.
1174184610Salfred */
1175184610Salfredstatic void
1176184610Salfredural_setup_desc_and_tx(struct ural_softc *sc, struct mbuf *m,
1177184610Salfred    uint32_t flags, uint16_t rate)
1178184610Salfred{
1179184610Salfred	struct ifnet *ifp = sc->sc_ifp;
1180184610Salfred	struct ieee80211com *ic = ifp->if_l2com;
1181184610Salfred	struct mbuf *mm;
1182184610Salfred	enum ieee80211_phytype phytype;
1183184610Salfred	uint16_t plcp_length;
1184184610Salfred	uint16_t len;
1185184610Salfred	uint8_t remainder;
1186184610Salfred
1187184610Salfred	DPRINTF("in\n");
1188184610Salfred
1189184610Salfred	if (sc->sc_tx_queue.ifq_len >= IFQ_MAXLEN) {
1190184610Salfred		/* free packet */
1191184610Salfred		ural_tx_freem(m);
1192184610Salfred		ifp->if_oerrors++;
1193184610Salfred		return;
1194184610Salfred	}
1195184610Salfred	if (!((sc->sc_flags & URAL_FLAG_LL_READY) &&
1196184610Salfred	    (sc->sc_flags & URAL_FLAG_HL_READY))) {
1197184610Salfred		/* free packet */
1198184610Salfred		ural_tx_freem(m);
1199184610Salfred		ifp->if_oerrors++;
1200184610Salfred		return;
1201184610Salfred	}
1202184610Salfred	if (rate < 2) {
1203184610Salfred		DPRINTF("rate < 2!\n");
1204184610Salfred
1205184610Salfred		/* avoid division by zero */
1206184610Salfred		rate = 2;
1207184610Salfred	}
1208184610Salfred	ic->ic_lastdata = ticks;
1209184610Salfred
1210184610Salfred	if (bpf_peers_present(ifp->if_bpf)) {
1211184610Salfred		struct ural_tx_radiotap_header *tap = &sc->sc_txtap;
1212184610Salfred
1213184610Salfred		tap->wt_flags = 0;
1214184610Salfred		tap->wt_rate = rate;
1215184610Salfred		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
1216184610Salfred		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
1217184610Salfred		tap->wt_antenna = sc->sc_tx_ant;
1218184610Salfred
1219184610Salfred		bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m);
1220184610Salfred	}
1221184610Salfred	len = m->m_pkthdr.len;
1222184610Salfred
1223184610Salfred	sc->sc_tx_desc.flags = htole32(flags);
1224184610Salfred	sc->sc_tx_desc.flags |= htole32(RAL_TX_NEWSEQ);
1225184610Salfred	sc->sc_tx_desc.flags |= htole32(len << 16);
1226184610Salfred
1227184610Salfred	sc->sc_tx_desc.wme = htole16(RAL_AIFSN(2) |
1228184610Salfred	    RAL_LOGCWMIN(3) |
1229184610Salfred	    RAL_LOGCWMAX(5) |
1230184610Salfred	    RAL_IVOFFSET(sizeof(struct ieee80211_frame)));
1231184610Salfred
1232184610Salfred	/* setup PLCP fields */
1233184610Salfred	sc->sc_tx_desc.plcp_signal = ural_plcp_signal(rate);
1234184610Salfred	sc->sc_tx_desc.plcp_service = 4;
1235184610Salfred
1236184610Salfred	len += IEEE80211_CRC_LEN;
1237184610Salfred
1238184610Salfred	phytype = ieee80211_rate2phytype(sc->sc_rates, rate);
1239184610Salfred
1240184610Salfred	if (phytype == IEEE80211_T_OFDM) {
1241184610Salfred		sc->sc_tx_desc.flags |= htole32(RAL_TX_OFDM);
1242184610Salfred
1243184610Salfred		plcp_length = len & 0xfff;
1244184610Salfred		sc->sc_tx_desc.plcp_length_hi = plcp_length >> 6;
1245184610Salfred		sc->sc_tx_desc.plcp_length_lo = plcp_length & 0x3f;
1246184610Salfred
1247184610Salfred	} else {
1248184610Salfred		plcp_length = ((16 * len) + rate - 1) / rate;
1249184610Salfred		if (rate == 22) {
1250184610Salfred			remainder = (16 * len) % 22;
1251184610Salfred			if ((remainder != 0) && (remainder < 7)) {
1252184610Salfred				sc->sc_tx_desc.plcp_service |=
1253184610Salfred				    RAL_PLCP_LENGEXT;
1254184610Salfred			}
1255184610Salfred		}
1256184610Salfred		sc->sc_tx_desc.plcp_length_hi = plcp_length >> 8;
1257184610Salfred		sc->sc_tx_desc.plcp_length_lo = plcp_length & 0xff;
1258184610Salfred
1259184610Salfred		if ((rate != 2) && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) {
1260184610Salfred			sc->sc_tx_desc.plcp_signal |= 0x08;
1261184610Salfred		}
1262184610Salfred	}
1263184610Salfred
1264184610Salfred	sc->sc_tx_desc.iv = 0;
1265184610Salfred	sc->sc_tx_desc.eiv = 0;
1266184610Salfred
1267184610Salfred	if (sizeof(sc->sc_tx_desc) > MHLEN) {
1268184610Salfred		DPRINTF("No room for header structure!\n");
1269184610Salfred		ural_tx_freem(m);
1270184610Salfred		return;
1271184610Salfred	}
1272184610Salfred	mm = m_gethdr(M_NOWAIT, MT_DATA);
1273184610Salfred	if (mm == NULL) {
1274184610Salfred		DPRINTF("Could not allocate header mbuf!\n");
1275184610Salfred		ural_tx_freem(m);
1276184610Salfred		return;
1277184610Salfred	}
1278184610Salfred	DPRINTF(" %zu %u (out)\n", sizeof(sc->sc_tx_desc), m->m_pkthdr.len);
1279184610Salfred
1280184610Salfred	bcopy(&sc->sc_tx_desc, mm->m_data, sizeof(sc->sc_tx_desc));
1281184610Salfred	mm->m_len = sizeof(sc->sc_tx_desc);
1282184610Salfred
1283184610Salfred	mm->m_next = m;
1284184610Salfred	mm->m_pkthdr.len = mm->m_len + m->m_pkthdr.len;
1285184610Salfred	mm->m_pkthdr.rcvif = NULL;
1286184610Salfred
1287184610Salfred	/* start write transfer, if not started */
1288184610Salfred	_IF_ENQUEUE(&sc->sc_tx_queue, mm);
1289184610Salfred
1290184610Salfred	usb2_transfer_start(sc->sc_xfer[0]);
1291184610Salfred	return;
1292184610Salfred}
1293184610Salfred
1294184610Salfredstatic void
1295184610Salfredural_bulk_write_callback(struct usb2_xfer *xfer)
1296184610Salfred{
1297184610Salfred	struct ural_softc *sc = xfer->priv_sc;
1298184610Salfred	struct ifnet *ifp = sc->sc_ifp;
1299184610Salfred	struct mbuf *m;
1300184610Salfred	uint16_t temp_len;
1301184610Salfred	uint8_t align;
1302184610Salfred
1303184610Salfred	switch (USB_GET_STATE(xfer)) {
1304184610Salfred	case USB_ST_TRANSFERRED:
1305184610Salfred		DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen);
1306184610Salfred
1307184610Salfred		ifp->if_opackets++;
1308184610Salfred
1309184610Salfred	case USB_ST_SETUP:
1310184610Salfred		if (sc->sc_flags & URAL_FLAG_WRITE_STALL) {
1311184610Salfred			usb2_transfer_start(sc->sc_xfer[2]);
1312184610Salfred			break;
1313184610Salfred		}
1314184610Salfred		if (sc->sc_flags & URAL_FLAG_WAIT_COMMAND) {
1315184610Salfred			/*
1316184610Salfred			 * don't send anything while a command is pending !
1317184610Salfred			 */
1318184610Salfred			break;
1319184610Salfred		}
1320184610Salfred		ural_fill_write_queue(sc);
1321184610Salfred
1322184610Salfred		_IF_DEQUEUE(&sc->sc_tx_queue, m);
1323184610Salfred
1324184610Salfred		if (m) {
1325184610Salfred
1326184610Salfred			if (m->m_pkthdr.len > (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE)) {
1327184610Salfred				DPRINTFN(0, "data overflow, %u bytes\n",
1328184610Salfred				    m->m_pkthdr.len);
1329184610Salfred				m->m_pkthdr.len = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE);
1330184610Salfred			}
1331184610Salfred			usb2_m_copy_in(xfer->frbuffers, 0,
1332184610Salfred			    m, 0, m->m_pkthdr.len);
1333184610Salfred
1334184610Salfred			/* compute transfer length */
1335184610Salfred			temp_len = m->m_pkthdr.len;
1336184610Salfred
1337184610Salfred			/* make transfer length 16-bit aligned */
1338184610Salfred			align = (temp_len & 1);
1339184610Salfred
1340184610Salfred			/* check if we need to add two extra bytes */
1341184610Salfred			if (((temp_len + align) % 64) == 0) {
1342184610Salfred				align += 2;
1343184610Salfred			}
1344184610Salfred			/* check if we need to align length */
1345184610Salfred			if (align != 0) {
1346184610Salfred				/* zero the extra bytes */
1347184610Salfred				usb2_bzero(xfer->frbuffers, temp_len, align);
1348184610Salfred				temp_len += align;
1349184610Salfred			}
1350184610Salfred			DPRINTFN(11, "sending frame len=%u xferlen=%u\n",
1351184610Salfred			    m->m_pkthdr.len, temp_len);
1352184610Salfred
1353184610Salfred			xfer->frlengths[0] = temp_len;
1354184610Salfred
1355184610Salfred			usb2_start_hardware(xfer);
1356184610Salfred
1357184610Salfred			/* free mbuf and node */
1358184610Salfred			ural_tx_freem(m);
1359184610Salfred		}
1360184610Salfred		break;
1361184610Salfred
1362184610Salfred	default:			/* Error */
1363184610Salfred		DPRINTFN(11, "transfer error, %s\n",
1364184610Salfred		    usb2_errstr(xfer->error));
1365184610Salfred
1366184610Salfred		if (xfer->error != USB_ERR_CANCELLED) {
1367184610Salfred			/* try to clear stall first */
1368184610Salfred			sc->sc_flags |= URAL_FLAG_WRITE_STALL;
1369184610Salfred			usb2_transfer_start(sc->sc_xfer[2]);
1370184610Salfred		}
1371184610Salfred		ifp->if_oerrors++;
1372184610Salfred		break;
1373184610Salfred	}
1374184610Salfred	return;
1375184610Salfred}
1376184610Salfred
1377184610Salfredstatic void
1378184610Salfredural_bulk_write_clear_stall_callback(struct usb2_xfer *xfer)
1379184610Salfred{
1380184610Salfred	struct ural_softc *sc = xfer->priv_sc;
1381184610Salfred	struct usb2_xfer *xfer_other = sc->sc_xfer[0];
1382184610Salfred
1383184610Salfred	if (usb2_clear_stall_callback(xfer, xfer_other)) {
1384184610Salfred		DPRINTF("stall cleared\n");
1385184610Salfred		sc->sc_flags &= ~URAL_FLAG_WRITE_STALL;
1386184610Salfred		usb2_transfer_start(xfer_other);
1387184610Salfred	}
1388184610Salfred	return;
1389184610Salfred}
1390184610Salfred
1391184610Salfredstatic void
1392184610Salfredural_watchdog(void *arg)
1393184610Salfred{
1394184610Salfred	struct ural_softc *sc = arg;
1395184610Salfred
1396184610Salfred	mtx_assert(&sc->sc_mtx, MA_OWNED);
1397184610Salfred
1398184610Salfred	if (sc->sc_amrr_timer) {
1399184610Salfred		usb2_config_td_queue_command
1400184610Salfred		    (&sc->sc_config_td, NULL,
1401184610Salfred		    &ural_cfg_amrr_timeout, 0, 0);
1402184610Salfred	}
1403184610Salfred	usb2_callout_reset(&sc->sc_watchdog,
1404184610Salfred	    hz, &ural_watchdog, sc);
1405184610Salfred
1406184610Salfred	mtx_unlock(&sc->sc_mtx);
1407184610Salfred
1408184610Salfred	return;
1409184610Salfred}
1410184610Salfred
1411184610Salfred/*========================================================================*
1412184610Salfred * IF-net callbacks
1413184610Salfred *========================================================================*/
1414184610Salfred
1415184610Salfredstatic void
1416184610Salfredural_init_cb(void *arg)
1417184610Salfred{
1418184610Salfred	struct ural_softc *sc = arg;
1419184610Salfred
1420184610Salfred	mtx_lock(&sc->sc_mtx);
1421184610Salfred	usb2_config_td_queue_command
1422184610Salfred	    (&sc->sc_config_td, &ural_cfg_pre_init,
1423184610Salfred	    &ural_cfg_init, 0, 0);
1424184610Salfred	mtx_unlock(&sc->sc_mtx);
1425184610Salfred
1426184610Salfred	return;
1427184610Salfred}
1428184610Salfred
1429184610Salfredstatic int
1430184610Salfredural_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data)
1431184610Salfred{
1432184610Salfred	struct ural_softc *sc = ifp->if_softc;
1433184610Salfred	struct ieee80211com *ic = ifp->if_l2com;
1434184610Salfred	int error;
1435184610Salfred
1436184610Salfred	switch (cmd) {
1437184610Salfred	case SIOCSIFFLAGS:
1438184610Salfred		mtx_lock(&sc->sc_mtx);
1439184610Salfred		if (ifp->if_flags & IFF_UP) {
1440184610Salfred			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1441184610Salfred				usb2_config_td_queue_command
1442184610Salfred				    (&sc->sc_config_td, &ural_cfg_pre_init,
1443184610Salfred				    &ural_cfg_init, 0, 0);
1444184610Salfred			}
1445184610Salfred		} else {
1446184610Salfred			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1447184610Salfred				usb2_config_td_queue_command
1448184610Salfred				    (&sc->sc_config_td, &ural_cfg_pre_stop,
1449184610Salfred				    &ural_cfg_stop, 0, 0);
1450184610Salfred			}
1451184610Salfred		}
1452184610Salfred		mtx_unlock(&sc->sc_mtx);
1453184610Salfred		error = 0;
1454184610Salfred		break;
1455184610Salfred
1456184610Salfred	case SIOCGIFMEDIA:
1457184610Salfred	case SIOCSIFMEDIA:
1458184610Salfred		error = ifmedia_ioctl(ifp, (void *)data, &ic->ic_media, cmd);
1459184610Salfred		break;
1460184610Salfred
1461184610Salfred	default:
1462184610Salfred		error = ether_ioctl(ifp, cmd, data);
1463184610Salfred	}
1464184610Salfred	return (error);
1465184610Salfred}
1466184610Salfred
1467184610Salfredstatic void
1468184610Salfredural_start_cb(struct ifnet *ifp)
1469184610Salfred{
1470184610Salfred	struct ural_softc *sc = ifp->if_softc;
1471184610Salfred
1472184610Salfred	mtx_lock(&sc->sc_mtx);
1473184610Salfred	/* start write transfer, if not started */
1474184610Salfred	usb2_transfer_start(sc->sc_xfer[0]);
1475184610Salfred	mtx_unlock(&sc->sc_mtx);
1476184610Salfred
1477184610Salfred	return;
1478184610Salfred}
1479184610Salfred
1480184610Salfredstatic void
1481184610Salfredural_cfg_newstate(struct ural_softc *sc,
1482184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1483184610Salfred{
1484184610Salfred	struct ifnet *ifp = sc->sc_ifp;
1485184610Salfred	struct ieee80211com *ic = ifp->if_l2com;
1486184610Salfred	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
1487184610Salfred	struct ural_vap *uvp = URAL_VAP(vap);
1488184610Salfred	enum ieee80211_state ostate;
1489184610Salfred	enum ieee80211_state nstate;
1490184610Salfred	int arg;
1491184610Salfred
1492184610Salfred	ostate = vap->iv_state;
1493184610Salfred	nstate = sc->sc_ns_state;
1494184610Salfred	arg = sc->sc_ns_arg;
1495184610Salfred
1496184610Salfred	if (ostate == IEEE80211_S_INIT) {
1497184610Salfred		/* We are leaving INIT. TSF sync should be off. */
1498184610Salfred		ural_cfg_disable_tsf_sync(sc);
1499184610Salfred	}
1500184610Salfred	switch (nstate) {
1501184610Salfred	case IEEE80211_S_INIT:
1502184610Salfred		break;
1503184610Salfred
1504184610Salfred	case IEEE80211_S_RUN:
1505184610Salfred		ural_cfg_set_run(sc, cc);
1506184610Salfred		break;
1507184610Salfred
1508184610Salfred	default:
1509184610Salfred		break;
1510184610Salfred	}
1511184610Salfred
1512184610Salfred	mtx_unlock(&sc->sc_mtx);
1513184610Salfred	IEEE80211_LOCK(ic);
1514184610Salfred	uvp->newstate(vap, nstate, arg);
1515184610Salfred	if (vap->iv_newstate_cb != NULL)
1516184610Salfred		vap->iv_newstate_cb(vap, nstate, arg);
1517184610Salfred	IEEE80211_UNLOCK(ic);
1518184610Salfred	mtx_lock(&sc->sc_mtx);
1519184610Salfred	return;
1520184610Salfred}
1521184610Salfred
1522184610Salfredstatic int
1523184610Salfredural_newstate_cb(struct ieee80211vap *vap,
1524184610Salfred    enum ieee80211_state nstate, int arg)
1525184610Salfred{
1526184610Salfred	struct ural_vap *uvp = URAL_VAP(vap);
1527184610Salfred	struct ieee80211com *ic = vap->iv_ic;
1528184610Salfred	struct ural_softc *sc = ic->ic_ifp->if_softc;
1529184610Salfred
1530184610Salfred	DPRINTF("setting new state: %d\n", nstate);
1531184610Salfred
1532184610Salfred	/* Special case - cannot defer this call and cannot block ! */
1533184610Salfred	if (nstate == IEEE80211_S_INIT) {
1534184610Salfred		/* stop timers */
1535184610Salfred		mtx_lock(&sc->sc_mtx);
1536184610Salfred		sc->sc_amrr_timer = 0;
1537184610Salfred		mtx_unlock(&sc->sc_mtx);
1538184610Salfred		return (uvp->newstate(vap, nstate, arg));
1539184610Salfred	}
1540184610Salfred	mtx_lock(&sc->sc_mtx);
1541184610Salfred	if (usb2_config_td_is_gone(&sc->sc_config_td)) {
1542184610Salfred		mtx_unlock(&sc->sc_mtx);
1543184610Salfred		return (0);		/* nothing to do */
1544184610Salfred	}
1545184610Salfred	/* store next state */
1546184610Salfred	sc->sc_ns_state = nstate;
1547184610Salfred	sc->sc_ns_arg = arg;
1548184610Salfred
1549184610Salfred	/* stop timers */
1550184610Salfred	sc->sc_amrr_timer = 0;
1551184610Salfred
1552184610Salfred	/*
1553184610Salfred	 * USB configuration can only be done from the USB configuration
1554184610Salfred	 * thread:
1555184610Salfred	 */
1556184610Salfred	usb2_config_td_queue_command
1557184610Salfred	    (&sc->sc_config_td, &ural_config_copy,
1558184610Salfred	    &ural_cfg_newstate, 0, 0);
1559184610Salfred
1560184610Salfred	mtx_unlock(&sc->sc_mtx);
1561184610Salfred
1562184610Salfred	return (EINPROGRESS);
1563184610Salfred}
1564184610Salfred
1565184610Salfredstatic void
1566184610Salfredural_std_command(struct ieee80211com *ic, usb2_config_td_command_t *func)
1567184610Salfred{
1568184610Salfred	struct ural_softc *sc = ic->ic_ifp->if_softc;
1569184610Salfred
1570184610Salfred	mtx_lock(&sc->sc_mtx);
1571184610Salfred
1572184610Salfred	sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
1573184610Salfred
1574184610Salfred	usb2_config_td_queue_command
1575184610Salfred	    (&sc->sc_config_td, &ural_config_copy, func, 0, 0);
1576184610Salfred
1577184610Salfred	mtx_unlock(&sc->sc_mtx);
1578184610Salfred
1579184610Salfred	return;
1580184610Salfred}
1581184610Salfred
1582184610Salfredstatic void
1583184610Salfredural_scan_start_cb(struct ieee80211com *ic)
1584184610Salfred{
1585184610Salfred	ural_std_command(ic, &ural_cfg_scan_start);
1586184610Salfred	return;
1587184610Salfred}
1588184610Salfred
1589184610Salfredstatic void
1590184610Salfredural_scan_end_cb(struct ieee80211com *ic)
1591184610Salfred{
1592184610Salfred	ural_std_command(ic, &ural_cfg_scan_end);
1593184610Salfred	return;
1594184610Salfred}
1595184610Salfred
1596184610Salfredstatic void
1597184610Salfredural_set_channel_cb(struct ieee80211com *ic)
1598184610Salfred{
1599184610Salfred	ural_std_command(ic, &ural_cfg_set_chan);
1600184610Salfred	return;
1601184610Salfred}
1602184610Salfred
1603184610Salfred/*========================================================================*
1604184610Salfred * configure sub-routines, ural_cfg_xxx
1605184610Salfred *========================================================================*/
1606184610Salfred
1607184610Salfredstatic void
1608184610Salfredural_cfg_scan_start(struct ural_softc *sc,
1609184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1610184610Salfred{
1611184610Salfred	/* abort TSF synchronization */
1612184610Salfred	ural_cfg_disable_tsf_sync(sc);
1613184610Salfred	ural_cfg_set_bssid(sc, cc->if_broadcastaddr);
1614184610Salfred	return;
1615184610Salfred}
1616184610Salfred
1617184610Salfredstatic void
1618184610Salfredural_cfg_scan_end(struct ural_softc *sc,
1619184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1620184610Salfred{
1621184610Salfred	/* enable TSF synchronization */
1622184610Salfred	ural_cfg_enable_tsf_sync(sc, cc, 0);
1623184610Salfred	ural_cfg_set_bssid(sc, cc->iv_bss.ni_bssid);
1624184610Salfred	return;
1625184610Salfred}
1626184610Salfred
1627184610Salfredstatic void
1628184610Salfredural_cfg_set_chan(struct ural_softc *sc,
1629184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1630184610Salfred{
1631184610Salfred	enum {
1632184610Salfred		N_RF5222 = (sizeof(ural_rf5222) / sizeof(ural_rf5222[0])),
1633184610Salfred	};
1634184610Salfred	uint32_t i;
1635184610Salfred	uint32_t chan;
1636184610Salfred	uint8_t power;
1637184610Salfred	uint8_t tmp;
1638184610Salfred
1639184610Salfred	chan = cc->ic_curchan.chan_to_ieee;
1640184610Salfred
1641184610Salfred	if ((chan == 0) ||
1642184610Salfred	    (chan == IEEE80211_CHAN_ANY)) {
1643184610Salfred		/* nothing to do */
1644184610Salfred		return;
1645184610Salfred	}
1646184610Salfred	if (cc->ic_curchan.chan_is_2ghz)
1647184610Salfred		power = min(sc->sc_txpow[chan - 1], 31);
1648184610Salfred	else
1649184610Salfred		power = 31;
1650184610Salfred
1651184610Salfred	/* adjust txpower using ifconfig settings */
1652184610Salfred	power -= (100 - cc->ic_txpowlimit) / 8;
1653184610Salfred
1654184610Salfred	DPRINTFN(3, "setting channel to %u, "
1655184610Salfred	    "tx-power to %u\n", chan, power);
1656184610Salfred
1657184610Salfred	switch (sc->sc_rf_rev) {
1658184610Salfred	case RAL_RF_2522:
1659184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x00814);
1660184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]);
1661184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x00040);
1662184610Salfred		break;
1663184610Salfred
1664184610Salfred	case RAL_RF_2523:
1665184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x08804);
1666184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]);
1667184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x38044);
1668184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
1669184610Salfred		break;
1670184610Salfred
1671184610Salfred	case RAL_RF_2524:
1672184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x0c808);
1673184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]);
1674184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x00040);
1675184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
1676184610Salfred		break;
1677184610Salfred
1678184610Salfred	case RAL_RF_2525:
1679184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x08808);
1680184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]);
1681184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x18044);
1682184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
1683184610Salfred
1684184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x08808);
1685184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]);
1686184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x18044);
1687184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
1688184610Salfred		break;
1689184610Salfred
1690184610Salfred	case RAL_RF_2525E:
1691184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x08808);
1692184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]);
1693184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x18044);
1694184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282);
1695184610Salfred		break;
1696184610Salfred
1697184610Salfred	case RAL_RF_2526:
1698184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]);
1699184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
1700184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, 0x08804);
1701184610Salfred
1702184610Salfred		ural_cfg_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]);
1703184610Salfred		ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x18044);
1704184610Salfred		ural_cfg_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
1705184610Salfred		break;
1706184610Salfred
1707184610Salfred		/* dual-band RF */
1708184610Salfred	case RAL_RF_5222:
1709184610Salfred		for (i = 0; i < N_RF5222; i++) {
1710184610Salfred			if (ural_rf5222[i].chan == chan) {
1711184610Salfred				ural_cfg_rf_write(sc, RAL_RF1, ural_rf5222[i].r1);
1712184610Salfred				ural_cfg_rf_write(sc, RAL_RF2, ural_rf5222[i].r2);
1713184610Salfred				ural_cfg_rf_write(sc, RAL_RF3, (power << 7) | 0x00040);
1714184610Salfred				ural_cfg_rf_write(sc, RAL_RF4, ural_rf5222[i].r4);
1715184610Salfred				break;
1716184610Salfred			}
1717184610Salfred		}
1718184610Salfred		break;
1719184610Salfred	}
1720184610Salfred
1721184610Salfred	if ((cc->ic_opmode != IEEE80211_M_MONITOR) &&
1722184610Salfred	    (!(cc->ic_flags & IEEE80211_F_SCAN))) {
1723184610Salfred
1724184610Salfred		/* set Japan filter bit for channel 14 */
1725184610Salfred		tmp = ural_cfg_bbp_read(sc, 70);
1726184610Salfred
1727184610Salfred		if (chan == 14) {
1728184610Salfred			tmp |= RAL_JAPAN_FILTER;
1729184610Salfred		} else {
1730184610Salfred			tmp &= ~RAL_JAPAN_FILTER;
1731184610Salfred		}
1732184610Salfred
1733184610Salfred		ural_cfg_bbp_write(sc, 70, tmp);
1734184610Salfred
1735184610Salfred		/* clear CRC errors */
1736184610Salfred		ural_cfg_read(sc, RAL_STA_CSR0);
1737184610Salfred
1738184610Salfred		ural_cfg_disable_rf_tune(sc);
1739184610Salfred	}
1740184610Salfred	/* update basic rate set */
1741184610Salfred	if (cc->ic_curchan.chan_is_b) {
1742184610Salfred		/* 11b basic rates: 1, 2Mbps */
1743184610Salfred		ural_cfg_write(sc, RAL_TXRX_CSR11, 0x3);
1744184610Salfred	} else if (cc->ic_curchan.chan_is_a) {
1745184610Salfred		/* 11a basic rates: 6, 12, 24Mbps */
1746184610Salfred		ural_cfg_write(sc, RAL_TXRX_CSR11, 0x150);
1747184610Salfred	} else {
1748184610Salfred		/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
1749184610Salfred		ural_cfg_write(sc, RAL_TXRX_CSR11, 0x15f);
1750184610Salfred	}
1751184610Salfred
1752184610Salfred	/* wait a little */
1753184610Salfred	if (usb2_config_td_sleep(&sc->sc_config_td, hz / 100)) {
1754184610Salfred		return;
1755184610Salfred	}
1756184610Salfred	return;
1757184610Salfred}
1758184610Salfred
1759184610Salfredstatic void
1760184610Salfredural_cfg_set_run(struct ural_softc *sc,
1761184610Salfred    struct usb2_config_td_cc *cc)
1762184610Salfred{
1763184610Salfred	if (cc->ic_opmode != IEEE80211_M_MONITOR) {
1764184610Salfred		ural_cfg_update_slot(sc, cc, 0);
1765184610Salfred		ural_cfg_set_txpreamble(sc, cc, 0);
1766184610Salfred
1767184610Salfred		/* update basic rate set */
1768184610Salfred
1769184610Salfred		if (cc->ic_bsschan.chan_is_5ghz) {
1770184610Salfred			/* 11a basic rates: 6, 12, 24Mbps */
1771184610Salfred			ural_cfg_write(sc, RAL_TXRX_CSR11, 0x150);
1772184610Salfred		} else if (cc->ic_bsschan.chan_is_g) {
1773184610Salfred			/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
1774184610Salfred			ural_cfg_write(sc, RAL_TXRX_CSR11, 0x15f);
1775184610Salfred		} else {
1776184610Salfred			/* 11b basic rates: 1, 2Mbps */
1777184610Salfred			ural_cfg_write(sc, RAL_TXRX_CSR11, 0x3);
1778184610Salfred		}
1779184610Salfred		ural_cfg_set_bssid(sc, cc->iv_bss.ni_bssid);
1780184610Salfred	}
1781184610Salfred	if ((cc->ic_opmode == IEEE80211_M_HOSTAP) ||
1782184610Salfred	    (cc->ic_opmode == IEEE80211_M_IBSS)) {
1783184610Salfred		ural_tx_bcn(sc);
1784184610Salfred	}
1785184610Salfred	/* make tx led blink on tx (controlled by ASIC) */
1786184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR20, 1);
1787184610Salfred
1788184610Salfred	if (cc->ic_opmode != IEEE80211_M_MONITOR) {
1789184610Salfred		ural_cfg_enable_tsf_sync(sc, cc, 0);
1790184610Salfred	}
1791184610Salfred	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
1792184610Salfred	ural_cfg_read_multi(sc, RAL_STA_CSR0, sc->sc_sta, sizeof(sc->sc_sta));
1793184610Salfred
1794184610Salfred	if (cc->iv_bss.fixed_rate_none) {
1795184610Salfred		/* enable automatic rate adaptation */
1796184610Salfred		ural_cfg_amrr_start(sc);
1797184610Salfred	}
1798184610Salfred	return;
1799184610Salfred}
1800184610Salfred
1801184610Salfred/*------------------------------------------------------------------------*
1802184610Salfred * ural_cfg_disable_rf_tune - disable RF auto-tuning
1803184610Salfred *------------------------------------------------------------------------*/
1804184610Salfredstatic void
1805184610Salfredural_cfg_disable_rf_tune(struct ural_softc *sc)
1806184610Salfred{
1807184610Salfred	uint32_t tmp;
1808184610Salfred
1809184610Salfred	if (sc->sc_rf_rev != RAL_RF_2523) {
1810184610Salfred		tmp = sc->sc_rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE;
1811184610Salfred		ural_cfg_rf_write(sc, RAL_RF1, tmp);
1812184610Salfred	}
1813184610Salfred	tmp = sc->sc_rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE;
1814184610Salfred	ural_cfg_rf_write(sc, RAL_RF3, tmp);
1815184610Salfred
1816184610Salfred	DPRINTFN(3, "disabling RF autotune\n");
1817184610Salfred
1818184610Salfred	return;
1819184610Salfred}
1820184610Salfred
1821184610Salfred/*------------------------------------------------------------------------*
1822184610Salfred * ural_cfg_enable_tsf_sync - refer to IEEE Std 802.11-1999 pp. 123
1823184610Salfred * for more information on TSF synchronization
1824184610Salfred *------------------------------------------------------------------------*/
1825184610Salfredstatic void
1826184610Salfredural_cfg_enable_tsf_sync(struct ural_softc *sc,
1827184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1828184610Salfred{
1829184610Salfred	uint16_t logcwmin;
1830184610Salfred	uint16_t preload;
1831184610Salfred	uint16_t tmp;
1832184610Salfred
1833184610Salfred	/* first, disable TSF synchronization */
1834184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR19, 0);
1835184610Salfred
1836184610Salfred	tmp = (16 * cc->iv_bss.ni_intval) << 4;
1837184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR18, tmp);
1838184610Salfred
1839184610Salfred	logcwmin = (cc->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0;
1840184610Salfred	preload = (cc->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6;
1841184610Salfred	tmp = (logcwmin << 12) | preload;
1842184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR20, tmp);
1843184610Salfred
1844184610Salfred	/* finally, enable TSF synchronization */
1845184610Salfred	tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN;
1846184610Salfred	if (cc->ic_opmode == IEEE80211_M_STA)
1847184610Salfred		tmp |= RAL_ENABLE_TSF_SYNC(1);
1848184610Salfred	else
1849184610Salfred		tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR;
1850184610Salfred
1851184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR19, tmp);
1852184610Salfred
1853184610Salfred	DPRINTF("enabling TSF synchronization\n");
1854184610Salfred
1855184610Salfred	return;
1856184610Salfred}
1857184610Salfred
1858184610Salfredstatic void
1859184610Salfredural_cfg_disable_tsf_sync(struct ural_softc *sc)
1860184610Salfred{
1861184610Salfred	/* abort TSF synchronization */
1862184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR19, 0);
1863184610Salfred
1864184610Salfred	/* force tx led to stop blinking */
1865184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR20, 0);
1866184610Salfred
1867184610Salfred	return;
1868184610Salfred}
1869184610Salfred
1870184610Salfred#define	RAL_RXTX_TURNAROUND    5	/* us */
1871184610Salfred
1872184610Salfredstatic void
1873184610Salfredural_cfg_update_slot(struct ural_softc *sc,
1874184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1875184610Salfred{
1876184610Salfred	uint16_t slottime;
1877184610Salfred	uint16_t sifs;
1878184610Salfred	uint16_t eifs;
1879184610Salfred
1880184610Salfred	slottime = (cc->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
1881184610Salfred
1882184610Salfred	/*
1883184610Salfred	 * These settings may sound a bit inconsistent but this is what the
1884184610Salfred	 * reference driver does.
1885184610Salfred	 */
1886184610Salfred	if (cc->ic_curmode == IEEE80211_MODE_11B) {
1887184610Salfred		sifs = 16 - RAL_RXTX_TURNAROUND;
1888184610Salfred		eifs = 364;
1889184610Salfred	} else {
1890184610Salfred		sifs = 10 - RAL_RXTX_TURNAROUND;
1891184610Salfred		eifs = 64;
1892184610Salfred	}
1893184610Salfred
1894184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR10, slottime);
1895184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR11, sifs);
1896184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR12, eifs);
1897184610Salfred	return;
1898184610Salfred}
1899184610Salfred
1900184610Salfredstatic void
1901184610Salfredural_cfg_set_txpreamble(struct ural_softc *sc,
1902184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1903184610Salfred{
1904184610Salfred	uint16_t tmp;
1905184610Salfred
1906184610Salfred	tmp = ural_cfg_read(sc, RAL_TXRX_CSR10);
1907184610Salfred
1908184610Salfred	if (cc->ic_flags & IEEE80211_F_SHPREAMBLE) {
1909184610Salfred		tmp |= RAL_SHORT_PREAMBLE;
1910184610Salfred	} else {
1911184610Salfred		tmp &= ~RAL_SHORT_PREAMBLE;
1912184610Salfred	}
1913184610Salfred
1914184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR10, tmp);
1915184610Salfred	return;
1916184610Salfred}
1917184610Salfred
1918184610Salfredstatic void
1919184610Salfredural_cfg_set_bssid(struct ural_softc *sc, uint8_t *bssid)
1920184610Salfred{
1921184610Salfred	ural_cfg_write_multi(sc, RAL_MAC_CSR5, bssid, IEEE80211_ADDR_LEN);
1922184610Salfred
1923184610Salfred	DPRINTF("setting BSSID to 0x%02x%02x%02x%02x%02x%02x\n",
1924184610Salfred	    bssid[5], bssid[4], bssid[3],
1925184610Salfred	    bssid[2], bssid[1], bssid[0]);
1926184610Salfred	return;
1927184610Salfred}
1928184610Salfred
1929184610Salfredstatic void
1930184610Salfredural_cfg_set_macaddr(struct ural_softc *sc, uint8_t *addr)
1931184610Salfred{
1932184610Salfred	ural_cfg_write_multi(sc, RAL_MAC_CSR2, addr, IEEE80211_ADDR_LEN);
1933184610Salfred
1934184610Salfred	DPRINTF("setting MAC to 0x%02x%02x%02x%02x%02x%02x\n",
1935184610Salfred	    addr[5], addr[4], addr[3],
1936184610Salfred	    addr[2], addr[1], addr[0]);
1937184610Salfred	return;
1938184610Salfred}
1939184610Salfred
1940184610Salfredstatic void
1941184610Salfredural_cfg_update_promisc(struct ural_softc *sc,
1942184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
1943184610Salfred{
1944184610Salfred	uint16_t tmp;
1945184610Salfred
1946184610Salfred	tmp = ural_cfg_read(sc, RAL_TXRX_CSR2);
1947184610Salfred
1948184610Salfred	if (cc->if_flags & IFF_PROMISC) {
1949184610Salfred		tmp &= ~RAL_DROP_NOT_TO_ME;
1950184610Salfred	} else {
1951184610Salfred		tmp |= RAL_DROP_NOT_TO_ME;
1952184610Salfred	}
1953184610Salfred
1954184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR2, tmp);
1955184610Salfred
1956184610Salfred	DPRINTF("%s promiscuous mode\n",
1957184610Salfred	    (cc->if_flags & IFF_PROMISC) ?
1958184610Salfred	    "entering" : "leaving");
1959184610Salfred	return;
1960184610Salfred}
1961184610Salfred
1962184610Salfredstatic void
1963184610Salfredural_cfg_set_txantenna(struct ural_softc *sc, uint8_t antenna)
1964184610Salfred{
1965184610Salfred	uint16_t tmp;
1966184610Salfred	uint8_t tx;
1967184610Salfred
1968184610Salfred	tx = ural_cfg_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK;
1969184610Salfred	if (antenna == 1)
1970184610Salfred		tx |= RAL_BBP_ANTA;
1971184610Salfred	else if (antenna == 2)
1972184610Salfred		tx |= RAL_BBP_ANTB;
1973184610Salfred	else
1974184610Salfred		tx |= RAL_BBP_DIVERSITY;
1975184610Salfred
1976184610Salfred	/* need to force I/Q flip for RF 2525e, 2526 and 5222 */
1977184610Salfred	if ((sc->sc_rf_rev == RAL_RF_2525E) ||
1978184610Salfred	    (sc->sc_rf_rev == RAL_RF_2526) ||
1979184610Salfred	    (sc->sc_rf_rev == RAL_RF_5222)) {
1980184610Salfred		tx |= RAL_BBP_FLIPIQ;
1981184610Salfred	}
1982184610Salfred	ural_cfg_bbp_write(sc, RAL_BBP_TX, tx);
1983184610Salfred
1984184610Salfred	/* update values in PHY_CSR5 and PHY_CSR6 */
1985184610Salfred	tmp = ural_cfg_read(sc, RAL_PHY_CSR5) & ~0x7;
1986184610Salfred	ural_cfg_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7));
1987184610Salfred
1988184610Salfred	tmp = ural_cfg_read(sc, RAL_PHY_CSR6) & ~0x7;
1989184610Salfred	ural_cfg_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7));
1990184610Salfred
1991184610Salfred	return;
1992184610Salfred}
1993184610Salfred
1994184610Salfredstatic void
1995184610Salfredural_cfg_set_rxantenna(struct ural_softc *sc, uint8_t antenna)
1996184610Salfred{
1997184610Salfred	uint8_t rx;
1998184610Salfred
1999184610Salfred	rx = ural_cfg_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK;
2000184610Salfred	if (antenna == 1)
2001184610Salfred		rx |= RAL_BBP_ANTA;
2002184610Salfred	else if (antenna == 2)
2003184610Salfred		rx |= RAL_BBP_ANTB;
2004184610Salfred	else
2005184610Salfred		rx |= RAL_BBP_DIVERSITY;
2006184610Salfred
2007184610Salfred	/* need to force no I/Q flip for RF 2525e and 2526 */
2008184610Salfred
2009184610Salfred	if ((sc->sc_rf_rev == RAL_RF_2525E) ||
2010184610Salfred	    (sc->sc_rf_rev == RAL_RF_2526)) {
2011184610Salfred		rx &= ~RAL_BBP_FLIPIQ;
2012184610Salfred	}
2013184610Salfred	ural_cfg_bbp_write(sc, RAL_BBP_RX, rx);
2014184610Salfred	return;
2015184610Salfred}
2016184610Salfred
2017184610Salfredstatic void
2018184610Salfredural_cfg_read_eeprom(struct ural_softc *sc)
2019184610Salfred{
2020184610Salfred	uint16_t val;
2021184610Salfred
2022184610Salfred	ural_cfg_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
2023184610Salfred
2024184610Salfred	val = le16toh(val);
2025184610Salfred
2026184610Salfred	sc->sc_rf_rev = (val >> 11) & 0x7;
2027184610Salfred	sc->sc_hw_radio = (val >> 10) & 0x1;
2028184610Salfred	sc->sc_led_mode = (val >> 6) & 0x7;
2029184610Salfred	sc->sc_rx_ant = (val >> 4) & 0x3;
2030184610Salfred	sc->sc_tx_ant = (val >> 2) & 0x3;
2031184610Salfred	sc->sc_nb_ant = (val & 0x3);
2032184610Salfred
2033184610Salfred	DPRINTF("val = 0x%04x\n", val);
2034184610Salfred
2035184610Salfred	/* read MAC address */
2036184610Salfred	ural_cfg_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_myaddr,
2037184610Salfred	    sizeof(sc->sc_myaddr));
2038184610Salfred
2039184610Salfred	/* read default values for BBP registers */
2040184610Salfred	ural_cfg_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->sc_bbp_prom,
2041184610Salfred	    sizeof(sc->sc_bbp_prom));
2042184610Salfred
2043184610Salfred	/* read Tx power for all b/g channels */
2044184610Salfred	ural_cfg_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->sc_txpow,
2045184610Salfred	    sizeof(sc->sc_txpow));
2046184610Salfred	return;
2047184610Salfred}
2048184610Salfred
2049184610Salfredstatic uint8_t
2050184610Salfredural_cfg_bbp_init(struct ural_softc *sc)
2051184610Salfred{
2052184610Salfred	enum {
2053184610Salfred		N_DEF_BBP = (sizeof(ural_def_bbp) / sizeof(ural_def_bbp[0])),
2054184610Salfred	};
2055184610Salfred	uint16_t i;
2056184610Salfred	uint8_t to;
2057184610Salfred
2058184610Salfred	/* wait for BBP to become ready */
2059184610Salfred	for (to = 0;; to++) {
2060184610Salfred		if (to < 100) {
2061184610Salfred			if (ural_cfg_bbp_read(sc, RAL_BBP_VERSION) != 0) {
2062184610Salfred				break;
2063184610Salfred			}
2064184610Salfred			if (usb2_config_td_sleep(&sc->sc_config_td, hz / 100)) {
2065184610Salfred				return (1);	/* failure */
2066184610Salfred			}
2067184610Salfred		} else {
2068184610Salfred			DPRINTF("timeout waiting for BBP\n");
2069184610Salfred			return (1);	/* failure */
2070184610Salfred		}
2071184610Salfred	}
2072184610Salfred
2073184610Salfred	/* initialize BBP registers to default values */
2074184610Salfred	for (i = 0; i < N_DEF_BBP; i++) {
2075184610Salfred		ural_cfg_bbp_write(sc, ural_def_bbp[i].reg,
2076184610Salfred		    ural_def_bbp[i].val);
2077184610Salfred	}
2078184610Salfred
2079184610Salfred#if 0
2080184610Salfred	/* initialize BBP registers to values stored in EEPROM */
2081184610Salfred	for (i = 0; i < 16; i++) {
2082184610Salfred		if (sc->sc_bbp_prom[i].reg == 0xff) {
2083184610Salfred			continue;
2084184610Salfred		}
2085184610Salfred		ural_cfg_bbp_write(sc, sc->sc_bbp_prom[i].reg,
2086184610Salfred		    sc->sc_bbp_prom[i].val);
2087184610Salfred	}
2088184610Salfred#endif
2089184610Salfred	return (0);			/* success */
2090184610Salfred}
2091184610Salfred
2092184610Salfredstatic void
2093184610Salfredural_cfg_pre_init(struct ural_softc *sc,
2094184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
2095184610Salfred{
2096184610Salfred	struct ifnet *ifp = sc->sc_ifp;
2097184610Salfred	struct ieee80211com *ic = ifp->if_l2com;
2098184610Salfred
2099184610Salfred	/* immediate configuration */
2100184610Salfred
2101184610Salfred	ural_cfg_pre_stop(sc, cc, 0);
2102184610Salfred
2103184610Salfred	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2104184610Salfred
2105184610Salfred	sc->sc_flags |= URAL_FLAG_HL_READY;
2106184610Salfred
2107184610Salfred	IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
2108184610Salfred
2109184610Salfred	return;
2110184610Salfred}
2111184610Salfred
2112184610Salfredstatic void
2113184610Salfredural_cfg_init(struct ural_softc *sc,
2114184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
2115184610Salfred{
2116184610Salfred	enum {
2117184610Salfred		N_DEF_MAC = (sizeof(ural_def_mac) / sizeof(ural_def_mac[0])),
2118184610Salfred	};
2119184610Salfred	uint16_t tmp;
2120184610Salfred	uint16_t i;
2121184610Salfred	uint8_t to;
2122184610Salfred
2123184610Salfred	/* delayed configuration */
2124184610Salfred
2125184610Salfred	ural_cfg_set_testmode(sc);
2126184610Salfred
2127184610Salfred	ural_cfg_write(sc, 0x308, 0x00f0);	/* XXX magic */
2128184610Salfred
2129184610Salfred	ural_cfg_stop(sc, cc, 0);
2130184610Salfred
2131184610Salfred	/* initialize MAC registers to default values */
2132184610Salfred	for (i = 0; i < N_DEF_MAC; i++) {
2133184610Salfred		ural_cfg_write(sc, ural_def_mac[i].reg,
2134184610Salfred		    ural_def_mac[i].val);
2135184610Salfred	}
2136184610Salfred
2137184610Salfred	/* wait for BBP and RF to wake up (this can take a long time!) */
2138184610Salfred	for (to = 0;; to++) {
2139184610Salfred		if (to < 100) {
2140184610Salfred			tmp = ural_cfg_read(sc, RAL_MAC_CSR17);
2141184610Salfred			if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) ==
2142184610Salfred			    (RAL_BBP_AWAKE | RAL_RF_AWAKE)) {
2143184610Salfred				break;
2144184610Salfred			}
2145184610Salfred			if (usb2_config_td_sleep(&sc->sc_config_td, hz / 100)) {
2146184610Salfred				goto fail;
2147184610Salfred			}
2148184610Salfred		} else {
2149184610Salfred			DPRINTF("timeout waiting for "
2150184610Salfred			    "BBP/RF to wakeup\n");
2151184610Salfred			goto fail;
2152184610Salfred		}
2153184610Salfred	}
2154184610Salfred
2155184610Salfred	/* we're ready! */
2156184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR1, RAL_HOST_READY);
2157184610Salfred
2158184610Salfred	/* set basic rate set (will be updated later) */
2159184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR11, 0x15f);
2160184610Salfred
2161184610Salfred	if (ural_cfg_bbp_init(sc)) {
2162184610Salfred		goto fail;
2163184610Salfred	}
2164184610Salfred	/* set default BSS channel */
2165184610Salfred	ural_cfg_set_chan(sc, cc, 0);
2166184610Salfred
2167184610Salfred	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
2168184610Salfred	ural_cfg_read_multi(sc, RAL_STA_CSR0, sc->sc_sta,
2169184610Salfred	    sizeof(sc->sc_sta));
2170184610Salfred
2171184610Salfred	DPRINTF("rx_ant=%d, tx_ant=%d\n",
2172184610Salfred	    sc->sc_rx_ant, sc->sc_tx_ant);
2173184610Salfred
2174184610Salfred	ural_cfg_set_txantenna(sc, sc->sc_tx_ant);
2175184610Salfred	ural_cfg_set_rxantenna(sc, sc->sc_rx_ant);
2176184610Salfred
2177184610Salfred	ural_cfg_set_macaddr(sc, cc->ic_myaddr);
2178184610Salfred
2179184610Salfred	/*
2180184610Salfred	 * make sure that the first transaction
2181184610Salfred	 * clears the stall:
2182184610Salfred	 */
2183184610Salfred	sc->sc_flags |= (URAL_FLAG_READ_STALL |
2184184610Salfred	    URAL_FLAG_WRITE_STALL |
2185184610Salfred	    URAL_FLAG_LL_READY);
2186184610Salfred
2187184610Salfred	if ((sc->sc_flags & URAL_FLAG_LL_READY) &&
2188184610Salfred	    (sc->sc_flags & URAL_FLAG_HL_READY)) {
2189184610Salfred		struct ifnet *ifp = sc->sc_ifp;
2190184610Salfred		struct ieee80211com *ic = ifp->if_l2com;
2191184610Salfred
2192184610Salfred		/*
2193184610Salfred		 * start the USB transfers, if not already started:
2194184610Salfred		 */
2195184610Salfred		usb2_transfer_start(sc->sc_xfer[1]);
2196184610Salfred		usb2_transfer_start(sc->sc_xfer[0]);
2197184610Salfred
2198184610Salfred		/*
2199184610Salfred		 * start IEEE802.11 layer
2200184610Salfred		 */
2201184610Salfred		mtx_unlock(&sc->sc_mtx);
2202184610Salfred		ieee80211_start_all(ic);
2203184610Salfred		mtx_lock(&sc->sc_mtx);
2204184610Salfred	}
2205184610Salfred	/*
2206184610Salfred	 * start Rx
2207184610Salfred	 */
2208184610Salfred	tmp = RAL_DROP_PHY | RAL_DROP_CRC;
2209184610Salfred	if (cc->ic_opmode != IEEE80211_M_MONITOR) {
2210184610Salfred
2211184610Salfred		tmp |= (RAL_DROP_CTL | RAL_DROP_BAD_VERSION);
2212184610Salfred
2213184610Salfred		if (cc->ic_opmode != IEEE80211_M_HOSTAP) {
2214184610Salfred			tmp |= RAL_DROP_TODS;
2215184610Salfred		}
2216184610Salfred		if (!(cc->if_flags & IFF_PROMISC)) {
2217184610Salfred			tmp |= RAL_DROP_NOT_TO_ME;
2218184610Salfred		}
2219184610Salfred	}
2220184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR2, tmp);
2221184610Salfred
2222184610Salfred	return;
2223184610Salfred
2224184610Salfredfail:
2225184610Salfred	ural_cfg_pre_stop(sc, NULL, 0);
2226184610Salfred
2227184610Salfred	if (cc) {
2228184610Salfred		ural_cfg_stop(sc, cc, 0);
2229184610Salfred	}
2230184610Salfred	return;
2231184610Salfred}
2232184610Salfred
2233184610Salfredstatic void
2234184610Salfredural_cfg_pre_stop(struct ural_softc *sc,
2235184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
2236184610Salfred{
2237184610Salfred	struct ifnet *ifp = sc->sc_ifp;
2238184610Salfred
2239184610Salfred	if (cc) {
2240184610Salfred		/* copy the needed configuration */
2241184610Salfred		ural_config_copy(sc, cc, refcount);
2242184610Salfred	}
2243184610Salfred	/* immediate configuration */
2244184610Salfred
2245184610Salfred	if (ifp) {
2246184610Salfred		/* clear flags */
2247184610Salfred		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
2248184610Salfred	}
2249184610Salfred	sc->sc_flags &= ~(URAL_FLAG_HL_READY |
2250184610Salfred	    URAL_FLAG_LL_READY);
2251184610Salfred
2252184610Salfred	/*
2253184610Salfred	 * stop all the transfers, if not already stopped:
2254184610Salfred	 */
2255184610Salfred	usb2_transfer_stop(sc->sc_xfer[0]);
2256184610Salfred	usb2_transfer_stop(sc->sc_xfer[1]);
2257184610Salfred	usb2_transfer_stop(sc->sc_xfer[2]);
2258184610Salfred	usb2_transfer_stop(sc->sc_xfer[3]);
2259184610Salfred
2260184610Salfred	/* clean up transmission */
2261184610Salfred	ural_tx_clean_queue(sc);
2262184610Salfred	return;
2263184610Salfred}
2264184610Salfred
2265184610Salfredstatic void
2266184610Salfredural_cfg_stop(struct ural_softc *sc,
2267184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
2268184610Salfred{
2269184610Salfred	/* disable Rx */
2270184610Salfred	ural_cfg_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
2271184610Salfred
2272184610Salfred	/* reset ASIC and BBP (but won't reset MAC registers!) */
2273184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP);
2274184610Salfred
2275184610Salfred	/* wait a little */
2276184610Salfred	usb2_config_td_sleep(&sc->sc_config_td, hz / 10);
2277184610Salfred
2278184610Salfred	/* clear reset */
2279184610Salfred	ural_cfg_write(sc, RAL_MAC_CSR1, 0);
2280184610Salfred
2281184610Salfred	/* wait a little */
2282184610Salfred	usb2_config_td_sleep(&sc->sc_config_td, hz / 10);
2283184610Salfred
2284184610Salfred	return;
2285184610Salfred}
2286184610Salfred
2287184610Salfredstatic void
2288184610Salfredural_cfg_amrr_start(struct ural_softc *sc)
2289184610Salfred{
2290184610Salfred	struct ieee80211vap *vap;
2291184610Salfred	struct ieee80211_node *ni;
2292184610Salfred
2293184610Salfred	vap = ural_get_vap(sc);
2294184610Salfred
2295184610Salfred	if (vap == NULL) {
2296184610Salfred		return;
2297184610Salfred	}
2298184610Salfred	ni = vap->iv_bss;
2299184610Salfred	if (ni == NULL) {
2300184610Salfred		return;
2301184610Salfred	}
2302184610Salfred	/* init AMRR */
2303184610Salfred
2304184610Salfred	ieee80211_amrr_node_init(&URAL_VAP(vap)->amrr, &URAL_NODE(ni)->amn, ni);
2305184610Salfred	/* enable AMRR timer */
2306184610Salfred
2307184610Salfred	sc->sc_amrr_timer = 1;
2308184610Salfred	return;
2309184610Salfred}
2310184610Salfred
2311184610Salfredstatic void
2312184610Salfredural_cfg_amrr_timeout(struct ural_softc *sc,
2313184610Salfred    struct usb2_config_td_cc *cc, uint16_t refcount)
2314184610Salfred{
2315184610Salfred	struct ifnet *ifp = sc->sc_ifp;
2316184610Salfred	struct ieee80211vap *vap;
2317184610Salfred	struct ieee80211_node *ni;
2318184610Salfred	uint32_t ok;
2319184610Salfred	uint32_t fail;
2320184610Salfred
2321184610Salfred	/* read and clear statistic registers (STA_CSR0 to STA_CSR10) */
2322184610Salfred	ural_cfg_read_multi(sc, RAL_STA_CSR0, sc->sc_sta, sizeof(sc->sc_sta));
2323184610Salfred
2324184610Salfred	vap = ural_get_vap(sc);
2325184610Salfred	if (vap == NULL) {
2326184610Salfred		return;
2327184610Salfred	}
2328184610Salfred	ni = vap->iv_bss;
2329184610Salfred	if (ni == NULL) {
2330184610Salfred		return;
2331184610Salfred	}
2332184610Salfred	if ((sc->sc_flags & URAL_FLAG_LL_READY) &&
2333184610Salfred	    (sc->sc_flags & URAL_FLAG_HL_READY)) {
2334184610Salfred
2335184610Salfred		ok = sc->sc_sta[7] +	/* TX ok w/o retry */
2336184610Salfred		    sc->sc_sta[8];	/* TX ok w/ retry */
2337184610Salfred		fail = sc->sc_sta[9];	/* TX retry-fail count */
2338184610Salfred
2339184610Salfred		if (sc->sc_amrr_timer) {
2340184610Salfred
2341184610Salfred			ieee80211_amrr_tx_update(&URAL_NODE(ni)->amn,
2342184610Salfred			    ok + fail, ok, sc->sc_sta[8] + fail);
2343184610Salfred
2344184610Salfred			if (ieee80211_amrr_choose(ni, &URAL_NODE(ni)->amn)) {
2345184610Salfred				/* ignore */
2346184610Salfred			}
2347184610Salfred		}
2348184610Salfred		ifp->if_oerrors += fail;
2349184610Salfred	}
2350184610Salfred	return;
2351184610Salfred}
2352184610Salfred
2353184610Salfredstatic struct ieee80211vap *
2354184610Salfredural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2355184610Salfred    int opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
2356184610Salfred    const uint8_t mac[IEEE80211_ADDR_LEN])
2357184610Salfred{
2358184610Salfred	struct ural_vap *uvp;
2359184610Salfred	struct ieee80211vap *vap;
2360184610Salfred	struct ural_softc *sc = ic->ic_ifp->if_softc;
2361184610Salfred
2362184610Salfred	/* Need to sync with config thread: */
2363184610Salfred	mtx_lock(&sc->sc_mtx);
2364184610Salfred	if (usb2_config_td_sync(&sc->sc_config_td)) {
2365184610Salfred		mtx_unlock(&sc->sc_mtx);
2366184610Salfred		/* config thread is gone */
2367184610Salfred		return (NULL);
2368184610Salfred	}
2369184610Salfred	mtx_unlock(&sc->sc_mtx);
2370184610Salfred
2371184610Salfred	if (!TAILQ_EMPTY(&ic->ic_vaps))	/* only one at a time */
2372184610Salfred		return NULL;
2373184610Salfred	uvp = (struct ural_vap *)malloc(sizeof(struct ural_vap),
2374184610Salfred	    M_80211_VAP, M_NOWAIT | M_ZERO);
2375184610Salfred	if (uvp == NULL)
2376184610Salfred		return NULL;
2377184610Salfred
2378184610Salfred	vap = &uvp->vap;
2379184610Salfred	/* enable s/w bmiss handling for sta mode */
2380184610Salfred	ieee80211_vap_setup(ic, vap, name, unit, opmode,
2381184610Salfred	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
2382184610Salfred
2383184610Salfred	/* override state transition machine */
2384184610Salfred	uvp->newstate = vap->iv_newstate;
2385184610Salfred	vap->iv_newstate = &ural_newstate_cb;
2386184610Salfred
2387184610Salfred	ieee80211_amrr_init(&uvp->amrr, vap,
2388184610Salfred	    IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
2389184610Salfred	    IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
2390184610Salfred	    1000 /* 1 sec */ );
2391184610Salfred
2392184610Salfred	/* complete setup */
2393184610Salfred	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
2394184610Salfred
2395184610Salfred	/* store current operation mode */
2396184610Salfred	ic->ic_opmode = opmode;
2397184610Salfred
2398184610Salfred	return (vap);
2399184610Salfred}
2400184610Salfred
2401184610Salfredstatic void
2402184610Salfredural_vap_delete(struct ieee80211vap *vap)
2403184610Salfred{
2404184610Salfred	struct ural_vap *uvp = URAL_VAP(vap);
2405184610Salfred	struct ural_softc *sc = vap->iv_ic->ic_ifp->if_softc;
2406184610Salfred
2407184610Salfred	/* Need to sync with config thread: */
2408184610Salfred	mtx_lock(&sc->sc_mtx);
2409184610Salfred	if (usb2_config_td_sync(&sc->sc_config_td)) {
2410184610Salfred		/* ignore */
2411184610Salfred	}
2412184610Salfred	mtx_unlock(&sc->sc_mtx);
2413184610Salfred
2414184610Salfred	ieee80211_amrr_cleanup(&uvp->amrr);
2415184610Salfred	ieee80211_vap_detach(vap);
2416184610Salfred	free(uvp, M_80211_VAP);
2417184610Salfred	return;
2418184610Salfred}
2419184610Salfred
2420184610Salfred/* ARGUSED */
2421184610Salfredstatic struct ieee80211_node *
2422184610Salfredural_node_alloc(struct ieee80211vap *vap __unused,
2423184610Salfred    const uint8_t mac[IEEE80211_ADDR_LEN] __unused)
2424184610Salfred{
2425184610Salfred	struct ural_node *un;
2426184610Salfred
2427184610Salfred	un = malloc(sizeof(struct ural_node), M_80211_NODE, M_NOWAIT | M_ZERO);
2428184610Salfred	return ((un != NULL) ? &un->ni : NULL);
2429184610Salfred}
2430184610Salfred
2431184610Salfredstatic void
2432184610Salfredural_newassoc(struct ieee80211_node *ni, int isnew)
2433184610Salfred{
2434184610Salfred	struct ieee80211vap *vap = ni->ni_vap;
2435184610Salfred
2436184610Salfred	ieee80211_amrr_node_init(&URAL_VAP(vap)->amrr, &URAL_NODE(ni)->amn, ni);
2437184610Salfred	return;
2438184610Salfred}
2439184610Salfred
2440184610Salfredstatic void
2441184610Salfredural_fill_write_queue(struct ural_softc *sc)
2442184610Salfred{
2443184610Salfred	struct ifnet *ifp = sc->sc_ifp;
2444184610Salfred	struct ieee80211_node *ni;
2445184610Salfred	struct mbuf *m;
2446184610Salfred
2447184610Salfred	/*
2448184610Salfred	 * We only fill up half of the queue with data frames. The rest is
2449184610Salfred	 * reserved for other kinds of frames.
2450184610Salfred	 */
2451184610Salfred
2452184610Salfred	while (sc->sc_tx_queue.ifq_len < (IFQ_MAXLEN / 2)) {
2453184610Salfred
2454184610Salfred		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
2455184610Salfred		if (m == NULL)
2456184610Salfred			break;
2457184610Salfred
2458184610Salfred		ni = (void *)(m->m_pkthdr.rcvif);
2459184610Salfred		m = ieee80211_encap(ni, m);
2460184610Salfred		if (m == NULL) {
2461184610Salfred			ieee80211_free_node(ni);
2462184610Salfred			continue;
2463184610Salfred		}
2464184610Salfred		ural_tx_data(sc, m, ni);
2465184610Salfred	}
2466184610Salfred	return;
2467184610Salfred}
2468184610Salfred
2469184610Salfredstatic void
2470184610Salfredural_tx_clean_queue(struct ural_softc *sc)
2471184610Salfred{
2472184610Salfred	struct mbuf *m;
2473184610Salfred
2474184610Salfred	for (;;) {
2475184610Salfred		_IF_DEQUEUE(&sc->sc_tx_queue, m);
2476184610Salfred
2477184610Salfred		if (!m) {
2478184610Salfred			break;
2479184610Salfred		}
2480184610Salfred		ural_tx_freem(m);
2481184610Salfred	}
2482184610Salfred
2483184610Salfred	return;
2484184610Salfred}
2485184610Salfred
2486184610Salfredstatic void
2487184610Salfredural_tx_freem(struct mbuf *m)
2488184610Salfred{
2489184610Salfred	struct ieee80211_node *ni;
2490184610Salfred
2491184610Salfred	while (m) {
2492184610Salfred		ni = (void *)(m->m_pkthdr.rcvif);
2493184610Salfred		if (!ni) {
2494184610Salfred			m = m_free(m);
2495184610Salfred			continue;
2496184610Salfred		}
2497184610Salfred		if (m->m_flags & M_TXCB) {
2498184610Salfred			ieee80211_process_callback(ni, m, 0);
2499184610Salfred		}
2500184610Salfred		m_freem(m);
2501184610Salfred		ieee80211_free_node(ni);
2502184610Salfred
2503184610Salfred		break;
2504184610Salfred	}
2505184610Salfred	return;
2506184610Salfred}
2507184610Salfred
2508184610Salfredstatic void
2509184610Salfredural_tx_mgt(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
2510184610Salfred{
2511184610Salfred	struct ieee80211vap *vap = ni->ni_vap;
2512184610Salfred	struct ieee80211com *ic = ni->ni_ic;
2513184610Salfred	const struct ieee80211_txparam *tp;
2514184610Salfred	struct ieee80211_frame *wh;
2515184610Salfred	struct ieee80211_key *k;
2516184610Salfred	uint32_t flags;
2517184610Salfred	uint16_t dur;
2518184610Salfred
2519184610Salfred	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
2520184610Salfred
2521184610Salfred	wh = mtod(m, struct ieee80211_frame *);
2522184610Salfred	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2523184610Salfred		k = ieee80211_crypto_encap(ni, m);
2524184610Salfred		if (k == NULL) {
2525184610Salfred			m_freem(m);
2526184610Salfred			ieee80211_free_node(ni);
2527184610Salfred			return;
2528184610Salfred		}
2529184610Salfred		wh = mtod(m, struct ieee80211_frame *);
2530184610Salfred	}
2531184610Salfred	flags = 0;
2532184610Salfred	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2533184610Salfred		flags |= RAL_TX_ACK;
2534184610Salfred
2535184610Salfred		dur = ieee80211_ack_duration(sc->sc_rates, tp->mgmtrate,
2536184610Salfred		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
2537184610Salfred		USETW(wh->i_dur, dur);
2538184610Salfred
2539184610Salfred		/* tell hardware to add timestamp for probe responses */
2540184610Salfred		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
2541184610Salfred		    IEEE80211_FC0_TYPE_MGT &&
2542184610Salfred		    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
2543184610Salfred		    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
2544184610Salfred			flags |= RAL_TX_TIMESTAMP;
2545184610Salfred	}
2546184610Salfred	m->m_pkthdr.rcvif = (void *)ni;
2547184610Salfred	ural_setup_desc_and_tx(sc, m, flags, tp->mgmtrate);
2548184610Salfred	return;
2549184610Salfred}
2550184610Salfred
2551184610Salfredstatic struct ieee80211vap *
2552184610Salfredural_get_vap(struct ural_softc *sc)
2553184610Salfred{
2554184610Salfred	struct ifnet *ifp;
2555184610Salfred	struct ieee80211com *ic;
2556184610Salfred
2557184610Salfred	if (sc == NULL) {
2558184610Salfred		return NULL;
2559184610Salfred	}
2560184610Salfred	ifp = sc->sc_ifp;
2561184610Salfred	if (ifp == NULL) {
2562184610Salfred		return NULL;
2563184610Salfred	}
2564184610Salfred	ic = ifp->if_l2com;
2565184610Salfred	if (ic == NULL) {
2566184610Salfred		return NULL;
2567184610Salfred	}
2568184610Salfred	return TAILQ_FIRST(&ic->ic_vaps);
2569184610Salfred}
2570184610Salfred
2571184610Salfredstatic void
2572184610Salfredural_tx_bcn(struct ural_softc *sc)
2573184610Salfred{
2574184610Salfred	struct ieee80211_node *ni;
2575184610Salfred	struct ieee80211vap *vap;
2576184610Salfred	struct ieee80211com *ic;
2577184610Salfred	const struct ieee80211_txparam *tp;
2578184610Salfred	struct mbuf *m;
2579184610Salfred
2580184610Salfred	vap = ural_get_vap(sc);
2581184610Salfred	if (vap == NULL) {
2582184610Salfred		return;
2583184610Salfred	}
2584184610Salfred	ni = vap->iv_bss;
2585184610Salfred	if (ni == NULL) {
2586184610Salfred		return;
2587184610Salfred	}
2588184610Salfred	ic = vap->iv_ic;
2589184610Salfred	if (ic == NULL) {
2590184610Salfred		return;
2591184610Salfred	}
2592184610Salfred	DPRINTFN(11, "Sending beacon frame.\n");
2593184610Salfred
2594184610Salfred	m = ieee80211_beacon_alloc(ni, &URAL_VAP(vap)->bo);
2595184610Salfred	if (m == NULL) {
2596184610Salfred		DPRINTFN(0, "could not allocate beacon\n");
2597184610Salfred		return;
2598184610Salfred	}
2599184610Salfred	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)];
2600184610Salfred
2601184610Salfred	m->m_pkthdr.rcvif = (void *)ieee80211_ref_node(ni);
2602184610Salfred	ural_setup_desc_and_tx(sc, m, RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP,
2603184610Salfred	    tp->mgmtrate);
2604184610Salfred	return;
2605184610Salfred}
2606184610Salfred
2607184610Salfredstatic void
2608184610Salfredural_tx_data(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
2609184610Salfred{
2610184610Salfred	struct ieee80211vap *vap = ni->ni_vap;
2611184610Salfred	struct ieee80211com *ic = ni->ni_ic;
2612184610Salfred	const struct ieee80211_txparam *tp;
2613184610Salfred	struct ieee80211_frame *wh;
2614184610Salfred	struct ieee80211_key *k;
2615184610Salfred	uint32_t flags = 0;
2616184610Salfred	uint16_t dur;
2617184610Salfred	uint16_t rate;
2618184610Salfred
2619184610Salfred	DPRINTFN(11, "Sending data.\n");
2620184610Salfred
2621184610Salfred	wh = mtod(m, struct ieee80211_frame *);
2622184610Salfred
2623184610Salfred	tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
2624184610Salfred	if (IEEE80211_IS_MULTICAST(wh->i_addr1))
2625184610Salfred		rate = tp->mcastrate;
2626184610Salfred	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
2627184610Salfred		rate = tp->ucastrate;
2628184610Salfred	else
2629184610Salfred		rate = ni->ni_txrate;
2630184610Salfred
2631184610Salfred	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2632184610Salfred		k = ieee80211_crypto_encap(ni, m);
2633184610Salfred		if (k == NULL) {
2634184610Salfred			m_freem(m);
2635184610Salfred			ieee80211_free_node(ni);
2636184610Salfred			return;
2637184610Salfred		}
2638184610Salfred		/* packet header may have moved, reset our local pointer */
2639184610Salfred		wh = mtod(m, struct ieee80211_frame *);
2640184610Salfred	}
2641184610Salfred	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2642184610Salfred		uint8_t prot = IEEE80211_PROT_NONE;
2643184610Salfred
2644184610Salfred		if (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
2645184610Salfred			prot = IEEE80211_PROT_RTSCTS;
2646184610Salfred		else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
2647184610Salfred		    ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM)
2648184610Salfred			prot = ic->ic_protmode;
2649184610Salfred		if (prot != IEEE80211_PROT_NONE) {
2650184610Salfred			ural_tx_prot(sc, m, ni, prot, rate);
2651184610Salfred			flags |= RAL_TX_IFS_SIFS;
2652184610Salfred		}
2653184610Salfred		flags |= RAL_TX_ACK;
2654184610Salfred		flags |= RAL_TX_RETRY(7);
2655184610Salfred
2656184610Salfred		dur = ieee80211_ack_duration(sc->sc_rates, rate,
2657184610Salfred		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
2658184610Salfred		USETW(wh->i_dur, dur);
2659184610Salfred	}
2660184610Salfred	m->m_pkthdr.rcvif = (void *)ni;
2661184610Salfred	ural_setup_desc_and_tx(sc, m, flags, rate);
2662184610Salfred	return;
2663184610Salfred}
2664184610Salfred
2665184610Salfredstatic void
2666184610Salfredural_tx_prot(struct ural_softc *sc,
2667184610Salfred    const struct mbuf *m, struct ieee80211_node *ni,
2668184610Salfred    uint8_t prot, uint16_t rate)
2669184610Salfred{
2670184610Salfred	struct ieee80211com *ic = ni->ni_ic;
2671184610Salfred	const struct ieee80211_frame *wh;
2672184610Salfred	struct mbuf *mprot;
2673184610Salfred	uint32_t flags;
2674184610Salfred	uint16_t protrate;
2675184610Salfred	uint16_t ackrate;
2676184610Salfred	uint16_t pktlen;
2677184610Salfred	uint16_t dur;
2678184610Salfred	uint8_t isshort;
2679184610Salfred
2680184610Salfred	KASSERT((prot == IEEE80211_PROT_RTSCTS) ||
2681184610Salfred	    (prot == IEEE80211_PROT_CTSONLY),
2682184610Salfred	    ("protection %u", prot));
2683184610Salfred
2684184610Salfred	DPRINTFN(16, "Sending protection frame.\n");
2685184610Salfred
2686184610Salfred	wh = mtod(m, const struct ieee80211_frame *);
2687184610Salfred	pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
2688184610Salfred
2689184610Salfred	protrate = ieee80211_ctl_rate(sc->sc_rates, rate);
2690184610Salfred	ackrate = ieee80211_ack_rate(sc->sc_rates, rate);
2691184610Salfred
2692184610Salfred	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
2693184610Salfred	dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort);
2694184610Salfred	+ieee80211_ack_duration(sc->sc_rates, rate, isshort);
2695184610Salfred	flags = RAL_TX_RETRY(7);
2696184610Salfred	if (prot == IEEE80211_PROT_RTSCTS) {
2697184610Salfred		/* NB: CTS is the same size as an ACK */
2698184610Salfred		dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort);
2699184610Salfred		flags |= RAL_TX_ACK;
2700184610Salfred		mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
2701184610Salfred	} else {
2702184610Salfred		mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
2703184610Salfred	}
2704184610Salfred	if (mprot == NULL) {
2705184610Salfred		return;
2706184610Salfred	}
2707184610Salfred	mprot->m_pkthdr.rcvif = (void *)ieee80211_ref_node(ni);
2708184610Salfred	ural_setup_desc_and_tx(sc, mprot, flags, protrate);
2709184610Salfred	return;
2710184610Salfred}
2711184610Salfred
2712184610Salfredstatic void
2713184610Salfredural_tx_raw(struct ural_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
2714184610Salfred    const struct ieee80211_bpf_params *params)
2715184610Salfred{
2716184610Salfred	uint32_t flags;
2717184610Salfred	uint16_t rate;
2718184610Salfred
2719184610Salfred	DPRINTFN(11, "Sending raw frame.\n");
2720184610Salfred
2721184610Salfred	rate = params->ibp_rate0 & IEEE80211_RATE_VAL;
2722184610Salfred
2723184610Salfred	/* XXX validate */
2724184610Salfred	if (rate == 0) {
2725184610Salfred		m_freem(m);
2726184610Salfred		ieee80211_free_node(ni);
2727184610Salfred		return;
2728184610Salfred	}
2729184610Salfred	flags = 0;
2730184610Salfred	if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
2731184610Salfred		flags |= RAL_TX_ACK;
2732184610Salfred	if (params->ibp_flags & (IEEE80211_BPF_RTS | IEEE80211_BPF_CTS)) {
2733184610Salfred		ural_tx_prot(sc, m, ni,
2734184610Salfred		    (params->ibp_flags & IEEE80211_BPF_RTS) ?
2735184610Salfred		    IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY,
2736184610Salfred		    rate);
2737184610Salfred		flags |= RAL_TX_IFS_SIFS;
2738184610Salfred	}
2739184610Salfred	m->m_pkthdr.rcvif = (void *)ni;
2740184610Salfred	ural_setup_desc_and_tx(sc, m, flags, rate);
2741184610Salfred	return;
2742184610Salfred}
2743184610Salfred
2744184610Salfredstatic int
2745184610Salfredural_raw_xmit_cb(struct ieee80211_node *ni, struct mbuf *m,
2746184610Salfred    const struct ieee80211_bpf_params *params)
2747184610Salfred{
2748184610Salfred	struct ieee80211com *ic = ni->ni_ic;
2749184610Salfred	struct ifnet *ifp = ic->ic_ifp;
2750184610Salfred	struct ural_softc *sc = ifp->if_softc;
2751184610Salfred
2752184610Salfred	mtx_lock(&sc->sc_mtx);
2753184610Salfred	if (params == NULL) {
2754184610Salfred		/*
2755184610Salfred		 * Legacy path; interpret frame contents to decide
2756184610Salfred		 * precisely how to send the frame.
2757184610Salfred		 */
2758184610Salfred		ural_tx_mgt(sc, m, ni);
2759184610Salfred	} else {
2760184610Salfred		/*
2761184610Salfred		 * Caller supplied explicit parameters to use in
2762184610Salfred		 * sending the frame.
2763184610Salfred		 */
2764184610Salfred		ural_tx_raw(sc, m, ni, params);
2765184610Salfred	}
2766184610Salfred	mtx_unlock(&sc->sc_mtx);
2767184610Salfred	return (0);
2768184610Salfred}
2769184610Salfred
2770184610Salfredstatic void
2771184610Salfredural_update_mcast_cb(struct ifnet *ifp)
2772184610Salfred{
2773184610Salfred	/* not supported */
2774184610Salfred	return;
2775184610Salfred}
2776184610Salfred
2777184610Salfredstatic void
2778184610Salfredural_update_promisc_cb(struct ifnet *ifp)
2779184610Salfred{
2780184610Salfred	struct ural_softc *sc = ifp->if_softc;
2781184610Salfred
2782184610Salfred	mtx_lock(&sc->sc_mtx);
2783184610Salfred	usb2_config_td_queue_command
2784184610Salfred	    (&sc->sc_config_td, &ural_config_copy,
2785184610Salfred	    &ural_cfg_update_promisc, 0, 0);
2786184610Salfred	mtx_unlock(&sc->sc_mtx);
2787184610Salfred	return;
2788184610Salfred}
2789