if_ural.c revision 211314
118334Speter/*	$FreeBSD: head/sys/dev/usb/wlan/if_ural.c 211314 2010-08-14 20:12:10Z bschmidt $	*/
290075Sobrien
390075Sobrien/*-
418334Speter * Copyright (c) 2005, 2006
590075Sobrien *	Damien Bergamini <damien.bergamini@free.fr>
618334Speter *
790075Sobrien * Copyright (c) 2006, 2008
890075Sobrien *	Hans Petter Selasky <hselasky@FreeBSD.org>
990075Sobrien *
1090075Sobrien * Permission to use, copy, modify, and distribute this software for any
1118334Speter * purpose with or without fee is hereby granted, provided that the above
1290075Sobrien * copyright notice and this permission notice appear in all copies.
1390075Sobrien *
1490075Sobrien * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1590075Sobrien * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1618334Speter * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1718334Speter * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1890075Sobrien * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1990075Sobrien * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2090075Sobrien * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2118334Speter */
2218334Speter
2318334Speter#include <sys/cdefs.h>
2450397Sobrien__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_ural.c 211314 2010-08-14 20:12:10Z bschmidt $");
2518334Speter
2650397Sobrien/*-
2790075Sobrien * Ralink Technology RT2500USB chipset driver
2818334Speter * http://www.ralinktech.com/
2918334Speter */
3050397Sobrien
3150397Sobrien#include <sys/param.h>
3290075Sobrien#include <sys/sockio.h>
3318334Speter#include <sys/sysctl.h>
3490075Sobrien#include <sys/lock.h>
3590075Sobrien#include <sys/mutex.h>
3618334Speter#include <sys/mbuf.h>
3790075Sobrien#include <sys/kernel.h>
3890075Sobrien#include <sys/socket.h>
3990075Sobrien#include <sys/systm.h>
4090075Sobrien#include <sys/malloc.h>
4118334Speter#include <sys/module.h>
4250397Sobrien#include <sys/bus.h>
4390075Sobrien#include <sys/endian.h>
4418334Speter#include <sys/kdb.h>
4518334Speter
4618334Speter#include <machine/bus.h>
4790075Sobrien#include <machine/resource.h>
4818334Speter#include <sys/rman.h>
4918334Speter
5018334Speter#include <net/bpf.h>
5190075Sobrien#include <net/if.h>
5218334Speter#include <net/if_arp.h>
5390075Sobrien#include <net/ethernet.h>
5490075Sobrien#include <net/if_dl.h>
5590075Sobrien#include <net/if_media.h>
5690075Sobrien#include <net/if_types.h>
5790075Sobrien
5890075Sobrien#ifdef INET
5990075Sobrien#include <netinet/in.h>
6090075Sobrien#include <netinet/in_systm.h>
6190075Sobrien#include <netinet/in_var.h>
6218334Speter#include <netinet/if_ether.h>
6318334Speter#include <netinet/ip.h>
6418334Speter#endif
6518334Speter
6618334Speter#include <net80211/ieee80211_var.h>
6718334Speter#include <net80211/ieee80211_regdomain.h>
6818334Speter#include <net80211/ieee80211_radiotap.h>
6918334Speter#include <net80211/ieee80211_ratectl.h>
7018334Speter
7118334Speter#include <dev/usb/usb.h>
7290075Sobrien#include <dev/usb/usbdi.h>
7390075Sobrien#include "usbdevs.h"
7490075Sobrien
7590075Sobrien#define	USB_DEBUG_VAR ural_debug
7690075Sobrien#include <dev/usb/usb_debug.h>
7790075Sobrien
7890075Sobrien#include <dev/usb/wlan/if_uralreg.h>
7990075Sobrien#include <dev/usb/wlan/if_uralvar.h>
8090075Sobrien
8190075Sobrien#ifdef USB_DEBUG
8290075Sobrienstatic int ural_debug = 0;
8318334Speter
8418334SpeterSYSCTL_NODE(_hw_usb, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural");
8518334SpeterSYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0,
8618334Speter    "Debug level");
8718334Speter#endif
8818334Speter
8918334Speter#define URAL_RSSI(rssi)					\
9018334Speter	((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ?	\
9118334Speter	 ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0)
9290075Sobrien
9318334Speter/* various supported device vendors/products */
9418334Speterstatic const struct usb_device_id ural_devs[] = {
9518334Speter#define	URAL_DEV(v,p)  { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
9618334Speter	URAL_DEV(ASUS, WL167G),
9790075Sobrien	URAL_DEV(ASUS, RT2570),
9890075Sobrien	URAL_DEV(BELKIN, F5D7050),
9990075Sobrien	URAL_DEV(BELKIN, F5D7051),
10090075Sobrien	URAL_DEV(CISCOLINKSYS, HU200TS),
10190075Sobrien	URAL_DEV(CISCOLINKSYS, WUSB54G),
10290075Sobrien	URAL_DEV(CISCOLINKSYS, WUSB54GP),
10390075Sobrien	URAL_DEV(CONCEPTRONIC2, C54RU),
10490075Sobrien	URAL_DEV(DLINK, DWLG122),
10590075Sobrien	URAL_DEV(GIGABYTE, GN54G),
10690075Sobrien	URAL_DEV(GIGABYTE, GNWBKG),
10790075Sobrien	URAL_DEV(GUILLEMOT, HWGUSB254),
10890075Sobrien	URAL_DEV(MELCO, KG54),
10990075Sobrien	URAL_DEV(MELCO, KG54AI),
11090075Sobrien	URAL_DEV(MELCO, KG54YB),
11190075Sobrien	URAL_DEV(MELCO, NINWIFI),
11290075Sobrien	URAL_DEV(MSI, RT2570),
11318334Speter	URAL_DEV(MSI, RT2570_2),
11490075Sobrien	URAL_DEV(MSI, RT2570_3),
11590075Sobrien	URAL_DEV(NOVATECH, NV902),
11690075Sobrien	URAL_DEV(RALINK, RT2570),
11790075Sobrien	URAL_DEV(RALINK, RT2570_2),
11890075Sobrien	URAL_DEV(RALINK, RT2570_3),
11990075Sobrien	URAL_DEV(SIEMENS2, WL54G),
12090075Sobrien	URAL_DEV(SMC, 2862WG),
12190075Sobrien	URAL_DEV(SPHAIRON, UB801R),
12290075Sobrien	URAL_DEV(SURECOM, RT2570),
12390075Sobrien	URAL_DEV(VTECH, RT2570),
12490075Sobrien	URAL_DEV(ZINWELL, RT2570),
12590075Sobrien#undef URAL_DEV
12690075Sobrien};
12790075Sobrien
12890075Sobrienstatic usb_callback_t ural_bulk_read_callback;
12990075Sobrienstatic usb_callback_t ural_bulk_write_callback;
13090075Sobrien
13190075Sobrienstatic usb_error_t	ural_do_request(struct ural_softc *sc,
13218334Speter			    struct usb_device_request *req, void *data);
13318334Speterstatic struct ieee80211vap *ural_vap_create(struct ieee80211com *,
13418334Speter			    const char name[IFNAMSIZ], int unit, int opmode,
13518334Speter			    int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
13618334Speter			    const uint8_t mac[IEEE80211_ADDR_LEN]);
13718334Speterstatic void		ural_vap_delete(struct ieee80211vap *);
13818334Speterstatic void		ural_tx_free(struct ural_tx_data *, int);
13918334Speterstatic void		ural_setup_tx_list(struct ural_softc *);
14018334Speterstatic void		ural_unsetup_tx_list(struct ural_softc *);
14118334Speterstatic int		ural_newstate(struct ieee80211vap *,
14218334Speter			    enum ieee80211_state, int);
14318334Speterstatic void		ural_setup_tx_desc(struct ural_softc *,
14418334Speter			    struct ural_tx_desc *, uint32_t, int, int);
14518334Speterstatic int		ural_tx_bcn(struct ural_softc *, struct mbuf *,
14618334Speter			    struct ieee80211_node *);
14718334Speterstatic int		ural_tx_mgt(struct ural_softc *, struct mbuf *,
14818334Speter			    struct ieee80211_node *);
14918334Speterstatic int		ural_tx_data(struct ural_softc *, struct mbuf *,
15090075Sobrien			    struct ieee80211_node *);
15190075Sobrienstatic void		ural_start(struct ifnet *);
15218334Speterstatic int		ural_ioctl(struct ifnet *, u_long, caddr_t);
15318334Speterstatic void		ural_set_testmode(struct ural_softc *);
15418334Speterstatic void		ural_eeprom_read(struct ural_softc *, uint16_t, void *,
15518334Speter			    int);
15618334Speterstatic uint16_t		ural_read(struct ural_softc *, uint16_t);
15718334Speterstatic void		ural_read_multi(struct ural_softc *, uint16_t, void *,
15890075Sobrien			    int);
15990075Sobrienstatic void		ural_write(struct ural_softc *, uint16_t, uint16_t);
16090075Sobrienstatic void		ural_write_multi(struct ural_softc *, uint16_t, void *,
16190075Sobrien			    int) __unused;
16290075Sobrienstatic void		ural_bbp_write(struct ural_softc *, uint8_t, uint8_t);
16390075Sobrienstatic uint8_t		ural_bbp_read(struct ural_softc *, uint8_t);
16490075Sobrienstatic void		ural_rf_write(struct ural_softc *, uint8_t, uint32_t);
16590075Sobrienstatic void		ural_scan_start(struct ieee80211com *);
16690075Sobrienstatic void		ural_scan_end(struct ieee80211com *);
16790075Sobrienstatic void		ural_set_channel(struct ieee80211com *);
16890075Sobrienstatic void		ural_set_chan(struct ural_softc *,
16918334Speter			    struct ieee80211_channel *);
17018334Speterstatic void		ural_disable_rf_tune(struct ural_softc *);
17118334Speterstatic void		ural_enable_tsf_sync(struct ural_softc *);
17218334Speterstatic void 		ural_enable_tsf(struct ural_softc *);
17318334Speterstatic void		ural_update_slot(struct ifnet *);
17418334Speterstatic void		ural_set_txpreamble(struct ural_softc *);
17518334Speterstatic void		ural_set_basicrates(struct ural_softc *,
17690075Sobrien			    const struct ieee80211_channel *);
17718334Speterstatic void		ural_set_bssid(struct ural_softc *, const uint8_t *);
17818334Speterstatic void		ural_set_macaddr(struct ural_softc *, uint8_t *);
17918334Speterstatic void		ural_update_promisc(struct ifnet *);
18018334Speterstatic void		ural_setpromisc(struct ural_softc *);
18118334Speterstatic const char	*ural_get_rf(int);
18290075Sobrienstatic void		ural_read_eeprom(struct ural_softc *);
18318334Speterstatic int		ural_bbp_init(struct ural_softc *);
18490075Sobrienstatic void		ural_set_txantenna(struct ural_softc *, int);
18590075Sobrienstatic void		ural_set_rxantenna(struct ural_softc *, int);
18690075Sobrienstatic void		ural_init_locked(struct ural_softc *);
18790075Sobrienstatic void		ural_init(void *);
18818334Speterstatic void		ural_stop(struct ural_softc *);
18990075Sobrienstatic int		ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
19018334Speter			    const struct ieee80211_bpf_params *);
19118334Speterstatic void		ural_ratectl_start(struct ural_softc *,
19218334Speter			    struct ieee80211_node *);
19318334Speterstatic void		ural_ratectl_timeout(void *);
19418334Speterstatic void		ural_ratectl_task(void *, int);
19518334Speterstatic int		ural_pause(struct ural_softc *sc, int timeout);
19618334Speter
19718334Speter/*
19818334Speter * Default values for MAC registers; values taken from the reference driver.
19918334Speter */
20018334Speterstatic const struct {
20118334Speter	uint16_t	reg;
20218334Speter	uint16_t	val;
20318334Speter} ural_def_mac[] = {
20418334Speter	{ RAL_TXRX_CSR5,  0x8c8d },
20518334Speter	{ RAL_TXRX_CSR6,  0x8b8a },
20618334Speter	{ RAL_TXRX_CSR7,  0x8687 },
20718334Speter	{ RAL_TXRX_CSR8,  0x0085 },
20818334Speter	{ RAL_MAC_CSR13,  0x1111 },
20990075Sobrien	{ RAL_MAC_CSR14,  0x1e11 },
21018334Speter	{ RAL_TXRX_CSR21, 0xe78f },
21190075Sobrien	{ RAL_MAC_CSR9,   0xff1d },
21218334Speter	{ RAL_MAC_CSR11,  0x0002 },
21318334Speter	{ RAL_MAC_CSR22,  0x0053 },
21418334Speter	{ RAL_MAC_CSR15,  0x0000 },
21518334Speter	{ RAL_MAC_CSR8,   RAL_FRAME_SIZE },
21618334Speter	{ RAL_TXRX_CSR19, 0x0000 },
21790075Sobrien	{ RAL_TXRX_CSR18, 0x005a },
21818334Speter	{ RAL_PHY_CSR2,   0x0000 },
21918334Speter	{ RAL_TXRX_CSR0,  0x1ec0 },
22018334Speter	{ RAL_PHY_CSR4,   0x000f }
22118334Speter};
22218334Speter
22390075Sobrien/*
22490075Sobrien * Default values for BBP registers; values taken from the reference driver.
22590075Sobrien */
22690075Sobrienstatic const struct {
22790075Sobrien	uint8_t	reg;
22890075Sobrien	uint8_t	val;
22990075Sobrien} ural_def_bbp[] = {
23090075Sobrien	{  3, 0x02 },
23190075Sobrien	{  4, 0x19 },
23290075Sobrien	{ 14, 0x1c },
23390075Sobrien	{ 15, 0x30 },
23490075Sobrien	{ 16, 0xac },
23590075Sobrien	{ 17, 0x48 },
23690075Sobrien	{ 18, 0x18 },
23790075Sobrien	{ 19, 0xff },
23890075Sobrien	{ 20, 0x1e },
23990075Sobrien	{ 21, 0x08 },
24090075Sobrien	{ 22, 0x08 },
24118334Speter	{ 23, 0x08 },
24218334Speter	{ 24, 0x80 },
24318334Speter	{ 25, 0x50 },
24452284Sobrien	{ 26, 0x08 },
24518334Speter	{ 27, 0x23 },
24618334Speter	{ 30, 0x10 },
24718334Speter	{ 31, 0x2b },
24818334Speter	{ 32, 0xb9 },
24990075Sobrien	{ 34, 0x12 },
25018334Speter	{ 35, 0x50 },
25118334Speter	{ 39, 0xc4 },
25218334Speter	{ 40, 0x02 },
25318334Speter	{ 41, 0x60 },
25418334Speter	{ 53, 0x10 },
25590075Sobrien	{ 54, 0x18 },
25618334Speter	{ 56, 0x08 },
25718334Speter	{ 57, 0x10 },
25818334Speter	{ 58, 0x08 },
25918334Speter	{ 61, 0x60 },
26018334Speter	{ 62, 0x10 },
26152284Sobrien	{ 75, 0xff }
26252284Sobrien};
26352284Sobrien
26452284Sobrien/*
26552284Sobrien * Default values for RF register R2 indexed by channel numbers.
26652284Sobrien */
26752284Sobrienstatic const uint32_t ural_rf2522_r2[] = {
26852284Sobrien	0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814,
26952284Sobrien	0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e
27052284Sobrien};
27152284Sobrien
27252284Sobrienstatic const uint32_t ural_rf2523_r2[] = {
27352284Sobrien	0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
27452284Sobrien	0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
27552284Sobrien};
27690075Sobrien
27790075Sobrienstatic const uint32_t ural_rf2524_r2[] = {
27852284Sobrien	0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
27952284Sobrien	0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
28052284Sobrien};
28152284Sobrien
28252284Sobrienstatic const uint32_t ural_rf2525_r2[] = {
28352284Sobrien	0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d,
28452284Sobrien	0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346
28590075Sobrien};
28690075Sobrien
28752284Sobrienstatic const uint32_t ural_rf2525_hi_r2[] = {
28852284Sobrien	0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345,
28990075Sobrien	0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e
29052284Sobrien};
29152284Sobrien
29252284Sobrienstatic const uint32_t ural_rf2525e_r2[] = {
29352284Sobrien	0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463,
29452284Sobrien	0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b
29590075Sobrien};
29690075Sobrien
29718334Speterstatic const uint32_t ural_rf2526_hi_r2[] = {
29818334Speter	0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d,
29918334Speter	0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241
30018334Speter};
30118334Speter
30218334Speterstatic const uint32_t ural_rf2526_r2[] = {
30390075Sobrien	0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229,
30490075Sobrien	0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d
30590075Sobrien};
30618334Speter
30790075Sobrien/*
30890075Sobrien * For dual-band RF, RF registers R1 and R4 also depend on channel number;
30990075Sobrien * values taken from the reference driver.
31090075Sobrien */
31190075Sobrienstatic const struct {
31290075Sobrien	uint8_t		chan;
31390075Sobrien	uint32_t	r1;
31490075Sobrien	uint32_t	r2;
31590075Sobrien	uint32_t	r4;
31690075Sobrien} ural_rf5222[] = {
31790075Sobrien	{   1, 0x08808, 0x0044d, 0x00282 },
31890075Sobrien	{   2, 0x08808, 0x0044e, 0x00282 },
31918334Speter	{   3, 0x08808, 0x0044f, 0x00282 },
32018334Speter	{   4, 0x08808, 0x00460, 0x00282 },
32118334Speter	{   5, 0x08808, 0x00461, 0x00282 },
32218334Speter	{   6, 0x08808, 0x00462, 0x00282 },
32318334Speter	{   7, 0x08808, 0x00463, 0x00282 },
32418334Speter	{   8, 0x08808, 0x00464, 0x00282 },
32518334Speter	{   9, 0x08808, 0x00465, 0x00282 },
32618334Speter	{  10, 0x08808, 0x00466, 0x00282 },
32718334Speter	{  11, 0x08808, 0x00467, 0x00282 },
32818334Speter	{  12, 0x08808, 0x00468, 0x00282 },
32918334Speter	{  13, 0x08808, 0x00469, 0x00282 },
33018334Speter	{  14, 0x08808, 0x0046b, 0x00286 },
33118334Speter
33218334Speter	{  36, 0x08804, 0x06225, 0x00287 },
33318334Speter	{  40, 0x08804, 0x06226, 0x00287 },
33418334Speter	{  44, 0x08804, 0x06227, 0x00287 },
33518334Speter	{  48, 0x08804, 0x06228, 0x00287 },
33690075Sobrien	{  52, 0x08804, 0x06229, 0x00287 },
33718334Speter	{  56, 0x08804, 0x0622a, 0x00287 },
33890075Sobrien	{  60, 0x08804, 0x0622b, 0x00287 },
33990075Sobrien	{  64, 0x08804, 0x0622c, 0x00287 },
34018334Speter
34118334Speter	{ 100, 0x08804, 0x02200, 0x00283 },
34218334Speter	{ 104, 0x08804, 0x02201, 0x00283 },
34390075Sobrien	{ 108, 0x08804, 0x02202, 0x00283 },
34490075Sobrien	{ 112, 0x08804, 0x02203, 0x00283 },
34518334Speter	{ 116, 0x08804, 0x02204, 0x00283 },
34618334Speter	{ 120, 0x08804, 0x02205, 0x00283 },
34718334Speter	{ 124, 0x08804, 0x02206, 0x00283 },
34890075Sobrien	{ 128, 0x08804, 0x02207, 0x00283 },
34918334Speter	{ 132, 0x08804, 0x02208, 0x00283 },
35090075Sobrien	{ 136, 0x08804, 0x02209, 0x00283 },
35190075Sobrien	{ 140, 0x08804, 0x0220a, 0x00283 },
35290075Sobrien
35390075Sobrien	{ 149, 0x08808, 0x02429, 0x00281 },
35490075Sobrien	{ 153, 0x08808, 0x0242b, 0x00281 },
35590075Sobrien	{ 157, 0x08808, 0x0242d, 0x00281 },
35690075Sobrien	{ 161, 0x08808, 0x0242f, 0x00281 }
35790075Sobrien};
35890075Sobrien
35918334Speterstatic const struct usb_config ural_config[URAL_N_TRANSFER] = {
36018334Speter	[URAL_BULK_WR] = {
36190075Sobrien		.type = UE_BULK,
36290075Sobrien		.endpoint = UE_ADDR_ANY,
36390075Sobrien		.direction = UE_DIR_OUT,
36418334Speter		.bufsize = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE + 4),
36518334Speter		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
36690075Sobrien		.callback = ural_bulk_write_callback,
36790075Sobrien		.timeout = 5000,	/* ms */
36890075Sobrien	},
36990075Sobrien	[URAL_BULK_RD] = {
37090075Sobrien		.type = UE_BULK,
37190075Sobrien		.endpoint = UE_ADDR_ANY,
37290075Sobrien		.direction = UE_DIR_IN,
37318334Speter		.bufsize = (RAL_FRAME_SIZE + RAL_RX_DESC_SIZE),
37418334Speter		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
37518334Speter		.callback = ural_bulk_read_callback,
37618334Speter	},
37790075Sobrien};
37890075Sobrien
37990075Sobrienstatic device_probe_t ural_match;
38090075Sobrienstatic device_attach_t ural_attach;
38190075Sobrienstatic device_detach_t ural_detach;
38290075Sobrien
38390075Sobrienstatic device_method_t ural_methods[] = {
38490075Sobrien	/* Device interface */
38518334Speter	DEVMETHOD(device_probe,		ural_match),
38690075Sobrien	DEVMETHOD(device_attach,	ural_attach),
38718334Speter	DEVMETHOD(device_detach,	ural_detach),
38818334Speter
38918334Speter	{ 0, 0 }
39018334Speter};
39190075Sobrien
39290075Sobrienstatic driver_t ural_driver = {
39390075Sobrien	.name = "ural",
39490075Sobrien	.methods = ural_methods,
39590075Sobrien	.size = sizeof(struct ural_softc),
39690075Sobrien};
39790075Sobrien
39890075Sobrienstatic devclass_t ural_devclass;
39990075Sobrien
40090075SobrienDRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, NULL, 0);
40190075SobrienMODULE_DEPEND(ural, usb, 1, 1, 1);
40290075SobrienMODULE_DEPEND(ural, wlan, 1, 1, 1);
40390075Sobrien
40490075Sobrienstatic int
40518334Speterural_match(device_t self)
40618334Speter{
40790075Sobrien	struct usb_attach_arg *uaa = device_get_ivars(self);
40890075Sobrien
40990075Sobrien	if (uaa->usb_mode != USB_MODE_HOST)
41090075Sobrien		return (ENXIO);
41118334Speter	if (uaa->info.bConfigIndex != 0)
41250397Sobrien		return (ENXIO);
41350397Sobrien	if (uaa->info.bIfaceIndex != RAL_IFACE_INDEX)
41418334Speter		return (ENXIO);
41590075Sobrien
41690075Sobrien	return (usbd_lookup_id_by_uaa(ural_devs, sizeof(ural_devs), uaa));
41718334Speter}
41890075Sobrien
41918334Speterstatic int
42090075Sobrienural_attach(device_t self)
42118334Speter{
42218334Speter	struct usb_attach_arg *uaa = device_get_ivars(self);
42318334Speter	struct ural_softc *sc = device_get_softc(self);
42418334Speter	struct ifnet *ifp;
42518334Speter	struct ieee80211com *ic;
42618334Speter	uint8_t iface_index, bands;
42750397Sobrien	int error;
42890075Sobrien
42990075Sobrien	device_set_usb_desc(self);
43090075Sobrien	sc->sc_udev = uaa->device;
43190075Sobrien	sc->sc_dev = self;
43290075Sobrien
43350397Sobrien	mtx_init(&sc->sc_mtx, device_get_nameunit(self),
43450397Sobrien	    MTX_NETWORK_LOCK, MTX_DEF);
43518334Speter
43618334Speter	iface_index = RAL_IFACE_INDEX;
43718334Speter	error = usbd_transfer_setup(uaa->device,
43890075Sobrien	    &iface_index, sc->sc_xfer, ural_config,
43990075Sobrien	    URAL_N_TRANSFER, sc, &sc->sc_mtx);
44090075Sobrien	if (error) {
44190075Sobrien		device_printf(self, "could not allocate USB transfers, "
44290075Sobrien		    "err=%s\n", usbd_errstr(error));
44390075Sobrien		goto detach;
44490075Sobrien	}
44590075Sobrien
44690075Sobrien	RAL_LOCK(sc);
44790075Sobrien	/* retrieve RT2570 rev. no */
44890075Sobrien	sc->asic_rev = ural_read(sc, RAL_MAC_CSR0);
44990075Sobrien
45090075Sobrien	/* retrieve MAC address and various other things from EEPROM */
45190075Sobrien	ural_read_eeprom(sc);
45290075Sobrien	RAL_UNLOCK(sc);
45390075Sobrien
45490075Sobrien	device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
45590075Sobrien	    sc->asic_rev, ural_get_rf(sc->rf_rev));
45690075Sobrien
45790075Sobrien	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
45890075Sobrien	if (ifp == NULL) {
45990075Sobrien		device_printf(sc->sc_dev, "can not if_alloc()\n");
46090075Sobrien		goto detach;
46118334Speter	}
46218334Speter	ic = ifp->if_l2com;
46390075Sobrien
46490075Sobrien	ifp->if_softc = sc;
46518334Speter	if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
46690075Sobrien	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
46718334Speter	ifp->if_init = ural_init;
46890075Sobrien	ifp->if_ioctl = ural_ioctl;
46990075Sobrien	ifp->if_start = ural_start;
47090075Sobrien	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
47190075Sobrien	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
47290075Sobrien	IFQ_SET_READY(&ifp->if_snd);
47390075Sobrien
47418334Speter	ic->ic_ifp = ifp;
47590075Sobrien	ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
47690075Sobrien
47790075Sobrien	/* set device capabilities */
47890075Sobrien	ic->ic_caps =
47990075Sobrien	      IEEE80211_C_STA		/* station mode supported */
48090075Sobrien	    | IEEE80211_C_IBSS		/* IBSS mode supported */
48190075Sobrien	    | IEEE80211_C_MONITOR	/* monitor mode supported */
48290075Sobrien	    | IEEE80211_C_HOSTAP	/* HostAp mode supported */
48390075Sobrien	    | IEEE80211_C_TXPMGT	/* tx power management */
48490075Sobrien	    | IEEE80211_C_SHPREAMBLE	/* short preamble supported */
48518334Speter	    | IEEE80211_C_SHSLOT	/* short slot time supported */
48690075Sobrien	    | IEEE80211_C_BGSCAN	/* bg scanning supported */
48790075Sobrien	    | IEEE80211_C_WPA		/* 802.11i */
48818334Speter	    | IEEE80211_C_RATECTL	/* use ratectl */
48990075Sobrien	    ;
49090075Sobrien
49190075Sobrien	bands = 0;
49290075Sobrien	setbit(&bands, IEEE80211_MODE_11B);
49390075Sobrien	setbit(&bands, IEEE80211_MODE_11G);
49490075Sobrien	if (sc->rf_rev == RAL_RF_5222)
49590075Sobrien		setbit(&bands, IEEE80211_MODE_11A);
49690075Sobrien	ieee80211_init_channels(ic, NULL, &bands);
49790075Sobrien
49850397Sobrien	ieee80211_ifattach(ic, sc->sc_bssid);
49950397Sobrien	ic->ic_update_promisc = ural_update_promisc;
50090075Sobrien	ic->ic_raw_xmit = ural_raw_xmit;
50190075Sobrien	ic->ic_scan_start = ural_scan_start;
50250397Sobrien	ic->ic_scan_end = ural_scan_end;
50318334Speter	ic->ic_set_channel = ural_set_channel;
50490075Sobrien
50590075Sobrien	ic->ic_vap_create = ural_vap_create;
50690075Sobrien	ic->ic_vap_delete = ural_vap_delete;
50790075Sobrien
50890075Sobrien	ieee80211_radiotap_attach(ic,
50990075Sobrien	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
51090075Sobrien		RAL_TX_RADIOTAP_PRESENT,
51190075Sobrien	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
51290075Sobrien		RAL_RX_RADIOTAP_PRESENT);
51390075Sobrien
51490075Sobrien	if (bootverbose)
51590075Sobrien		ieee80211_announce(ic);
51690075Sobrien
51790075Sobrien	return (0);
51890075Sobrien
51990075Sobriendetach:
52090075Sobrien	ural_detach(self);
52190075Sobrien	return (ENXIO);			/* failure */
52290075Sobrien}
52390075Sobrien
52490075Sobrienstatic int
52590075Sobrienural_detach(device_t self)
52690075Sobrien{
52790075Sobrien	struct ural_softc *sc = device_get_softc(self);
52890075Sobrien	struct ifnet *ifp = sc->sc_ifp;
52990075Sobrien	struct ieee80211com *ic;
53090075Sobrien
53190075Sobrien	/* stop all USB transfers */
53290075Sobrien	usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
53390075Sobrien
53490075Sobrien	/* free TX list, if any */
53590075Sobrien	RAL_LOCK(sc);
53690075Sobrien	ural_unsetup_tx_list(sc);
53790075Sobrien	RAL_UNLOCK(sc);
53890075Sobrien
53990075Sobrien	if (ifp) {
54090075Sobrien		ic = ifp->if_l2com;
54190075Sobrien		ieee80211_ifdetach(ic);
54290075Sobrien		if_free(ifp);
54390075Sobrien	}
54490075Sobrien	mtx_destroy(&sc->sc_mtx);
54590075Sobrien
54690075Sobrien	return (0);
54790075Sobrien}
54890075Sobrien
54990075Sobrienstatic usb_error_t
55090075Sobrienural_do_request(struct ural_softc *sc,
55190075Sobrien    struct usb_device_request *req, void *data)
55290075Sobrien{
55390075Sobrien	usb_error_t err;
55490075Sobrien	int ntries = 10;
55590075Sobrien
55690075Sobrien	while (ntries--) {
55790075Sobrien		err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx,
55890075Sobrien		    req, data, 0, NULL, 250 /* ms */);
55990075Sobrien		if (err == 0)
56090075Sobrien			break;
56190075Sobrien
56290075Sobrien		DPRINTFN(1, "Control request failed, %s (retrying)\n",
56390075Sobrien		    usbd_errstr(err));
56490075Sobrien		if (ural_pause(sc, hz / 100))
56590075Sobrien			break;
56690075Sobrien	}
56790075Sobrien	return (err);
56890075Sobrien}
56990075Sobrien
57090075Sobrienstatic struct ieee80211vap *
57190075Sobrienural_vap_create(struct ieee80211com *ic,
57290075Sobrien	const char name[IFNAMSIZ], int unit, int opmode, int flags,
57390075Sobrien	const uint8_t bssid[IEEE80211_ADDR_LEN],
57490075Sobrien	const uint8_t mac[IEEE80211_ADDR_LEN])
57590075Sobrien{
57690075Sobrien	struct ural_softc *sc = ic->ic_ifp->if_softc;
57790075Sobrien	struct ural_vap *uvp;
57818334Speter	struct ieee80211vap *vap;
57990075Sobrien
58090075Sobrien	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
58118334Speter		return NULL;
58290075Sobrien	uvp = (struct ural_vap *) malloc(sizeof(struct ural_vap),
58390075Sobrien	    M_80211_VAP, M_NOWAIT | M_ZERO);
58490075Sobrien	if (uvp == NULL)
58590075Sobrien		return NULL;
58690075Sobrien	vap = &uvp->vap;
58790075Sobrien	/* enable s/w bmiss handling for sta mode */
58890075Sobrien	ieee80211_vap_setup(ic, vap, name, unit, opmode,
58990075Sobrien	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
59090075Sobrien
59118334Speter	/* override state transition machine */
59290075Sobrien	uvp->newstate = vap->iv_newstate;
59318334Speter	vap->iv_newstate = ural_newstate;
59490075Sobrien
59590075Sobrien	usb_callout_init_mtx(&uvp->ratectl_ch, &sc->sc_mtx, 0);
59690075Sobrien	TASK_INIT(&uvp->ratectl_task, 0, ural_ratectl_task, uvp);
59790075Sobrien	ieee80211_ratectl_init(vap);
59890075Sobrien	ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
59990075Sobrien
60090075Sobrien	/* complete setup */
60190075Sobrien	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
60290075Sobrien	ic->ic_opmode = opmode;
60390075Sobrien	return vap;
60490075Sobrien}
60590075Sobrien
60690075Sobrienstatic void
60790075Sobrienural_vap_delete(struct ieee80211vap *vap)
60890075Sobrien{
60990075Sobrien	struct ural_vap *uvp = URAL_VAP(vap);
61090075Sobrien	struct ieee80211com *ic = vap->iv_ic;
61190075Sobrien
61290075Sobrien	usb_callout_drain(&uvp->ratectl_ch);
61390075Sobrien	ieee80211_draintask(ic, &uvp->ratectl_task);
61490075Sobrien	ieee80211_ratectl_deinit(vap);
61590075Sobrien	ieee80211_vap_detach(vap);
61690075Sobrien	free(uvp, M_80211_VAP);
61790075Sobrien}
61890075Sobrien
61990075Sobrienstatic void
62090075Sobrienural_tx_free(struct ural_tx_data *data, int txerr)
62190075Sobrien{
62290075Sobrien	struct ural_softc *sc = data->sc;
62390075Sobrien
62490075Sobrien	if (data->m != NULL) {
62590075Sobrien		if (data->m->m_flags & M_TXCB)
62690075Sobrien			ieee80211_process_callback(data->ni, data->m,
62790075Sobrien			    txerr ? ETIMEDOUT : 0);
62890075Sobrien		m_freem(data->m);
62990075Sobrien		data->m = NULL;
63090075Sobrien
63190075Sobrien		ieee80211_free_node(data->ni);
63290075Sobrien		data->ni = NULL;
63390075Sobrien	}
63490075Sobrien	STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
63590075Sobrien	sc->tx_nfree++;
63690075Sobrien}
63790075Sobrien
63890075Sobrienstatic void
63990075Sobrienural_setup_tx_list(struct ural_softc *sc)
64090075Sobrien{
64190075Sobrien	struct ural_tx_data *data;
64290075Sobrien	int i;
64390075Sobrien
64490075Sobrien	sc->tx_nfree = 0;
64590075Sobrien	STAILQ_INIT(&sc->tx_q);
64690075Sobrien	STAILQ_INIT(&sc->tx_free);
64790075Sobrien
64890075Sobrien	for (i = 0; i < RAL_TX_LIST_COUNT; i++) {
64990075Sobrien		data = &sc->tx_data[i];
65090075Sobrien
65190075Sobrien		data->sc = sc;
65290075Sobrien		STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
65390075Sobrien		sc->tx_nfree++;
65490075Sobrien	}
65590075Sobrien}
65690075Sobrien
65790075Sobrienstatic void
65890075Sobrienural_unsetup_tx_list(struct ural_softc *sc)
65990075Sobrien{
66018334Speter	struct ural_tx_data *data;
66190075Sobrien	int i;
66290075Sobrien
66390075Sobrien	/* make sure any subsequent use of the queues will fail */
66490075Sobrien	sc->tx_nfree = 0;
66590075Sobrien	STAILQ_INIT(&sc->tx_q);
66690075Sobrien	STAILQ_INIT(&sc->tx_free);
66718334Speter
66890075Sobrien	/* free up all node references and mbufs */
66950397Sobrien	for (i = 0; i < RAL_TX_LIST_COUNT; i++) {
67090075Sobrien		data = &sc->tx_data[i];
67150397Sobrien
67218334Speter		if (data->m != NULL) {
67390075Sobrien			m_freem(data->m);
67418334Speter			data->m = NULL;
67590075Sobrien		}
67690075Sobrien		if (data->ni != NULL) {
67790075Sobrien			ieee80211_free_node(data->ni);
67818334Speter			data->ni = NULL;
67990075Sobrien		}
68090075Sobrien	}
68190075Sobrien}
68290075Sobrien
68390075Sobrienstatic int
68490075Sobrienural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
68590075Sobrien{
68690075Sobrien	struct ural_vap *uvp = URAL_VAP(vap);
68790075Sobrien	struct ieee80211com *ic = vap->iv_ic;
68890075Sobrien	struct ural_softc *sc = ic->ic_ifp->if_softc;
68918334Speter	const struct ieee80211_txparam *tp;
69018334Speter	struct ieee80211_node *ni;
69190075Sobrien	struct mbuf *m;
69290075Sobrien
69390075Sobrien	DPRINTF("%s -> %s\n",
69490075Sobrien		ieee80211_state_name[vap->iv_state],
69590075Sobrien		ieee80211_state_name[nstate]);
69690075Sobrien
69790075Sobrien	IEEE80211_UNLOCK(ic);
69890075Sobrien	RAL_LOCK(sc);
69990075Sobrien	usb_callout_stop(&uvp->ratectl_ch);
70018334Speter
70190075Sobrien	switch (nstate) {
70290075Sobrien	case IEEE80211_S_INIT:
70390075Sobrien		if (vap->iv_state == IEEE80211_S_RUN) {
70490075Sobrien			/* abort TSF synchronization */
70518334Speter			ural_write(sc, RAL_TXRX_CSR19, 0);
70690075Sobrien
70790075Sobrien			/* force tx led to stop blinking */
70890075Sobrien			ural_write(sc, RAL_MAC_CSR20, 0);
70990075Sobrien		}
71090075Sobrien		break;
71190075Sobrien
71290075Sobrien	case IEEE80211_S_RUN:
71390075Sobrien		ni = vap->iv_bss;
71490075Sobrien
71590075Sobrien		if (vap->iv_opmode != IEEE80211_M_MONITOR) {
71690075Sobrien			ural_update_slot(ic->ic_ifp);
71790075Sobrien			ural_set_txpreamble(sc);
71890075Sobrien			ural_set_basicrates(sc, ic->ic_bsschan);
71990075Sobrien			IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
72090075Sobrien			ural_set_bssid(sc, sc->sc_bssid);
72190075Sobrien		}
72290075Sobrien
72318334Speter		if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
72490075Sobrien		    vap->iv_opmode == IEEE80211_M_IBSS) {
72590075Sobrien			m = ieee80211_beacon_alloc(ni, &uvp->bo);
72690075Sobrien			if (m == NULL) {
72790075Sobrien				device_printf(sc->sc_dev,
72890075Sobrien				    "could not allocate beacon\n");
72990075Sobrien				RAL_UNLOCK(sc);
73090075Sobrien				IEEE80211_LOCK(ic);
73190075Sobrien				return (-1);
73290075Sobrien			}
73390075Sobrien			ieee80211_ref_node(ni);
73418334Speter			if (ural_tx_bcn(sc, m, ni) != 0) {
73590075Sobrien				device_printf(sc->sc_dev,
73690075Sobrien				    "could not send beacon\n");
73790075Sobrien				RAL_UNLOCK(sc);
73890075Sobrien				IEEE80211_LOCK(ic);
73990075Sobrien				return (-1);
74090075Sobrien			}
74190075Sobrien		}
74290075Sobrien
74390075Sobrien		/* make tx led blink on tx (controlled by ASIC) */
74490075Sobrien		ural_write(sc, RAL_MAC_CSR20, 1);
74590075Sobrien
74690075Sobrien		if (vap->iv_opmode != IEEE80211_M_MONITOR)
74790075Sobrien			ural_enable_tsf_sync(sc);
74890075Sobrien		else
74990075Sobrien			ural_enable_tsf(sc);
75090075Sobrien
75190075Sobrien		/* enable automatic rate adaptation */
75290075Sobrien		/* XXX should use ic_bsschan but not valid until after newstate call below */
75390075Sobrien		tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
75490075Sobrien		if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
75590075Sobrien			ural_ratectl_start(sc, ni);
75690075Sobrien
75790075Sobrien		break;
75890075Sobrien
75990075Sobrien	default:
76090075Sobrien		break;
76190075Sobrien	}
76290075Sobrien	RAL_UNLOCK(sc);
76390075Sobrien	IEEE80211_LOCK(ic);
76490075Sobrien	return (uvp->newstate(vap, nstate, arg));
76590075Sobrien}
76690075Sobrien
76790075Sobrien
76890075Sobrienstatic void
76990075Sobrienural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
77090075Sobrien{
77190075Sobrien	struct ural_softc *sc = usbd_xfer_softc(xfer);
77290075Sobrien	struct ifnet *ifp = sc->sc_ifp;
77390075Sobrien	struct ieee80211vap *vap;
77490075Sobrien	struct ural_tx_data *data;
77590075Sobrien	struct mbuf *m;
77690075Sobrien	struct usb_page_cache *pc;
77790075Sobrien	int len;
77890075Sobrien
77990075Sobrien	usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
78090075Sobrien
78118334Speter	switch (USB_GET_STATE(xfer)) {
78218334Speter	case USB_ST_TRANSFERRED:
78390075Sobrien		DPRINTFN(11, "transfer complete, %d bytes\n", len);
78490075Sobrien
78590075Sobrien		/* free resources */
78690075Sobrien		data = usbd_xfer_get_priv(xfer);
78790075Sobrien		ural_tx_free(data, 0);
78890075Sobrien		usbd_xfer_set_priv(xfer, NULL);
78990075Sobrien
79090075Sobrien		ifp->if_opackets++;
79190075Sobrien		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
79290075Sobrien
79390075Sobrien		/* FALLTHROUGH */
79490075Sobrien	case USB_ST_SETUP:
79590075Sobrientr_setup:
79690075Sobrien		data = STAILQ_FIRST(&sc->tx_q);
79790075Sobrien		if (data) {
79890075Sobrien			STAILQ_REMOVE_HEAD(&sc->tx_q, next);
79990075Sobrien			m = data->m;
80090075Sobrien
80190075Sobrien			if (m->m_pkthdr.len > (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE)) {
80290075Sobrien				DPRINTFN(0, "data overflow, %u bytes\n",
80390075Sobrien				    m->m_pkthdr.len);
80490075Sobrien				m->m_pkthdr.len = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE);
80590075Sobrien			}
80690075Sobrien			pc = usbd_xfer_get_frame(xfer, 0);
80718334Speter			usbd_copy_in(pc, 0, &data->desc, RAL_TX_DESC_SIZE);
80890075Sobrien			usbd_m_copy_in(pc, RAL_TX_DESC_SIZE, m, 0,
80918334Speter			    m->m_pkthdr.len);
81018334Speter
81118334Speter			vap = data->ni->ni_vap;
81250397Sobrien			if (ieee80211_radiotap_active_vap(vap)) {
81318334Speter				struct ural_tx_radiotap_header *tap = &sc->sc_txtap;
81418334Speter
81590075Sobrien				tap->wt_flags = 0;
81690075Sobrien				tap->wt_rate = data->rate;
81790075Sobrien				tap->wt_antenna = sc->tx_ant;
81890075Sobrien
81918334Speter				ieee80211_radiotap_tx(vap, m);
82090075Sobrien			}
82190075Sobrien
82218334Speter			/* xfer length needs to be a multiple of two! */
82390075Sobrien			len = (RAL_TX_DESC_SIZE + m->m_pkthdr.len + 1) & ~1;
82490075Sobrien			if ((len % 64) == 0)
82590075Sobrien				len += 2;
82690075Sobrien
82790075Sobrien			DPRINTFN(11, "sending frame len=%u xferlen=%u\n",
82818334Speter			    m->m_pkthdr.len, len);
82990075Sobrien
83090075Sobrien			usbd_xfer_set_frame_len(xfer, 0, len);
83190075Sobrien			usbd_xfer_set_priv(xfer, data);
83290075Sobrien
83390075Sobrien			usbd_transfer_submit(xfer);
83490075Sobrien		}
83590075Sobrien		RAL_UNLOCK(sc);
83690075Sobrien		ural_start(ifp);
83790075Sobrien		RAL_LOCK(sc);
83890075Sobrien		break;
83990075Sobrien
84090075Sobrien	default:			/* Error */
84190075Sobrien		DPRINTFN(11, "transfer error, %s\n",
84290075Sobrien		    usbd_errstr(error));
84390075Sobrien
84418334Speter		ifp->if_oerrors++;
84590075Sobrien		data = usbd_xfer_get_priv(xfer);
84690075Sobrien		if (data != NULL) {
84790075Sobrien			ural_tx_free(data, error);
84890075Sobrien			usbd_xfer_set_priv(xfer, NULL);
84990075Sobrien		}
85090075Sobrien
85190075Sobrien		if (error == USB_ERR_STALLED) {
85290075Sobrien			/* try to clear stall first */
85390075Sobrien			usbd_xfer_set_stall(xfer);
85490075Sobrien			goto tr_setup;
85590075Sobrien		}
85690075Sobrien		if (error == USB_ERR_TIMEOUT)
85790075Sobrien			device_printf(sc->sc_dev, "device timeout\n");
85890075Sobrien		break;
85918334Speter	}
86018334Speter}
86190075Sobrien
86290075Sobrienstatic void
86390075Sobrienural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
86490075Sobrien{
86590075Sobrien	struct ural_softc *sc = usbd_xfer_softc(xfer);
86690075Sobrien	struct ifnet *ifp = sc->sc_ifp;
86790075Sobrien	struct ieee80211com *ic = ifp->if_l2com;
86818334Speter	struct ieee80211_node *ni;
86990075Sobrien	struct mbuf *m = NULL;
87018334Speter	struct usb_page_cache *pc;
87118334Speter	uint32_t flags;
87290075Sobrien	int8_t rssi = 0, nf = 0;
87390075Sobrien	int len;
87418334Speter
87590075Sobrien	usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
87618334Speter
87790075Sobrien	switch (USB_GET_STATE(xfer)) {
87890075Sobrien	case USB_ST_TRANSFERRED:
87990075Sobrien
88090075Sobrien		DPRINTFN(15, "rx done, actlen=%d\n", len);
88190075Sobrien
88290075Sobrien		if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) {
88390075Sobrien			DPRINTF("%s: xfer too short %d\n",
88490075Sobrien			    device_get_nameunit(sc->sc_dev), len);
88590075Sobrien			ifp->if_ierrors++;
88690075Sobrien			goto tr_setup;
88790075Sobrien		}
88890075Sobrien
88990075Sobrien		len -= RAL_RX_DESC_SIZE;
89090075Sobrien		/* rx descriptor is located at the end */
89190075Sobrien		pc = usbd_xfer_get_frame(xfer, 0);
89290075Sobrien		usbd_copy_out(pc, len, &sc->sc_rx_desc, RAL_RX_DESC_SIZE);
89390075Sobrien
89490075Sobrien		rssi = URAL_RSSI(sc->sc_rx_desc.rssi);
89590075Sobrien		nf = RAL_NOISE_FLOOR;
89690075Sobrien		flags = le32toh(sc->sc_rx_desc.flags);
89790075Sobrien		if (flags & (RAL_RX_PHY_ERROR | RAL_RX_CRC_ERROR)) {
89890075Sobrien			/*
89990075Sobrien		         * This should not happen since we did not
90090075Sobrien		         * request to receive those frames when we
90190075Sobrien		         * filled RAL_TXRX_CSR2:
90290075Sobrien		         */
90390075Sobrien			DPRINTFN(5, "PHY or CRC error\n");
90490075Sobrien			ifp->if_ierrors++;
90518334Speter			goto tr_setup;
90690075Sobrien		}
90718334Speter
90890075Sobrien		m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
90990075Sobrien		if (m == NULL) {
91090075Sobrien			DPRINTF("could not allocate mbuf\n");
91190075Sobrien			ifp->if_ierrors++;
91290075Sobrien			goto tr_setup;
91390075Sobrien		}
91490075Sobrien		usbd_copy_out(pc, 0, mtod(m, uint8_t *), len);
91590075Sobrien
91690075Sobrien		/* finalize mbuf */
91790075Sobrien		m->m_pkthdr.rcvif = ifp;
91890075Sobrien		m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
91990075Sobrien
92090075Sobrien		if (ieee80211_radiotap_active(ic)) {
92190075Sobrien			struct ural_rx_radiotap_header *tap = &sc->sc_rxtap;
92290075Sobrien
92390075Sobrien			/* XXX set once */
92418334Speter			tap->wr_flags = 0;
92590075Sobrien			tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate,
92690075Sobrien			    (flags & RAL_RX_OFDM) ?
92790075Sobrien			    IEEE80211_T_OFDM : IEEE80211_T_CCK);
92890075Sobrien			tap->wr_antenna = sc->rx_ant;
92990075Sobrien			tap->wr_antsignal = nf + rssi;
93090075Sobrien			tap->wr_antnoise = nf;
93190075Sobrien		}
93290075Sobrien		/* Strip trailing 802.11 MAC FCS. */
93390075Sobrien		m_adj(m, -IEEE80211_CRC_LEN);
93490075Sobrien
93590075Sobrien		/* FALLTHROUGH */
93690075Sobrien	case USB_ST_SETUP:
93790075Sobrientr_setup:
93890075Sobrien		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
93990075Sobrien		usbd_transfer_submit(xfer);
94090075Sobrien
94190075Sobrien		/*
94290075Sobrien		 * At the end of a USB callback it is always safe to unlock
94390075Sobrien		 * the private mutex of a device! That is why we do the
94490075Sobrien		 * "ieee80211_input" here, and not some lines up!
94590075Sobrien		 */
94690075Sobrien		RAL_UNLOCK(sc);
94790075Sobrien		if (m) {
94890075Sobrien			ni = ieee80211_find_rxnode(ic,
94990075Sobrien			    mtod(m, struct ieee80211_frame_min *));
95090075Sobrien			if (ni != NULL) {
95190075Sobrien				(void) ieee80211_input(ni, m, rssi, nf);
95290075Sobrien				ieee80211_free_node(ni);
95390075Sobrien			} else
95490075Sobrien				(void) ieee80211_input_all(ic, m, rssi, nf);
95590075Sobrien		}
95690075Sobrien		if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
95790075Sobrien		    !IFQ_IS_EMPTY(&ifp->if_snd))
95890075Sobrien			ural_start(ifp);
95990075Sobrien		RAL_LOCK(sc);
96090075Sobrien		return;
96190075Sobrien
96290075Sobrien	default:			/* Error */
96390075Sobrien		if (error != USB_ERR_CANCELLED) {
96490075Sobrien			/* try to clear stall first */
96590075Sobrien			usbd_xfer_set_stall(xfer);
96690075Sobrien			goto tr_setup;
96790075Sobrien		}
96890075Sobrien		return;
96990075Sobrien	}
97090075Sobrien}
97190075Sobrien
97290075Sobrienstatic uint8_t
97390075Sobrienural_plcp_signal(int rate)
97490075Sobrien{
97590075Sobrien	switch (rate) {
97690075Sobrien	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
97790075Sobrien	case 12:	return 0xb;
97890075Sobrien	case 18:	return 0xf;
97990075Sobrien	case 24:	return 0xa;
98018334Speter	case 36:	return 0xe;
98190075Sobrien	case 48:	return 0x9;
98290075Sobrien	case 72:	return 0xd;
98390075Sobrien	case 96:	return 0x8;
98490075Sobrien	case 108:	return 0xc;
98590075Sobrien
98690075Sobrien	/* CCK rates (NB: not IEEE std, device-specific) */
98790075Sobrien	case 2:		return 0x0;
98890075Sobrien	case 4:		return 0x1;
98990075Sobrien	case 11:	return 0x2;
99018334Speter	case 22:	return 0x3;
99118334Speter	}
99218334Speter	return 0xff;		/* XXX unsupported/unknown rate */
99390075Sobrien}
99490075Sobrien
99518334Speterstatic void
99690075Sobrienural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
99718334Speter    uint32_t flags, int len, int rate)
99890075Sobrien{
99990075Sobrien	struct ifnet *ifp = sc->sc_ifp;
100090075Sobrien	struct ieee80211com *ic = ifp->if_l2com;
100190075Sobrien	uint16_t plcp_length;
100290075Sobrien	int remainder;
100390075Sobrien
100490075Sobrien	desc->flags = htole32(flags);
100590075Sobrien	desc->flags |= htole32(RAL_TX_NEWSEQ);
100690075Sobrien	desc->flags |= htole32(len << 16);
100790075Sobrien
100890075Sobrien	desc->wme = htole16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5));
100990075Sobrien	desc->wme |= htole16(RAL_IVOFFSET(sizeof (struct ieee80211_frame)));
101090075Sobrien
101190075Sobrien	/* setup PLCP fields */
101290075Sobrien	desc->plcp_signal  = ural_plcp_signal(rate);
101318334Speter	desc->plcp_service = 4;
101418334Speter
101590075Sobrien	len += IEEE80211_CRC_LEN;
101690075Sobrien	if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
101718334Speter		desc->flags |= htole32(RAL_TX_OFDM);
101890075Sobrien
101918334Speter		plcp_length = len & 0xfff;
102018334Speter		desc->plcp_length_hi = plcp_length >> 6;
102190075Sobrien		desc->plcp_length_lo = plcp_length & 0x3f;
102290075Sobrien	} else {
102390075Sobrien		plcp_length = (16 * len + rate - 1) / rate;
102490075Sobrien		if (rate == 22) {
102590075Sobrien			remainder = (16 * len) % 22;
102690075Sobrien			if (remainder != 0 && remainder < 7)
102790075Sobrien				desc->plcp_service |= RAL_PLCP_LENGEXT;
102890075Sobrien		}
102990075Sobrien		desc->plcp_length_hi = plcp_length >> 8;
103050397Sobrien		desc->plcp_length_lo = plcp_length & 0xff;
103150397Sobrien
103290075Sobrien		if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
103390075Sobrien			desc->plcp_signal |= 0x08;
103490075Sobrien	}
103590075Sobrien
103690075Sobrien	desc->iv = 0;
103750397Sobrien	desc->eiv = 0;
103890075Sobrien}
103918334Speter
104090075Sobrien#define RAL_TX_TIMEOUT	5000
104190075Sobrien
104290075Sobrienstatic int
104390075Sobrienural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
104490075Sobrien{
104518334Speter	struct ieee80211vap *vap = ni->ni_vap;
104690075Sobrien	struct ieee80211com *ic = ni->ni_ic;
104790075Sobrien	struct ifnet *ifp = sc->sc_ifp;
104890075Sobrien	const struct ieee80211_txparam *tp;
104918334Speter	struct ural_tx_data *data;
105018334Speter
105190075Sobrien	if (sc->tx_nfree == 0) {
105290075Sobrien		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
105390075Sobrien		m_freem(m0);
105490075Sobrien		ieee80211_free_node(ni);
105590075Sobrien		return EIO;
105690075Sobrien	}
105790075Sobrien	data = STAILQ_FIRST(&sc->tx_free);
105890075Sobrien	STAILQ_REMOVE_HEAD(&sc->tx_free, next);
105990075Sobrien	sc->tx_nfree--;
106090075Sobrien	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)];
106190075Sobrien
106290075Sobrien	data->m = m0;
106390075Sobrien	data->ni = ni;
106490075Sobrien	data->rate = tp->mgmtrate;
106590075Sobrien
106690075Sobrien	ural_setup_tx_desc(sc, &data->desc,
106790075Sobrien	    RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP, m0->m_pkthdr.len,
106890075Sobrien	    tp->mgmtrate);
106990075Sobrien
107090075Sobrien	DPRINTFN(10, "sending beacon frame len=%u rate=%u\n",
107190075Sobrien	    m0->m_pkthdr.len, tp->mgmtrate);
107290075Sobrien
107390075Sobrien	STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
107490075Sobrien	usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]);
107590075Sobrien
107690075Sobrien	return (0);
107790075Sobrien}
107890075Sobrien
107990075Sobrienstatic int
108090075Sobrienural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
108190075Sobrien{
108290075Sobrien	struct ieee80211vap *vap = ni->ni_vap;
108390075Sobrien	struct ieee80211com *ic = ni->ni_ic;
108490075Sobrien	const struct ieee80211_txparam *tp;
108590075Sobrien	struct ural_tx_data *data;
108690075Sobrien	struct ieee80211_frame *wh;
108790075Sobrien	struct ieee80211_key *k;
108890075Sobrien	uint32_t flags;
108990075Sobrien	uint16_t dur;
109090075Sobrien
109190075Sobrien	RAL_LOCK_ASSERT(sc, MA_OWNED);
109290075Sobrien
109390075Sobrien	data = STAILQ_FIRST(&sc->tx_free);
109490075Sobrien	STAILQ_REMOVE_HEAD(&sc->tx_free, next);
109590075Sobrien	sc->tx_nfree--;
109690075Sobrien
109790075Sobrien	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
109890075Sobrien
109990075Sobrien	wh = mtod(m0, struct ieee80211_frame *);
110090075Sobrien	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
110190075Sobrien		k = ieee80211_crypto_encap(ni, m0);
110218334Speter		if (k == NULL) {
110318334Speter			m_freem(m0);
110490075Sobrien			return ENOBUFS;
110590075Sobrien		}
110690075Sobrien		wh = mtod(m0, struct ieee80211_frame *);
110790075Sobrien	}
110890075Sobrien
110918334Speter	data->m = m0;
111090075Sobrien	data->ni = ni;
111190075Sobrien	data->rate = tp->mgmtrate;
111218334Speter
111390075Sobrien	flags = 0;
111490075Sobrien	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
111590075Sobrien		flags |= RAL_TX_ACK;
111690075Sobrien
111790075Sobrien		dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate,
111818334Speter		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
111990075Sobrien		*(uint16_t *)wh->i_dur = htole16(dur);
112090075Sobrien
112150397Sobrien		/* tell hardware to add timestamp for probe responses */
112290075Sobrien		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
112390075Sobrien		    IEEE80211_FC0_TYPE_MGT &&
112490075Sobrien		    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
112590075Sobrien		    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
112690075Sobrien			flags |= RAL_TX_TIMESTAMP;
112790075Sobrien	}
112818334Speter
112990075Sobrien	ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, tp->mgmtrate);
113018334Speter
113118334Speter	DPRINTFN(10, "sending mgt frame len=%u rate=%u\n",
113290075Sobrien	    m0->m_pkthdr.len, tp->mgmtrate);
113390075Sobrien
113490075Sobrien	STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
113590075Sobrien	usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]);
113690075Sobrien
113790075Sobrien	return 0;
113890075Sobrien}
113918334Speter
114090075Sobrienstatic int
114190075Sobrienural_sendprot(struct ural_softc *sc,
114290075Sobrien    const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
114390075Sobrien{
114490075Sobrien	struct ieee80211com *ic = ni->ni_ic;
114590075Sobrien	const struct ieee80211_frame *wh;
114690075Sobrien	struct ural_tx_data *data;
114790075Sobrien	struct mbuf *mprot;
114890075Sobrien	int protrate, ackrate, pktlen, flags, isshort;
114990075Sobrien	uint16_t dur;
115018334Speter
115190075Sobrien	KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
115290075Sobrien	    ("protection %d", prot));
115390075Sobrien
115490075Sobrien	wh = mtod(m, const struct ieee80211_frame *);
115590075Sobrien	pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
115618334Speter
115790075Sobrien	protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
115890075Sobrien	ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
115990075Sobrien
116018334Speter	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
116190075Sobrien	dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
116290075Sobrien	    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
116390075Sobrien	flags = RAL_TX_RETRY(7);
116490075Sobrien	if (prot == IEEE80211_PROT_RTSCTS) {
116590075Sobrien		/* NB: CTS is the same size as an ACK */
116690075Sobrien		dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
116790075Sobrien		flags |= RAL_TX_ACK;
116818334Speter		mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
116990075Sobrien	} else {
117090075Sobrien		mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
117190075Sobrien	}
117290075Sobrien	if (mprot == NULL) {
117390075Sobrien		/* XXX stat + msg */
117418334Speter		return ENOBUFS;
117590075Sobrien	}
117690075Sobrien	data = STAILQ_FIRST(&sc->tx_free);
117790075Sobrien	STAILQ_REMOVE_HEAD(&sc->tx_free, next);
117890075Sobrien	sc->tx_nfree--;
117918334Speter
118090075Sobrien	data->m = mprot;
118118334Speter	data->ni = ieee80211_ref_node(ni);
118290075Sobrien	data->rate = protrate;
118390075Sobrien	ural_setup_tx_desc(sc, &data->desc, flags, mprot->m_pkthdr.len, protrate);
118490075Sobrien
118590075Sobrien	STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
118690075Sobrien	usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]);
118790075Sobrien
118890075Sobrien	return 0;
118990075Sobrien}
119090075Sobrien
119190075Sobrienstatic int
119290075Sobrienural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
119390075Sobrien    const struct ieee80211_bpf_params *params)
119490075Sobrien{
119590075Sobrien	struct ieee80211com *ic = ni->ni_ic;
119690075Sobrien	struct ural_tx_data *data;
119790075Sobrien	uint32_t flags;
119890075Sobrien	int error;
119990075Sobrien	int rate;
120090075Sobrien
120190075Sobrien	RAL_LOCK_ASSERT(sc, MA_OWNED);
120290075Sobrien	KASSERT(params != NULL, ("no raw xmit params"));
120390075Sobrien
120490075Sobrien	rate = params->ibp_rate0;
120590075Sobrien	if (!ieee80211_isratevalid(ic->ic_rt, rate)) {
120690075Sobrien		m_freem(m0);
120790075Sobrien		return EINVAL;
120890075Sobrien	}
120990075Sobrien	flags = 0;
121090075Sobrien	if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
121190075Sobrien		flags |= RAL_TX_ACK;
121290075Sobrien	if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) {
121390075Sobrien		error = ural_sendprot(sc, m0, ni,
121490075Sobrien		    params->ibp_flags & IEEE80211_BPF_RTS ?
121590075Sobrien			 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY,
121690075Sobrien		    rate);
121790075Sobrien		if (error || sc->tx_nfree == 0) {
121890075Sobrien			m_freem(m0);
121918334Speter			return ENOBUFS;
122090075Sobrien		}
122190075Sobrien		flags |= RAL_TX_IFS_SIFS;
122218334Speter	}
122318334Speter
122490075Sobrien	data = STAILQ_FIRST(&sc->tx_free);
122590075Sobrien	STAILQ_REMOVE_HEAD(&sc->tx_free, next);
122690075Sobrien	sc->tx_nfree--;
122790075Sobrien
122890075Sobrien	data->m = m0;
122990075Sobrien	data->ni = ni;
123090075Sobrien	data->rate = rate;
123190075Sobrien
123290075Sobrien	/* XXX need to setup descriptor ourself */
123390075Sobrien	ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate);
123490075Sobrien
123590075Sobrien	DPRINTFN(10, "sending raw frame len=%u rate=%u\n",
123690075Sobrien	    m0->m_pkthdr.len, rate);
123718334Speter
123890075Sobrien	STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
123990075Sobrien	usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]);
124090075Sobrien
124190075Sobrien	return 0;
124290075Sobrien}
124318334Speter
124490075Sobrienstatic int
124590075Sobrienural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
124690075Sobrien{
124718334Speter	struct ieee80211vap *vap = ni->ni_vap;
124890075Sobrien	struct ieee80211com *ic = ni->ni_ic;
124990075Sobrien	struct ural_tx_data *data;
125090075Sobrien	struct ieee80211_frame *wh;
125190075Sobrien	const struct ieee80211_txparam *tp;
125290075Sobrien	struct ieee80211_key *k;
125390075Sobrien	uint32_t flags = 0;
125490075Sobrien	uint16_t dur;
125590075Sobrien	int error, rate;
125690075Sobrien
125790075Sobrien	RAL_LOCK_ASSERT(sc, MA_OWNED);
125890075Sobrien
125990075Sobrien	wh = mtod(m0, struct ieee80211_frame *);
126090075Sobrien
126190075Sobrien	tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
126290075Sobrien	if (IEEE80211_IS_MULTICAST(wh->i_addr1))
126390075Sobrien		rate = tp->mcastrate;
126490075Sobrien	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
126590075Sobrien		rate = tp->ucastrate;
126690075Sobrien	else
126790075Sobrien		rate = ni->ni_txrate;
126890075Sobrien
126990075Sobrien	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
127090075Sobrien		k = ieee80211_crypto_encap(ni, m0);
127190075Sobrien		if (k == NULL) {
127290075Sobrien			m_freem(m0);
127390075Sobrien			return ENOBUFS;
127490075Sobrien		}
127590075Sobrien		/* packet header may have moved, reset our local pointer */
127690075Sobrien		wh = mtod(m0, struct ieee80211_frame *);
127790075Sobrien	}
127890075Sobrien
127990075Sobrien	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
128090075Sobrien		int prot = IEEE80211_PROT_NONE;
128118334Speter		if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
128290075Sobrien			prot = IEEE80211_PROT_RTSCTS;
128390075Sobrien		else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
128490075Sobrien		    ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM)
128590075Sobrien			prot = ic->ic_protmode;
128690075Sobrien		if (prot != IEEE80211_PROT_NONE) {
128790075Sobrien			error = ural_sendprot(sc, m0, ni, prot, rate);
128890075Sobrien			if (error || sc->tx_nfree == 0) {
128990075Sobrien				m_freem(m0);
129090075Sobrien				return ENOBUFS;
129190075Sobrien			}
129290075Sobrien			flags |= RAL_TX_IFS_SIFS;
129390075Sobrien		}
129490075Sobrien	}
129590075Sobrien
129690075Sobrien	data = STAILQ_FIRST(&sc->tx_free);
129790075Sobrien	STAILQ_REMOVE_HEAD(&sc->tx_free, next);
129890075Sobrien	sc->tx_nfree--;
129990075Sobrien
130090075Sobrien	data->m = m0;
130190075Sobrien	data->ni = ni;
130290075Sobrien	data->rate = rate;
130390075Sobrien
130490075Sobrien	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
130590075Sobrien		flags |= RAL_TX_ACK;
130690075Sobrien		flags |= RAL_TX_RETRY(7);
130790075Sobrien
130890075Sobrien		dur = ieee80211_ack_duration(ic->ic_rt, rate,
130990075Sobrien		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
131090075Sobrien		*(uint16_t *)wh->i_dur = htole16(dur);
131118334Speter	}
131218334Speter
131318334Speter	ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate);
131418334Speter
131518334Speter	DPRINTFN(10, "sending data frame len=%u rate=%u\n",
131618334Speter	    m0->m_pkthdr.len, rate);
131718334Speter
131818334Speter	STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
131918334Speter	usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]);
132018334Speter
132118334Speter	return 0;
132218334Speter}
132318334Speter
132418334Speterstatic void
132518334Speterural_start(struct ifnet *ifp)
132618334Speter{
132718334Speter	struct ural_softc *sc = ifp->if_softc;
132818334Speter	struct ieee80211_node *ni;
132918334Speter	struct mbuf *m;
133018334Speter
133118334Speter	RAL_LOCK(sc);
133218334Speter	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
133318334Speter		RAL_UNLOCK(sc);
133418334Speter		return;
133518334Speter	}
133618334Speter	for (;;) {
133718334Speter		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
133818334Speter		if (m == NULL)
133918334Speter			break;
134090075Sobrien		if (sc->tx_nfree < RAL_TX_MINFREE) {
134150397Sobrien			IFQ_DRV_PREPEND(&ifp->if_snd, m);
134290075Sobrien			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
134350397Sobrien			break;
134490075Sobrien		}
134590075Sobrien		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
134618334Speter		if (ural_tx_data(sc, m, ni) != 0) {
134718334Speter			ieee80211_free_node(ni);
134850397Sobrien			ifp->if_oerrors++;
134918334Speter			break;
135018334Speter		}
135118334Speter	}
135218334Speter	RAL_UNLOCK(sc);
135318334Speter}
135418334Speter
135590075Sobrienstatic int
135650397Sobrienural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
135718334Speter{
135818334Speter	struct ural_softc *sc = ifp->if_softc;
135918334Speter	struct ieee80211com *ic = ifp->if_l2com;
136018334Speter	struct ifreq *ifr = (struct ifreq *) data;
136190075Sobrien	int error = 0, startall = 0;
136250397Sobrien
136318334Speter	switch (cmd) {
136418334Speter	case SIOCSIFFLAGS:
136518334Speter		RAL_LOCK(sc);
136618334Speter		if (ifp->if_flags & IFF_UP) {
136718334Speter			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
136818334Speter				ural_init_locked(sc);
136918334Speter				startall = 1;
137018334Speter			} else
137118334Speter				ural_setpromisc(sc);
137290075Sobrien		} else {
137350397Sobrien			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
137418334Speter				ural_stop(sc);
137518334Speter		}
137690075Sobrien		RAL_UNLOCK(sc);
137790075Sobrien		if (startall)
137890075Sobrien			ieee80211_start_all(ic);
137990075Sobrien		break;
138090075Sobrien	case SIOCGIFMEDIA:
138190075Sobrien	case SIOCSIFMEDIA:
138290075Sobrien		error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
138390075Sobrien		break;
138490075Sobrien	default:
138590075Sobrien		error = ether_ioctl(ifp, cmd, data);
138690075Sobrien		break;
138718334Speter	}
138890075Sobrien	return error;
138918334Speter}
139090075Sobrien
139118334Speterstatic void
139218334Speterural_set_testmode(struct ural_softc *sc)
139318334Speter{
139418334Speter	struct usb_device_request req;
139590075Sobrien	usb_error_t error;
139650397Sobrien
139790075Sobrien	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
139890075Sobrien	req.bRequest = RAL_VENDOR_REQUEST;
139990075Sobrien	USETW(req.wValue, 4);
140018334Speter	USETW(req.wIndex, 1);
140118334Speter	USETW(req.wLength, 0);
140218334Speter
140318334Speter	error = ural_do_request(sc, &req, NULL);
140418334Speter	if (error != 0) {
140590075Sobrien		device_printf(sc->sc_dev, "could not set test mode: %s\n",
140650397Sobrien		    usbd_errstr(error));
140718334Speter	}
140818334Speter}
140918334Speter
141018334Speterstatic void
141190075Sobrienural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len)
141290075Sobrien{
141390075Sobrien	struct usb_device_request req;
141490075Sobrien	usb_error_t error;
141590075Sobrien
141690075Sobrien	req.bmRequestType = UT_READ_VENDOR_DEVICE;
141790075Sobrien	req.bRequest = RAL_READ_EEPROM;
141890075Sobrien	USETW(req.wValue, 0);
141990075Sobrien	USETW(req.wIndex, addr);
142090075Sobrien	USETW(req.wLength, len);
142190075Sobrien
142218334Speter	error = ural_do_request(sc, &req, buf);
142318334Speter	if (error != 0) {
142418334Speter		device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
142518334Speter		    usbd_errstr(error));
142690075Sobrien	}
142790075Sobrien}
142818334Speter
142918334Speterstatic uint16_t
143018334Speterural_read(struct ural_softc *sc, uint16_t reg)
143118334Speter{
143218334Speter	struct usb_device_request req;
143318334Speter	usb_error_t error;
143418334Speter	uint16_t val;
143518334Speter
143618334Speter	req.bmRequestType = UT_READ_VENDOR_DEVICE;
143718334Speter	req.bRequest = RAL_READ_MAC;
143852284Sobrien	USETW(req.wValue, 0);
143918334Speter	USETW(req.wIndex, reg);
144050397Sobrien	USETW(req.wLength, sizeof (uint16_t));
144150397Sobrien
144218334Speter	error = ural_do_request(sc, &req, &val);
144390075Sobrien	if (error != 0) {
144490075Sobrien		device_printf(sc->sc_dev, "could not read MAC register: %s\n",
144590075Sobrien		    usbd_errstr(error));
144690075Sobrien		return 0;
144718334Speter	}
144852284Sobrien
144952284Sobrien	return le16toh(val);
145090075Sobrien}
145190075Sobrien
145290075Sobrienstatic void
145390075Sobrienural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
145452284Sobrien{
145590075Sobrien	struct usb_device_request req;
145690075Sobrien	usb_error_t error;
145790075Sobrien
145890075Sobrien	req.bmRequestType = UT_READ_VENDOR_DEVICE;
145990075Sobrien	req.bRequest = RAL_READ_MULTI_MAC;
146052284Sobrien	USETW(req.wValue, 0);
146152284Sobrien	USETW(req.wIndex, reg);
146252284Sobrien	USETW(req.wLength, len);
146352284Sobrien
146450397Sobrien	error = ural_do_request(sc, &req, buf);
146590075Sobrien	if (error != 0) {
146690075Sobrien		device_printf(sc->sc_dev, "could not read MAC register: %s\n",
146752284Sobrien		    usbd_errstr(error));
146850397Sobrien	}
146950397Sobrien}
147050397Sobrien
147150397Sobrienstatic void
147252284Sobrienural_write(struct ural_softc *sc, uint16_t reg, uint16_t val)
147352284Sobrien{
147452284Sobrien	struct usb_device_request req;
147552284Sobrien	usb_error_t error;
147690075Sobrien
147790075Sobrien	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
147890075Sobrien	req.bRequest = RAL_WRITE_MAC;
147918334Speter	USETW(req.wValue, val);
148018334Speter	USETW(req.wIndex, reg);
148118334Speter	USETW(req.wLength, 0);
148218334Speter
148318334Speter	error = ural_do_request(sc, &req, NULL);
148418334Speter	if (error != 0) {
148518334Speter		device_printf(sc->sc_dev, "could not write MAC register: %s\n",
148618334Speter		    usbd_errstr(error));
148718334Speter	}
148818334Speter}
148918334Speter
149090075Sobrienstatic void
149118334Speterural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
149218334Speter{
149318334Speter	struct usb_device_request req;
149450397Sobrien	usb_error_t error;
149590075Sobrien
149690075Sobrien	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
149790075Sobrien	req.bRequest = RAL_WRITE_MULTI_MAC;
149850397Sobrien	USETW(req.wValue, 0);
149950397Sobrien	USETW(req.wIndex, reg);
150050397Sobrien	USETW(req.wLength, len);
150150397Sobrien
150290075Sobrien	error = ural_do_request(sc, &req, buf);
150350397Sobrien	if (error != 0) {
150450397Sobrien		device_printf(sc->sc_dev, "could not write MAC register: %s\n",
150518334Speter		    usbd_errstr(error));
150618334Speter	}
150718334Speter}
150818334Speter
150990075Sobrienstatic void
151090075Sobrienural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val)
151190075Sobrien{
151218334Speter	uint16_t tmp;
151318334Speter	int ntries;
151418334Speter
151518334Speter	for (ntries = 0; ntries < 100; ntries++) {
151618334Speter		if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY))
151718334Speter			break;
151890075Sobrien		if (ural_pause(sc, hz / 100))
151918334Speter			break;
152090075Sobrien	}
152190075Sobrien	if (ntries == 100) {
152290075Sobrien		device_printf(sc->sc_dev, "could not write to BBP\n");
152318334Speter		return;
152418334Speter	}
152518334Speter
152618334Speter	tmp = reg << 8 | val;
152718334Speter	ural_write(sc, RAL_PHY_CSR7, tmp);
152818334Speter}
152918334Speter
153018334Speterstatic uint8_t
153118334Speterural_bbp_read(struct ural_softc *sc, uint8_t reg)
153218334Speter{
153390075Sobrien	uint16_t val;
153490075Sobrien	int ntries;
153590075Sobrien
153690075Sobrien	val = RAL_BBP_WRITE | reg << 8;
153790075Sobrien	ural_write(sc, RAL_PHY_CSR7, val);
153850397Sobrien
153990075Sobrien	for (ntries = 0; ntries < 100; ntries++) {
154090075Sobrien		if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY))
154118334Speter			break;
154290075Sobrien		if (ural_pause(sc, hz / 100))
154390075Sobrien			break;
154490075Sobrien	}
154590075Sobrien	if (ntries == 100) {
154690075Sobrien		device_printf(sc->sc_dev, "could not read BBP\n");
154718334Speter		return 0;
154890075Sobrien	}
154990075Sobrien
155090075Sobrien	return ural_read(sc, RAL_PHY_CSR7) & 0xff;
155118334Speter}
155290075Sobrien
155390075Sobrienstatic void
155418334Speterural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
155590075Sobrien{
155690075Sobrien	uint32_t tmp;
155718334Speter	int ntries;
155890075Sobrien
155990075Sobrien	for (ntries = 0; ntries < 100; ntries++) {
156090075Sobrien		if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY))
156118334Speter			break;
156218334Speter		if (ural_pause(sc, hz / 100))
156390075Sobrien			break;
156418334Speter	}
156518334Speter	if (ntries == 100) {
156690075Sobrien		device_printf(sc->sc_dev, "could not write to RF\n");
156718334Speter		return;
156818334Speter	}
156918334Speter
157018334Speter	tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xfffff) << 2 | (reg & 0x3);
157118334Speter	ural_write(sc, RAL_PHY_CSR9,  tmp & 0xffff);
157290075Sobrien	ural_write(sc, RAL_PHY_CSR10, tmp >> 16);
157390075Sobrien
157450397Sobrien	/* remember last written value in sc */
157550397Sobrien	sc->rf_regs[reg] = val;
157650397Sobrien
157718334Speter	DPRINTFN(15, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff);
157818334Speter}
157990075Sobrien
158090075Sobrienstatic void
158118334Speterural_scan_start(struct ieee80211com *ic)
158218334Speter{
158318334Speter	struct ifnet *ifp = ic->ic_ifp;
158490075Sobrien	struct ural_softc *sc = ifp->if_softc;
158590075Sobrien
158650397Sobrien	RAL_LOCK(sc);
158718334Speter	ural_write(sc, RAL_TXRX_CSR19, 0);
158890075Sobrien	ural_set_bssid(sc, ifp->if_broadcastaddr);
158918334Speter	RAL_UNLOCK(sc);
159018334Speter}
159118334Speter
159218334Speterstatic void
159318334Speterural_scan_end(struct ieee80211com *ic)
159418334Speter{
159518334Speter	struct ural_softc *sc = ic->ic_ifp->if_softc;
159618334Speter
159790075Sobrien	RAL_LOCK(sc);
159818334Speter	ural_enable_tsf_sync(sc);
159918334Speter	ural_set_bssid(sc, sc->sc_bssid);
160018334Speter	RAL_UNLOCK(sc);
160118334Speter
160218334Speter}
160350397Sobrien
160450397Sobrienstatic void
160590075Sobrienural_set_channel(struct ieee80211com *ic)
160690075Sobrien{
160790075Sobrien	struct ural_softc *sc = ic->ic_ifp->if_softc;
160890075Sobrien
160990075Sobrien	RAL_LOCK(sc);
161090075Sobrien	ural_set_chan(sc, ic->ic_curchan);
161190075Sobrien	RAL_UNLOCK(sc);
161250397Sobrien}
161390075Sobrien
161490075Sobrienstatic void
161590075Sobrienural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
161690075Sobrien{
161718334Speter	struct ifnet *ifp = sc->sc_ifp;
161890075Sobrien	struct ieee80211com *ic = ifp->if_l2com;
161990075Sobrien	uint8_t power, tmp;
162090075Sobrien	int i, chan;
162190075Sobrien
162290075Sobrien	chan = ieee80211_chan2ieee(ic, c);
162390075Sobrien	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
162490075Sobrien		return;
162518334Speter
162618334Speter	if (IEEE80211_IS_CHAN_2GHZ(c))
162718334Speter		power = min(sc->txpow[chan - 1], 31);
162818334Speter	else
162918334Speter		power = 31;
163018334Speter
163118334Speter	/* adjust txpower using ifconfig settings */
163218334Speter	power -= (100 - ic->ic_txpowlimit) / 8;
163390075Sobrien
163418334Speter	DPRINTFN(2, "setting channel to %u, txpower to %u\n", chan, power);
163518334Speter
163618334Speter	switch (sc->rf_rev) {
163790075Sobrien	case RAL_RF_2522:
163818334Speter		ural_rf_write(sc, RAL_RF1, 0x00814);
163918334Speter		ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]);
164018334Speter		ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
164118334Speter		break;
164218334Speter
164318334Speter	case RAL_RF_2523:
164418334Speter		ural_rf_write(sc, RAL_RF1, 0x08804);
164518334Speter		ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]);
164618334Speter		ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044);
164790075Sobrien		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
164818334Speter		break;
164918334Speter
165018334Speter	case RAL_RF_2524:
165118334Speter		ural_rf_write(sc, RAL_RF1, 0x0c808);
165218334Speter		ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]);
165318334Speter		ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
165490075Sobrien		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
165590075Sobrien		break;
165690075Sobrien
165718334Speter	case RAL_RF_2525:
165890075Sobrien		ural_rf_write(sc, RAL_RF1, 0x08808);
165990075Sobrien		ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]);
166090075Sobrien		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
166190075Sobrien		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
166290075Sobrien
166390075Sobrien		ural_rf_write(sc, RAL_RF1, 0x08808);
166490075Sobrien		ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]);
166590075Sobrien		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
166690075Sobrien		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
166790075Sobrien		break;
166890075Sobrien
166990075Sobrien	case RAL_RF_2525E:
167090075Sobrien		ural_rf_write(sc, RAL_RF1, 0x08808);
167190075Sobrien		ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]);
167290075Sobrien		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
167390075Sobrien		ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282);
167490075Sobrien		break;
167590075Sobrien
167690075Sobrien	case RAL_RF_2526:
167790075Sobrien		ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]);
167890075Sobrien		ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
167990075Sobrien		ural_rf_write(sc, RAL_RF1, 0x08804);
168090075Sobrien
168190075Sobrien		ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]);
168290075Sobrien		ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
168390075Sobrien		ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
168490075Sobrien		break;
168590075Sobrien
168690075Sobrien	/* dual-band RF */
168790075Sobrien	case RAL_RF_5222:
168850397Sobrien		for (i = 0; ural_rf5222[i].chan != chan; i++);
168950397Sobrien
169050397Sobrien		ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1);
169150397Sobrien		ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2);
169250397Sobrien		ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
169350397Sobrien		ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4);
169450397Sobrien		break;
169590075Sobrien	}
169650397Sobrien
169790075Sobrien	if (ic->ic_opmode != IEEE80211_M_MONITOR &&
169890075Sobrien	    (ic->ic_flags & IEEE80211_F_SCAN) == 0) {
169990075Sobrien		/* set Japan filter bit for channel 14 */
170090075Sobrien		tmp = ural_bbp_read(sc, 70);
170190075Sobrien
170290075Sobrien		tmp &= ~RAL_JAPAN_FILTER;
170390075Sobrien		if (chan == 14)
170450397Sobrien			tmp |= RAL_JAPAN_FILTER;
170590075Sobrien
170690075Sobrien		ural_bbp_write(sc, 70, tmp);
170750397Sobrien
170890075Sobrien		/* clear CRC errors */
170990075Sobrien		ural_read(sc, RAL_STA_CSR0);
171090075Sobrien
171190075Sobrien		ural_pause(sc, hz / 100);
171290075Sobrien		ural_disable_rf_tune(sc);
171390075Sobrien	}
171450397Sobrien
171590075Sobrien	/* XXX doesn't belong here */
171690075Sobrien	/* update basic rate set */
171750397Sobrien	ural_set_basicrates(sc, c);
171850397Sobrien
171950397Sobrien	/* give the hardware some time to do the switchover */
172050397Sobrien	ural_pause(sc, hz / 100);
172190075Sobrien}
172250397Sobrien
172350397Sobrien/*
172450397Sobrien * Disable RF auto-tuning.
172550397Sobrien */
172650397Sobrienstatic void
172750397Sobrienural_disable_rf_tune(struct ural_softc *sc)
172890075Sobrien{
172990075Sobrien	uint32_t tmp;
173050397Sobrien
173150397Sobrien	if (sc->rf_rev != RAL_RF_2523) {
173250397Sobrien		tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE;
173350397Sobrien		ural_rf_write(sc, RAL_RF1, tmp);
173450397Sobrien	}
173590075Sobrien
173690075Sobrien	tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE;
173750397Sobrien	ural_rf_write(sc, RAL_RF3, tmp);
173890075Sobrien
173990075Sobrien	DPRINTFN(2, "disabling RF autotune\n");
174090075Sobrien}
174190075Sobrien
174290075Sobrien/*
174390075Sobrien * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
174490075Sobrien * synchronization.
174590075Sobrien */
174690075Sobrienstatic void
174790075Sobrienural_enable_tsf_sync(struct ural_softc *sc)
174890075Sobrien{
174990075Sobrien	struct ifnet *ifp = sc->sc_ifp;
175090075Sobrien	struct ieee80211com *ic = ifp->if_l2com;
175190075Sobrien	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
175290075Sobrien	uint16_t logcwmin, preload, tmp;
175390075Sobrien
175490075Sobrien	/* first, disable TSF synchronization */
175590075Sobrien	ural_write(sc, RAL_TXRX_CSR19, 0);
175690075Sobrien
175790075Sobrien	tmp = (16 * vap->iv_bss->ni_intval) << 4;
175890075Sobrien	ural_write(sc, RAL_TXRX_CSR18, tmp);
175990075Sobrien
176090075Sobrien	logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0;
176190075Sobrien	preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6;
176290075Sobrien	tmp = logcwmin << 12 | preload;
176390075Sobrien	ural_write(sc, RAL_TXRX_CSR20, tmp);
176490075Sobrien
176590075Sobrien	/* finally, enable TSF synchronization */
176690075Sobrien	tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN;
176750397Sobrien	if (ic->ic_opmode == IEEE80211_M_STA)
176890075Sobrien		tmp |= RAL_ENABLE_TSF_SYNC(1);
176918334Speter	else
177018334Speter		tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR;
177118334Speter	ural_write(sc, RAL_TXRX_CSR19, tmp);
177218334Speter
177318334Speter	DPRINTF("enabling TSF synchronization\n");
177418334Speter}
177518334Speter
177618334Speterstatic void
177718334Speterural_enable_tsf(struct ural_softc *sc)
177890075Sobrien{
177918334Speter	/* first, disable TSF synchronization */
178090075Sobrien	ural_write(sc, RAL_TXRX_CSR19, 0);
178190075Sobrien	ural_write(sc, RAL_TXRX_CSR19, RAL_ENABLE_TSF | RAL_ENABLE_TSF_SYNC(2));
178290075Sobrien}
178390075Sobrien
178490075Sobrien#define RAL_RXTX_TURNAROUND	5	/* us */
178590075Sobrienstatic void
178618334Speterural_update_slot(struct ifnet *ifp)
178718334Speter{
178818334Speter	struct ural_softc *sc = ifp->if_softc;
178918334Speter	struct ieee80211com *ic = ifp->if_l2com;
179018334Speter	uint16_t slottime, sifs, eifs;
179118334Speter
179218334Speter	slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
179318334Speter
179418334Speter	/*
179518334Speter	 * These settings may sound a bit inconsistent but this is what the
179618334Speter	 * reference driver does.
179718334Speter	 */
179818334Speter	if (ic->ic_curmode == IEEE80211_MODE_11B) {
179918334Speter		sifs = 16 - RAL_RXTX_TURNAROUND;
180018334Speter		eifs = 364;
180118334Speter	} else {
180218334Speter		sifs = 10 - RAL_RXTX_TURNAROUND;
180318334Speter		eifs = 64;
180418334Speter	}
180518334Speter
180618334Speter	ural_write(sc, RAL_MAC_CSR10, slottime);
180718334Speter	ural_write(sc, RAL_MAC_CSR11, sifs);
180818334Speter	ural_write(sc, RAL_MAC_CSR12, eifs);
180918334Speter}
181018334Speter
181118334Speterstatic void
181218334Speterural_set_txpreamble(struct ural_softc *sc)
181318334Speter{
181418334Speter	struct ifnet *ifp = sc->sc_ifp;
181518334Speter	struct ieee80211com *ic = ifp->if_l2com;
181690075Sobrien	uint16_t tmp;
181718334Speter
181890075Sobrien	tmp = ural_read(sc, RAL_TXRX_CSR10);
181990075Sobrien
182090075Sobrien	tmp &= ~RAL_SHORT_PREAMBLE;
182190075Sobrien	if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
182290075Sobrien		tmp |= RAL_SHORT_PREAMBLE;
182390075Sobrien
182418334Speter	ural_write(sc, RAL_TXRX_CSR10, tmp);
182518334Speter}
182618334Speter
182718334Speterstatic void
182818334Speterural_set_basicrates(struct ural_softc *sc, const struct ieee80211_channel *c)
182918334Speter{
183018334Speter	/* XXX wrong, take from rate set */
183118334Speter	/* update basic rate set */
183218334Speter	if (IEEE80211_IS_CHAN_5GHZ(c)) {
183318334Speter		/* 11a basic rates: 6, 12, 24Mbps */
183418334Speter		ural_write(sc, RAL_TXRX_CSR11, 0x150);
183518334Speter	} else if (IEEE80211_IS_CHAN_ANYG(c)) {
183618334Speter		/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
183718334Speter		ural_write(sc, RAL_TXRX_CSR11, 0x15f);
183818334Speter	} else {
183918334Speter		/* 11b basic rates: 1, 2Mbps */
184018334Speter		ural_write(sc, RAL_TXRX_CSR11, 0x3);
184118334Speter	}
184218334Speter}
184318334Speter
184418334Speterstatic void
184518334Speterural_set_bssid(struct ural_softc *sc, const uint8_t *bssid)
184618334Speter{
184718334Speter	uint16_t tmp;
184818334Speter
184918334Speter	tmp = bssid[0] | bssid[1] << 8;
185018334Speter	ural_write(sc, RAL_MAC_CSR5, tmp);
185118334Speter
185218334Speter	tmp = bssid[2] | bssid[3] << 8;
185318334Speter	ural_write(sc, RAL_MAC_CSR6, tmp);
185418334Speter
185518334Speter	tmp = bssid[4] | bssid[5] << 8;
185618334Speter	ural_write(sc, RAL_MAC_CSR7, tmp);
185718334Speter
185890075Sobrien	DPRINTF("setting BSSID to %6D\n", bssid, ":");
185918334Speter}
186018334Speter
186118334Speterstatic void
186218334Speterural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
186390075Sobrien{
186418334Speter	uint16_t tmp;
186518334Speter
186618334Speter	tmp = addr[0] | addr[1] << 8;
186718334Speter	ural_write(sc, RAL_MAC_CSR2, tmp);
186818334Speter
186918334Speter	tmp = addr[2] | addr[3] << 8;
187050397Sobrien	ural_write(sc, RAL_MAC_CSR3, tmp);
187118334Speter
187218334Speter	tmp = addr[4] | addr[5] << 8;
187318334Speter	ural_write(sc, RAL_MAC_CSR4, tmp);
187490075Sobrien
187518334Speter	DPRINTF("setting MAC address to %6D\n", addr, ":");
187618334Speter}
187718334Speter
187818334Speterstatic void
187918334Speterural_setpromisc(struct ural_softc *sc)
188018334Speter{
188118334Speter	struct ifnet *ifp = sc->sc_ifp;
188218334Speter	uint32_t tmp;
188318334Speter
188418334Speter	tmp = ural_read(sc, RAL_TXRX_CSR2);
188518334Speter
188618334Speter	tmp &= ~RAL_DROP_NOT_TO_ME;
188718334Speter	if (!(ifp->if_flags & IFF_PROMISC))
188818334Speter		tmp |= RAL_DROP_NOT_TO_ME;
188918334Speter
189018334Speter	ural_write(sc, RAL_TXRX_CSR2, tmp);
189118334Speter
189218334Speter	DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
189318334Speter	    "entering" : "leaving");
189418334Speter}
189518334Speter
189618334Speterstatic void
189718334Speterural_update_promisc(struct ifnet *ifp)
189818334Speter{
189918334Speter	struct ural_softc *sc = ifp->if_softc;
190018334Speter
190118334Speter	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
190218334Speter		return;
190318334Speter
190418334Speter	RAL_LOCK(sc);
190518334Speter	ural_setpromisc(sc);
190618334Speter	RAL_UNLOCK(sc);
190718334Speter}
190818334Speter
190990075Sobrienstatic const char *
191018334Speterural_get_rf(int rev)
191118334Speter{
191290075Sobrien	switch (rev) {
191318334Speter	case RAL_RF_2522:	return "RT2522";
191490075Sobrien	case RAL_RF_2523:	return "RT2523";
191518334Speter	case RAL_RF_2524:	return "RT2524";
1916	case RAL_RF_2525:	return "RT2525";
1917	case RAL_RF_2525E:	return "RT2525e";
1918	case RAL_RF_2526:	return "RT2526";
1919	case RAL_RF_5222:	return "RT5222";
1920	default:		return "unknown";
1921	}
1922}
1923
1924static void
1925ural_read_eeprom(struct ural_softc *sc)
1926{
1927	uint16_t val;
1928
1929	ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
1930	val = le16toh(val);
1931	sc->rf_rev =   (val >> 11) & 0x7;
1932	sc->hw_radio = (val >> 10) & 0x1;
1933	sc->led_mode = (val >> 6)  & 0x7;
1934	sc->rx_ant =   (val >> 4)  & 0x3;
1935	sc->tx_ant =   (val >> 2)  & 0x3;
1936	sc->nb_ant =   val & 0x3;
1937
1938	/* read MAC address */
1939	ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6);
1940
1941	/* read default values for BBP registers */
1942	ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
1943
1944	/* read Tx power for all b/g channels */
1945	ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14);
1946}
1947
1948static int
1949ural_bbp_init(struct ural_softc *sc)
1950{
1951#define N(a)	(sizeof (a) / sizeof ((a)[0]))
1952	int i, ntries;
1953
1954	/* wait for BBP to be ready */
1955	for (ntries = 0; ntries < 100; ntries++) {
1956		if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0)
1957			break;
1958		if (ural_pause(sc, hz / 100))
1959			break;
1960	}
1961	if (ntries == 100) {
1962		device_printf(sc->sc_dev, "timeout waiting for BBP\n");
1963		return EIO;
1964	}
1965
1966	/* initialize BBP registers to default values */
1967	for (i = 0; i < N(ural_def_bbp); i++)
1968		ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val);
1969
1970#if 0
1971	/* initialize BBP registers to values stored in EEPROM */
1972	for (i = 0; i < 16; i++) {
1973		if (sc->bbp_prom[i].reg == 0xff)
1974			continue;
1975		ural_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
1976	}
1977#endif
1978
1979	return 0;
1980#undef N
1981}
1982
1983static void
1984ural_set_txantenna(struct ural_softc *sc, int antenna)
1985{
1986	uint16_t tmp;
1987	uint8_t tx;
1988
1989	tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK;
1990	if (antenna == 1)
1991		tx |= RAL_BBP_ANTA;
1992	else if (antenna == 2)
1993		tx |= RAL_BBP_ANTB;
1994	else
1995		tx |= RAL_BBP_DIVERSITY;
1996
1997	/* need to force I/Q flip for RF 2525e, 2526 and 5222 */
1998	if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 ||
1999	    sc->rf_rev == RAL_RF_5222)
2000		tx |= RAL_BBP_FLIPIQ;
2001
2002	ural_bbp_write(sc, RAL_BBP_TX, tx);
2003
2004	/* update values in PHY_CSR5 and PHY_CSR6 */
2005	tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7;
2006	ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7));
2007
2008	tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7;
2009	ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7));
2010}
2011
2012static void
2013ural_set_rxantenna(struct ural_softc *sc, int antenna)
2014{
2015	uint8_t rx;
2016
2017	rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK;
2018	if (antenna == 1)
2019		rx |= RAL_BBP_ANTA;
2020	else if (antenna == 2)
2021		rx |= RAL_BBP_ANTB;
2022	else
2023		rx |= RAL_BBP_DIVERSITY;
2024
2025	/* need to force no I/Q flip for RF 2525e and 2526 */
2026	if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526)
2027		rx &= ~RAL_BBP_FLIPIQ;
2028
2029	ural_bbp_write(sc, RAL_BBP_RX, rx);
2030}
2031
2032static void
2033ural_init_locked(struct ural_softc *sc)
2034{
2035#define N(a)	(sizeof (a) / sizeof ((a)[0]))
2036	struct ifnet *ifp = sc->sc_ifp;
2037	struct ieee80211com *ic = ifp->if_l2com;
2038	uint16_t tmp;
2039	int i, ntries;
2040
2041	RAL_LOCK_ASSERT(sc, MA_OWNED);
2042
2043	ural_set_testmode(sc);
2044	ural_write(sc, 0x308, 0x00f0);	/* XXX magic */
2045
2046	ural_stop(sc);
2047
2048	/* initialize MAC registers to default values */
2049	for (i = 0; i < N(ural_def_mac); i++)
2050		ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val);
2051
2052	/* wait for BBP and RF to wake up (this can take a long time!) */
2053	for (ntries = 0; ntries < 100; ntries++) {
2054		tmp = ural_read(sc, RAL_MAC_CSR17);
2055		if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) ==
2056		    (RAL_BBP_AWAKE | RAL_RF_AWAKE))
2057			break;
2058		if (ural_pause(sc, hz / 100))
2059			break;
2060	}
2061	if (ntries == 100) {
2062		device_printf(sc->sc_dev,
2063		    "timeout waiting for BBP/RF to wakeup\n");
2064		goto fail;
2065	}
2066
2067	/* we're ready! */
2068	ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY);
2069
2070	/* set basic rate set (will be updated later) */
2071	ural_write(sc, RAL_TXRX_CSR11, 0x15f);
2072
2073	if (ural_bbp_init(sc) != 0)
2074		goto fail;
2075
2076	ural_set_chan(sc, ic->ic_curchan);
2077
2078	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
2079	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta);
2080
2081	ural_set_txantenna(sc, sc->tx_ant);
2082	ural_set_rxantenna(sc, sc->rx_ant);
2083
2084	ural_set_macaddr(sc, IF_LLADDR(ifp));
2085
2086	/*
2087	 * Allocate Tx and Rx xfer queues.
2088	 */
2089	ural_setup_tx_list(sc);
2090
2091	/* kick Rx */
2092	tmp = RAL_DROP_PHY | RAL_DROP_CRC;
2093	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2094		tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
2095		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2096			tmp |= RAL_DROP_TODS;
2097		if (!(ifp->if_flags & IFF_PROMISC))
2098			tmp |= RAL_DROP_NOT_TO_ME;
2099	}
2100	ural_write(sc, RAL_TXRX_CSR2, tmp);
2101
2102	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2103	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2104	usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]);
2105	usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
2106	return;
2107
2108fail:	ural_stop(sc);
2109#undef N
2110}
2111
2112static void
2113ural_init(void *priv)
2114{
2115	struct ural_softc *sc = priv;
2116	struct ifnet *ifp = sc->sc_ifp;
2117	struct ieee80211com *ic = ifp->if_l2com;
2118
2119	RAL_LOCK(sc);
2120	ural_init_locked(sc);
2121	RAL_UNLOCK(sc);
2122
2123	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2124		ieee80211_start_all(ic);		/* start all vap's */
2125}
2126
2127static void
2128ural_stop(struct ural_softc *sc)
2129{
2130	struct ifnet *ifp = sc->sc_ifp;
2131
2132	RAL_LOCK_ASSERT(sc, MA_OWNED);
2133
2134	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
2135
2136	/*
2137	 * Drain all the transfers, if not already drained:
2138	 */
2139	RAL_UNLOCK(sc);
2140	usbd_transfer_drain(sc->sc_xfer[URAL_BULK_WR]);
2141	usbd_transfer_drain(sc->sc_xfer[URAL_BULK_RD]);
2142	RAL_LOCK(sc);
2143
2144	ural_unsetup_tx_list(sc);
2145
2146	/* disable Rx */
2147	ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
2148	/* reset ASIC and BBP (but won't reset MAC registers!) */
2149	ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP);
2150	/* wait a little */
2151	ural_pause(sc, hz / 10);
2152	ural_write(sc, RAL_MAC_CSR1, 0);
2153	/* wait a little */
2154	ural_pause(sc, hz / 10);
2155}
2156
2157static int
2158ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2159	const struct ieee80211_bpf_params *params)
2160{
2161	struct ieee80211com *ic = ni->ni_ic;
2162	struct ifnet *ifp = ic->ic_ifp;
2163	struct ural_softc *sc = ifp->if_softc;
2164
2165	RAL_LOCK(sc);
2166	/* prevent management frames from being sent if we're not ready */
2167	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
2168		RAL_UNLOCK(sc);
2169		m_freem(m);
2170		ieee80211_free_node(ni);
2171		return ENETDOWN;
2172	}
2173	if (sc->tx_nfree < RAL_TX_MINFREE) {
2174		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
2175		RAL_UNLOCK(sc);
2176		m_freem(m);
2177		ieee80211_free_node(ni);
2178		return EIO;
2179	}
2180
2181	ifp->if_opackets++;
2182
2183	if (params == NULL) {
2184		/*
2185		 * Legacy path; interpret frame contents to decide
2186		 * precisely how to send the frame.
2187		 */
2188		if (ural_tx_mgt(sc, m, ni) != 0)
2189			goto bad;
2190	} else {
2191		/*
2192		 * Caller supplied explicit parameters to use in
2193		 * sending the frame.
2194		 */
2195		if (ural_tx_raw(sc, m, ni, params) != 0)
2196			goto bad;
2197	}
2198	RAL_UNLOCK(sc);
2199	return 0;
2200bad:
2201	ifp->if_oerrors++;
2202	RAL_UNLOCK(sc);
2203	ieee80211_free_node(ni);
2204	return EIO;		/* XXX */
2205}
2206
2207static void
2208ural_ratectl_start(struct ural_softc *sc, struct ieee80211_node *ni)
2209{
2210	struct ieee80211vap *vap = ni->ni_vap;
2211	struct ural_vap *uvp = URAL_VAP(vap);
2212
2213	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
2214	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta);
2215
2216	ieee80211_ratectl_node_init(ni);
2217
2218	usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp);
2219}
2220
2221static void
2222ural_ratectl_timeout(void *arg)
2223{
2224	struct ural_vap *uvp = arg;
2225	struct ieee80211vap *vap = &uvp->vap;
2226	struct ieee80211com *ic = vap->iv_ic;
2227
2228	ieee80211_runtask(ic, &uvp->ratectl_task);
2229}
2230
2231static void
2232ural_ratectl_task(void *arg, int pending)
2233{
2234	struct ural_vap *uvp = arg;
2235	struct ieee80211vap *vap = &uvp->vap;
2236	struct ieee80211com *ic = vap->iv_ic;
2237	struct ifnet *ifp = ic->ic_ifp;
2238	struct ural_softc *sc = ifp->if_softc;
2239	struct ieee80211_node *ni = vap->iv_bss;
2240	int ok, fail;
2241	int sum, retrycnt;
2242
2243	RAL_LOCK(sc);
2244	/* read and clear statistic registers (STA_CSR0 to STA_CSR10) */
2245	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta));
2246
2247	ok = sc->sta[7] +		/* TX ok w/o retry */
2248	     sc->sta[8];		/* TX ok w/ retry */
2249	fail = sc->sta[9];		/* TX retry-fail count */
2250	sum = ok+fail;
2251	retrycnt = sc->sta[8] + fail;
2252
2253	ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
2254	(void) ieee80211_ratectl_rate(ni, NULL, 0);
2255
2256	ifp->if_oerrors += fail;	/* count TX retry-fail as Tx errors */
2257
2258	usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp);
2259	RAL_UNLOCK(sc);
2260}
2261
2262static int
2263ural_pause(struct ural_softc *sc, int timeout)
2264{
2265
2266	usb_pause_mtx(&sc->sc_mtx, timeout);
2267	return (0);
2268}
2269