rt2560.c revision 298818
154359Sroberto/*	$FreeBSD: head/sys/dev/ral/rt2560.c 298818 2016-04-29 22:14:11Z avos $	*/
254359Sroberto
354359Sroberto/*-
454359Sroberto * Copyright (c) 2005, 2006
554359Sroberto *	Damien Bergamini <damien.bergamini@free.fr>
654359Sroberto *
754359Sroberto * Permission to use, copy, modify, and distribute this software for any
854359Sroberto * purpose with or without fee is hereby granted, provided that the above
954359Sroberto * copyright notice and this permission notice appear in all copies.
1054359Sroberto *
1154359Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1254359Sroberto * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1354359Sroberto * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1454359Sroberto * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1554359Sroberto * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1654359Sroberto * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1754359Sroberto * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1854359Sroberto */
1954359Sroberto
2054359Sroberto#include <sys/cdefs.h>
2154359Sroberto__FBSDID("$FreeBSD: head/sys/dev/ral/rt2560.c 298818 2016-04-29 22:14:11Z avos $");
2254359Sroberto
2354359Sroberto/*-
2454359Sroberto * Ralink Technology RT2560 chipset driver
2554359Sroberto * http://www.ralinktech.com/
2654359Sroberto */
2754359Sroberto
2854359Sroberto#include <sys/param.h>
2954359Sroberto#include <sys/sysctl.h>
3054359Sroberto#include <sys/sockio.h>
3154359Sroberto#include <sys/mbuf.h>
3254359Sroberto#include <sys/kernel.h>
3354359Sroberto#include <sys/socket.h>
3454359Sroberto#include <sys/systm.h>
3554359Sroberto#include <sys/malloc.h>
3654359Sroberto#include <sys/lock.h>
3754359Sroberto#include <sys/mutex.h>
3854359Sroberto#include <sys/module.h>
3954359Sroberto#include <sys/bus.h>
4054359Sroberto#include <sys/endian.h>
4154359Sroberto
4254359Sroberto#include <machine/bus.h>
4354359Sroberto#include <machine/resource.h>
4454359Sroberto#include <sys/rman.h>
4554359Sroberto
4654359Sroberto#include <net/bpf.h>
4754359Sroberto#include <net/if.h>
4854359Sroberto#include <net/if_var.h>
4954359Sroberto#include <net/if_arp.h>
5054359Sroberto#include <net/ethernet.h>
5154359Sroberto#include <net/if_dl.h>
5254359Sroberto#include <net/if_media.h>
5354359Sroberto#include <net/if_types.h>
5454359Sroberto
5554359Sroberto#include <net80211/ieee80211_var.h>
5654359Sroberto#include <net80211/ieee80211_radiotap.h>
5754359Sroberto#include <net80211/ieee80211_regdomain.h>
5854359Sroberto#include <net80211/ieee80211_ratectl.h>
5954359Sroberto
6054359Sroberto#include <netinet/in.h>
6154359Sroberto#include <netinet/in_systm.h>
6254359Sroberto#include <netinet/in_var.h>
6354359Sroberto#include <netinet/ip.h>
6454359Sroberto#include <netinet/if_ether.h>
6554359Sroberto
6654359Sroberto#include <dev/ral/rt2560reg.h>
6754359Sroberto#include <dev/ral/rt2560var.h>
6854359Sroberto
6954359Sroberto#define RT2560_RSSI(sc, rssi)					\
7054359Sroberto	((rssi) > (RT2560_NOISE_FLOOR + (sc)->rssi_corr) ?	\
7154359Sroberto	 ((rssi) - RT2560_NOISE_FLOOR - (sc)->rssi_corr) : 0)
7254359Sroberto
7354359Sroberto#define RAL_DEBUG
7454359Sroberto#ifdef RAL_DEBUG
7554359Sroberto#define DPRINTF(sc, fmt, ...) do {				\
7654359Sroberto	if (sc->sc_debug > 0)					\
7754359Sroberto		printf(fmt, __VA_ARGS__);			\
7854359Sroberto} while (0)
7954359Sroberto#define DPRINTFN(sc, n, fmt, ...) do {				\
8054359Sroberto	if (sc->sc_debug >= (n))				\
8154359Sroberto		printf(fmt, __VA_ARGS__);			\
8254359Sroberto} while (0)
8354359Sroberto#else
8454359Sroberto#define DPRINTF(sc, fmt, ...)
8554359Sroberto#define DPRINTFN(sc, n, fmt, ...)
8654359Sroberto#endif
8754359Sroberto
8854359Srobertostatic struct ieee80211vap *rt2560_vap_create(struct ieee80211com *,
8954359Sroberto			    const char [IFNAMSIZ], int, enum ieee80211_opmode,
9054359Sroberto			    int, const uint8_t [IEEE80211_ADDR_LEN],
9154359Sroberto			    const uint8_t [IEEE80211_ADDR_LEN]);
9254359Srobertostatic void		rt2560_vap_delete(struct ieee80211vap *);
9354359Srobertostatic void		rt2560_dma_map_addr(void *, bus_dma_segment_t *, int,
9454359Sroberto			    int);
9554359Srobertostatic int		rt2560_alloc_tx_ring(struct rt2560_softc *,
9654359Sroberto			    struct rt2560_tx_ring *, int);
9754359Srobertostatic void		rt2560_reset_tx_ring(struct rt2560_softc *,
9854359Sroberto			    struct rt2560_tx_ring *);
9954359Srobertostatic void		rt2560_free_tx_ring(struct rt2560_softc *,
10054359Sroberto			    struct rt2560_tx_ring *);
10154359Srobertostatic int		rt2560_alloc_rx_ring(struct rt2560_softc *,
10254359Sroberto			    struct rt2560_rx_ring *, int);
10354359Srobertostatic void		rt2560_reset_rx_ring(struct rt2560_softc *,
10454359Sroberto			    struct rt2560_rx_ring *);
10554359Srobertostatic void		rt2560_free_rx_ring(struct rt2560_softc *,
10654359Sroberto			    struct rt2560_rx_ring *);
10754359Srobertostatic int		rt2560_newstate(struct ieee80211vap *,
10854359Sroberto			    enum ieee80211_state, int);
10954359Srobertostatic uint16_t		rt2560_eeprom_read(struct rt2560_softc *, uint8_t);
11054359Srobertostatic void		rt2560_encryption_intr(struct rt2560_softc *);
11154359Srobertostatic void		rt2560_tx_intr(struct rt2560_softc *);
11254359Srobertostatic void		rt2560_prio_intr(struct rt2560_softc *);
11354359Srobertostatic void		rt2560_decryption_intr(struct rt2560_softc *);
11454359Srobertostatic void		rt2560_rx_intr(struct rt2560_softc *);
11554359Srobertostatic void		rt2560_beacon_update(struct ieee80211vap *, int item);
11654359Srobertostatic void		rt2560_beacon_expire(struct rt2560_softc *);
11754359Srobertostatic void		rt2560_wakeup_expire(struct rt2560_softc *);
11854359Srobertostatic void		rt2560_scan_start(struct ieee80211com *);
11954359Srobertostatic void		rt2560_scan_end(struct ieee80211com *);
12054359Srobertostatic void		rt2560_set_channel(struct ieee80211com *);
12154359Srobertostatic void		rt2560_setup_tx_desc(struct rt2560_softc *,
12254359Sroberto			    struct rt2560_tx_desc *, uint32_t, int, int, int,
12354359Sroberto			    bus_addr_t);
12454359Srobertostatic int		rt2560_tx_bcn(struct rt2560_softc *, struct mbuf *,
12554359Sroberto			    struct ieee80211_node *);
12654359Srobertostatic int		rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
12754359Sroberto			    struct ieee80211_node *);
12854359Srobertostatic int		rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
12954359Sroberto			    struct ieee80211_node *);
13054359Srobertostatic int		rt2560_transmit(struct ieee80211com *, struct mbuf *);
13154359Srobertostatic void		rt2560_start(struct rt2560_softc *);
13254359Srobertostatic void		rt2560_watchdog(void *);
13354359Srobertostatic void		rt2560_parent(struct ieee80211com *);
13454359Srobertostatic void		rt2560_bbp_write(struct rt2560_softc *, uint8_t,
13554359Sroberto			    uint8_t);
13654359Srobertostatic uint8_t		rt2560_bbp_read(struct rt2560_softc *, uint8_t);
13754359Srobertostatic void		rt2560_rf_write(struct rt2560_softc *, uint8_t,
13854359Sroberto			    uint32_t);
13954359Srobertostatic void		rt2560_set_chan(struct rt2560_softc *,
14054359Sroberto			    struct ieee80211_channel *);
14154359Sroberto#if 0
14254359Srobertostatic void		rt2560_disable_rf_tune(struct rt2560_softc *);
14354359Sroberto#endif
14454359Srobertostatic void		rt2560_enable_tsf_sync(struct rt2560_softc *);
14554359Srobertostatic void		rt2560_enable_tsf(struct rt2560_softc *);
14654359Srobertostatic void		rt2560_update_plcp(struct rt2560_softc *);
14754359Srobertostatic void		rt2560_update_slot(struct ieee80211com *);
14854359Srobertostatic void		rt2560_set_basicrates(struct rt2560_softc *,
14954359Sroberto			    const struct ieee80211_rateset *);
15054359Srobertostatic void		rt2560_update_led(struct rt2560_softc *, int, int);
15154359Srobertostatic void		rt2560_set_bssid(struct rt2560_softc *, const uint8_t *);
15254359Srobertostatic void		rt2560_set_macaddr(struct rt2560_softc *,
15354359Sroberto			    const uint8_t *);
15454359Srobertostatic void		rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
15554359Srobertostatic void		rt2560_update_promisc(struct ieee80211com *);
15654359Srobertostatic const char	*rt2560_get_rf(int);
15754359Srobertostatic void		rt2560_read_config(struct rt2560_softc *);
15854359Srobertostatic int		rt2560_bbp_init(struct rt2560_softc *);
15954359Srobertostatic void		rt2560_set_txantenna(struct rt2560_softc *, int);
16054359Srobertostatic void		rt2560_set_rxantenna(struct rt2560_softc *, int);
16154359Srobertostatic void		rt2560_init_locked(struct rt2560_softc *);
16254359Srobertostatic void		rt2560_init(void *);
16354359Srobertostatic void		rt2560_stop_locked(struct rt2560_softc *);
16454359Srobertostatic int		rt2560_raw_xmit(struct ieee80211_node *, struct mbuf *,
16554359Sroberto				const struct ieee80211_bpf_params *);
16654359Sroberto
16754359Srobertostatic const struct {
16854359Sroberto	uint32_t	reg;
16954359Sroberto	uint32_t	val;
17054359Sroberto} rt2560_def_mac[] = {
17154359Sroberto	RT2560_DEF_MAC
17254359Sroberto};
17354359Sroberto
17454359Srobertostatic const struct {
17554359Sroberto	uint8_t	reg;
17654359Sroberto	uint8_t	val;
17754359Sroberto} rt2560_def_bbp[] = {
17854359Sroberto	RT2560_DEF_BBP
17954359Sroberto};
18054359Sroberto
18154359Srobertostatic const uint32_t rt2560_rf2522_r2[]    = RT2560_RF2522_R2;
18254359Srobertostatic const uint32_t rt2560_rf2523_r2[]    = RT2560_RF2523_R2;
18354359Srobertostatic const uint32_t rt2560_rf2524_r2[]    = RT2560_RF2524_R2;
18454359Srobertostatic const uint32_t rt2560_rf2525_r2[]    = RT2560_RF2525_R2;
18554359Srobertostatic const uint32_t rt2560_rf2525_hi_r2[] = RT2560_RF2525_HI_R2;
18654359Srobertostatic const uint32_t rt2560_rf2525e_r2[]   = RT2560_RF2525E_R2;
18754359Srobertostatic const uint32_t rt2560_rf2526_r2[]    = RT2560_RF2526_R2;
18854359Srobertostatic const uint32_t rt2560_rf2526_hi_r2[] = RT2560_RF2526_HI_R2;
18954359Sroberto
19054359Srobertostatic const struct {
19154359Sroberto	uint8_t		chan;
19254359Sroberto	uint32_t	r1, r2, r4;
19354359Sroberto} rt2560_rf5222[] = {
19454359Sroberto	RT2560_RF5222
19554359Sroberto};
19654359Sroberto
19754359Srobertoint
19854359Srobertort2560_attach(device_t dev, int id)
19954359Sroberto{
20054359Sroberto	struct rt2560_softc *sc = device_get_softc(dev);
20154359Sroberto	struct ieee80211com *ic = &sc->sc_ic;
20254359Sroberto	uint8_t bands[IEEE80211_MODE_BYTES];
20354359Sroberto	int error;
20454359Sroberto
20554359Sroberto	sc->sc_dev = dev;
20654359Sroberto
20754359Sroberto	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
20854359Sroberto	    MTX_DEF | MTX_RECURSE);
20954359Sroberto
21054359Sroberto	callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
21154359Sroberto	mbufq_init(&sc->sc_snd, ifqmaxlen);
21254359Sroberto
21354359Sroberto	/* retrieve RT2560 rev. no */
21454359Sroberto	sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
21554359Sroberto
21654359Sroberto	/* retrieve RF rev. no and various other things from EEPROM */
21754359Sroberto	rt2560_read_config(sc);
21854359Sroberto
21954359Sroberto	device_printf(dev, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n",
22054359Sroberto	    sc->asic_rev, rt2560_get_rf(sc->rf_rev));
22154359Sroberto
22254359Sroberto	/*
22354359Sroberto	 * Allocate Tx and Rx rings.
22454359Sroberto	 */
22554359Sroberto	error = rt2560_alloc_tx_ring(sc, &sc->txq, RT2560_TX_RING_COUNT);
22654359Sroberto	if (error != 0) {
22754359Sroberto		device_printf(sc->sc_dev, "could not allocate Tx ring\n");
22854359Sroberto		goto fail1;
22954359Sroberto	}
23054359Sroberto
23154359Sroberto	error = rt2560_alloc_tx_ring(sc, &sc->atimq, RT2560_ATIM_RING_COUNT);
23254359Sroberto	if (error != 0) {
23354359Sroberto		device_printf(sc->sc_dev, "could not allocate ATIM ring\n");
23454359Sroberto		goto fail2;
23554359Sroberto	}
23654359Sroberto
23754359Sroberto	error = rt2560_alloc_tx_ring(sc, &sc->prioq, RT2560_PRIO_RING_COUNT);
23854359Sroberto	if (error != 0) {
23954359Sroberto		device_printf(sc->sc_dev, "could not allocate Prio ring\n");
24054359Sroberto		goto fail3;
24154359Sroberto	}
24254359Sroberto
24354359Sroberto	error = rt2560_alloc_tx_ring(sc, &sc->bcnq, RT2560_BEACON_RING_COUNT);
24454359Sroberto	if (error != 0) {
24554359Sroberto		device_printf(sc->sc_dev, "could not allocate Beacon ring\n");
24654359Sroberto		goto fail4;
24754359Sroberto	}
24854359Sroberto
24954359Sroberto	error = rt2560_alloc_rx_ring(sc, &sc->rxq, RT2560_RX_RING_COUNT);
25054359Sroberto	if (error != 0) {
25154359Sroberto		device_printf(sc->sc_dev, "could not allocate Rx ring\n");
25254359Sroberto		goto fail5;
25354359Sroberto	}
25454359Sroberto
25554359Sroberto	/* retrieve MAC address */
25654359Sroberto	rt2560_get_macaddr(sc, ic->ic_macaddr);
25754359Sroberto
25854359Sroberto	ic->ic_softc = sc;
25954359Sroberto	ic->ic_name = device_get_nameunit(dev);
26054359Sroberto	ic->ic_opmode = IEEE80211_M_STA;
26154359Sroberto	ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
26254359Sroberto
26354359Sroberto	/* set device capabilities */
26454359Sroberto	ic->ic_caps =
26554359Sroberto		  IEEE80211_C_STA		/* station mode */
26654359Sroberto		| IEEE80211_C_IBSS		/* ibss, nee adhoc, mode */
26754359Sroberto		| IEEE80211_C_HOSTAP		/* hostap mode */
26854359Sroberto		| IEEE80211_C_MONITOR		/* monitor mode */
26954359Sroberto		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
27054359Sroberto		| IEEE80211_C_WDS		/* 4-address traffic works */
27154359Sroberto		| IEEE80211_C_MBSS		/* mesh point link mode */
27254359Sroberto		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
27354359Sroberto		| IEEE80211_C_SHSLOT		/* short slot time supported */
27454359Sroberto		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
27554359Sroberto		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
27654359Sroberto#ifdef notyet
27754359Sroberto		| IEEE80211_C_TXFRAG		/* handle tx frags */
27854359Sroberto#endif
27954359Sroberto		;
28054359Sroberto
28154359Sroberto	memset(bands, 0, sizeof(bands));
28254359Sroberto	setbit(bands, IEEE80211_MODE_11B);
28354359Sroberto	setbit(bands, IEEE80211_MODE_11G);
28454359Sroberto	if (sc->rf_rev == RT2560_RF_5222)
28554359Sroberto		setbit(bands, IEEE80211_MODE_11A);
28654359Sroberto	ieee80211_init_channels(ic, NULL, bands);
28754359Sroberto
28854359Sroberto	ieee80211_ifattach(ic);
28954359Sroberto	ic->ic_raw_xmit = rt2560_raw_xmit;
29054359Sroberto	ic->ic_updateslot = rt2560_update_slot;
29154359Sroberto	ic->ic_update_promisc = rt2560_update_promisc;
29254359Sroberto	ic->ic_scan_start = rt2560_scan_start;
29354359Sroberto	ic->ic_scan_end = rt2560_scan_end;
29454359Sroberto	ic->ic_set_channel = rt2560_set_channel;
29554359Sroberto
29654359Sroberto	ic->ic_vap_create = rt2560_vap_create;
29754359Sroberto	ic->ic_vap_delete = rt2560_vap_delete;
29854359Sroberto	ic->ic_parent = rt2560_parent;
29954359Sroberto	ic->ic_transmit = rt2560_transmit;
30054359Sroberto
30154359Sroberto	ieee80211_radiotap_attach(ic,
30254359Sroberto	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
30354359Sroberto		RT2560_TX_RADIOTAP_PRESENT,
30454359Sroberto	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
30554359Sroberto		RT2560_RX_RADIOTAP_PRESENT);
30654359Sroberto
30754359Sroberto	/*
30854359Sroberto	 * Add a few sysctl knobs.
30954359Sroberto	 */
31054359Sroberto#ifdef RAL_DEBUG
31154359Sroberto	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
31254359Sroberto	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
31354359Sroberto	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug msgs");
31454359Sroberto#endif
31554359Sroberto	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
31654359Sroberto	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
31754359Sroberto	    "txantenna", CTLFLAG_RW, &sc->tx_ant, 0, "tx antenna (0=auto)");
31854359Sroberto
31954359Sroberto	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
32054359Sroberto	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
32154359Sroberto	    "rxantenna", CTLFLAG_RW, &sc->rx_ant, 0, "rx antenna (0=auto)");
32254359Sroberto
32354359Sroberto	if (bootverbose)
32454359Sroberto		ieee80211_announce(ic);
32554359Sroberto
32654359Sroberto	return 0;
32754359Sroberto
32854359Srobertofail5:	rt2560_free_tx_ring(sc, &sc->bcnq);
32954359Srobertofail4:	rt2560_free_tx_ring(sc, &sc->prioq);
33054359Srobertofail3:	rt2560_free_tx_ring(sc, &sc->atimq);
33154359Srobertofail2:	rt2560_free_tx_ring(sc, &sc->txq);
33254359Srobertofail1:	mtx_destroy(&sc->sc_mtx);
33354359Sroberto
33454359Sroberto	return ENXIO;
33554359Sroberto}
33654359Sroberto
33754359Srobertoint
33854359Srobertort2560_detach(void *xsc)
33954359Sroberto{
34054359Sroberto	struct rt2560_softc *sc = xsc;
34154359Sroberto	struct ieee80211com *ic = &sc->sc_ic;
34254359Sroberto
34354359Sroberto	rt2560_stop(sc);
34454359Sroberto
34554359Sroberto	ieee80211_ifdetach(ic);
34654359Sroberto	mbufq_drain(&sc->sc_snd);
34754359Sroberto
34854359Sroberto	rt2560_free_tx_ring(sc, &sc->txq);
34954359Sroberto	rt2560_free_tx_ring(sc, &sc->atimq);
35054359Sroberto	rt2560_free_tx_ring(sc, &sc->prioq);
35154359Sroberto	rt2560_free_tx_ring(sc, &sc->bcnq);
35254359Sroberto	rt2560_free_rx_ring(sc, &sc->rxq);
35354359Sroberto
35454359Sroberto	mtx_destroy(&sc->sc_mtx);
35554359Sroberto
35654359Sroberto	return 0;
35754359Sroberto}
35854359Sroberto
35954359Srobertostatic struct ieee80211vap *
36054359Srobertort2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
36154359Sroberto    enum ieee80211_opmode opmode, int flags,
36254359Sroberto    const uint8_t bssid[IEEE80211_ADDR_LEN],
36354359Sroberto    const uint8_t mac[IEEE80211_ADDR_LEN])
36454359Sroberto{
36554359Sroberto	struct rt2560_softc *sc = ic->ic_softc;
36654359Sroberto	struct rt2560_vap *rvp;
36754359Sroberto	struct ieee80211vap *vap;
36854359Sroberto
36954359Sroberto	switch (opmode) {
37054359Sroberto	case IEEE80211_M_STA:
37154359Sroberto	case IEEE80211_M_IBSS:
37254359Sroberto	case IEEE80211_M_AHDEMO:
37354359Sroberto	case IEEE80211_M_MONITOR:
37454359Sroberto	case IEEE80211_M_HOSTAP:
37554359Sroberto	case IEEE80211_M_MBSS:
37654359Sroberto		/* XXXRP: TBD */
37754359Sroberto		if (!TAILQ_EMPTY(&ic->ic_vaps)) {
37854359Sroberto			device_printf(sc->sc_dev, "only 1 vap supported\n");
37954359Sroberto			return NULL;
38054359Sroberto		}
38154359Sroberto		if (opmode == IEEE80211_M_STA)
38254359Sroberto			flags |= IEEE80211_CLONE_NOBEACONS;
38354359Sroberto		break;
38454359Sroberto	case IEEE80211_M_WDS:
38554359Sroberto		if (TAILQ_EMPTY(&ic->ic_vaps) ||
38654359Sroberto		    ic->ic_opmode != IEEE80211_M_HOSTAP) {
38754359Sroberto			device_printf(sc->sc_dev,
38854359Sroberto			    "wds only supported in ap mode\n");
38954359Sroberto			return NULL;
39054359Sroberto		}
39154359Sroberto		/*
39254359Sroberto		 * Silently remove any request for a unique
39354359Sroberto		 * bssid; WDS vap's always share the local
39454359Sroberto		 * mac address.
39554359Sroberto		 */
39654359Sroberto		flags &= ~IEEE80211_CLONE_BSSID;
39754359Sroberto		break;
39854359Sroberto	default:
39954359Sroberto		device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
40054359Sroberto		return NULL;
40154359Sroberto	}
40254359Sroberto	rvp = malloc(sizeof(struct rt2560_vap), M_80211_VAP, M_WAITOK | M_ZERO);
40354359Sroberto	vap = &rvp->ral_vap;
40454359Sroberto	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
40554359Sroberto
40654359Sroberto	/* override state transition machine */
40754359Sroberto	rvp->ral_newstate = vap->iv_newstate;
40854359Sroberto	vap->iv_newstate = rt2560_newstate;
40954359Sroberto	vap->iv_update_beacon = rt2560_beacon_update;
41054359Sroberto
41154359Sroberto	ieee80211_ratectl_init(vap);
41254359Sroberto	/* complete setup */
41354359Sroberto	ieee80211_vap_attach(vap, ieee80211_media_change,
41454359Sroberto	    ieee80211_media_status, mac);
41554359Sroberto	if (TAILQ_FIRST(&ic->ic_vaps) == vap)
41654359Sroberto		ic->ic_opmode = opmode;
41754359Sroberto	return vap;
41854359Sroberto}
41954359Sroberto
42054359Srobertostatic void
42154359Srobertort2560_vap_delete(struct ieee80211vap *vap)
42254359Sroberto{
42354359Sroberto	struct rt2560_vap *rvp = RT2560_VAP(vap);
42454359Sroberto
42554359Sroberto	ieee80211_ratectl_deinit(vap);
42654359Sroberto	ieee80211_vap_detach(vap);
42754359Sroberto	free(rvp, M_80211_VAP);
42854359Sroberto}
42954359Sroberto
43054359Srobertovoid
43154359Srobertort2560_resume(void *xsc)
43254359Sroberto{
43354359Sroberto	struct rt2560_softc *sc = xsc;
43454359Sroberto
43554359Sroberto	if (sc->sc_ic.ic_nrunning > 0)
43654359Sroberto		rt2560_init(sc);
43754359Sroberto}
43854359Sroberto
43954359Srobertostatic void
44054359Srobertort2560_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
44154359Sroberto{
44254359Sroberto	if (error != 0)
44354359Sroberto		return;
44454359Sroberto
44554359Sroberto	KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
44654359Sroberto
44754359Sroberto	*(bus_addr_t *)arg = segs[0].ds_addr;
44854359Sroberto}
44954359Sroberto
45054359Srobertostatic int
45154359Srobertort2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring,
45254359Sroberto    int count)
45354359Sroberto{
45454359Sroberto	int i, error;
45554359Sroberto
45654359Sroberto	ring->count = count;
45754359Sroberto	ring->queued = 0;
45854359Sroberto	ring->cur = ring->next = 0;
45954359Sroberto	ring->cur_encrypt = ring->next_encrypt = 0;
46054359Sroberto
46154359Sroberto	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0,
46254359Sroberto	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
46354359Sroberto	    count * RT2560_TX_DESC_SIZE, 1, count * RT2560_TX_DESC_SIZE,
46454359Sroberto	    0, NULL, NULL, &ring->desc_dmat);
46554359Sroberto	if (error != 0) {
46654359Sroberto		device_printf(sc->sc_dev, "could not create desc DMA tag\n");
46754359Sroberto		goto fail;
46854359Sroberto	}
46954359Sroberto
47054359Sroberto	error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc,
47154359Sroberto	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map);
47254359Sroberto	if (error != 0) {
47354359Sroberto		device_printf(sc->sc_dev, "could not allocate DMA memory\n");
47454359Sroberto		goto fail;
47554359Sroberto	}
47654359Sroberto
47754359Sroberto	error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc,
47854359Sroberto	    count * RT2560_TX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr,
47954359Sroberto	    0);
48054359Sroberto	if (error != 0) {
48154359Sroberto		device_printf(sc->sc_dev, "could not load desc DMA map\n");
48254359Sroberto		goto fail;
48354359Sroberto	}
48454359Sroberto
48554359Sroberto	ring->data = malloc(count * sizeof (struct rt2560_tx_data), M_DEVBUF,
48654359Sroberto	    M_NOWAIT | M_ZERO);
48754359Sroberto	if (ring->data == NULL) {
48854359Sroberto		device_printf(sc->sc_dev, "could not allocate soft data\n");
48954359Sroberto		error = ENOMEM;
49054359Sroberto		goto fail;
49154359Sroberto	}
49254359Sroberto
49354359Sroberto	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
49454359Sroberto	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
49554359Sroberto	    MCLBYTES, RT2560_MAX_SCATTER, MCLBYTES, 0, NULL, NULL,
49654359Sroberto	    &ring->data_dmat);
49754359Sroberto	if (error != 0) {
49854359Sroberto		device_printf(sc->sc_dev, "could not create data DMA tag\n");
49954359Sroberto		goto fail;
50054359Sroberto	}
50154359Sroberto
50254359Sroberto	for (i = 0; i < count; i++) {
50354359Sroberto		error = bus_dmamap_create(ring->data_dmat, 0,
50454359Sroberto		    &ring->data[i].map);
50554359Sroberto		if (error != 0) {
50654359Sroberto			device_printf(sc->sc_dev, "could not create DMA map\n");
50754359Sroberto			goto fail;
50854359Sroberto		}
50954359Sroberto	}
51054359Sroberto
51154359Sroberto	return 0;
51254359Sroberto
51354359Srobertofail:	rt2560_free_tx_ring(sc, ring);
51454359Sroberto	return error;
51554359Sroberto}
51654359Sroberto
51754359Srobertostatic void
51854359Srobertort2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
51954359Sroberto{
52054359Sroberto	struct rt2560_tx_desc *desc;
52154359Sroberto	struct rt2560_tx_data *data;
52254359Sroberto	int i;
52354359Sroberto
52454359Sroberto	for (i = 0; i < ring->count; i++) {
52554359Sroberto		desc = &ring->desc[i];
52654359Sroberto		data = &ring->data[i];
52754359Sroberto
52854359Sroberto		if (data->m != NULL) {
52954359Sroberto			bus_dmamap_sync(ring->data_dmat, data->map,
53054359Sroberto			    BUS_DMASYNC_POSTWRITE);
53154359Sroberto			bus_dmamap_unload(ring->data_dmat, data->map);
53254359Sroberto			m_freem(data->m);
53354359Sroberto			data->m = NULL;
53454359Sroberto		}
53554359Sroberto
53654359Sroberto		if (data->ni != NULL) {
53754359Sroberto			ieee80211_free_node(data->ni);
53854359Sroberto			data->ni = NULL;
53954359Sroberto		}
54054359Sroberto
54154359Sroberto		desc->flags = 0;
54254359Sroberto	}
54354359Sroberto
54454359Sroberto	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
54554359Sroberto
54654359Sroberto	ring->queued = 0;
54754359Sroberto	ring->cur = ring->next = 0;
54854359Sroberto	ring->cur_encrypt = ring->next_encrypt = 0;
54954359Sroberto}
55054359Sroberto
55154359Srobertostatic void
55254359Srobertort2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
55354359Sroberto{
55454359Sroberto	struct rt2560_tx_data *data;
55554359Sroberto	int i;
55654359Sroberto
55754359Sroberto	if (ring->desc != NULL) {
55854359Sroberto		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
55954359Sroberto		    BUS_DMASYNC_POSTWRITE);
56054359Sroberto		bus_dmamap_unload(ring->desc_dmat, ring->desc_map);
56154359Sroberto		bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map);
56254359Sroberto	}
56354359Sroberto
56454359Sroberto	if (ring->desc_dmat != NULL)
56554359Sroberto		bus_dma_tag_destroy(ring->desc_dmat);
56654359Sroberto
56754359Sroberto	if (ring->data != NULL) {
56854359Sroberto		for (i = 0; i < ring->count; i++) {
56954359Sroberto			data = &ring->data[i];
57054359Sroberto
57154359Sroberto			if (data->m != NULL) {
57254359Sroberto				bus_dmamap_sync(ring->data_dmat, data->map,
57354359Sroberto				    BUS_DMASYNC_POSTWRITE);
57454359Sroberto				bus_dmamap_unload(ring->data_dmat, data->map);
57554359Sroberto				m_freem(data->m);
57654359Sroberto			}
57754359Sroberto
57854359Sroberto			if (data->ni != NULL)
57954359Sroberto				ieee80211_free_node(data->ni);
58054359Sroberto
58154359Sroberto			if (data->map != NULL)
58254359Sroberto				bus_dmamap_destroy(ring->data_dmat, data->map);
58354359Sroberto		}
58454359Sroberto
58554359Sroberto		free(ring->data, M_DEVBUF);
58654359Sroberto	}
58754359Sroberto
58854359Sroberto	if (ring->data_dmat != NULL)
58954359Sroberto		bus_dma_tag_destroy(ring->data_dmat);
59054359Sroberto}
59154359Sroberto
59254359Srobertostatic int
59354359Srobertort2560_alloc_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring,
59454359Sroberto    int count)
59554359Sroberto{
59654359Sroberto	struct rt2560_rx_desc *desc;
59754359Sroberto	struct rt2560_rx_data *data;
59854359Sroberto	bus_addr_t physaddr;
59954359Sroberto	int i, error;
60054359Sroberto
60154359Sroberto	ring->count = count;
60254359Sroberto	ring->cur = ring->next = 0;
60354359Sroberto	ring->cur_decrypt = 0;
60454359Sroberto
60554359Sroberto	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0,
60654359Sroberto	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
60754359Sroberto	    count * RT2560_RX_DESC_SIZE, 1, count * RT2560_RX_DESC_SIZE,
60854359Sroberto	    0, NULL, NULL, &ring->desc_dmat);
60954359Sroberto	if (error != 0) {
61054359Sroberto		device_printf(sc->sc_dev, "could not create desc DMA tag\n");
61154359Sroberto		goto fail;
61254359Sroberto	}
61354359Sroberto
61454359Sroberto	error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc,
61554359Sroberto	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map);
61654359Sroberto	if (error != 0) {
61754359Sroberto		device_printf(sc->sc_dev, "could not allocate DMA memory\n");
61854359Sroberto		goto fail;
61954359Sroberto	}
62054359Sroberto
62154359Sroberto	error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc,
62254359Sroberto	    count * RT2560_RX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr,
62354359Sroberto	    0);
62454359Sroberto	if (error != 0) {
62554359Sroberto		device_printf(sc->sc_dev, "could not load desc DMA map\n");
62654359Sroberto		goto fail;
62754359Sroberto	}
62854359Sroberto
62954359Sroberto	ring->data = malloc(count * sizeof (struct rt2560_rx_data), M_DEVBUF,
63054359Sroberto	    M_NOWAIT | M_ZERO);
63154359Sroberto	if (ring->data == NULL) {
63254359Sroberto		device_printf(sc->sc_dev, "could not allocate soft data\n");
63354359Sroberto		error = ENOMEM;
63454359Sroberto		goto fail;
63554359Sroberto	}
63654359Sroberto
63754359Sroberto	/*
63854359Sroberto	 * Pre-allocate Rx buffers and populate Rx ring.
63954359Sroberto	 */
64054359Sroberto	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
64154359Sroberto	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
64254359Sroberto	    1, MCLBYTES, 0, NULL, NULL, &ring->data_dmat);
64354359Sroberto	if (error != 0) {
64454359Sroberto		device_printf(sc->sc_dev, "could not create data DMA tag\n");
64554359Sroberto		goto fail;
64654359Sroberto	}
64754359Sroberto
64854359Sroberto	for (i = 0; i < count; i++) {
64954359Sroberto		desc = &sc->rxq.desc[i];
65054359Sroberto		data = &sc->rxq.data[i];
65154359Sroberto
65254359Sroberto		error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
65354359Sroberto		if (error != 0) {
65454359Sroberto			device_printf(sc->sc_dev, "could not create DMA map\n");
65554359Sroberto			goto fail;
65654359Sroberto		}
65754359Sroberto
65854359Sroberto		data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
65954359Sroberto		if (data->m == NULL) {
66054359Sroberto			device_printf(sc->sc_dev,
66154359Sroberto			    "could not allocate rx mbuf\n");
66254359Sroberto			error = ENOMEM;
66354359Sroberto			goto fail;
66454359Sroberto		}
66554359Sroberto
66654359Sroberto		error = bus_dmamap_load(ring->data_dmat, data->map,
66754359Sroberto		    mtod(data->m, void *), MCLBYTES, rt2560_dma_map_addr,
66854359Sroberto		    &physaddr, 0);
66954359Sroberto		if (error != 0) {
67054359Sroberto			device_printf(sc->sc_dev,
67154359Sroberto			    "could not load rx buf DMA map");
67254359Sroberto			goto fail;
67354359Sroberto		}
67454359Sroberto
67554359Sroberto		desc->flags = htole32(RT2560_RX_BUSY);
67654359Sroberto		desc->physaddr = htole32(physaddr);
67754359Sroberto	}
67854359Sroberto
67954359Sroberto	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
68054359Sroberto
68154359Sroberto	return 0;
68254359Sroberto
68354359Srobertofail:	rt2560_free_rx_ring(sc, ring);
68454359Sroberto	return error;
68554359Sroberto}
68654359Sroberto
68754359Srobertostatic void
68854359Srobertort2560_reset_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring)
68954359Sroberto{
69054359Sroberto	int i;
69154359Sroberto
69254359Sroberto	for (i = 0; i < ring->count; i++) {
69354359Sroberto		ring->desc[i].flags = htole32(RT2560_RX_BUSY);
69454359Sroberto		ring->data[i].drop = 0;
69554359Sroberto	}
69654359Sroberto
69754359Sroberto	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
69854359Sroberto
69954359Sroberto	ring->cur = ring->next = 0;
70054359Sroberto	ring->cur_decrypt = 0;
70154359Sroberto}
70254359Sroberto
70354359Srobertostatic void
70454359Srobertort2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring)
70554359Sroberto{
70654359Sroberto	struct rt2560_rx_data *data;
70754359Sroberto	int i;
70854359Sroberto
70954359Sroberto	if (ring->desc != NULL) {
71054359Sroberto		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
71154359Sroberto		    BUS_DMASYNC_POSTWRITE);
71254359Sroberto		bus_dmamap_unload(ring->desc_dmat, ring->desc_map);
71354359Sroberto		bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map);
71454359Sroberto	}
71554359Sroberto
71654359Sroberto	if (ring->desc_dmat != NULL)
71754359Sroberto		bus_dma_tag_destroy(ring->desc_dmat);
71854359Sroberto
71954359Sroberto	if (ring->data != NULL) {
72054359Sroberto		for (i = 0; i < ring->count; i++) {
72154359Sroberto			data = &ring->data[i];
72254359Sroberto
72354359Sroberto			if (data->m != NULL) {
72454359Sroberto				bus_dmamap_sync(ring->data_dmat, data->map,
72554359Sroberto				    BUS_DMASYNC_POSTREAD);
72654359Sroberto				bus_dmamap_unload(ring->data_dmat, data->map);
72754359Sroberto				m_freem(data->m);
72854359Sroberto			}
72954359Sroberto
73054359Sroberto			if (data->map != NULL)
73154359Sroberto				bus_dmamap_destroy(ring->data_dmat, data->map);
73254359Sroberto		}
73354359Sroberto
73454359Sroberto		free(ring->data, M_DEVBUF);
73554359Sroberto	}
73654359Sroberto
73754359Sroberto	if (ring->data_dmat != NULL)
73854359Sroberto		bus_dma_tag_destroy(ring->data_dmat);
73954359Sroberto}
74054359Sroberto
74154359Srobertostatic int
74254359Srobertort2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
74354359Sroberto{
74454359Sroberto	struct rt2560_vap *rvp = RT2560_VAP(vap);
74554359Sroberto	struct rt2560_softc *sc = vap->iv_ic->ic_softc;
74654359Sroberto	int error;
74754359Sroberto
74854359Sroberto	if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
74954359Sroberto		/* abort TSF synchronization */
75054359Sroberto		RAL_WRITE(sc, RT2560_CSR14, 0);
75154359Sroberto
75254359Sroberto		/* turn association led off */
75354359Sroberto		rt2560_update_led(sc, 0, 0);
75454359Sroberto	}
75554359Sroberto
75654359Sroberto	error = rvp->ral_newstate(vap, nstate, arg);
75754359Sroberto
75854359Sroberto	if (error == 0 && nstate == IEEE80211_S_RUN) {
75954359Sroberto		struct ieee80211_node *ni = vap->iv_bss;
76054359Sroberto		struct mbuf *m;
76154359Sroberto
76254359Sroberto		if (vap->iv_opmode != IEEE80211_M_MONITOR) {
76354359Sroberto			rt2560_update_plcp(sc);
76454359Sroberto			rt2560_set_basicrates(sc, &ni->ni_rates);
76554359Sroberto			rt2560_set_bssid(sc, ni->ni_bssid);
76654359Sroberto		}
76754359Sroberto
76854359Sroberto		if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
76954359Sroberto		    vap->iv_opmode == IEEE80211_M_IBSS ||
77054359Sroberto		    vap->iv_opmode == IEEE80211_M_MBSS) {
77154359Sroberto			m = ieee80211_beacon_alloc(ni);
77254359Sroberto			if (m == NULL) {
77354359Sroberto				device_printf(sc->sc_dev,
77454359Sroberto				    "could not allocate beacon\n");
77554359Sroberto				return ENOBUFS;
77654359Sroberto			}
77754359Sroberto			ieee80211_ref_node(ni);
77854359Sroberto			error = rt2560_tx_bcn(sc, m, ni);
77954359Sroberto			if (error != 0)
78054359Sroberto				return error;
78154359Sroberto		}
78254359Sroberto
78354359Sroberto		/* turn assocation led on */
78454359Sroberto		rt2560_update_led(sc, 1, 0);
78554359Sroberto
78654359Sroberto		if (vap->iv_opmode != IEEE80211_M_MONITOR)
78754359Sroberto			rt2560_enable_tsf_sync(sc);
78854359Sroberto		else
78954359Sroberto			rt2560_enable_tsf(sc);
79054359Sroberto	}
79154359Sroberto	return error;
79254359Sroberto}
79354359Sroberto
79454359Sroberto/*
79554359Sroberto * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
79654359Sroberto * 93C66).
79754359Sroberto */
79854359Srobertostatic uint16_t
79954359Srobertort2560_eeprom_read(struct rt2560_softc *sc, uint8_t addr)
80054359Sroberto{
80154359Sroberto	uint32_t tmp;
80254359Sroberto	uint16_t val;
80354359Sroberto	int n;
80454359Sroberto
80554359Sroberto	/* clock C once before the first command */
80654359Sroberto	RT2560_EEPROM_CTL(sc, 0);
80754359Sroberto
80854359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S);
80954359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
81054359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S);
81154359Sroberto
81254359Sroberto	/* write start bit (1) */
81354359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D);
81454359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C);
81554359Sroberto
81654359Sroberto	/* write READ opcode (10) */
81754359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D);
81854359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C);
81954359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S);
82054359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
82154359Sroberto
82254359Sroberto	/* write address (A5-A0 or A7-A0) */
82354359Sroberto	n = (RAL_READ(sc, RT2560_CSR21) & RT2560_93C46) ? 5 : 7;
82454359Sroberto	for (; n >= 0; n--) {
82554359Sroberto		RT2560_EEPROM_CTL(sc, RT2560_S |
82654359Sroberto		    (((addr >> n) & 1) << RT2560_SHIFT_D));
82754359Sroberto		RT2560_EEPROM_CTL(sc, RT2560_S |
82854359Sroberto		    (((addr >> n) & 1) << RT2560_SHIFT_D) | RT2560_C);
82954359Sroberto	}
83054359Sroberto
83154359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S);
83254359Sroberto
83354359Sroberto	/* read data Q15-Q0 */
83454359Sroberto	val = 0;
83554359Sroberto	for (n = 15; n >= 0; n--) {
83654359Sroberto		RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
83754359Sroberto		tmp = RAL_READ(sc, RT2560_CSR21);
83854359Sroberto		val |= ((tmp & RT2560_Q) >> RT2560_SHIFT_Q) << n;
83954359Sroberto		RT2560_EEPROM_CTL(sc, RT2560_S);
84054359Sroberto	}
84154359Sroberto
84254359Sroberto	RT2560_EEPROM_CTL(sc, 0);
84354359Sroberto
84454359Sroberto	/* clear Chip Select and clock C */
84554359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_S);
84654359Sroberto	RT2560_EEPROM_CTL(sc, 0);
84754359Sroberto	RT2560_EEPROM_CTL(sc, RT2560_C);
84854359Sroberto
84954359Sroberto	return val;
85054359Sroberto}
85154359Sroberto
85254359Sroberto/*
85354359Sroberto * Some frames were processed by the hardware cipher engine and are ready for
85454359Sroberto * transmission.
85554359Sroberto */
85654359Srobertostatic void
85754359Srobertort2560_encryption_intr(struct rt2560_softc *sc)
85854359Sroberto{
85954359Sroberto	struct rt2560_tx_desc *desc;
86054359Sroberto	int hw;
86154359Sroberto
86254359Sroberto	/* retrieve last descriptor index processed by cipher engine */
86354359Sroberto	hw = RAL_READ(sc, RT2560_SECCSR1) - sc->txq.physaddr;
86454359Sroberto	hw /= RT2560_TX_DESC_SIZE;
86554359Sroberto
86654359Sroberto	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
86754359Sroberto	    BUS_DMASYNC_POSTREAD);
86854359Sroberto
86954359Sroberto	while (sc->txq.next_encrypt != hw) {
87054359Sroberto		if (sc->txq.next_encrypt == sc->txq.cur_encrypt) {
87154359Sroberto			printf("hw encrypt %d, cur_encrypt %d\n", hw,
87254359Sroberto			    sc->txq.cur_encrypt);
87354359Sroberto			break;
87454359Sroberto		}
87554359Sroberto
87654359Sroberto		desc = &sc->txq.desc[sc->txq.next_encrypt];
87754359Sroberto
87854359Sroberto		if ((le32toh(desc->flags) & RT2560_TX_BUSY) ||
87954359Sroberto		    (le32toh(desc->flags) & RT2560_TX_CIPHER_BUSY))
88054359Sroberto			break;
88154359Sroberto
88254359Sroberto		/* for TKIP, swap eiv field to fix a bug in ASIC */
88354359Sroberto		if ((le32toh(desc->flags) & RT2560_TX_CIPHER_MASK) ==
88454359Sroberto		    RT2560_TX_CIPHER_TKIP)
88554359Sroberto			desc->eiv = bswap32(desc->eiv);
88654359Sroberto
88754359Sroberto		/* mark the frame ready for transmission */
88854359Sroberto		desc->flags |= htole32(RT2560_TX_VALID);
88954359Sroberto		desc->flags |= htole32(RT2560_TX_BUSY);
89054359Sroberto
89154359Sroberto		DPRINTFN(sc, 15, "encryption done idx=%u\n",
89254359Sroberto		    sc->txq.next_encrypt);
89354359Sroberto
89454359Sroberto		sc->txq.next_encrypt =
89554359Sroberto		    (sc->txq.next_encrypt + 1) % RT2560_TX_RING_COUNT;
89654359Sroberto	}
89754359Sroberto
89854359Sroberto	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
89954359Sroberto	    BUS_DMASYNC_PREWRITE);
90054359Sroberto
90154359Sroberto	/* kick Tx */
90254359Sroberto	RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_TX);
90354359Sroberto}
90454359Sroberto
90554359Srobertostatic void
90654359Srobertort2560_tx_intr(struct rt2560_softc *sc)
90754359Sroberto{
90854359Sroberto	struct rt2560_tx_desc *desc;
90954359Sroberto	struct rt2560_tx_data *data;
91054359Sroberto	struct mbuf *m;
91154359Sroberto	struct ieee80211vap *vap;
91254359Sroberto	struct ieee80211_node *ni;
91354359Sroberto	uint32_t flags;
91454359Sroberto	int retrycnt, status;
91554359Sroberto
91654359Sroberto	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
91754359Sroberto	    BUS_DMASYNC_POSTREAD);
91854359Sroberto
91954359Sroberto	for (;;) {
92054359Sroberto		desc = &sc->txq.desc[sc->txq.next];
92154359Sroberto		data = &sc->txq.data[sc->txq.next];
92254359Sroberto
92354359Sroberto		flags = le32toh(desc->flags);
92454359Sroberto		if ((flags & RT2560_TX_BUSY) ||
92554359Sroberto		    (flags & RT2560_TX_CIPHER_BUSY) ||
92654359Sroberto		    !(flags & RT2560_TX_VALID))
92754359Sroberto			break;
92854359Sroberto
92954359Sroberto		m = data->m;
93054359Sroberto		ni = data->ni;
93154359Sroberto		vap = ni->ni_vap;
93254359Sroberto
93354359Sroberto		switch (flags & RT2560_TX_RESULT_MASK) {
93454359Sroberto		case RT2560_TX_SUCCESS:
93554359Sroberto			retrycnt = 0;
93654359Sroberto
93754359Sroberto			DPRINTFN(sc, 10, "%s\n", "data frame sent successfully");
93854359Sroberto			if (data->rix != IEEE80211_FIXED_RATE_NONE)
93954359Sroberto				ieee80211_ratectl_tx_complete(vap, ni,
94054359Sroberto				    IEEE80211_RATECTL_TX_SUCCESS,
94154359Sroberto				    &retrycnt, NULL);
94254359Sroberto			status = 0;
94354359Sroberto			break;
94454359Sroberto
94554359Sroberto		case RT2560_TX_SUCCESS_RETRY:
94654359Sroberto			retrycnt = RT2560_TX_RETRYCNT(flags);
94754359Sroberto
94854359Sroberto			DPRINTFN(sc, 9, "data frame sent after %u retries\n",
94954359Sroberto			    retrycnt);
95054359Sroberto			if (data->rix != IEEE80211_FIXED_RATE_NONE)
95154359Sroberto				ieee80211_ratectl_tx_complete(vap, ni,
95254359Sroberto				    IEEE80211_RATECTL_TX_SUCCESS,
95354359Sroberto				    &retrycnt, NULL);
95454359Sroberto			status = 0;
95554359Sroberto			break;
95654359Sroberto
95754359Sroberto		case RT2560_TX_FAIL_RETRY:
95854359Sroberto			retrycnt = RT2560_TX_RETRYCNT(flags);
95954359Sroberto
96054359Sroberto			DPRINTFN(sc, 9, "data frame failed after %d retries\n",
96154359Sroberto			    retrycnt);
96254359Sroberto			if (data->rix != IEEE80211_FIXED_RATE_NONE)
96354359Sroberto				ieee80211_ratectl_tx_complete(vap, ni,
96454359Sroberto				    IEEE80211_RATECTL_TX_FAILURE,
96554359Sroberto				    &retrycnt, NULL);
96654359Sroberto			status = 1;
96754359Sroberto			break;
96854359Sroberto
96954359Sroberto		case RT2560_TX_FAIL_INVALID:
97054359Sroberto		case RT2560_TX_FAIL_OTHER:
97154359Sroberto		default:
97254359Sroberto			device_printf(sc->sc_dev, "sending data frame failed "
97354359Sroberto			    "0x%08x\n", flags);
97454359Sroberto			status = 1;
97554359Sroberto		}
97654359Sroberto
97754359Sroberto		bus_dmamap_sync(sc->txq.data_dmat, data->map,
97854359Sroberto		    BUS_DMASYNC_POSTWRITE);
97954359Sroberto		bus_dmamap_unload(sc->txq.data_dmat, data->map);
98054359Sroberto
98154359Sroberto		ieee80211_tx_complete(ni, m, status);
98254359Sroberto		data->ni = NULL;
98354359Sroberto		data->m = NULL;
98454359Sroberto
98554359Sroberto		/* descriptor is no longer valid */
98654359Sroberto		desc->flags &= ~htole32(RT2560_TX_VALID);
98754359Sroberto
98854359Sroberto		DPRINTFN(sc, 15, "tx done idx=%u\n", sc->txq.next);
98954359Sroberto
99054359Sroberto		sc->txq.queued--;
99154359Sroberto		sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT;
99254359Sroberto	}
99354359Sroberto
99454359Sroberto	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
99554359Sroberto	    BUS_DMASYNC_PREWRITE);
99654359Sroberto
99754359Sroberto	if (sc->prioq.queued == 0 && sc->txq.queued == 0)
99854359Sroberto		sc->sc_tx_timer = 0;
99954359Sroberto
100054359Sroberto	if (sc->txq.queued < RT2560_TX_RING_COUNT - 1)
100154359Sroberto		rt2560_start(sc);
100254359Sroberto}
100354359Sroberto
100454359Srobertostatic void
100554359Srobertort2560_prio_intr(struct rt2560_softc *sc)
100654359Sroberto{
100754359Sroberto	struct rt2560_tx_desc *desc;
100854359Sroberto	struct rt2560_tx_data *data;
100954359Sroberto	struct ieee80211_node *ni;
101054359Sroberto	struct mbuf *m;
101154359Sroberto	int flags;
101254359Sroberto
101354359Sroberto	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
101454359Sroberto	    BUS_DMASYNC_POSTREAD);
101554359Sroberto
101654359Sroberto	for (;;) {
101754359Sroberto		desc = &sc->prioq.desc[sc->prioq.next];
101854359Sroberto		data = &sc->prioq.data[sc->prioq.next];
101954359Sroberto
102054359Sroberto		flags = le32toh(desc->flags);
102154359Sroberto		if ((flags & RT2560_TX_BUSY) || (flags & RT2560_TX_VALID) == 0)
102254359Sroberto			break;
102354359Sroberto
102454359Sroberto		switch (flags & RT2560_TX_RESULT_MASK) {
102554359Sroberto		case RT2560_TX_SUCCESS:
102654359Sroberto			DPRINTFN(sc, 10, "%s\n", "mgt frame sent successfully");
102754359Sroberto			break;
102854359Sroberto
102954359Sroberto		case RT2560_TX_SUCCESS_RETRY:
103054359Sroberto			DPRINTFN(sc, 9, "mgt frame sent after %u retries\n",
103154359Sroberto			    (flags >> 5) & 0x7);
103254359Sroberto			break;
103354359Sroberto
103454359Sroberto		case RT2560_TX_FAIL_RETRY:
103554359Sroberto			DPRINTFN(sc, 9, "%s\n",
103654359Sroberto			    "sending mgt frame failed (too much retries)");
103754359Sroberto			break;
103854359Sroberto
103954359Sroberto		case RT2560_TX_FAIL_INVALID:
104054359Sroberto		case RT2560_TX_FAIL_OTHER:
104154359Sroberto		default:
104254359Sroberto			device_printf(sc->sc_dev, "sending mgt frame failed "
104354359Sroberto			    "0x%08x\n", flags);
104454359Sroberto			break;
104554359Sroberto		}
104654359Sroberto
104754359Sroberto		bus_dmamap_sync(sc->prioq.data_dmat, data->map,
104854359Sroberto		    BUS_DMASYNC_POSTWRITE);
104954359Sroberto		bus_dmamap_unload(sc->prioq.data_dmat, data->map);
105054359Sroberto
105154359Sroberto		m = data->m;
105254359Sroberto		data->m = NULL;
105354359Sroberto		ni = data->ni;
105454359Sroberto		data->ni = NULL;
105554359Sroberto
105654359Sroberto		/* descriptor is no longer valid */
105754359Sroberto		desc->flags &= ~htole32(RT2560_TX_VALID);
105854359Sroberto
105954359Sroberto		DPRINTFN(sc, 15, "prio done idx=%u\n", sc->prioq.next);
106054359Sroberto
106154359Sroberto		sc->prioq.queued--;
106254359Sroberto		sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT;
106354359Sroberto
106454359Sroberto		if (m->m_flags & M_TXCB)
106554359Sroberto			ieee80211_process_callback(ni, m,
106654359Sroberto				(flags & RT2560_TX_RESULT_MASK) &~
106754359Sroberto				(RT2560_TX_SUCCESS | RT2560_TX_SUCCESS_RETRY));
106854359Sroberto		m_freem(m);
106954359Sroberto		ieee80211_free_node(ni);
107054359Sroberto	}
107154359Sroberto
107254359Sroberto	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
107354359Sroberto	    BUS_DMASYNC_PREWRITE);
107454359Sroberto
107554359Sroberto	if (sc->prioq.queued == 0 && sc->txq.queued == 0)
107654359Sroberto		sc->sc_tx_timer = 0;
107754359Sroberto
107854359Sroberto	if (sc->prioq.queued < RT2560_PRIO_RING_COUNT)
107954359Sroberto		rt2560_start(sc);
108054359Sroberto}
108154359Sroberto
108254359Sroberto/*
108354359Sroberto * Some frames were processed by the hardware cipher engine and are ready for
108454359Sroberto * handoff to the IEEE802.11 layer.
108554359Sroberto */
108654359Srobertostatic void
108754359Srobertort2560_decryption_intr(struct rt2560_softc *sc)
108854359Sroberto{
108954359Sroberto	struct ieee80211com *ic = &sc->sc_ic;
109054359Sroberto	struct rt2560_rx_desc *desc;
109154359Sroberto	struct rt2560_rx_data *data;
109254359Sroberto	bus_addr_t physaddr;
109354359Sroberto	struct ieee80211_frame *wh;
109454359Sroberto	struct ieee80211_node *ni;
109554359Sroberto	struct mbuf *mnew, *m;
109654359Sroberto	int hw, error;
109754359Sroberto	int8_t rssi, nf;
109854359Sroberto
109954359Sroberto	/* retrieve last decriptor index processed by cipher engine */
110054359Sroberto	hw = RAL_READ(sc, RT2560_SECCSR0) - sc->rxq.physaddr;
110154359Sroberto	hw /= RT2560_RX_DESC_SIZE;
110254359Sroberto
110354359Sroberto	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
110454359Sroberto	    BUS_DMASYNC_POSTREAD);
110554359Sroberto
110654359Sroberto	for (; sc->rxq.cur_decrypt != hw;) {
110754359Sroberto		desc = &sc->rxq.desc[sc->rxq.cur_decrypt];
110854359Sroberto		data = &sc->rxq.data[sc->rxq.cur_decrypt];
110954359Sroberto
111054359Sroberto		if ((le32toh(desc->flags) & RT2560_RX_BUSY) ||
111154359Sroberto		    (le32toh(desc->flags) & RT2560_RX_CIPHER_BUSY))
111254359Sroberto			break;
111354359Sroberto
111454359Sroberto		if (data->drop) {
111554359Sroberto			counter_u64_add(ic->ic_ierrors, 1);
111654359Sroberto			goto skip;
111754359Sroberto		}
111854359Sroberto
111954359Sroberto		if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 &&
112054359Sroberto		    (le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) {
112154359Sroberto			counter_u64_add(ic->ic_ierrors, 1);
112254359Sroberto			goto skip;
112354359Sroberto		}
112454359Sroberto
112554359Sroberto		/*
112654359Sroberto		 * Try to allocate a new mbuf for this ring element and load it
112754359Sroberto		 * before processing the current mbuf. If the ring element
112854359Sroberto		 * cannot be loaded, drop the received packet and reuse the old
112954359Sroberto		 * mbuf. In the unlikely case that the old mbuf can't be
113054359Sroberto		 * reloaded either, explicitly panic.
113154359Sroberto		 */
113254359Sroberto		mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
113354359Sroberto		if (mnew == NULL) {
113454359Sroberto			counter_u64_add(ic->ic_ierrors, 1);
113554359Sroberto			goto skip;
113654359Sroberto		}
113754359Sroberto
113854359Sroberto		bus_dmamap_sync(sc->rxq.data_dmat, data->map,
113954359Sroberto		    BUS_DMASYNC_POSTREAD);
114054359Sroberto		bus_dmamap_unload(sc->rxq.data_dmat, data->map);
114154359Sroberto
114254359Sroberto		error = bus_dmamap_load(sc->rxq.data_dmat, data->map,
114354359Sroberto		    mtod(mnew, void *), MCLBYTES, rt2560_dma_map_addr,
114454359Sroberto		    &physaddr, 0);
114554359Sroberto		if (error != 0) {
114654359Sroberto			m_freem(mnew);
114754359Sroberto
114854359Sroberto			/* try to reload the old mbuf */
114954359Sroberto			error = bus_dmamap_load(sc->rxq.data_dmat, data->map,
115054359Sroberto			    mtod(data->m, void *), MCLBYTES,
115154359Sroberto			    rt2560_dma_map_addr, &physaddr, 0);
115254359Sroberto			if (error != 0) {
115354359Sroberto				/* very unlikely that it will fail... */
115454359Sroberto				panic("%s: could not load old rx mbuf",
115554359Sroberto				    device_get_name(sc->sc_dev));
115654359Sroberto			}
115754359Sroberto			counter_u64_add(ic->ic_ierrors, 1);
115854359Sroberto			goto skip;
115954359Sroberto		}
116054359Sroberto
116154359Sroberto		/*
116254359Sroberto	 	 * New mbuf successfully loaded, update Rx ring and continue
116354359Sroberto		 * processing.
116454359Sroberto		 */
116554359Sroberto		m = data->m;
116654359Sroberto		data->m = mnew;
116754359Sroberto		desc->physaddr = htole32(physaddr);
116854359Sroberto
116954359Sroberto		/* finalize mbuf */
117054359Sroberto		m->m_pkthdr.len = m->m_len =
117154359Sroberto		    (le32toh(desc->flags) >> 16) & 0xfff;
117254359Sroberto
117354359Sroberto		rssi = RT2560_RSSI(sc, desc->rssi);
117454359Sroberto		nf = RT2560_NOISE_FLOOR;
117554359Sroberto		if (ieee80211_radiotap_active(ic)) {
117654359Sroberto			struct rt2560_rx_radiotap_header *tap = &sc->sc_rxtap;
117754359Sroberto			uint32_t tsf_lo, tsf_hi;
117854359Sroberto
117954359Sroberto			/* get timestamp (low and high 32 bits) */
118054359Sroberto			tsf_hi = RAL_READ(sc, RT2560_CSR17);
118154359Sroberto			tsf_lo = RAL_READ(sc, RT2560_CSR16);
118254359Sroberto
118354359Sroberto			tap->wr_tsf =
118454359Sroberto			    htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
118554359Sroberto			tap->wr_flags = 0;
118654359Sroberto			tap->wr_rate = ieee80211_plcp2rate(desc->rate,
118754359Sroberto			    (desc->flags & htole32(RT2560_RX_OFDM)) ?
118854359Sroberto				IEEE80211_T_OFDM : IEEE80211_T_CCK);
118954359Sroberto			tap->wr_antenna = sc->rx_ant;
119054359Sroberto			tap->wr_antsignal = nf + rssi;
119154359Sroberto			tap->wr_antnoise = nf;
119254359Sroberto		}
119354359Sroberto
119454359Sroberto		sc->sc_flags |= RT2560_F_INPUT_RUNNING;
119554359Sroberto		RAL_UNLOCK(sc);
119654359Sroberto		wh = mtod(m, struct ieee80211_frame *);
119754359Sroberto		ni = ieee80211_find_rxnode(ic,
119854359Sroberto		    (struct ieee80211_frame_min *)wh);
119954359Sroberto		if (ni != NULL) {
120054359Sroberto			(void) ieee80211_input(ni, m, rssi, nf);
120154359Sroberto			ieee80211_free_node(ni);
120254359Sroberto		} else
120354359Sroberto			(void) ieee80211_input_all(ic, m, rssi, nf);
120454359Sroberto
120554359Sroberto		RAL_LOCK(sc);
120654359Sroberto		sc->sc_flags &= ~RT2560_F_INPUT_RUNNING;
120754359Srobertoskip:		desc->flags = htole32(RT2560_RX_BUSY);
120854359Sroberto
120954359Sroberto		DPRINTFN(sc, 15, "decryption done idx=%u\n", sc->rxq.cur_decrypt);
121054359Sroberto
121154359Sroberto		sc->rxq.cur_decrypt =
121254359Sroberto		    (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT;
121354359Sroberto	}
121454359Sroberto
121554359Sroberto	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
121654359Sroberto	    BUS_DMASYNC_PREWRITE);
121754359Sroberto}
121854359Sroberto
121954359Sroberto/*
122054359Sroberto * Some frames were received. Pass them to the hardware cipher engine before
122154359Sroberto * sending them to the 802.11 layer.
122254359Sroberto */
122354359Srobertostatic void
122454359Srobertort2560_rx_intr(struct rt2560_softc *sc)
122554359Sroberto{
122654359Sroberto	struct rt2560_rx_desc *desc;
122754359Sroberto	struct rt2560_rx_data *data;
122854359Sroberto
122954359Sroberto	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
123054359Sroberto	    BUS_DMASYNC_POSTREAD);
123154359Sroberto
123254359Sroberto	for (;;) {
123354359Sroberto		desc = &sc->rxq.desc[sc->rxq.cur];
123454359Sroberto		data = &sc->rxq.data[sc->rxq.cur];
123554359Sroberto
123654359Sroberto		if ((le32toh(desc->flags) & RT2560_RX_BUSY) ||
123754359Sroberto		    (le32toh(desc->flags) & RT2560_RX_CIPHER_BUSY))
123854359Sroberto			break;
123954359Sroberto
124054359Sroberto		data->drop = 0;
124154359Sroberto
124254359Sroberto		if ((le32toh(desc->flags) & RT2560_RX_PHY_ERROR) ||
124354359Sroberto		    (le32toh(desc->flags) & RT2560_RX_CRC_ERROR)) {
124454359Sroberto			/*
124554359Sroberto			 * This should not happen since we did not request
124654359Sroberto			 * to receive those frames when we filled RXCSR0.
124754359Sroberto			 */
124854359Sroberto			DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n",
124954359Sroberto			    le32toh(desc->flags));
125054359Sroberto			data->drop = 1;
125154359Sroberto		}
125254359Sroberto
125354359Sroberto		if (((le32toh(desc->flags) >> 16) & 0xfff) > MCLBYTES) {
125454359Sroberto			DPRINTFN(sc, 5, "%s\n", "bad length");
125554359Sroberto			data->drop = 1;
125654359Sroberto		}
125754359Sroberto
125854359Sroberto		/* mark the frame for decryption */
125954359Sroberto		desc->flags |= htole32(RT2560_RX_CIPHER_BUSY);
126054359Sroberto
126154359Sroberto		DPRINTFN(sc, 15, "rx done idx=%u\n", sc->rxq.cur);
126254359Sroberto
126354359Sroberto		sc->rxq.cur = (sc->rxq.cur + 1) % RT2560_RX_RING_COUNT;
126454359Sroberto	}
126554359Sroberto
126654359Sroberto	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
126754359Sroberto	    BUS_DMASYNC_PREWRITE);
126854359Sroberto
126954359Sroberto	/* kick decrypt */
127054359Sroberto	RAL_WRITE(sc, RT2560_SECCSR0, RT2560_KICK_DECRYPT);
127154359Sroberto}
127254359Sroberto
127354359Srobertostatic void
127454359Srobertort2560_beacon_update(struct ieee80211vap *vap, int item)
127554359Sroberto{
127654359Sroberto	struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
127754359Sroberto
127854359Sroberto	setbit(bo->bo_flags, item);
127954359Sroberto}
128054359Sroberto
128154359Sroberto/*
128254359Sroberto * This function is called periodically in IBSS mode when a new beacon must be
128354359Sroberto * sent out.
128454359Sroberto */
128554359Srobertostatic void
128654359Srobertort2560_beacon_expire(struct rt2560_softc *sc)
128754359Sroberto{
128854359Sroberto	struct ieee80211com *ic = &sc->sc_ic;
128954359Sroberto	struct rt2560_tx_data *data;
129054359Sroberto
129154359Sroberto	if (ic->ic_opmode != IEEE80211_M_IBSS &&
129254359Sroberto	    ic->ic_opmode != IEEE80211_M_HOSTAP &&
129354359Sroberto	    ic->ic_opmode != IEEE80211_M_MBSS)
129454359Sroberto		return;
129554359Sroberto
129654359Sroberto	data = &sc->bcnq.data[sc->bcnq.next];
129754359Sroberto	/*
129854359Sroberto	 * Don't send beacon if bsschan isn't set
129954359Sroberto	 */
130054359Sroberto	if (data->ni == NULL)
130154359Sroberto	        return;
130254359Sroberto
130354359Sroberto	bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
130454359Sroberto	bus_dmamap_unload(sc->bcnq.data_dmat, data->map);
130554359Sroberto
130654359Sroberto	/* XXX 1 =>'s mcast frames which means all PS sta's will wakeup! */
130754359Sroberto	ieee80211_beacon_update(data->ni, data->m, 1);
130854359Sroberto
130954359Sroberto	rt2560_tx_bcn(sc, data->m, data->ni);
131054359Sroberto
131154359Sroberto	DPRINTFN(sc, 15, "%s", "beacon expired\n");
131254359Sroberto
131354359Sroberto	sc->bcnq.next = (sc->bcnq.next + 1) % RT2560_BEACON_RING_COUNT;
131454359Sroberto}
131554359Sroberto
131654359Sroberto/* ARGSUSED */
131754359Srobertostatic void
131854359Srobertort2560_wakeup_expire(struct rt2560_softc *sc)
131954359Sroberto{
132054359Sroberto	DPRINTFN(sc, 2, "%s", "wakeup expired\n");
132154359Sroberto}
132254359Sroberto
132354359Srobertovoid
132454359Srobertort2560_intr(void *arg)
132554359Sroberto{
132654359Sroberto	struct rt2560_softc *sc = arg;
132754359Sroberto	uint32_t r;
132854359Sroberto
132954359Sroberto	RAL_LOCK(sc);
133054359Sroberto
133154359Sroberto	/* disable interrupts */
133254359Sroberto	RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
133354359Sroberto
133454359Sroberto	/* don't re-enable interrupts if we're shutting down */
133554359Sroberto	if (!(sc->sc_flags & RT2560_F_RUNNING)) {
133654359Sroberto		RAL_UNLOCK(sc);
133754359Sroberto		return;
133854359Sroberto	}
133954359Sroberto
134054359Sroberto	r = RAL_READ(sc, RT2560_CSR7);
134154359Sroberto	RAL_WRITE(sc, RT2560_CSR7, r);
134254359Sroberto
134354359Sroberto	if (r & RT2560_BEACON_EXPIRE)
134454359Sroberto		rt2560_beacon_expire(sc);
134554359Sroberto
134654359Sroberto	if (r & RT2560_WAKEUP_EXPIRE)
134754359Sroberto		rt2560_wakeup_expire(sc);
134854359Sroberto
134954359Sroberto	if (r & RT2560_ENCRYPTION_DONE)
135054359Sroberto		rt2560_encryption_intr(sc);
135154359Sroberto
135254359Sroberto	if (r & RT2560_TX_DONE)
135354359Sroberto		rt2560_tx_intr(sc);
135454359Sroberto
135554359Sroberto	if (r & RT2560_PRIO_DONE)
135654359Sroberto		rt2560_prio_intr(sc);
135754359Sroberto
135854359Sroberto	if (r & RT2560_DECRYPTION_DONE)
135954359Sroberto		rt2560_decryption_intr(sc);
136054359Sroberto
136154359Sroberto	if (r & RT2560_RX_DONE) {
136254359Sroberto		rt2560_rx_intr(sc);
136354359Sroberto		rt2560_encryption_intr(sc);
136454359Sroberto	}
136554359Sroberto
136654359Sroberto	/* re-enable interrupts */
136754359Sroberto	RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
136854359Sroberto
136954359Sroberto	RAL_UNLOCK(sc);
137054359Sroberto}
137154359Sroberto
137254359Sroberto#define RAL_SIFS		10	/* us */
137354359Sroberto
137454359Sroberto#define RT2560_TXRX_TURNAROUND	10	/* us */
137554359Sroberto
137654359Srobertostatic uint8_t
137754359Srobertort2560_plcp_signal(int rate)
137854359Sroberto{
137954359Sroberto	switch (rate) {
138054359Sroberto	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
138154359Sroberto	case 12:	return 0xb;
138254359Sroberto	case 18:	return 0xf;
138354359Sroberto	case 24:	return 0xa;
138454359Sroberto	case 36:	return 0xe;
138554359Sroberto	case 48:	return 0x9;
138654359Sroberto	case 72:	return 0xd;
138754359Sroberto	case 96:	return 0x8;
138854359Sroberto	case 108:	return 0xc;
138954359Sroberto
139054359Sroberto	/* CCK rates (NB: not IEEE std, device-specific) */
139154359Sroberto	case 2:		return 0x0;
139254359Sroberto	case 4:		return 0x1;
139354359Sroberto	case 11:	return 0x2;
139454359Sroberto	case 22:	return 0x3;
139554359Sroberto	}
139654359Sroberto	return 0xff;		/* XXX unsupported/unknown rate */
139754359Sroberto}
139854359Sroberto
139954359Srobertostatic void
140054359Srobertort2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
140154359Sroberto    uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr)
140254359Sroberto{
140354359Sroberto	struct ieee80211com *ic = &sc->sc_ic;
140454359Sroberto	uint16_t plcp_length;
140554359Sroberto	int remainder;
140654359Sroberto
140754359Sroberto	desc->flags = htole32(flags);
140854359Sroberto	desc->flags |= htole32(len << 16);
140954359Sroberto
141054359Sroberto	desc->physaddr = htole32(physaddr);
141154359Sroberto	desc->wme = htole16(
141254359Sroberto	    RT2560_AIFSN(2) |
141354359Sroberto	    RT2560_LOGCWMIN(3) |
141454359Sroberto	    RT2560_LOGCWMAX(8));
141554359Sroberto
141654359Sroberto	/* setup PLCP fields */
141754359Sroberto	desc->plcp_signal  = rt2560_plcp_signal(rate);
141854359Sroberto	desc->plcp_service = 4;
141954359Sroberto
142054359Sroberto	len += IEEE80211_CRC_LEN;
142154359Sroberto	if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
142254359Sroberto		desc->flags |= htole32(RT2560_TX_OFDM);
142354359Sroberto
142454359Sroberto		plcp_length = len & 0xfff;
142554359Sroberto		desc->plcp_length_hi = plcp_length >> 6;
142654359Sroberto		desc->plcp_length_lo = plcp_length & 0x3f;
142754359Sroberto	} else {
142854359Sroberto		plcp_length = howmany(16 * len, rate);
142954359Sroberto		if (rate == 22) {
143054359Sroberto			remainder = (16 * len) % 22;
143154359Sroberto			if (remainder != 0 && remainder < 7)
143254359Sroberto				desc->plcp_service |= RT2560_PLCP_LENGEXT;
143354359Sroberto		}
143454359Sroberto		desc->plcp_length_hi = plcp_length >> 8;
143554359Sroberto		desc->plcp_length_lo = plcp_length & 0xff;
143654359Sroberto
143754359Sroberto		if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
143854359Sroberto			desc->plcp_signal |= 0x08;
143954359Sroberto	}
144054359Sroberto
144154359Sroberto	if (!encrypt)
144254359Sroberto		desc->flags |= htole32(RT2560_TX_VALID);
144354359Sroberto	desc->flags |= encrypt ? htole32(RT2560_TX_CIPHER_BUSY)
144454359Sroberto			       : htole32(RT2560_TX_BUSY);
144554359Sroberto}
144654359Sroberto
144754359Srobertostatic int
144854359Srobertort2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0,
144954359Sroberto    struct ieee80211_node *ni)
145054359Sroberto{
145154359Sroberto	struct ieee80211vap *vap = ni->ni_vap;
145254359Sroberto	struct rt2560_tx_desc *desc;
145354359Sroberto	struct rt2560_tx_data *data;
145454359Sroberto	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
145554359Sroberto	int nsegs, rate, error;
145654359Sroberto
145754359Sroberto	desc = &sc->bcnq.desc[sc->bcnq.cur];
145854359Sroberto	data = &sc->bcnq.data[sc->bcnq.cur];
145954359Sroberto
146054359Sroberto	/* XXX maybe a separate beacon rate? */
146154359Sroberto	rate = vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)].mgmtrate;
146254359Sroberto
146354359Sroberto	error = bus_dmamap_load_mbuf_sg(sc->bcnq.data_dmat, data->map, m0,
146454359Sroberto	    segs, &nsegs, BUS_DMA_NOWAIT);
146554359Sroberto	if (error != 0) {
146654359Sroberto		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
146754359Sroberto		    error);
146854359Sroberto		m_freem(m0);
146954359Sroberto		return error;
147054359Sroberto	}
147154359Sroberto
147254359Sroberto	if (ieee80211_radiotap_active_vap(vap)) {
147354359Sroberto		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
147454359Sroberto
147554359Sroberto		tap->wt_flags = 0;
147654359Sroberto		tap->wt_rate = rate;
147754359Sroberto		tap->wt_antenna = sc->tx_ant;
147854359Sroberto
147954359Sroberto		ieee80211_radiotap_tx(vap, m0);
148054359Sroberto	}
148154359Sroberto
148254359Sroberto	data->m = m0;
148354359Sroberto	data->ni = ni;
148454359Sroberto
148554359Sroberto	rt2560_setup_tx_desc(sc, desc, RT2560_TX_IFS_NEWBACKOFF |
148654359Sroberto	    RT2560_TX_TIMESTAMP, m0->m_pkthdr.len, rate, 0, segs->ds_addr);
148754359Sroberto
148854359Sroberto	DPRINTFN(sc, 10, "sending beacon frame len=%u idx=%u rate=%u\n",
148954359Sroberto	    m0->m_pkthdr.len, sc->bcnq.cur, rate);
149054359Sroberto
149154359Sroberto	bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
149254359Sroberto	bus_dmamap_sync(sc->bcnq.desc_dmat, sc->bcnq.desc_map,
149354359Sroberto	    BUS_DMASYNC_PREWRITE);
149454359Sroberto
149554359Sroberto	sc->bcnq.cur = (sc->bcnq.cur + 1) % RT2560_BEACON_RING_COUNT;
149654359Sroberto
149754359Sroberto	return 0;
149854359Sroberto}
149954359Sroberto
150054359Srobertostatic int
150154359Srobertort2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0,
150254359Sroberto    struct ieee80211_node *ni)
150354359Sroberto{
150454359Sroberto	struct ieee80211vap *vap = ni->ni_vap;
150554359Sroberto	struct ieee80211com *ic = ni->ni_ic;
150654359Sroberto	struct rt2560_tx_desc *desc;
150754359Sroberto	struct rt2560_tx_data *data;
150854359Sroberto	struct ieee80211_frame *wh;
150954359Sroberto	struct ieee80211_key *k;
151054359Sroberto	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
151154359Sroberto	uint16_t dur;
151254359Sroberto	uint32_t flags = 0;
151354359Sroberto	int nsegs, rate, error;
151454359Sroberto
151554359Sroberto	desc = &sc->prioq.desc[sc->prioq.cur];
151654359Sroberto	data = &sc->prioq.data[sc->prioq.cur];
151754359Sroberto
151854359Sroberto	rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate;
151954359Sroberto
152054359Sroberto	wh = mtod(m0, struct ieee80211_frame *);
152154359Sroberto
152254359Sroberto	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
152354359Sroberto		k = ieee80211_crypto_encap(ni, m0);
152454359Sroberto		if (k == NULL) {
152554359Sroberto			m_freem(m0);
152654359Sroberto			return ENOBUFS;
152754359Sroberto		}
152854359Sroberto	}
152954359Sroberto
153054359Sroberto	error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0,
153154359Sroberto	    segs, &nsegs, 0);
153254359Sroberto	if (error != 0) {
153354359Sroberto		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
153454359Sroberto		    error);
153554359Sroberto		m_freem(m0);
153654359Sroberto		return error;
153754359Sroberto	}
153854359Sroberto
153954359Sroberto	if (ieee80211_radiotap_active_vap(vap)) {
154054359Sroberto		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
154154359Sroberto
154254359Sroberto		tap->wt_flags = 0;
154354359Sroberto		tap->wt_rate = rate;
154454359Sroberto		tap->wt_antenna = sc->tx_ant;
154554359Sroberto
154654359Sroberto		ieee80211_radiotap_tx(vap, m0);
154754359Sroberto	}
154854359Sroberto
154954359Sroberto	data->m = m0;
155054359Sroberto	data->ni = ni;
155154359Sroberto	/* management frames are not taken into account for amrr */
155254359Sroberto	data->rix = IEEE80211_FIXED_RATE_NONE;
155354359Sroberto
155454359Sroberto	wh = mtod(m0, struct ieee80211_frame *);
155554359Sroberto
155654359Sroberto	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
155754359Sroberto		flags |= RT2560_TX_ACK;
155854359Sroberto
155954359Sroberto		dur = ieee80211_ack_duration(ic->ic_rt,
156054359Sroberto		    rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
156154359Sroberto		*(uint16_t *)wh->i_dur = htole16(dur);
156254359Sroberto
156354359Sroberto		/* tell hardware to add timestamp for probe responses */
156454359Sroberto		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
156554359Sroberto		    IEEE80211_FC0_TYPE_MGT &&
156654359Sroberto		    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
156754359Sroberto		    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
156854359Sroberto			flags |= RT2560_TX_TIMESTAMP;
156954359Sroberto	}
157054359Sroberto
157154359Sroberto	rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 0,
157254359Sroberto	    segs->ds_addr);
157354359Sroberto
157454359Sroberto	bus_dmamap_sync(sc->prioq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
157554359Sroberto	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
157654359Sroberto	    BUS_DMASYNC_PREWRITE);
157754359Sroberto
157854359Sroberto	DPRINTFN(sc, 10, "sending mgt frame len=%u idx=%u rate=%u\n",
157954359Sroberto	    m0->m_pkthdr.len, sc->prioq.cur, rate);
158054359Sroberto
158154359Sroberto	/* kick prio */
158254359Sroberto	sc->prioq.queued++;
158354359Sroberto	sc->prioq.cur = (sc->prioq.cur + 1) % RT2560_PRIO_RING_COUNT;
158454359Sroberto	RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_PRIO);
158554359Sroberto
158654359Sroberto	return 0;
158754359Sroberto}
158854359Sroberto
158954359Srobertostatic int
159054359Srobertort2560_sendprot(struct rt2560_softc *sc,
159154359Sroberto    const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate)
159254359Sroberto{
159354359Sroberto	struct ieee80211com *ic = ni->ni_ic;
159454359Sroberto	const struct ieee80211_frame *wh;
159554359Sroberto	struct rt2560_tx_desc *desc;
159654359Sroberto	struct rt2560_tx_data *data;
159754359Sroberto	struct mbuf *mprot;
159854359Sroberto	int protrate, ackrate, pktlen, flags, isshort, error;
159954359Sroberto	uint16_t dur;
160054359Sroberto	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
160154359Sroberto	int nsegs;
160254359Sroberto
160354359Sroberto	KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
160454359Sroberto	    ("protection %d", prot));
160554359Sroberto
160654359Sroberto	wh = mtod(m, const struct ieee80211_frame *);
160754359Sroberto	pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
160854359Sroberto
160954359Sroberto	protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
161054359Sroberto	ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
161154359Sroberto
161254359Sroberto	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
161354359Sroberto	dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
161454359Sroberto	    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
161554359Sroberto	flags = RT2560_TX_MORE_FRAG;
161654359Sroberto	if (prot == IEEE80211_PROT_RTSCTS) {
161754359Sroberto		/* NB: CTS is the same size as an ACK */
161854359Sroberto		dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
161954359Sroberto		flags |= RT2560_TX_ACK;
162054359Sroberto		mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
162154359Sroberto	} else {
162254359Sroberto		mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
162354359Sroberto	}
162454359Sroberto	if (mprot == NULL) {
162554359Sroberto		/* XXX stat + msg */
162654359Sroberto		return ENOBUFS;
162754359Sroberto	}
162854359Sroberto
162954359Sroberto	desc = &sc->txq.desc[sc->txq.cur_encrypt];
163054359Sroberto	data = &sc->txq.data[sc->txq.cur_encrypt];
163154359Sroberto
163254359Sroberto	error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map,
163354359Sroberto	    mprot, segs, &nsegs, 0);
163454359Sroberto	if (error != 0) {
163554359Sroberto		device_printf(sc->sc_dev,
163654359Sroberto		    "could not map mbuf (error %d)\n", error);
163754359Sroberto		m_freem(mprot);
163854359Sroberto		return error;
163954359Sroberto	}
164054359Sroberto
164154359Sroberto	data->m = mprot;
164254359Sroberto	data->ni = ieee80211_ref_node(ni);
164354359Sroberto	/* ctl frames are not taken into account for amrr */
164454359Sroberto	data->rix = IEEE80211_FIXED_RATE_NONE;
164554359Sroberto
164654359Sroberto	rt2560_setup_tx_desc(sc, desc, flags, mprot->m_pkthdr.len, protrate, 1,
164754359Sroberto	    segs->ds_addr);
164854359Sroberto
164954359Sroberto	bus_dmamap_sync(sc->txq.data_dmat, data->map,
165054359Sroberto	    BUS_DMASYNC_PREWRITE);
165154359Sroberto
165254359Sroberto	sc->txq.queued++;
165354359Sroberto	sc->txq.cur_encrypt = (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT;
165454359Sroberto
165554359Sroberto	return 0;
165654359Sroberto}
165754359Sroberto
165854359Srobertostatic int
165954359Srobertort2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0,
166054359Sroberto    struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
166154359Sroberto{
166254359Sroberto	struct ieee80211vap *vap = ni->ni_vap;
166354359Sroberto	struct ieee80211com *ic = ni->ni_ic;
166454359Sroberto	struct rt2560_tx_desc *desc;
166554359Sroberto	struct rt2560_tx_data *data;
166654359Sroberto	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
166754359Sroberto	uint32_t flags;
166854359Sroberto	int nsegs, rate, error;
166954359Sroberto
167054359Sroberto	desc = &sc->prioq.desc[sc->prioq.cur];
167154359Sroberto	data = &sc->prioq.data[sc->prioq.cur];
167254359Sroberto
167354359Sroberto	rate = params->ibp_rate0;
167454359Sroberto	if (!ieee80211_isratevalid(ic->ic_rt, rate)) {
167554359Sroberto		/* XXX fall back to mcast/mgmt rate? */
167654359Sroberto		m_freem(m0);
167754359Sroberto		return EINVAL;
167854359Sroberto	}
167954359Sroberto
168054359Sroberto	flags = 0;
168154359Sroberto	if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
168254359Sroberto		flags |= RT2560_TX_ACK;
168354359Sroberto	if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) {
168454359Sroberto		error = rt2560_sendprot(sc, m0, ni,
168554359Sroberto		    params->ibp_flags & IEEE80211_BPF_RTS ?
168654359Sroberto			 IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY,
168754359Sroberto		    rate);
168854359Sroberto		if (error) {
168954359Sroberto			m_freem(m0);
169054359Sroberto			return error;
169154359Sroberto		}
169254359Sroberto		flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
169354359Sroberto	}
169454359Sroberto
169554359Sroberto	error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0,
169654359Sroberto	    segs, &nsegs, 0);
169754359Sroberto	if (error != 0) {
169854359Sroberto		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
169954359Sroberto		    error);
170054359Sroberto		m_freem(m0);
170154359Sroberto		return error;
170254359Sroberto	}
170354359Sroberto
170454359Sroberto	if (ieee80211_radiotap_active_vap(vap)) {
170554359Sroberto		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
170654359Sroberto
170754359Sroberto		tap->wt_flags = 0;
170854359Sroberto		tap->wt_rate = rate;
170954359Sroberto		tap->wt_antenna = sc->tx_ant;
171054359Sroberto
171154359Sroberto		ieee80211_radiotap_tx(ni->ni_vap, m0);
171254359Sroberto	}
171354359Sroberto
171454359Sroberto	data->m = m0;
171554359Sroberto	data->ni = ni;
171654359Sroberto
171754359Sroberto	/* XXX need to setup descriptor ourself */
171854359Sroberto	rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len,
171954359Sroberto	    rate, (params->ibp_flags & IEEE80211_BPF_CRYPTO) != 0,
172054359Sroberto	    segs->ds_addr);
172154359Sroberto
172254359Sroberto	bus_dmamap_sync(sc->prioq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
172354359Sroberto	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
172454359Sroberto	    BUS_DMASYNC_PREWRITE);
172554359Sroberto
172654359Sroberto	DPRINTFN(sc, 10, "sending raw frame len=%u idx=%u rate=%u\n",
172754359Sroberto	    m0->m_pkthdr.len, sc->prioq.cur, rate);
172854359Sroberto
172954359Sroberto	/* kick prio */
173054359Sroberto	sc->prioq.queued++;
173154359Sroberto	sc->prioq.cur = (sc->prioq.cur + 1) % RT2560_PRIO_RING_COUNT;
173254359Sroberto	RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_PRIO);
173354359Sroberto
173454359Sroberto	return 0;
173554359Sroberto}
173654359Sroberto
173754359Srobertostatic int
173854359Srobertort2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
173954359Sroberto    struct ieee80211_node *ni)
174054359Sroberto{
174154359Sroberto	struct ieee80211vap *vap = ni->ni_vap;
174254359Sroberto	struct ieee80211com *ic = ni->ni_ic;
174354359Sroberto	struct rt2560_tx_desc *desc;
174454359Sroberto	struct rt2560_tx_data *data;
174554359Sroberto	struct ieee80211_frame *wh;
174654359Sroberto	const struct ieee80211_txparam *tp;
174754359Sroberto	struct ieee80211_key *k;
174854359Sroberto	struct mbuf *mnew;
174954359Sroberto	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
175054359Sroberto	uint16_t dur;
175154359Sroberto	uint32_t flags;
175254359Sroberto	int nsegs, rate, error;
175354359Sroberto
175454359Sroberto	wh = mtod(m0, struct ieee80211_frame *);
175554359Sroberto
175654359Sroberto	tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
175754359Sroberto	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
175854359Sroberto		rate = tp->mcastrate;
175954359Sroberto	} else if (m0->m_flags & M_EAPOL) {
176054359Sroberto		rate = tp->mgmtrate;
176154359Sroberto	} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
176254359Sroberto		rate = tp->ucastrate;
176354359Sroberto	} else {
176454359Sroberto		(void) ieee80211_ratectl_rate(ni, NULL, 0);
176554359Sroberto		rate = ni->ni_txrate;
176654359Sroberto	}
176754359Sroberto
176854359Sroberto	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
176954359Sroberto		k = ieee80211_crypto_encap(ni, m0);
177054359Sroberto		if (k == NULL) {
177154359Sroberto			m_freem(m0);
177254359Sroberto			return ENOBUFS;
177354359Sroberto		}
177454359Sroberto
1775		/* packet header may have moved, reset our local pointer */
1776		wh = mtod(m0, struct ieee80211_frame *);
1777	}
1778
1779	flags = 0;
1780	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1781		int prot = IEEE80211_PROT_NONE;
1782		if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
1783			prot = IEEE80211_PROT_RTSCTS;
1784		else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
1785		    ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM)
1786			prot = ic->ic_protmode;
1787		if (prot != IEEE80211_PROT_NONE) {
1788			error = rt2560_sendprot(sc, m0, ni, prot, rate);
1789			if (error) {
1790				m_freem(m0);
1791				return error;
1792			}
1793			flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
1794		}
1795	}
1796
1797	data = &sc->txq.data[sc->txq.cur_encrypt];
1798	desc = &sc->txq.desc[sc->txq.cur_encrypt];
1799
1800	error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, m0,
1801	    segs, &nsegs, 0);
1802	if (error != 0 && error != EFBIG) {
1803		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
1804		    error);
1805		m_freem(m0);
1806		return error;
1807	}
1808	if (error != 0) {
1809		mnew = m_defrag(m0, M_NOWAIT);
1810		if (mnew == NULL) {
1811			device_printf(sc->sc_dev,
1812			    "could not defragment mbuf\n");
1813			m_freem(m0);
1814			return ENOBUFS;
1815		}
1816		m0 = mnew;
1817
1818		error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map,
1819		    m0, segs, &nsegs, 0);
1820		if (error != 0) {
1821			device_printf(sc->sc_dev,
1822			    "could not map mbuf (error %d)\n", error);
1823			m_freem(m0);
1824			return error;
1825		}
1826
1827		/* packet header may have moved, reset our local pointer */
1828		wh = mtod(m0, struct ieee80211_frame *);
1829	}
1830
1831	if (ieee80211_radiotap_active_vap(vap)) {
1832		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
1833
1834		tap->wt_flags = 0;
1835		tap->wt_rate = rate;
1836		tap->wt_antenna = sc->tx_ant;
1837
1838		ieee80211_radiotap_tx(vap, m0);
1839	}
1840
1841	data->m = m0;
1842	data->ni = ni;
1843
1844	/* remember link conditions for rate adaptation algorithm */
1845	if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) {
1846		data->rix = ni->ni_txrate;
1847		/* XXX probably need last rssi value and not avg */
1848		data->rssi = ic->ic_node_getrssi(ni);
1849	} else
1850		data->rix = IEEE80211_FIXED_RATE_NONE;
1851
1852	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1853		flags |= RT2560_TX_ACK;
1854
1855		dur = ieee80211_ack_duration(ic->ic_rt,
1856		    rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
1857		*(uint16_t *)wh->i_dur = htole16(dur);
1858	}
1859
1860	rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 1,
1861	    segs->ds_addr);
1862
1863	bus_dmamap_sync(sc->txq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
1864	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
1865	    BUS_DMASYNC_PREWRITE);
1866
1867	DPRINTFN(sc, 10, "sending data frame len=%u idx=%u rate=%u\n",
1868	    m0->m_pkthdr.len, sc->txq.cur_encrypt, rate);
1869
1870	/* kick encrypt */
1871	sc->txq.queued++;
1872	sc->txq.cur_encrypt = (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT;
1873	RAL_WRITE(sc, RT2560_SECCSR1, RT2560_KICK_ENCRYPT);
1874
1875	return 0;
1876}
1877
1878static int
1879rt2560_transmit(struct ieee80211com *ic, struct mbuf *m)
1880{
1881	struct rt2560_softc *sc = ic->ic_softc;
1882	int error;
1883
1884	RAL_LOCK(sc);
1885	if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
1886		RAL_UNLOCK(sc);
1887		return (ENXIO);
1888	}
1889	error = mbufq_enqueue(&sc->sc_snd, m);
1890	if (error) {
1891		RAL_UNLOCK(sc);
1892		return (error);
1893	}
1894	rt2560_start(sc);
1895	RAL_UNLOCK(sc);
1896
1897	return (0);
1898}
1899
1900static void
1901rt2560_start(struct rt2560_softc *sc)
1902{
1903	struct ieee80211_node *ni;
1904	struct mbuf *m;
1905
1906	RAL_LOCK_ASSERT(sc);
1907
1908	while (sc->txq.queued < RT2560_TX_RING_COUNT - 1 &&
1909	    (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
1910		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1911		if (rt2560_tx_data(sc, m, ni) != 0) {
1912			if_inc_counter(ni->ni_vap->iv_ifp,
1913			    IFCOUNTER_OERRORS, 1);
1914			ieee80211_free_node(ni);
1915			break;
1916		}
1917		sc->sc_tx_timer = 5;
1918	}
1919}
1920
1921static void
1922rt2560_watchdog(void *arg)
1923{
1924	struct rt2560_softc *sc = arg;
1925
1926	RAL_LOCK_ASSERT(sc);
1927
1928	KASSERT(sc->sc_flags & RT2560_F_RUNNING, ("not running"));
1929
1930	if (sc->sc_invalid)		/* card ejected */
1931		return;
1932
1933	rt2560_encryption_intr(sc);
1934	rt2560_tx_intr(sc);
1935
1936	if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
1937		device_printf(sc->sc_dev, "device timeout\n");
1938		rt2560_init_locked(sc);
1939		counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1940		/* NB: callout is reset in rt2560_init() */
1941		return;
1942	}
1943	callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
1944}
1945
1946static void
1947rt2560_parent(struct ieee80211com *ic)
1948{
1949	struct rt2560_softc *sc = ic->ic_softc;
1950	int startall = 0;
1951
1952	RAL_LOCK(sc);
1953	if (ic->ic_nrunning > 0) {
1954		if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
1955			rt2560_init_locked(sc);
1956			startall = 1;
1957		} else
1958			rt2560_update_promisc(ic);
1959	} else if (sc->sc_flags & RT2560_F_RUNNING)
1960		rt2560_stop_locked(sc);
1961	RAL_UNLOCK(sc);
1962	if (startall)
1963		ieee80211_start_all(ic);
1964}
1965
1966static void
1967rt2560_bbp_write(struct rt2560_softc *sc, uint8_t reg, uint8_t val)
1968{
1969	uint32_t tmp;
1970	int ntries;
1971
1972	for (ntries = 0; ntries < 100; ntries++) {
1973		if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY))
1974			break;
1975		DELAY(1);
1976	}
1977	if (ntries == 100) {
1978		device_printf(sc->sc_dev, "could not write to BBP\n");
1979		return;
1980	}
1981
1982	tmp = RT2560_BBP_WRITE | RT2560_BBP_BUSY | reg << 8 | val;
1983	RAL_WRITE(sc, RT2560_BBPCSR, tmp);
1984
1985	DPRINTFN(sc, 15, "BBP R%u <- 0x%02x\n", reg, val);
1986}
1987
1988static uint8_t
1989rt2560_bbp_read(struct rt2560_softc *sc, uint8_t reg)
1990{
1991	uint32_t val;
1992	int ntries;
1993
1994	for (ntries = 0; ntries < 100; ntries++) {
1995		if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY))
1996			break;
1997		DELAY(1);
1998	}
1999	if (ntries == 100) {
2000		device_printf(sc->sc_dev, "could not read from BBP\n");
2001		return 0;
2002	}
2003
2004	val = RT2560_BBP_BUSY | reg << 8;
2005	RAL_WRITE(sc, RT2560_BBPCSR, val);
2006
2007	for (ntries = 0; ntries < 100; ntries++) {
2008		val = RAL_READ(sc, RT2560_BBPCSR);
2009		if (!(val & RT2560_BBP_BUSY))
2010			return val & 0xff;
2011		DELAY(1);
2012	}
2013
2014	device_printf(sc->sc_dev, "could not read from BBP\n");
2015	return 0;
2016}
2017
2018static void
2019rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val)
2020{
2021	uint32_t tmp;
2022	int ntries;
2023
2024	for (ntries = 0; ntries < 100; ntries++) {
2025		if (!(RAL_READ(sc, RT2560_RFCSR) & RT2560_RF_BUSY))
2026			break;
2027		DELAY(1);
2028	}
2029	if (ntries == 100) {
2030		device_printf(sc->sc_dev, "could not write to RF\n");
2031		return;
2032	}
2033
2034	tmp = RT2560_RF_BUSY | RT2560_RF_20BIT | (val & 0xfffff) << 2 |
2035	    (reg & 0x3);
2036	RAL_WRITE(sc, RT2560_RFCSR, tmp);
2037
2038	/* remember last written value in sc */
2039	sc->rf_regs[reg] = val;
2040
2041	DPRINTFN(sc, 15, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff);
2042}
2043
2044static void
2045rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
2046{
2047	struct ieee80211com *ic = &sc->sc_ic;
2048	uint8_t power, tmp;
2049	u_int i, chan;
2050
2051	chan = ieee80211_chan2ieee(ic, c);
2052	KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan));
2053
2054	if (IEEE80211_IS_CHAN_2GHZ(c))
2055		power = min(sc->txpow[chan - 1], 31);
2056	else
2057		power = 31;
2058
2059	/* adjust txpower using ifconfig settings */
2060	power -= (100 - ic->ic_txpowlimit) / 8;
2061
2062	DPRINTFN(sc, 2, "setting channel to %u, txpower to %u\n", chan, power);
2063
2064	switch (sc->rf_rev) {
2065	case RT2560_RF_2522:
2066		rt2560_rf_write(sc, RAL_RF1, 0x00814);
2067		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2522_r2[chan - 1]);
2068		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
2069		break;
2070
2071	case RT2560_RF_2523:
2072		rt2560_rf_write(sc, RAL_RF1, 0x08804);
2073		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2523_r2[chan - 1]);
2074		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x38044);
2075		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2076		break;
2077
2078	case RT2560_RF_2524:
2079		rt2560_rf_write(sc, RAL_RF1, 0x0c808);
2080		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2524_r2[chan - 1]);
2081		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
2082		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2083		break;
2084
2085	case RT2560_RF_2525:
2086		rt2560_rf_write(sc, RAL_RF1, 0x08808);
2087		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_hi_r2[chan - 1]);
2088		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2089		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2090
2091		rt2560_rf_write(sc, RAL_RF1, 0x08808);
2092		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_r2[chan - 1]);
2093		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2094		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2095		break;
2096
2097	case RT2560_RF_2525E:
2098		rt2560_rf_write(sc, RAL_RF1, 0x08808);
2099		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525e_r2[chan - 1]);
2100		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2101		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282);
2102		break;
2103
2104	case RT2560_RF_2526:
2105		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_hi_r2[chan - 1]);
2106		rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
2107		rt2560_rf_write(sc, RAL_RF1, 0x08804);
2108
2109		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_r2[chan - 1]);
2110		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2111		rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
2112		break;
2113
2114	/* dual-band RF */
2115	case RT2560_RF_5222:
2116		for (i = 0; rt2560_rf5222[i].chan != chan; i++);
2117
2118		rt2560_rf_write(sc, RAL_RF1, rt2560_rf5222[i].r1);
2119		rt2560_rf_write(sc, RAL_RF2, rt2560_rf5222[i].r2);
2120		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
2121		rt2560_rf_write(sc, RAL_RF4, rt2560_rf5222[i].r4);
2122		break;
2123	default:
2124 	        printf("unknown ral rev=%d\n", sc->rf_rev);
2125	}
2126
2127	/* XXX */
2128	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
2129		/* set Japan filter bit for channel 14 */
2130		tmp = rt2560_bbp_read(sc, 70);
2131
2132		tmp &= ~RT2560_JAPAN_FILTER;
2133		if (chan == 14)
2134			tmp |= RT2560_JAPAN_FILTER;
2135
2136		rt2560_bbp_write(sc, 70, tmp);
2137
2138		/* clear CRC errors */
2139		RAL_READ(sc, RT2560_CNT0);
2140	}
2141}
2142
2143static void
2144rt2560_set_channel(struct ieee80211com *ic)
2145{
2146	struct rt2560_softc *sc = ic->ic_softc;
2147
2148	RAL_LOCK(sc);
2149	rt2560_set_chan(sc, ic->ic_curchan);
2150	RAL_UNLOCK(sc);
2151
2152}
2153
2154#if 0
2155/*
2156 * Disable RF auto-tuning.
2157 */
2158static void
2159rt2560_disable_rf_tune(struct rt2560_softc *sc)
2160{
2161	uint32_t tmp;
2162
2163	if (sc->rf_rev != RT2560_RF_2523) {
2164		tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE;
2165		rt2560_rf_write(sc, RAL_RF1, tmp);
2166	}
2167
2168	tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE;
2169	rt2560_rf_write(sc, RAL_RF3, tmp);
2170
2171	DPRINTFN(sc, 2, "%s", "disabling RF autotune\n");
2172}
2173#endif
2174
2175/*
2176 * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
2177 * synchronization.
2178 */
2179static void
2180rt2560_enable_tsf_sync(struct rt2560_softc *sc)
2181{
2182	struct ieee80211com *ic = &sc->sc_ic;
2183	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2184	uint16_t logcwmin, preload;
2185	uint32_t tmp;
2186
2187	/* first, disable TSF synchronization */
2188	RAL_WRITE(sc, RT2560_CSR14, 0);
2189
2190	tmp = 16 * vap->iv_bss->ni_intval;
2191	RAL_WRITE(sc, RT2560_CSR12, tmp);
2192
2193	RAL_WRITE(sc, RT2560_CSR13, 0);
2194
2195	logcwmin = 5;
2196	preload = (vap->iv_opmode == IEEE80211_M_STA) ? 384 : 1024;
2197	tmp = logcwmin << 16 | preload;
2198	RAL_WRITE(sc, RT2560_BCNOCSR, tmp);
2199
2200	/* finally, enable TSF synchronization */
2201	tmp = RT2560_ENABLE_TSF | RT2560_ENABLE_TBCN;
2202	if (ic->ic_opmode == IEEE80211_M_STA)
2203		tmp |= RT2560_ENABLE_TSF_SYNC(1);
2204	else
2205		tmp |= RT2560_ENABLE_TSF_SYNC(2) |
2206		       RT2560_ENABLE_BEACON_GENERATOR;
2207	RAL_WRITE(sc, RT2560_CSR14, tmp);
2208
2209	DPRINTF(sc, "%s", "enabling TSF synchronization\n");
2210}
2211
2212static void
2213rt2560_enable_tsf(struct rt2560_softc *sc)
2214{
2215	RAL_WRITE(sc, RT2560_CSR14, 0);
2216	RAL_WRITE(sc, RT2560_CSR14,
2217	    RT2560_ENABLE_TSF_SYNC(2) | RT2560_ENABLE_TSF);
2218}
2219
2220static void
2221rt2560_update_plcp(struct rt2560_softc *sc)
2222{
2223	struct ieee80211com *ic = &sc->sc_ic;
2224
2225	/* no short preamble for 1Mbps */
2226	RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400);
2227
2228	if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) {
2229		/* values taken from the reference driver */
2230		RAL_WRITE(sc, RT2560_PLCP2MCSR,   0x00380401);
2231		RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x00150402);
2232		RAL_WRITE(sc, RT2560_PLCP11MCSR,  0x000b8403);
2233	} else {
2234		/* same values as above or'ed 0x8 */
2235		RAL_WRITE(sc, RT2560_PLCP2MCSR,   0x00380409);
2236		RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x0015040a);
2237		RAL_WRITE(sc, RT2560_PLCP11MCSR,  0x000b840b);
2238	}
2239
2240	DPRINTF(sc, "updating PLCP for %s preamble\n",
2241	    (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long");
2242}
2243
2244/*
2245 * This function can be called by ieee80211_set_shortslottime(). Refer to
2246 * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
2247 */
2248static void
2249rt2560_update_slot(struct ieee80211com *ic)
2250{
2251	struct rt2560_softc *sc = ic->ic_softc;
2252	uint8_t slottime;
2253	uint16_t tx_sifs, tx_pifs, tx_difs, eifs;
2254	uint32_t tmp;
2255
2256#ifndef FORCE_SLOTTIME
2257	slottime = IEEE80211_GET_SLOTTIME(ic);
2258#else
2259	/*
2260	 * Setting slot time according to "short slot time" capability
2261	 * in beacon/probe_resp seems to cause problem to acknowledge
2262	 * certain AP's data frames transimitted at CCK/DS rates: the
2263	 * problematic AP keeps retransmitting data frames, probably
2264	 * because MAC level acks are not received by hardware.
2265	 * So we cheat a little bit here by claiming we are capable of
2266	 * "short slot time" but setting hardware slot time to the normal
2267	 * slot time.  ral(4) does not seem to have trouble to receive
2268	 * frames transmitted using short slot time even if hardware
2269	 * slot time is set to normal slot time.  If we didn't use this
2270	 * trick, we would have to claim that short slot time is not
2271	 * supported; this would give relative poor RX performance
2272	 * (-1Mb~-2Mb lower) and the _whole_ BSS would stop using short
2273	 * slot time.
2274	 */
2275	slottime = IEEE80211_DUR_SLOT;
2276#endif
2277
2278	/* update the MAC slot boundaries */
2279	tx_sifs = RAL_SIFS - RT2560_TXRX_TURNAROUND;
2280	tx_pifs = tx_sifs + slottime;
2281	tx_difs = IEEE80211_DUR_DIFS(tx_sifs, slottime);
2282	eifs = (ic->ic_curmode == IEEE80211_MODE_11B) ? 364 : 60;
2283
2284	tmp = RAL_READ(sc, RT2560_CSR11);
2285	tmp = (tmp & ~0x1f00) | slottime << 8;
2286	RAL_WRITE(sc, RT2560_CSR11, tmp);
2287
2288	tmp = tx_pifs << 16 | tx_sifs;
2289	RAL_WRITE(sc, RT2560_CSR18, tmp);
2290
2291	tmp = eifs << 16 | tx_difs;
2292	RAL_WRITE(sc, RT2560_CSR19, tmp);
2293
2294	DPRINTF(sc, "setting slottime to %uus\n", slottime);
2295}
2296
2297static void
2298rt2560_set_basicrates(struct rt2560_softc *sc,
2299    const struct ieee80211_rateset *rs)
2300{
2301	struct ieee80211com *ic = &sc->sc_ic;
2302	uint32_t mask = 0;
2303	uint8_t rate;
2304	int i;
2305
2306	for (i = 0; i < rs->rs_nrates; i++) {
2307		rate = rs->rs_rates[i];
2308
2309		if (!(rate & IEEE80211_RATE_BASIC))
2310			continue;
2311
2312		mask |= 1 << ieee80211_legacy_rate_lookup(ic->ic_rt,
2313		    IEEE80211_RV(rate));
2314	}
2315
2316	RAL_WRITE(sc, RT2560_ARSP_PLCP_1, mask);
2317
2318	DPRINTF(sc, "Setting basic rate mask to 0x%x\n", mask);
2319}
2320
2321static void
2322rt2560_update_led(struct rt2560_softc *sc, int led1, int led2)
2323{
2324	uint32_t tmp;
2325
2326	/* set ON period to 70ms and OFF period to 30ms */
2327	tmp = led1 << 16 | led2 << 17 | 70 << 8 | 30;
2328	RAL_WRITE(sc, RT2560_LEDCSR, tmp);
2329}
2330
2331static void
2332rt2560_set_bssid(struct rt2560_softc *sc, const uint8_t *bssid)
2333{
2334	uint32_t tmp;
2335
2336	tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
2337	RAL_WRITE(sc, RT2560_CSR5, tmp);
2338
2339	tmp = bssid[4] | bssid[5] << 8;
2340	RAL_WRITE(sc, RT2560_CSR6, tmp);
2341
2342	DPRINTF(sc, "setting BSSID to %6D\n", bssid, ":");
2343}
2344
2345static void
2346rt2560_set_macaddr(struct rt2560_softc *sc, const uint8_t *addr)
2347{
2348	uint32_t tmp;
2349
2350	tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
2351	RAL_WRITE(sc, RT2560_CSR3, tmp);
2352
2353	tmp = addr[4] | addr[5] << 8;
2354	RAL_WRITE(sc, RT2560_CSR4, tmp);
2355
2356	DPRINTF(sc, "setting MAC address to %6D\n", addr, ":");
2357}
2358
2359static void
2360rt2560_get_macaddr(struct rt2560_softc *sc, uint8_t *addr)
2361{
2362	uint32_t tmp;
2363
2364	tmp = RAL_READ(sc, RT2560_CSR3);
2365	addr[0] = tmp & 0xff;
2366	addr[1] = (tmp >>  8) & 0xff;
2367	addr[2] = (tmp >> 16) & 0xff;
2368	addr[3] = (tmp >> 24);
2369
2370	tmp = RAL_READ(sc, RT2560_CSR4);
2371	addr[4] = tmp & 0xff;
2372	addr[5] = (tmp >> 8) & 0xff;
2373}
2374
2375static void
2376rt2560_update_promisc(struct ieee80211com *ic)
2377{
2378	struct rt2560_softc *sc = ic->ic_softc;
2379	uint32_t tmp;
2380
2381	tmp = RAL_READ(sc, RT2560_RXCSR0);
2382
2383	tmp &= ~RT2560_DROP_NOT_TO_ME;
2384	if (ic->ic_promisc == 0)
2385		tmp |= RT2560_DROP_NOT_TO_ME;
2386
2387	RAL_WRITE(sc, RT2560_RXCSR0, tmp);
2388
2389	DPRINTF(sc, "%s promiscuous mode\n",
2390	    (ic->ic_promisc > 0) ?  "entering" : "leaving");
2391}
2392
2393static const char *
2394rt2560_get_rf(int rev)
2395{
2396	switch (rev) {
2397	case RT2560_RF_2522:	return "RT2522";
2398	case RT2560_RF_2523:	return "RT2523";
2399	case RT2560_RF_2524:	return "RT2524";
2400	case RT2560_RF_2525:	return "RT2525";
2401	case RT2560_RF_2525E:	return "RT2525e";
2402	case RT2560_RF_2526:	return "RT2526";
2403	case RT2560_RF_5222:	return "RT5222";
2404	default:		return "unknown";
2405	}
2406}
2407
2408static void
2409rt2560_read_config(struct rt2560_softc *sc)
2410{
2411	uint16_t val;
2412	int i;
2413
2414	val = rt2560_eeprom_read(sc, RT2560_EEPROM_CONFIG0);
2415	sc->rf_rev =   (val >> 11) & 0x7;
2416	sc->hw_radio = (val >> 10) & 0x1;
2417	sc->led_mode = (val >> 6)  & 0x7;
2418	sc->rx_ant =   (val >> 4)  & 0x3;
2419	sc->tx_ant =   (val >> 2)  & 0x3;
2420	sc->nb_ant =   val & 0x3;
2421
2422	/* read default values for BBP registers */
2423	for (i = 0; i < 16; i++) {
2424		val = rt2560_eeprom_read(sc, RT2560_EEPROM_BBP_BASE + i);
2425		if (val == 0 || val == 0xffff)
2426			continue;
2427
2428		sc->bbp_prom[i].reg = val >> 8;
2429		sc->bbp_prom[i].val = val & 0xff;
2430	}
2431
2432	/* read Tx power for all b/g channels */
2433	for (i = 0; i < 14 / 2; i++) {
2434		val = rt2560_eeprom_read(sc, RT2560_EEPROM_TXPOWER + i);
2435		sc->txpow[i * 2] = val & 0xff;
2436		sc->txpow[i * 2 + 1] = val >> 8;
2437	}
2438	for (i = 0; i < 14; ++i) {
2439		if (sc->txpow[i] > 31)
2440			sc->txpow[i] = 24;
2441	}
2442
2443	val = rt2560_eeprom_read(sc, RT2560_EEPROM_CALIBRATE);
2444	if ((val & 0xff) == 0xff)
2445		sc->rssi_corr = RT2560_DEFAULT_RSSI_CORR;
2446	else
2447		sc->rssi_corr = val & 0xff;
2448	DPRINTF(sc, "rssi correction %d, calibrate 0x%02x\n",
2449		 sc->rssi_corr, val);
2450}
2451
2452
2453static void
2454rt2560_scan_start(struct ieee80211com *ic)
2455{
2456	struct rt2560_softc *sc = ic->ic_softc;
2457
2458	/* abort TSF synchronization */
2459	RAL_WRITE(sc, RT2560_CSR14, 0);
2460	rt2560_set_bssid(sc, ieee80211broadcastaddr);
2461}
2462
2463static void
2464rt2560_scan_end(struct ieee80211com *ic)
2465{
2466	struct rt2560_softc *sc = ic->ic_softc;
2467	struct ieee80211vap *vap = ic->ic_scan->ss_vap;
2468
2469	rt2560_enable_tsf_sync(sc);
2470	/* XXX keep local copy */
2471	rt2560_set_bssid(sc, vap->iv_bss->ni_bssid);
2472}
2473
2474static int
2475rt2560_bbp_init(struct rt2560_softc *sc)
2476{
2477	int i, ntries;
2478
2479	/* wait for BBP to be ready */
2480	for (ntries = 0; ntries < 100; ntries++) {
2481		if (rt2560_bbp_read(sc, RT2560_BBP_VERSION) != 0)
2482			break;
2483		DELAY(1);
2484	}
2485	if (ntries == 100) {
2486		device_printf(sc->sc_dev, "timeout waiting for BBP\n");
2487		return EIO;
2488	}
2489
2490	/* initialize BBP registers to default values */
2491	for (i = 0; i < nitems(rt2560_def_bbp); i++) {
2492		rt2560_bbp_write(sc, rt2560_def_bbp[i].reg,
2493		    rt2560_def_bbp[i].val);
2494	}
2495
2496	/* initialize BBP registers to values stored in EEPROM */
2497	for (i = 0; i < 16; i++) {
2498		if (sc->bbp_prom[i].reg == 0 && sc->bbp_prom[i].val == 0)
2499			break;
2500		rt2560_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
2501	}
2502	rt2560_bbp_write(sc, 17, 0x48);	/* XXX restore bbp17 */
2503
2504	return 0;
2505}
2506
2507static void
2508rt2560_set_txantenna(struct rt2560_softc *sc, int antenna)
2509{
2510	uint32_t tmp;
2511	uint8_t tx;
2512
2513	tx = rt2560_bbp_read(sc, RT2560_BBP_TX) & ~RT2560_BBP_ANTMASK;
2514	if (antenna == 1)
2515		tx |= RT2560_BBP_ANTA;
2516	else if (antenna == 2)
2517		tx |= RT2560_BBP_ANTB;
2518	else
2519		tx |= RT2560_BBP_DIVERSITY;
2520
2521	/* need to force I/Q flip for RF 2525e, 2526 and 5222 */
2522	if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526 ||
2523	    sc->rf_rev == RT2560_RF_5222)
2524		tx |= RT2560_BBP_FLIPIQ;
2525
2526	rt2560_bbp_write(sc, RT2560_BBP_TX, tx);
2527
2528	/* update values for CCK and OFDM in BBPCSR1 */
2529	tmp = RAL_READ(sc, RT2560_BBPCSR1) & ~0x00070007;
2530	tmp |= (tx & 0x7) << 16 | (tx & 0x7);
2531	RAL_WRITE(sc, RT2560_BBPCSR1, tmp);
2532}
2533
2534static void
2535rt2560_set_rxantenna(struct rt2560_softc *sc, int antenna)
2536{
2537	uint8_t rx;
2538
2539	rx = rt2560_bbp_read(sc, RT2560_BBP_RX) & ~RT2560_BBP_ANTMASK;
2540	if (antenna == 1)
2541		rx |= RT2560_BBP_ANTA;
2542	else if (antenna == 2)
2543		rx |= RT2560_BBP_ANTB;
2544	else
2545		rx |= RT2560_BBP_DIVERSITY;
2546
2547	/* need to force no I/Q flip for RF 2525e and 2526 */
2548	if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526)
2549		rx &= ~RT2560_BBP_FLIPIQ;
2550
2551	rt2560_bbp_write(sc, RT2560_BBP_RX, rx);
2552}
2553
2554static void
2555rt2560_init_locked(struct rt2560_softc *sc)
2556{
2557	struct ieee80211com *ic = &sc->sc_ic;
2558	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
2559	uint32_t tmp;
2560	int i;
2561
2562	RAL_LOCK_ASSERT(sc);
2563
2564	rt2560_stop_locked(sc);
2565
2566	/* setup tx rings */
2567	tmp = RT2560_PRIO_RING_COUNT << 24 |
2568	      RT2560_ATIM_RING_COUNT << 16 |
2569	      RT2560_TX_RING_COUNT   <<  8 |
2570	      RT2560_TX_DESC_SIZE;
2571
2572	/* rings must be initialized in this exact order */
2573	RAL_WRITE(sc, RT2560_TXCSR2, tmp);
2574	RAL_WRITE(sc, RT2560_TXCSR3, sc->txq.physaddr);
2575	RAL_WRITE(sc, RT2560_TXCSR5, sc->prioq.physaddr);
2576	RAL_WRITE(sc, RT2560_TXCSR4, sc->atimq.physaddr);
2577	RAL_WRITE(sc, RT2560_TXCSR6, sc->bcnq.physaddr);
2578
2579	/* setup rx ring */
2580	tmp = RT2560_RX_RING_COUNT << 8 | RT2560_RX_DESC_SIZE;
2581
2582	RAL_WRITE(sc, RT2560_RXCSR1, tmp);
2583	RAL_WRITE(sc, RT2560_RXCSR2, sc->rxq.physaddr);
2584
2585	/* initialize MAC registers to default values */
2586	for (i = 0; i < nitems(rt2560_def_mac); i++)
2587		RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
2588
2589	rt2560_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
2590
2591	/* set basic rate set (will be updated later) */
2592	RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
2593
2594	rt2560_update_slot(ic);
2595	rt2560_update_plcp(sc);
2596	rt2560_update_led(sc, 0, 0);
2597
2598	RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC);
2599	RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY);
2600
2601	if (rt2560_bbp_init(sc) != 0) {
2602		rt2560_stop_locked(sc);
2603		return;
2604	}
2605
2606	rt2560_set_txantenna(sc, sc->tx_ant);
2607	rt2560_set_rxantenna(sc, sc->rx_ant);
2608
2609	/* set default BSS channel */
2610	rt2560_set_chan(sc, ic->ic_curchan);
2611
2612	/* kick Rx */
2613	tmp = RT2560_DROP_PHY_ERROR | RT2560_DROP_CRC_ERROR;
2614	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2615		tmp |= RT2560_DROP_CTL | RT2560_DROP_VERSION_ERROR;
2616		if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
2617		    ic->ic_opmode != IEEE80211_M_MBSS)
2618			tmp |= RT2560_DROP_TODS;
2619		if (ic->ic_promisc == 0)
2620			tmp |= RT2560_DROP_NOT_TO_ME;
2621	}
2622	RAL_WRITE(sc, RT2560_RXCSR0, tmp);
2623
2624	/* clear old FCS and Rx FIFO errors */
2625	RAL_READ(sc, RT2560_CNT0);
2626	RAL_READ(sc, RT2560_CNT4);
2627
2628	/* clear any pending interrupts */
2629	RAL_WRITE(sc, RT2560_CSR7, 0xffffffff);
2630
2631	/* enable interrupts */
2632	RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
2633
2634	sc->sc_flags |= RT2560_F_RUNNING;
2635
2636	callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
2637}
2638
2639static void
2640rt2560_init(void *priv)
2641{
2642	struct rt2560_softc *sc = priv;
2643	struct ieee80211com *ic = &sc->sc_ic;
2644
2645	RAL_LOCK(sc);
2646	rt2560_init_locked(sc);
2647	RAL_UNLOCK(sc);
2648
2649	if (sc->sc_flags & RT2560_F_RUNNING)
2650		ieee80211_start_all(ic);		/* start all vap's */
2651}
2652
2653static void
2654rt2560_stop_locked(struct rt2560_softc *sc)
2655{
2656	volatile int *flags = &sc->sc_flags;
2657
2658	RAL_LOCK_ASSERT(sc);
2659
2660	while (*flags & RT2560_F_INPUT_RUNNING)
2661		msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10);
2662
2663	callout_stop(&sc->watchdog_ch);
2664	sc->sc_tx_timer = 0;
2665
2666	if (sc->sc_flags & RT2560_F_RUNNING) {
2667		sc->sc_flags &= ~RT2560_F_RUNNING;
2668
2669		/* abort Tx */
2670		RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX);
2671
2672		/* disable Rx */
2673		RAL_WRITE(sc, RT2560_RXCSR0, RT2560_DISABLE_RX);
2674
2675		/* reset ASIC (imply reset BBP) */
2676		RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC);
2677		RAL_WRITE(sc, RT2560_CSR1, 0);
2678
2679		/* disable interrupts */
2680		RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
2681
2682		/* reset Tx and Rx rings */
2683		rt2560_reset_tx_ring(sc, &sc->txq);
2684		rt2560_reset_tx_ring(sc, &sc->atimq);
2685		rt2560_reset_tx_ring(sc, &sc->prioq);
2686		rt2560_reset_tx_ring(sc, &sc->bcnq);
2687		rt2560_reset_rx_ring(sc, &sc->rxq);
2688	}
2689}
2690
2691void
2692rt2560_stop(void *arg)
2693{
2694	struct rt2560_softc *sc = arg;
2695
2696	RAL_LOCK(sc);
2697	rt2560_stop_locked(sc);
2698	RAL_UNLOCK(sc);
2699}
2700
2701static int
2702rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2703	const struct ieee80211_bpf_params *params)
2704{
2705	struct ieee80211com *ic = ni->ni_ic;
2706	struct rt2560_softc *sc = ic->ic_softc;
2707
2708	RAL_LOCK(sc);
2709
2710	/* prevent management frames from being sent if we're not ready */
2711	if (!(sc->sc_flags & RT2560_F_RUNNING)) {
2712		RAL_UNLOCK(sc);
2713		m_freem(m);
2714		return ENETDOWN;
2715	}
2716	if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
2717		RAL_UNLOCK(sc);
2718		m_freem(m);
2719		return ENOBUFS;		/* XXX */
2720	}
2721
2722	if (params == NULL) {
2723		/*
2724		 * Legacy path; interpret frame contents to decide
2725		 * precisely how to send the frame.
2726		 */
2727		if (rt2560_tx_mgt(sc, m, ni) != 0)
2728			goto bad;
2729	} else {
2730		/*
2731		 * Caller supplied explicit parameters to use in
2732		 * sending the frame.
2733		 */
2734		if (rt2560_tx_raw(sc, m, ni, params))
2735			goto bad;
2736	}
2737	sc->sc_tx_timer = 5;
2738
2739	RAL_UNLOCK(sc);
2740
2741	return 0;
2742bad:
2743	RAL_UNLOCK(sc);
2744	return EIO;		/* XXX */
2745}
2746