rt2560.c revision 159180
1170530Ssam/*	$FreeBSD: head/sys/dev/ral/rt2560.c 159180 2006-06-02 19:59:33Z csjp $	*/
2178354Ssam
3170530Ssam/*-
4170530Ssam * Copyright (c) 2005, 2006
5170530Ssam *	Damien Bergamini <damien.bergamini@free.fr>
6170530Ssam *
7170530Ssam * Permission to use, copy, modify, and distribute this software for any
8170530Ssam * purpose with or without fee is hereby granted, provided that the above
9170530Ssam * copyright notice and this permission notice appear in all copies.
10170530Ssam *
11170530Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12170530Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13170530Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14170530Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15170530Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16170530Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17170530Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18170530Ssam */
19170530Ssam
20170530Ssam#include <sys/cdefs.h>
21170530Ssam__FBSDID("$FreeBSD: head/sys/dev/ral/rt2560.c 159180 2006-06-02 19:59:33Z csjp $");
22170530Ssam
23170530Ssam/*-
24170530Ssam * Ralink Technology RT2560 chipset driver
25170530Ssam * http://www.ralinktech.com/
26170530Ssam */
27170530Ssam
28170530Ssam#include <sys/param.h>
29170530Ssam#include <sys/sysctl.h>
30170530Ssam#include <sys/sockio.h>
31170530Ssam#include <sys/mbuf.h>
32170530Ssam#include <sys/kernel.h>
33170530Ssam#include <sys/socket.h>
34170530Ssam#include <sys/systm.h>
35170530Ssam#include <sys/malloc.h>
36178354Ssam#include <sys/module.h>
37170530Ssam#include <sys/bus.h>
38170530Ssam#include <sys/endian.h>
39170530Ssam
40170530Ssam#include <machine/bus.h>
41170530Ssam#include <machine/resource.h>
42170530Ssam#include <sys/rman.h>
43170530Ssam
44170530Ssam#include <net/bpf.h>
45170530Ssam#include <net/if.h>
46170530Ssam#include <net/if_arp.h>
47170530Ssam#include <net/ethernet.h>
48170530Ssam#include <net/if_dl.h>
49170530Ssam#include <net/if_media.h>
50178354Ssam#include <net/if_types.h>
51170530Ssam
52170530Ssam#include <net80211/ieee80211_var.h>
53170530Ssam#include <net80211/ieee80211_radiotap.h>
54170530Ssam
55170530Ssam#include <netinet/in.h>
56178354Ssam#include <netinet/in_systm.h>
57178354Ssam#include <netinet/in_var.h>
58178354Ssam#include <netinet/ip.h>
59178354Ssam#include <netinet/if_ether.h>
60178354Ssam
61178354Ssam#include <dev/ral/if_ralrate.h>
62178354Ssam#include <dev/ral/rt2560reg.h>
63178354Ssam#include <dev/ral/rt2560var.h>
64178354Ssam
65178354Ssam#ifdef RAL_DEBUG
66178354Ssam#define DPRINTF(x)	do { if (ral_debug > 0) printf x; } while (0)
67178354Ssam#define DPRINTFN(n, x)	do { if (ral_debug >= (n)) printf x; } while (0)
68178354Ssamextern int ral_debug;
69178354Ssam#else
70178354Ssam#define DPRINTF(x)
71178354Ssam#define DPRINTFN(n, x)
72178354Ssam#endif
73170530Ssam
74170530Ssamstatic void		rt2560_dma_map_addr(void *, bus_dma_segment_t *, int,
75170530Ssam			    int);
76170530Ssamstatic int		rt2560_alloc_tx_ring(struct rt2560_softc *,
77170530Ssam			    struct rt2560_tx_ring *, int);
78170530Ssamstatic void		rt2560_reset_tx_ring(struct rt2560_softc *,
79170530Ssam			    struct rt2560_tx_ring *);
80170530Ssamstatic void		rt2560_free_tx_ring(struct rt2560_softc *,
81173273Ssam			    struct rt2560_tx_ring *);
82173273Ssamstatic int		rt2560_alloc_rx_ring(struct rt2560_softc *,
83173273Ssam			    struct rt2560_rx_ring *, int);
84173273Ssamstatic void		rt2560_reset_rx_ring(struct rt2560_softc *,
85173273Ssam			    struct rt2560_rx_ring *);
86178354Ssamstatic void		rt2560_free_rx_ring(struct rt2560_softc *,
87178354Ssam			    struct rt2560_rx_ring *);
88178354Ssamstatic struct		ieee80211_node *rt2560_node_alloc(
89173273Ssam			    struct ieee80211_node_table *);
90178354Ssamstatic int		rt2560_media_change(struct ifnet *);
91178354Ssamstatic void		rt2560_next_scan(void *);
92178354Ssamstatic void		rt2560_iter_func(void *, struct ieee80211_node *);
93178354Ssamstatic void		rt2560_update_rssadapt(void *);
94178354Ssamstatic int		rt2560_newstate(struct ieee80211com *,
95178354Ssam			    enum ieee80211_state, int);
96178354Ssamstatic uint16_t		rt2560_eeprom_read(struct rt2560_softc *, uint8_t);
97178354Ssamstatic void		rt2560_encryption_intr(struct rt2560_softc *);
98178354Ssamstatic void		rt2560_tx_intr(struct rt2560_softc *);
99178354Ssamstatic void		rt2560_prio_intr(struct rt2560_softc *);
100178354Ssamstatic void		rt2560_decryption_intr(struct rt2560_softc *);
101178354Ssamstatic void		rt2560_rx_intr(struct rt2560_softc *);
102178354Ssamstatic void		rt2560_beacon_expire(struct rt2560_softc *);
103170530Ssamstatic void		rt2560_wakeup_expire(struct rt2560_softc *);
104178354Ssamstatic uint8_t		rt2560_rxrate(struct rt2560_rx_desc *);
105178354Ssamstatic int		rt2560_ack_rate(struct ieee80211com *, int);
106170530Ssamstatic uint16_t		rt2560_txtime(int, int, uint32_t);
107170530Ssamstatic uint8_t		rt2560_plcp_signal(int);
108170530Ssamstatic void		rt2560_setup_tx_desc(struct rt2560_softc *,
109170530Ssam			    struct rt2560_tx_desc *, uint32_t, int, int, int,
110170530Ssam			    bus_addr_t);
111170530Ssamstatic int		rt2560_tx_bcn(struct rt2560_softc *, struct mbuf *,
112170530Ssam			    struct ieee80211_node *);
113170530Ssamstatic int		rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
114170530Ssam			    struct ieee80211_node *);
115170530Ssamstatic struct		mbuf *rt2560_get_rts(struct rt2560_softc *,
116170530Ssam			    struct ieee80211_frame *, uint16_t);
117170530Ssamstatic int		rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
118170530Ssam			    struct ieee80211_node *);
119170530Ssamstatic void		rt2560_start(struct ifnet *);
120170530Ssamstatic void		rt2560_watchdog(struct ifnet *);
121170530Ssamstatic int		rt2560_reset(struct ifnet *);
122170530Ssamstatic int		rt2560_ioctl(struct ifnet *, u_long, caddr_t);
123178354Ssamstatic void		rt2560_bbp_write(struct rt2560_softc *, uint8_t,
124170530Ssam			    uint8_t);
125170530Ssamstatic uint8_t		rt2560_bbp_read(struct rt2560_softc *, uint8_t);
126170530Ssamstatic void		rt2560_rf_write(struct rt2560_softc *, uint8_t,
127170530Ssam			    uint32_t);
128173273Ssamstatic void		rt2560_set_chan(struct rt2560_softc *,
129173273Ssam			    struct ieee80211_channel *);
130178354Ssam#if 0
131173273Ssamstatic void		rt2560_disable_rf_tune(struct rt2560_softc *);
132178354Ssam#endif
133178354Ssamstatic void		rt2560_enable_tsf_sync(struct rt2560_softc *);
134178354Ssamstatic void		rt2560_update_plcp(struct rt2560_softc *);
135178354Ssamstatic void		rt2560_update_slot(struct ifnet *);
136173273Ssamstatic void		rt2560_set_basicrates(struct rt2560_softc *);
137178354Ssamstatic void		rt2560_update_led(struct rt2560_softc *, int, int);
138178354Ssamstatic void		rt2560_set_bssid(struct rt2560_softc *, uint8_t *);
139178354Ssamstatic void		rt2560_set_macaddr(struct rt2560_softc *, uint8_t *);
140178354Ssamstatic void		rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
141178354Ssamstatic void		rt2560_update_promisc(struct rt2560_softc *);
142178354Ssamstatic const char	*rt2560_get_rf(int);
143178354Ssamstatic void		rt2560_read_eeprom(struct rt2560_softc *);
144178354Ssamstatic int		rt2560_bbp_init(struct rt2560_softc *);
145178354Ssamstatic void		rt2560_set_txantenna(struct rt2560_softc *, int);
146178354Ssamstatic void		rt2560_set_rxantenna(struct rt2560_softc *, int);
147178354Ssamstatic void		rt2560_init(void *);
148178354Ssamstatic void		rt2560_stop(void *);
149178354Ssam
150178354Ssam/*
151178354Ssam * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
152178354Ssam */
153170530Ssamstatic const struct ieee80211_rateset rt2560_rateset_11a =
154173273Ssam	{ 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
155173273Ssam
156170530Ssamstatic const struct ieee80211_rateset rt2560_rateset_11b =
157170530Ssam	{ 4, { 2, 4, 11, 22 } };
158178354Ssam
159178354Ssamstatic const struct ieee80211_rateset rt2560_rateset_11g =
160178354Ssam	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
161178354Ssam
162178354Ssamstatic const struct {
163173273Ssam	uint32_t	reg;
164178354Ssam	uint32_t	val;
165178354Ssam} rt2560_def_mac[] = {
166178354Ssam	RT2560_DEF_MAC
167178354Ssam};
168170530Ssam
169170530Ssamstatic const struct {
170178354Ssam	uint8_t	reg;
171178354Ssam	uint8_t	val;
172178354Ssam} rt2560_def_bbp[] = {
173178354Ssam	RT2560_DEF_BBP
174178354Ssam};
175178354Ssam
176170530Ssamstatic const uint32_t rt2560_rf2522_r2[]    = RT2560_RF2522_R2;
177178354Ssamstatic const uint32_t rt2560_rf2523_r2[]    = RT2560_RF2523_R2;
178178354Ssamstatic const uint32_t rt2560_rf2524_r2[]    = RT2560_RF2524_R2;
179178354Ssamstatic const uint32_t rt2560_rf2525_r2[]    = RT2560_RF2525_R2;
180170530Ssamstatic const uint32_t rt2560_rf2525_hi_r2[] = RT2560_RF2525_HI_R2;
181170530Ssamstatic const uint32_t rt2560_rf2525e_r2[]   = RT2560_RF2525E_R2;
182170530Ssamstatic const uint32_t rt2560_rf2526_r2[]    = RT2560_RF2526_R2;
183178354Ssamstatic const uint32_t rt2560_rf2526_hi_r2[] = RT2560_RF2526_HI_R2;
184170530Ssam
185170530Ssamstatic const struct {
186170530Ssam	uint8_t		chan;
187170530Ssam	uint32_t	r1, r2, r4;
188170530Ssam} rt2560_rf5222[] = {
189170530Ssam	RT2560_RF5222
190170530Ssam};
191170530Ssam
192170530Ssamint
193170530Ssamrt2560_attach(device_t dev, int id)
194170530Ssam{
195170530Ssam	struct rt2560_softc *sc = device_get_softc(dev);
196172226Ssam	struct ieee80211com *ic = &sc->sc_ic;
197172226Ssam	struct ifnet *ifp;
198170530Ssam	int error, i;
199170530Ssam
200178354Ssam	sc->sc_dev = dev;
201170530Ssam
202170530Ssam	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
203170530Ssam	    MTX_DEF | MTX_RECURSE);
204170530Ssam
205170530Ssam	callout_init(&sc->scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
206170530Ssam	callout_init(&sc->rssadapt_ch, CALLOUT_MPSAFE);
207170530Ssam
208170530Ssam	/* retrieve RT2560 rev. no */
209170530Ssam	sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
210170530Ssam
211170530Ssam	/* retrieve MAC address */
212170530Ssam	rt2560_get_macaddr(sc, ic->ic_myaddr);
213170530Ssam
214170530Ssam	/* retrieve RF rev. no and various other things from EEPROM */
215170530Ssam	rt2560_read_eeprom(sc);
216170530Ssam
217170530Ssam	device_printf(dev, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n",
218170530Ssam	    sc->asic_rev, rt2560_get_rf(sc->rf_rev));
219170530Ssam
220173273Ssam	/*
221170530Ssam	 * Allocate Tx and Rx rings.
222170530Ssam	 */
223170530Ssam	error = rt2560_alloc_tx_ring(sc, &sc->txq, RT2560_TX_RING_COUNT);
224170530Ssam	if (error != 0) {
225170530Ssam		device_printf(sc->sc_dev, "could not allocate Tx ring\n");
226170530Ssam		goto fail1;
227170530Ssam	}
228170530Ssam
229170530Ssam	error = rt2560_alloc_tx_ring(sc, &sc->atimq, RT2560_ATIM_RING_COUNT);
230170530Ssam	if (error != 0) {
231170530Ssam		device_printf(sc->sc_dev, "could not allocate ATIM ring\n");
232170530Ssam		goto fail2;
233170530Ssam	}
234170530Ssam
235178354Ssam	error = rt2560_alloc_tx_ring(sc, &sc->prioq, RT2560_PRIO_RING_COUNT);
236173462Ssam	if (error != 0) {
237170530Ssam		device_printf(sc->sc_dev, "could not allocate Prio ring\n");
238170530Ssam		goto fail3;
239170530Ssam	}
240170530Ssam
241170530Ssam	error = rt2560_alloc_tx_ring(sc, &sc->bcnq, RT2560_BEACON_RING_COUNT);
242178354Ssam	if (error != 0) {
243170530Ssam		device_printf(sc->sc_dev, "could not allocate Beacon ring\n");
244170530Ssam		goto fail4;
245170530Ssam	}
246170530Ssam
247170530Ssam	error = rt2560_alloc_rx_ring(sc, &sc->rxq, RT2560_RX_RING_COUNT);
248170530Ssam	if (error != 0) {
249170530Ssam		device_printf(sc->sc_dev, "could not allocate Rx ring\n");
250170530Ssam		goto fail5;
251170530Ssam	}
252170530Ssam
253178354Ssam	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
254173462Ssam	if (ifp == NULL) {
255178354Ssam		device_printf(sc->sc_dev, "can not if_alloc()\n");
256170530Ssam		goto fail6;
257170530Ssam	}
258173462Ssam
259170530Ssam	ifp->if_softc = sc;
260170530Ssam	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
261170530Ssam	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
262178354Ssam	ifp->if_init = rt2560_init;
263170530Ssam	ifp->if_ioctl = rt2560_ioctl;
264170530Ssam	ifp->if_start = rt2560_start;
265178354Ssam	ifp->if_watchdog = rt2560_watchdog;
266170530Ssam	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
267170530Ssam	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
268170530Ssam	IFQ_SET_READY(&ifp->if_snd);
269178354Ssam
270170530Ssam	ic->ic_ifp = ifp;
271170530Ssam	ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
272170530Ssam	ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
273170530Ssam	ic->ic_state = IEEE80211_S_INIT;
274170530Ssam
275170530Ssam	/* set device capabilities */
276170530Ssam	ic->ic_caps =
277170530Ssam	    IEEE80211_C_IBSS |		/* IBSS mode supported */
278170530Ssam	    IEEE80211_C_MONITOR |	/* monitor mode supported */
279170530Ssam	    IEEE80211_C_HOSTAP |	/* HostAp mode supported */
280170530Ssam	    IEEE80211_C_TXPMGT |	/* tx power management */
281170530Ssam	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
282170530Ssam	    IEEE80211_C_SHSLOT |	/* short slot time supported */
283170530Ssam	    IEEE80211_C_WPA;		/* 802.11i */
284170530Ssam
285170530Ssam	if (sc->rf_rev == RT2560_RF_5222) {
286170530Ssam		/* set supported .11a rates */
287170530Ssam		ic->ic_sup_rates[IEEE80211_MODE_11A] = rt2560_rateset_11a;
288170530Ssam
289170530Ssam		/* set supported .11a channels */
290170530Ssam		for (i = 36; i <= 64; i += 4) {
291170530Ssam			ic->ic_channels[i].ic_freq =
292170530Ssam			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
293170530Ssam			ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
294170530Ssam		}
295170530Ssam		for (i = 100; i <= 140; i += 4) {
296170530Ssam			ic->ic_channels[i].ic_freq =
297170530Ssam			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
298170530Ssam			ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
299170530Ssam		}
300170530Ssam		for (i = 149; i <= 161; i += 4) {
301170530Ssam			ic->ic_channels[i].ic_freq =
302170530Ssam			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
303170530Ssam			ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
304170530Ssam		}
305170530Ssam	}
306178354Ssam
307178354Ssam	/* set supported .11b and .11g rates */
308178354Ssam	ic->ic_sup_rates[IEEE80211_MODE_11B] = rt2560_rateset_11b;
309178354Ssam	ic->ic_sup_rates[IEEE80211_MODE_11G] = rt2560_rateset_11g;
310178354Ssam
311178354Ssam	/* set supported .11b and .11g channels (1 through 14) */
312178354Ssam	for (i = 1; i <= 14; i++) {
313178354Ssam		ic->ic_channels[i].ic_freq =
314178354Ssam		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
315178354Ssam		ic->ic_channels[i].ic_flags =
316178354Ssam		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
317178354Ssam		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
318178354Ssam	}
319178354Ssam
320178354Ssam	ieee80211_ifattach(ic);
321178354Ssam	ic->ic_node_alloc = rt2560_node_alloc;
322178354Ssam	ic->ic_updateslot = rt2560_update_slot;
323178354Ssam	ic->ic_reset = rt2560_reset;
324178354Ssam	/* enable s/w bmiss handling in sta mode */
325178354Ssam	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
326170530Ssam
327170530Ssam	/* override state transition machine */
328170530Ssam	sc->sc_newstate = ic->ic_newstate;
329170530Ssam	ic->ic_newstate = rt2560_newstate;
330170530Ssam	ieee80211_media_init(ic, rt2560_media_change, ieee80211_media_status);
331170530Ssam
332178354Ssam	bpfattach2(ifp, DLT_IEEE802_11_RADIO,
333170530Ssam	    sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf);
334170530Ssam
335170530Ssam	sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
336170530Ssam	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
337170530Ssam	sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2560_RX_RADIOTAP_PRESENT);
338170530Ssam
339170530Ssam	sc->sc_txtap_len = sizeof sc->sc_txtapu;
340170530Ssam	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
341170530Ssam	sc->sc_txtap.wt_ihdr.it_present = htole32(RT2560_TX_RADIOTAP_PRESENT);
342170530Ssam
343170530Ssam	/*
344170530Ssam	 * Add a few sysctl knobs.
345170530Ssam	 */
346178354Ssam	sc->dwelltime = 200;
347170530Ssam
348170530Ssam	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
349170530Ssam	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
350170530Ssam	    "txantenna", CTLFLAG_RW, &sc->tx_ant, 0, "tx antenna (0=auto)");
351170530Ssam
352170530Ssam	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
353170530Ssam	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
354170530Ssam	    "rxantenna", CTLFLAG_RW, &sc->rx_ant, 0, "rx antenna (0=auto)");
355170530Ssam
356170530Ssam	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
357170530Ssam	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "dwell",
358170530Ssam	    CTLFLAG_RW, &sc->dwelltime, 0,
359170530Ssam	    "channel dwell time (ms) for AP/station scanning");
360178354Ssam
361170530Ssam	if (bootverbose)
362170530Ssam		ieee80211_announce(ic);
363170530Ssam
364170530Ssam	return 0;
365170530Ssam
366170530Ssamfail6:	rt2560_free_rx_ring(sc, &sc->rxq);
367170530Ssamfail5:	rt2560_free_tx_ring(sc, &sc->bcnq);
368170530Ssamfail4:	rt2560_free_tx_ring(sc, &sc->prioq);
369170530Ssamfail3:	rt2560_free_tx_ring(sc, &sc->atimq);
370170530Ssamfail2:	rt2560_free_tx_ring(sc, &sc->txq);
371170530Ssamfail1:	mtx_destroy(&sc->sc_mtx);
372170530Ssam
373170530Ssam	return ENXIO;
374170530Ssam}
375170530Ssam
376170530Ssamint
377170530Ssamrt2560_detach(void *xsc)
378170530Ssam{
379170530Ssam	struct rt2560_softc *sc = xsc;
380170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
381170530Ssam	struct ifnet *ifp = ic->ic_ifp;
382170530Ssam
383170530Ssam	rt2560_stop(sc);
384170530Ssam	callout_stop(&sc->scan_ch);
385170530Ssam	callout_stop(&sc->rssadapt_ch);
386170530Ssam
387170530Ssam	bpfdetach(ifp);
388170530Ssam	ieee80211_ifdetach(ic);
389170530Ssam
390178354Ssam	rt2560_free_tx_ring(sc, &sc->txq);
391170530Ssam	rt2560_free_tx_ring(sc, &sc->atimq);
392173273Ssam	rt2560_free_tx_ring(sc, &sc->prioq);
393173273Ssam	rt2560_free_tx_ring(sc, &sc->bcnq);
394173273Ssam	rt2560_free_rx_ring(sc, &sc->rxq);
395173273Ssam
396173273Ssam	if_free(ifp);
397178354Ssam
398170530Ssam	mtx_destroy(&sc->sc_mtx);
399170530Ssam
400173273Ssam	return 0;
401170530Ssam}
402173273Ssam
403170530Ssamvoid
404170530Ssamrt2560_shutdown(void *xsc)
405173273Ssam{
406170530Ssam	struct rt2560_softc *sc = xsc;
407178354Ssam
408170530Ssam	rt2560_stop(sc);
409170530Ssam}
410170530Ssam
411173273Ssamvoid
412170530Ssamrt2560_suspend(void *xsc)
413170530Ssam{
414170530Ssam	struct rt2560_softc *sc = xsc;
415170530Ssam
416170530Ssam	rt2560_stop(sc);
417173273Ssam}
418178354Ssam
419173273Ssamvoid
420170530Ssamrt2560_resume(void *xsc)
421173273Ssam{
422170530Ssam	struct rt2560_softc *sc = xsc;
423170530Ssam	struct ifnet *ifp = sc->sc_ic.ic_ifp;
424170530Ssam
425173273Ssam	if (ifp->if_flags & IFF_UP) {
426170530Ssam		ifp->if_init(ifp->if_softc);
427170530Ssam		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
428173273Ssam			ifp->if_start(ifp);
429173273Ssam	}
430173273Ssam}
431173273Ssam
432173273Ssamstatic void
433173273Ssamrt2560_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
434173273Ssam{
435173273Ssam	if (error != 0)
436178354Ssam		return;
437173273Ssam
438173273Ssam	KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
439173273Ssam
440173273Ssam	*(bus_addr_t *)arg = segs[0].ds_addr;
441173273Ssam}
442173273Ssam
443173273Ssamstatic int
444173273Ssamrt2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring,
445173273Ssam    int count)
446173273Ssam{
447173273Ssam	int i, error;
448173273Ssam
449173273Ssam	ring->count = count;
450173273Ssam	ring->queued = 0;
451173273Ssam	ring->cur = ring->next = 0;
452173273Ssam	ring->cur_encrypt = ring->next_encrypt = 0;
453173273Ssam
454173273Ssam	error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT,
455178354Ssam	    BUS_SPACE_MAXADDR, NULL, NULL, count * RT2560_TX_DESC_SIZE, 1,
456173273Ssam	    count * RT2560_TX_DESC_SIZE, 0, NULL, NULL, &ring->desc_dmat);
457173273Ssam	if (error != 0) {
458173273Ssam		device_printf(sc->sc_dev, "could not create desc DMA tag\n");
459173273Ssam		goto fail;
460173273Ssam	}
461173273Ssam
462173273Ssam	error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc,
463173273Ssam	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map);
464173273Ssam	if (error != 0) {
465173273Ssam		device_printf(sc->sc_dev, "could not allocate DMA memory\n");
466173273Ssam		goto fail;
467173273Ssam	}
468173273Ssam
469173273Ssam	error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc,
470178354Ssam	    count * RT2560_TX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr,
471178354Ssam	    0);
472178354Ssam	if (error != 0) {
473178354Ssam		device_printf(sc->sc_dev, "could not load desc DMA map\n");
474173273Ssam		goto fail;
475173273Ssam	}
476173273Ssam
477173273Ssam	ring->data = malloc(count * sizeof (struct rt2560_tx_data), M_DEVBUF,
478173273Ssam	    M_NOWAIT | M_ZERO);
479173273Ssam	if (ring->data == NULL) {
480173273Ssam		device_printf(sc->sc_dev, "could not allocate soft data\n");
481173273Ssam		error = ENOMEM;
482173273Ssam		goto fail;
483173273Ssam	}
484173273Ssam
485173273Ssam	error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
486173273Ssam	    BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, RT2560_MAX_SCATTER,
487178354Ssam	    MCLBYTES, 0, NULL, NULL, &ring->data_dmat);
488173273Ssam	if (error != 0) {
489173273Ssam		device_printf(sc->sc_dev, "could not create data DMA tag\n");
490173273Ssam		goto fail;
491173273Ssam	}
492173273Ssam
493173273Ssam	for (i = 0; i < count; i++) {
494173273Ssam		error = bus_dmamap_create(ring->data_dmat, 0,
495173273Ssam		    &ring->data[i].map);
496173273Ssam		if (error != 0) {
497173273Ssam			device_printf(sc->sc_dev, "could not create DMA map\n");
498173273Ssam			goto fail;
499170530Ssam		}
500170530Ssam	}
501170530Ssam
502173273Ssam	return 0;
503170530Ssam
504170530Ssamfail:	rt2560_free_tx_ring(sc, ring);
505170530Ssam	return error;
506170530Ssam}
507170530Ssam
508170530Ssamstatic void
509170530Ssamrt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
510170530Ssam{
511173273Ssam	struct rt2560_tx_desc *desc;
512173273Ssam	struct rt2560_tx_data *data;
513178354Ssam	int i;
514170530Ssam
515170530Ssam	for (i = 0; i < ring->count; i++) {
516170530Ssam		desc = &ring->desc[i];
517170530Ssam		data = &ring->data[i];
518170530Ssam
519170530Ssam		if (data->m != NULL) {
520170530Ssam			bus_dmamap_sync(ring->data_dmat, data->map,
521170530Ssam			    BUS_DMASYNC_POSTWRITE);
522170530Ssam			bus_dmamap_unload(ring->data_dmat, data->map);
523170530Ssam			m_freem(data->m);
524170530Ssam			data->m = NULL;
525170530Ssam		}
526173273Ssam
527173273Ssam		if (data->ni != NULL) {
528173273Ssam			ieee80211_free_node(data->ni);
529173273Ssam			data->ni = NULL;
530173273Ssam		}
531170530Ssam
532170530Ssam		desc->flags = 0;
533170530Ssam	}
534170530Ssam
535170530Ssam	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
536173273Ssam
537170530Ssam	ring->queued = 0;
538182827Ssam	ring->cur = ring->next = 0;
539182827Ssam	ring->cur_encrypt = ring->next_encrypt = 0;
540182827Ssam}
541182827Ssam
542182827Ssamstatic void
543182827Ssamrt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
544182827Ssam{
545182827Ssam	struct rt2560_tx_data *data;
546182827Ssam	int i;
547182827Ssam
548182827Ssam	if (ring->desc != NULL) {
549182827Ssam		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
550182827Ssam		    BUS_DMASYNC_POSTWRITE);
551182827Ssam		bus_dmamap_unload(ring->desc_dmat, ring->desc_map);
552182827Ssam		bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map);
553173273Ssam	}
554173273Ssam
555170530Ssam	if (ring->desc_dmat != NULL)
556170530Ssam		bus_dma_tag_destroy(ring->desc_dmat);
557170530Ssam
558170530Ssam	if (ring->data != NULL) {
559170530Ssam		for (i = 0; i < ring->count; i++) {
560170530Ssam			data = &ring->data[i];
561170530Ssam
562170530Ssam			if (data->m != NULL) {
563170530Ssam				bus_dmamap_sync(ring->data_dmat, data->map,
564170530Ssam				    BUS_DMASYNC_POSTWRITE);
565170530Ssam				bus_dmamap_unload(ring->data_dmat, data->map);
566173273Ssam				m_freem(data->m);
567170530Ssam			}
568170530Ssam
569170530Ssam			if (data->ni != NULL)
570170530Ssam				ieee80211_free_node(data->ni);
571170530Ssam
572170530Ssam			if (data->map != NULL)
573173273Ssam				bus_dmamap_destroy(ring->data_dmat, data->map);
574170530Ssam		}
575170530Ssam
576170530Ssam		free(ring->data, M_DEVBUF);
577173273Ssam	}
578170530Ssam
579170530Ssam	if (ring->data_dmat != NULL)
580170530Ssam		bus_dma_tag_destroy(ring->data_dmat);
581173273Ssam}
582170530Ssam
583173273Ssamstatic int
584173273Ssamrt2560_alloc_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring,
585173273Ssam    int count)
586173273Ssam{
587173273Ssam	struct rt2560_rx_desc *desc;
588173273Ssam	struct rt2560_rx_data *data;
589173273Ssam	bus_addr_t physaddr;
590173273Ssam	int i, error;
591173273Ssam
592173273Ssam	ring->count = count;
593173273Ssam	ring->cur = ring->next = 0;
594173273Ssam	ring->cur_decrypt = 0;
595173273Ssam
596173273Ssam	error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT,
597170530Ssam	    BUS_SPACE_MAXADDR, NULL, NULL, count * RT2560_RX_DESC_SIZE, 1,
598173273Ssam	    count * RT2560_RX_DESC_SIZE, 0, NULL, NULL, &ring->desc_dmat);
599173273Ssam	if (error != 0) {
600173273Ssam		device_printf(sc->sc_dev, "could not create desc DMA tag\n");
601173273Ssam		goto fail;
602173273Ssam	}
603170530Ssam
604173273Ssam	error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc,
605173273Ssam	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map);
606173273Ssam	if (error != 0) {
607173273Ssam		device_printf(sc->sc_dev, "could not allocate DMA memory\n");
608173273Ssam		goto fail;
609173273Ssam	}
610173273Ssam
611173273Ssam	error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc,
612178354Ssam	    count * RT2560_RX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr,
613173273Ssam	    0);
614173273Ssam	if (error != 0) {
615173273Ssam		device_printf(sc->sc_dev, "could not load desc DMA map\n");
616173273Ssam		goto fail;
617173273Ssam	}
618173273Ssam
619173273Ssam	ring->data = malloc(count * sizeof (struct rt2560_rx_data), M_DEVBUF,
620173273Ssam	    M_NOWAIT | M_ZERO);
621173273Ssam	if (ring->data == NULL) {
622173273Ssam		device_printf(sc->sc_dev, "could not allocate soft data\n");
623173273Ssam		error = ENOMEM;
624173273Ssam		goto fail;
625173273Ssam	}
626173273Ssam
627173273Ssam	/*
628173273Ssam	 * Pre-allocate Rx buffers and populate Rx ring.
629173273Ssam	 */
630173273Ssam	error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
631178354Ssam	    BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, NULL,
632173273Ssam	    NULL, &ring->data_dmat);
633178354Ssam	if (error != 0) {
634173273Ssam		device_printf(sc->sc_dev, "could not create data DMA tag\n");
635173273Ssam		goto fail;
636173273Ssam	}
637173273Ssam
638173273Ssam	for (i = 0; i < count; i++) {
639178354Ssam		desc = &sc->rxq.desc[i];
640173273Ssam		data = &sc->rxq.data[i];
641173273Ssam
642173273Ssam		error = bus_dmamap_create(ring->data_dmat, 0, &data->map);
643173273Ssam		if (error != 0) {
644173273Ssam			device_printf(sc->sc_dev, "could not create DMA map\n");
645173273Ssam			goto fail;
646173273Ssam		}
647173273Ssam
648173273Ssam		data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
649173273Ssam		if (data->m == NULL) {
650173273Ssam			device_printf(sc->sc_dev,
651178354Ssam			    "could not allocate rx mbuf\n");
652173273Ssam			error = ENOMEM;
653170530Ssam			goto fail;
654173273Ssam		}
655170530Ssam
656178354Ssam		error = bus_dmamap_load(ring->data_dmat, data->map,
657170530Ssam		    mtod(data->m, void *), MCLBYTES, rt2560_dma_map_addr,
658173273Ssam		    &physaddr, 0);
659173273Ssam		if (error != 0) {
660173273Ssam			device_printf(sc->sc_dev,
661173273Ssam			    "could not load rx buf DMA map");
662173273Ssam			goto fail;
663173273Ssam		}
664173273Ssam
665173273Ssam		desc->flags = htole32(RT2560_RX_BUSY);
666173273Ssam		desc->physaddr = htole32(physaddr);
667173273Ssam	}
668173273Ssam
669173273Ssam	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
670170530Ssam
671170530Ssam	return 0;
672173273Ssam
673173273Ssamfail:	rt2560_free_rx_ring(sc, ring);
674170530Ssam	return error;
675178354Ssam}
676173273Ssam
677178354Ssamstatic void
678173273Ssamrt2560_reset_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring)
679173273Ssam{
680173273Ssam	int i;
681173273Ssam
682178354Ssam	for (i = 0; i < ring->count; i++) {
683173273Ssam		ring->desc[i].flags = htole32(RT2560_RX_BUSY);
684170530Ssam		ring->data[i].drop = 0;
685173273Ssam	}
686170530Ssam
687173273Ssam	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
688173273Ssam
689170530Ssam	ring->cur = ring->next = 0;
690170530Ssam	ring->cur_decrypt = 0;
691170530Ssam}
692170530Ssam
693170530Ssamstatic void
694170530Ssamrt2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring)
695173273Ssam{
696170530Ssam	struct rt2560_rx_data *data;
697170530Ssam	int i;
698170530Ssam
699170530Ssam	if (ring->desc != NULL) {
700178354Ssam		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
701170530Ssam		    BUS_DMASYNC_POSTWRITE);
702170530Ssam		bus_dmamap_unload(ring->desc_dmat, ring->desc_map);
703170530Ssam		bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map);
704170530Ssam	}
705170530Ssam
706173273Ssam	if (ring->desc_dmat != NULL)
707173273Ssam		bus_dma_tag_destroy(ring->desc_dmat);
708178354Ssam
709173273Ssam	if (ring->data != NULL) {
710173273Ssam		for (i = 0; i < ring->count; i++) {
711178354Ssam			data = &ring->data[i];
712173273Ssam
713173273Ssam			if (data->m != NULL) {
714170530Ssam				bus_dmamap_sync(ring->data_dmat, data->map,
715170530Ssam				    BUS_DMASYNC_POSTREAD);
716170530Ssam				bus_dmamap_unload(ring->data_dmat, data->map);
717170530Ssam				m_freem(data->m);
718170530Ssam			}
719170530Ssam
720170530Ssam			if (data->map != NULL)
721170530Ssam				bus_dmamap_destroy(ring->data_dmat, data->map);
722178354Ssam		}
723170530Ssam
724170530Ssam		free(ring->data, M_DEVBUF);
725178354Ssam	}
726170530Ssam
727170530Ssam	if (ring->data_dmat != NULL)
728178354Ssam		bus_dma_tag_destroy(ring->data_dmat);
729170530Ssam}
730173273Ssam
731173273Ssamstatic struct ieee80211_node *
732170530Ssamrt2560_node_alloc(struct ieee80211_node_table *nt)
733170530Ssam{
734173273Ssam	struct rt2560_node *rn;
735170530Ssam
736173273Ssam	rn = malloc(sizeof (struct rt2560_node), M_80211_NODE,
737173273Ssam	    M_NOWAIT | M_ZERO);
738170530Ssam
739178354Ssam	return (rn != NULL) ? &rn->ni : NULL;
740173273Ssam}
741170530Ssam
742173273Ssamstatic int
743173273Ssamrt2560_media_change(struct ifnet *ifp)
744178354Ssam{
745173273Ssam	struct rt2560_softc *sc = ifp->if_softc;
746173273Ssam	int error;
747173273Ssam
748173273Ssam	error = ieee80211_media_change(ifp);
749173273Ssam	if (error != ENETRESET)
750173273Ssam		return error;
751173273Ssam
752173273Ssam	if ((ifp->if_flags & IFF_UP) &&
753173273Ssam	    (ifp->if_drv_flags & IFF_DRV_RUNNING))
754170530Ssam		rt2560_init(sc);
755173273Ssam
756170530Ssam	return 0;
757173273Ssam}
758173273Ssam
759170530Ssam/*
760178354Ssam * This function is called periodically (every 200ms) during scanning to
761173273Ssam * switch from one channel to another.
762173273Ssam */
763173273Ssamstatic void
764173273Ssamrt2560_next_scan(void *arg)
765173273Ssam{
766173273Ssam	struct rt2560_softc *sc = arg;
767178354Ssam	struct ieee80211com *ic = &sc->sc_ic;
768173273Ssam
769170530Ssam	if (ic->ic_state == IEEE80211_S_SCAN)
770170530Ssam		ieee80211_next_scan(ic);
771170530Ssam}
772170530Ssam
773170530Ssam/*
774170530Ssam * This function is called for each node present in the node station table.
775170530Ssam */
776170530Ssamstatic void
777170530Ssamrt2560_iter_func(void *arg, struct ieee80211_node *ni)
778170530Ssam{
779170530Ssam	struct rt2560_node *rn = (struct rt2560_node *)ni;
780170530Ssam
781170530Ssam	ral_rssadapt_updatestats(&rn->rssadapt);
782170530Ssam}
783173273Ssam
784173273Ssam/*
785173273Ssam * This function is called periodically (every 100ms) in RUN state to update
786173273Ssam * the rate adaptation statistics.
787173273Ssam */
788173273Ssamstatic void
789173273Ssamrt2560_update_rssadapt(void *arg)
790173273Ssam{
791170530Ssam	struct rt2560_softc *sc = arg;
792170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
793170530Ssam
794170530Ssam	RAL_LOCK(sc);
795173273Ssam
796170530Ssam	ieee80211_iterate_nodes(&ic->ic_sta, rt2560_iter_func, arg);
797173273Ssam	callout_reset(&sc->rssadapt_ch, hz / 10, rt2560_update_rssadapt, sc);
798170530Ssam
799170530Ssam	RAL_UNLOCK(sc);
800170530Ssam}
801170530Ssam
802170530Ssamstatic int
803170530Ssamrt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
804170530Ssam{
805170530Ssam	struct rt2560_softc *sc = ic->ic_ifp->if_softc;
806170530Ssam	enum ieee80211_state ostate;
807170530Ssam	struct ieee80211_node *ni;
808170530Ssam	struct mbuf *m;
809170530Ssam	int error = 0;
810170530Ssam
811170530Ssam	ostate = ic->ic_state;
812170530Ssam	callout_stop(&sc->scan_ch);
813170530Ssam
814170530Ssam	switch (nstate) {
815173273Ssam	case IEEE80211_S_INIT:
816173273Ssam		callout_stop(&sc->rssadapt_ch);
817173273Ssam
818173273Ssam		if (ostate == IEEE80211_S_RUN) {
819173273Ssam			/* abort TSF synchronization */
820170530Ssam			RAL_WRITE(sc, RT2560_CSR14, 0);
821178354Ssam
822178354Ssam			/* turn association led off */
823173273Ssam			rt2560_update_led(sc, 0, 0);
824173273Ssam		}
825173273Ssam		break;
826173273Ssam
827170530Ssam	case IEEE80211_S_SCAN:
828170530Ssam		rt2560_set_chan(sc, ic->ic_curchan);
829170530Ssam		callout_reset(&sc->scan_ch, (sc->dwelltime * hz) / 1000,
830170530Ssam		    rt2560_next_scan, sc);
831170530Ssam		break;
832173273Ssam
833173273Ssam	case IEEE80211_S_AUTH:
834170530Ssam		rt2560_set_chan(sc, ic->ic_curchan);
835170530Ssam		break;
836178354Ssam
837178354Ssam	case IEEE80211_S_ASSOC:
838178354Ssam		rt2560_set_chan(sc, ic->ic_curchan);
839178354Ssam		break;
840178354Ssam
841178354Ssam	case IEEE80211_S_RUN:
842178354Ssam		rt2560_set_chan(sc, ic->ic_curchan);
843178354Ssam
844178354Ssam		ni = ic->ic_bss;
845178354Ssam
846178354Ssam		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
847178354Ssam			rt2560_update_plcp(sc);
848178354Ssam			rt2560_set_basicrates(sc);
849178354Ssam			rt2560_set_bssid(sc, ni->ni_bssid);
850178354Ssam		}
851178354Ssam
852178354Ssam		if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
853178354Ssam		    ic->ic_opmode == IEEE80211_M_IBSS) {
854178354Ssam			m = ieee80211_beacon_alloc(ic, ni, &sc->sc_bo);
855178354Ssam			if (m == NULL) {
856178354Ssam				device_printf(sc->sc_dev,
857178354Ssam				    "could not allocate beacon\n");
858178354Ssam				error = ENOBUFS;
859178354Ssam				break;
860178354Ssam			}
861178354Ssam
862178354Ssam			ieee80211_ref_node(ni);
863178354Ssam			error = rt2560_tx_bcn(sc, m, ni);
864178354Ssam			if (error != 0)
865178354Ssam				break;
866178354Ssam		}
867178354Ssam
868178354Ssam		/* turn assocation led on */
869178354Ssam		rt2560_update_led(sc, 1, 0);
870178354Ssam
871178354Ssam		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
872178354Ssam			callout_reset(&sc->rssadapt_ch, hz / 10,
873178354Ssam			    rt2560_update_rssadapt, sc);
874178354Ssam
875173273Ssam			rt2560_enable_tsf_sync(sc);
876173273Ssam		}
877173273Ssam		break;
878173273Ssam	}
879173273Ssam
880173273Ssam	return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg);
881173273Ssam}
882173273Ssam
883173273Ssam/*
884173273Ssam * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
885173273Ssam * 93C66).
886173273Ssam */
887173273Ssamstatic uint16_t
888173273Ssamrt2560_eeprom_read(struct rt2560_softc *sc, uint8_t addr)
889173273Ssam{
890173273Ssam	uint32_t tmp;
891173273Ssam	uint16_t val;
892173273Ssam	int n;
893173273Ssam
894173273Ssam	/* clock C once before the first command */
895173273Ssam	RT2560_EEPROM_CTL(sc, 0);
896173273Ssam
897173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S);
898173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
899173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S);
900173273Ssam
901173273Ssam	/* write start bit (1) */
902173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D);
903173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C);
904173273Ssam
905173273Ssam	/* write READ opcode (10) */
906173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D);
907173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C);
908173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S);
909173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
910173273Ssam
911173273Ssam	/* write address (A5-A0 or A7-A0) */
912173273Ssam	n = (RAL_READ(sc, RT2560_CSR21) & RT2560_93C46) ? 5 : 7;
913173273Ssam	for (; n >= 0; n--) {
914173273Ssam		RT2560_EEPROM_CTL(sc, RT2560_S |
915173273Ssam		    (((addr >> n) & 1) << RT2560_SHIFT_D));
916173273Ssam		RT2560_EEPROM_CTL(sc, RT2560_S |
917173273Ssam		    (((addr >> n) & 1) << RT2560_SHIFT_D) | RT2560_C);
918173273Ssam	}
919173273Ssam
920173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S);
921173273Ssam
922173273Ssam	/* read data Q15-Q0 */
923173273Ssam	val = 0;
924173273Ssam	for (n = 15; n >= 0; n--) {
925173273Ssam		RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
926173273Ssam		tmp = RAL_READ(sc, RT2560_CSR21);
927178354Ssam		val |= ((tmp & RT2560_Q) >> RT2560_SHIFT_Q) << n;
928173273Ssam		RT2560_EEPROM_CTL(sc, RT2560_S);
929173273Ssam	}
930173273Ssam
931178354Ssam	RT2560_EEPROM_CTL(sc, 0);
932173273Ssam
933173273Ssam	/* clear Chip Select and clock C */
934173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_S);
935173273Ssam	RT2560_EEPROM_CTL(sc, 0);
936173273Ssam	RT2560_EEPROM_CTL(sc, RT2560_C);
937173273Ssam
938173273Ssam	return val;
939173273Ssam}
940178354Ssam
941178354Ssam/*
942173273Ssam * Some frames were processed by the hardware cipher engine and are ready for
943173273Ssam * transmission.
944178354Ssam */
945173273Ssamstatic void
946173273Ssamrt2560_encryption_intr(struct rt2560_softc *sc)
947173273Ssam{
948173273Ssam	struct rt2560_tx_desc *desc;
949173273Ssam	int hw;
950173273Ssam
951173273Ssam	/* retrieve last descriptor index processed by cipher engine */
952173273Ssam	hw = RAL_READ(sc, RT2560_SECCSR1) - sc->txq.physaddr;
953178354Ssam	hw /= RT2560_TX_DESC_SIZE;
954173273Ssam
955173273Ssam	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
956173273Ssam	    BUS_DMASYNC_POSTREAD);
957173273Ssam
958173273Ssam	for (; sc->txq.next_encrypt != hw;) {
959173273Ssam		desc = &sc->txq.desc[sc->txq.next_encrypt];
960173273Ssam
961173273Ssam		if ((le32toh(desc->flags) & RT2560_TX_BUSY) ||
962173273Ssam		    (le32toh(desc->flags) & RT2560_TX_CIPHER_BUSY))
963173273Ssam			break;
964173273Ssam
965173273Ssam		/* for TKIP, swap eiv field to fix a bug in ASIC */
966173273Ssam		if ((le32toh(desc->flags) & RT2560_TX_CIPHER_MASK) ==
967173273Ssam		    RT2560_TX_CIPHER_TKIP)
968173273Ssam			desc->eiv = bswap32(desc->eiv);
969173273Ssam
970173273Ssam		/* mark the frame ready for transmission */
971173273Ssam		desc->flags |= htole32(RT2560_TX_BUSY | RT2560_TX_VALID);
972173273Ssam
973173273Ssam		DPRINTFN(15, ("encryption done idx=%u\n",
974173273Ssam		    sc->txq.next_encrypt));
975173273Ssam
976173273Ssam		sc->txq.next_encrypt =
977173273Ssam		    (sc->txq.next_encrypt + 1) % RT2560_TX_RING_COUNT;
978178354Ssam	}
979178354Ssam
980178354Ssam	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
981178354Ssam	    BUS_DMASYNC_PREWRITE);
982178354Ssam
983178354Ssam	/* kick Tx */
984178354Ssam	RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_TX);
985178354Ssam}
986178354Ssam
987178354Ssamstatic void
988178354Ssamrt2560_tx_intr(struct rt2560_softc *sc)
989178354Ssam{
990178354Ssam	struct ieee80211com *ic = &sc->sc_ic;
991178354Ssam	struct ifnet *ifp = ic->ic_ifp;
992178354Ssam	struct rt2560_tx_desc *desc;
993178354Ssam	struct rt2560_tx_data *data;
994178354Ssam	struct rt2560_node *rn;
995178354Ssam
996178354Ssam	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
997178354Ssam	    BUS_DMASYNC_POSTREAD);
998178354Ssam
999178354Ssam	for (;;) {
1000178354Ssam		desc = &sc->txq.desc[sc->txq.next];
1001178354Ssam		data = &sc->txq.data[sc->txq.next];
1002173273Ssam
1003173273Ssam		if ((le32toh(desc->flags) & RT2560_TX_BUSY) ||
1004173273Ssam		    (le32toh(desc->flags) & RT2560_TX_CIPHER_BUSY) ||
1005173273Ssam		    !(le32toh(desc->flags) & RT2560_TX_VALID))
1006173273Ssam			break;
1007173273Ssam
1008173273Ssam		rn = (struct rt2560_node *)data->ni;
1009173273Ssam
1010173273Ssam		switch (le32toh(desc->flags) & RT2560_TX_RESULT_MASK) {
1011173273Ssam		case RT2560_TX_SUCCESS:
1012173273Ssam			DPRINTFN(10, ("data frame sent successfully\n"));
1013178354Ssam			if (data->id.id_node != NULL) {
1014178354Ssam				ral_rssadapt_raise_rate(ic, &rn->rssadapt,
1015178354Ssam				    &data->id);
1016178354Ssam			}
1017173273Ssam			ifp->if_opackets++;
1018178354Ssam			break;
1019178354Ssam
1020178354Ssam		case RT2560_TX_SUCCESS_RETRY:
1021173273Ssam			DPRINTFN(9, ("data frame sent after %u retries\n",
1022173273Ssam			    (le32toh(desc->flags) >> 5) & 0x7));
1023173273Ssam			ifp->if_opackets++;
1024173273Ssam			break;
1025173273Ssam
1026173273Ssam		case RT2560_TX_FAIL_RETRY:
1027173273Ssam			DPRINTFN(9, ("sending data frame failed (too much "
1028173273Ssam			    "retries)\n"));
1029173273Ssam			if (data->id.id_node != NULL) {
1030173273Ssam				ral_rssadapt_lower_rate(ic, data->ni,
1031173273Ssam				    &rn->rssadapt, &data->id);
1032173273Ssam			}
1033173273Ssam			ifp->if_oerrors++;
1034173273Ssam			break;
1035173273Ssam
1036173273Ssam		case RT2560_TX_FAIL_INVALID:
1037173273Ssam		case RT2560_TX_FAIL_OTHER:
1038173273Ssam		default:
1039173273Ssam			device_printf(sc->sc_dev, "sending data frame failed "
1040173273Ssam			    "0x%08x\n", le32toh(desc->flags));
1041173273Ssam			ifp->if_oerrors++;
1042173273Ssam		}
1043173273Ssam
1044173273Ssam		bus_dmamap_sync(sc->txq.data_dmat, data->map,
1045173273Ssam		    BUS_DMASYNC_POSTWRITE);
1046173273Ssam		bus_dmamap_unload(sc->txq.data_dmat, data->map);
1047173273Ssam		m_freem(data->m);
1048173273Ssam		data->m = NULL;
1049173273Ssam		ieee80211_free_node(data->ni);
1050173273Ssam		data->ni = NULL;
1051173273Ssam
1052173273Ssam		/* descriptor is no longer valid */
1053173273Ssam		desc->flags &= ~htole32(RT2560_TX_VALID);
1054173273Ssam
1055173273Ssam		DPRINTFN(15, ("tx done idx=%u\n", sc->txq.next));
1056173273Ssam
1057173273Ssam		sc->txq.queued--;
1058173273Ssam		sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT;
1059173273Ssam	}
1060173273Ssam
1061173273Ssam	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
1062173273Ssam	    BUS_DMASYNC_PREWRITE);
1063173273Ssam
1064173273Ssam	sc->sc_tx_timer = 0;
1065173273Ssam	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1066173273Ssam	rt2560_start(ifp);
1067173273Ssam}
1068173273Ssam
1069173273Ssamstatic void
1070178354Ssamrt2560_prio_intr(struct rt2560_softc *sc)
1071178354Ssam{
1072178354Ssam	struct ieee80211com *ic = &sc->sc_ic;
1073178354Ssam	struct ifnet *ifp = ic->ic_ifp;
1074178354Ssam	struct rt2560_tx_desc *desc;
1075178354Ssam	struct rt2560_tx_data *data;
1076178354Ssam
1077178354Ssam	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
1078178354Ssam	    BUS_DMASYNC_POSTREAD);
1079173273Ssam
1080173273Ssam	for (;;) {
1081178354Ssam		desc = &sc->prioq.desc[sc->prioq.next];
1082173273Ssam		data = &sc->prioq.data[sc->prioq.next];
1083178354Ssam
1084178354Ssam		if ((le32toh(desc->flags) & RT2560_TX_BUSY) ||
1085178354Ssam		    !(le32toh(desc->flags) & RT2560_TX_VALID))
1086178354Ssam			break;
1087178354Ssam
1088178354Ssam		switch (le32toh(desc->flags) & RT2560_TX_RESULT_MASK) {
1089178354Ssam		case RT2560_TX_SUCCESS:
1090181197Ssam			DPRINTFN(10, ("mgt frame sent successfully\n"));
1091178354Ssam			break;
1092178354Ssam
1093178354Ssam		case RT2560_TX_SUCCESS_RETRY:
1094178354Ssam			DPRINTFN(9, ("mgt frame sent after %u retries\n",
1095178354Ssam			    (le32toh(desc->flags) >> 5) & 0x7));
1096178354Ssam			break;
1097178354Ssam
1098178354Ssam		case RT2560_TX_FAIL_RETRY:
1099178354Ssam			DPRINTFN(9, ("sending mgt frame failed (too much "
1100181197Ssam			    "retries)\n"));
1101178354Ssam			break;
1102173273Ssam
1103173273Ssam		case RT2560_TX_FAIL_INVALID:
1104173273Ssam		case RT2560_TX_FAIL_OTHER:
1105173273Ssam		default:
1106173273Ssam			device_printf(sc->sc_dev, "sending mgt frame failed "
1107173273Ssam			    "0x%08x\n", le32toh(desc->flags));
1108173273Ssam		}
1109173273Ssam
1110173273Ssam		bus_dmamap_sync(sc->prioq.data_dmat, data->map,
1111173273Ssam		    BUS_DMASYNC_POSTWRITE);
1112173273Ssam		bus_dmamap_unload(sc->prioq.data_dmat, data->map);
1113173273Ssam		m_freem(data->m);
1114173273Ssam		data->m = NULL;
1115173273Ssam		ieee80211_free_node(data->ni);
1116173273Ssam		data->ni = NULL;
1117173273Ssam
1118173273Ssam		/* descriptor is no longer valid */
1119173273Ssam		desc->flags &= ~htole32(RT2560_TX_VALID);
1120178354Ssam
1121173273Ssam		DPRINTFN(15, ("prio done idx=%u\n", sc->prioq.next));
1122173273Ssam
1123173273Ssam		sc->prioq.queued--;
1124173273Ssam		sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT;
1125173273Ssam	}
1126173273Ssam
1127173273Ssam	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
1128170530Ssam	    BUS_DMASYNC_PREWRITE);
1129170530Ssam
1130170530Ssam	sc->sc_tx_timer = 0;
1131170530Ssam	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1132170530Ssam	rt2560_start(ifp);
1133170530Ssam}
1134170530Ssam
1135170530Ssam/*
1136170530Ssam * Some frames were processed by the hardware cipher engine and are ready for
1137170530Ssam * transmission to the IEEE802.11 layer.
1138170530Ssam */
1139170530Ssamstatic void
1140178354Ssamrt2560_decryption_intr(struct rt2560_softc *sc)
1141170530Ssam{
1142170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1143170530Ssam	struct ifnet *ifp = ic->ic_ifp;
1144170530Ssam	struct rt2560_rx_desc *desc;
1145170530Ssam	struct rt2560_rx_data *data;
1146170530Ssam	bus_addr_t physaddr;
1147170530Ssam	struct ieee80211_frame *wh;
1148170530Ssam	struct ieee80211_node *ni;
1149170530Ssam	struct rt2560_node *rn;
1150170530Ssam	struct mbuf *mnew, *m;
1151170530Ssam	int hw, error;
1152170530Ssam
1153170530Ssam	/* retrieve last decriptor index processed by cipher engine */
1154170530Ssam	hw = RAL_READ(sc, RT2560_SECCSR0) - sc->rxq.physaddr;
1155170530Ssam	hw /= RT2560_RX_DESC_SIZE;
1156173273Ssam
1157173273Ssam	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
1158178354Ssam	    BUS_DMASYNC_POSTREAD);
1159170530Ssam
1160170530Ssam	for (; sc->rxq.cur_decrypt != hw;) {
1161170530Ssam		desc = &sc->rxq.desc[sc->rxq.cur_decrypt];
1162173273Ssam		data = &sc->rxq.data[sc->rxq.cur_decrypt];
1163173273Ssam
1164173273Ssam		if ((le32toh(desc->flags) & RT2560_RX_BUSY) ||
1165173273Ssam		    (le32toh(desc->flags) & RT2560_RX_CIPHER_BUSY))
1166173273Ssam			break;
1167173273Ssam
1168170530Ssam		if (data->drop) {
1169170530Ssam			ifp->if_ierrors++;
1170170530Ssam			goto skip;
1171170530Ssam		}
1172173273Ssam
1173178354Ssam		if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 &&
1174170530Ssam		    (le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) {
1175173273Ssam			ifp->if_ierrors++;
1176170530Ssam			goto skip;
1177173273Ssam		}
1178170530Ssam
1179170530Ssam		/*
1180170530Ssam		 * Try to allocate a new mbuf for this ring element and load it
1181170530Ssam		 * before processing the current mbuf. If the ring element
1182170530Ssam		 * cannot be loaded, drop the received packet and reuse the old
1183170530Ssam		 * mbuf. In the unlikely case that the old mbuf can't be
1184172055Ssam		 * reloaded either, explicitly panic.
1185170530Ssam		 */
1186170530Ssam		mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1187170530Ssam		if (mnew == NULL) {
1188173273Ssam			ifp->if_ierrors++;
1189173273Ssam			goto skip;
1190173273Ssam		}
1191173273Ssam
1192173273Ssam		bus_dmamap_sync(sc->rxq.data_dmat, data->map,
1193178354Ssam		    BUS_DMASYNC_POSTREAD);
1194178354Ssam		bus_dmamap_unload(sc->rxq.data_dmat, data->map);
1195173273Ssam
1196173273Ssam		error = bus_dmamap_load(sc->rxq.data_dmat, data->map,
1197178354Ssam		    mtod(mnew, void *), MCLBYTES, rt2560_dma_map_addr,
1198173273Ssam		    &physaddr, 0);
1199173273Ssam		if (error != 0) {
1200173273Ssam			m_freem(mnew);
1201173273Ssam
1202170530Ssam			/* try to reload the old mbuf */
1203173273Ssam			error = bus_dmamap_load(sc->rxq.data_dmat, data->map,
1204173273Ssam			    mtod(data->m, void *), MCLBYTES,
1205173273Ssam			    rt2560_dma_map_addr, &physaddr, 0);
1206178354Ssam			if (error != 0) {
1207173273Ssam				/* very unlikely that it will fail... */
1208173273Ssam				panic("%s: could not load old rx mbuf",
1209173273Ssam				    device_get_name(sc->sc_dev));
1210173273Ssam			}
1211173273Ssam			ifp->if_ierrors++;
1212178354Ssam			goto skip;
1213173273Ssam		}
1214173273Ssam
1215173273Ssam		/*
1216173273Ssam	 	 * New mbuf successfully loaded, update Rx ring and continue
1217173273Ssam		 * processing.
1218173273Ssam		 */
1219178354Ssam		m = data->m;
1220173273Ssam		data->m = mnew;
1221173273Ssam		desc->physaddr = htole32(physaddr);
1222173273Ssam
1223173273Ssam		/* finalize mbuf */
1224173273Ssam		m->m_pkthdr.rcvif = ifp;
1225173273Ssam		m->m_pkthdr.len = m->m_len =
1226173273Ssam		    (le32toh(desc->flags) >> 16) & 0xfff;
1227173273Ssam
1228173273Ssam		if (bpf_peers_present(sc->sc_drvbpf)) {
1229173273Ssam			struct rt2560_rx_radiotap_header *tap = &sc->sc_rxtap;
1230170530Ssam			uint32_t tsf_lo, tsf_hi;
1231170530Ssam
1232170530Ssam			/* get timestamp (low and high 32 bits) */
1233170530Ssam			tsf_hi = RAL_READ(sc, RT2560_CSR17);
1234170530Ssam			tsf_lo = RAL_READ(sc, RT2560_CSR16);
1235170530Ssam
1236170530Ssam			tap->wr_tsf =
1237170530Ssam			    htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
1238178354Ssam			tap->wr_flags = 0;
1239170530Ssam			tap->wr_rate = rt2560_rxrate(desc);
1240170530Ssam			tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
1241170530Ssam			tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
1242170530Ssam			tap->wr_antenna = sc->rx_ant;
1243170530Ssam			tap->wr_antsignal = desc->rssi;
1244170530Ssam
1245170530Ssam			bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
1246170530Ssam		}
1247170530Ssam
1248170530Ssam		wh = mtod(m, struct ieee80211_frame *);
1249170530Ssam		ni = ieee80211_find_rxnode(ic,
1250170530Ssam		    (struct ieee80211_frame_min *)wh);
1251170530Ssam
1252170530Ssam		/* send the frame to the 802.11 layer */
1253178354Ssam		ieee80211_input(ic, m, ni, desc->rssi, 0);
1254170530Ssam
1255170530Ssam		/* give rssi to the rate adatation algorithm */
1256170530Ssam		rn = (struct rt2560_node *)ni;
1257178354Ssam		ral_rssadapt_input(ic, ni, &rn->rssadapt, desc->rssi);
1258170530Ssam
1259170530Ssam		/* node is no longer needed */
1260170530Ssam		ieee80211_free_node(ni);
1261170530Ssam
1262170530Ssamskip:		desc->flags = htole32(RT2560_RX_BUSY);
1263170530Ssam
1264170530Ssam		DPRINTFN(15, ("decryption done idx=%u\n", sc->rxq.cur_decrypt));
1265170530Ssam
1266170530Ssam		sc->rxq.cur_decrypt =
1267170530Ssam		    (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT;
1268170530Ssam	}
1269170530Ssam
1270170530Ssam	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
1271170530Ssam	    BUS_DMASYNC_PREWRITE);
1272170530Ssam}
1273170530Ssam
1274170530Ssam/*
1275170530Ssam * Some frames were received. Pass them to the hardware cipher engine before
1276170530Ssam * sending them to the 802.11 layer.
1277170530Ssam */
1278170530Ssamstatic void
1279170530Ssamrt2560_rx_intr(struct rt2560_softc *sc)
1280170530Ssam{
1281170530Ssam	struct rt2560_rx_desc *desc;
1282178354Ssam	struct rt2560_rx_data *data;
1283170530Ssam
1284170530Ssam	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
1285170530Ssam	    BUS_DMASYNC_POSTREAD);
1286170530Ssam
1287170530Ssam	for (;;) {
1288170530Ssam		desc = &sc->rxq.desc[sc->rxq.cur];
1289170530Ssam		data = &sc->rxq.data[sc->rxq.cur];
1290170530Ssam
1291170530Ssam		if ((le32toh(desc->flags) & RT2560_RX_BUSY) ||
1292170530Ssam		    (le32toh(desc->flags) & RT2560_RX_CIPHER_BUSY))
1293170530Ssam			break;
1294170530Ssam
1295170530Ssam		data->drop = 0;
1296170530Ssam
1297170530Ssam		if ((le32toh(desc->flags) & RT2560_RX_PHY_ERROR) ||
1298170530Ssam		    (le32toh(desc->flags) & RT2560_RX_CRC_ERROR)) {
1299170530Ssam			/*
1300170530Ssam			 * This should not happen since we did not request
1301170530Ssam			 * to receive those frames when we filled RXCSR0.
1302170530Ssam			 */
1303170530Ssam			DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n",
1304170530Ssam			    le32toh(desc->flags)));
1305170530Ssam			data->drop = 1;
1306170530Ssam		}
1307170530Ssam
1308170530Ssam		if (((le32toh(desc->flags) >> 16) & 0xfff) > MCLBYTES) {
1309170530Ssam			DPRINTFN(5, ("bad length\n"));
1310178354Ssam			data->drop = 1;
1311170530Ssam		}
1312170530Ssam
1313178354Ssam		/* mark the frame for decryption */
1314170530Ssam		desc->flags |= htole32(RT2560_RX_CIPHER_BUSY);
1315170530Ssam
1316170530Ssam		DPRINTFN(15, ("rx done idx=%u\n", sc->rxq.cur));
1317170530Ssam
1318170530Ssam		sc->rxq.cur = (sc->rxq.cur + 1) % RT2560_RX_RING_COUNT;
1319170530Ssam	}
1320170530Ssam
1321170530Ssam	bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map,
1322170530Ssam	    BUS_DMASYNC_PREWRITE);
1323170530Ssam
1324170530Ssam	/* kick decrypt */
1325170530Ssam	RAL_WRITE(sc, RT2560_SECCSR0, RT2560_KICK_DECRYPT);
1326170530Ssam}
1327170530Ssam
1328170530Ssam/*
1329170530Ssam * This function is called periodically in IBSS mode when a new beacon must be
1330170530Ssam * sent out.
1331170530Ssam */
1332170530Ssamstatic void
1333170530Ssamrt2560_beacon_expire(struct rt2560_softc *sc)
1334170530Ssam{
1335170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1336170530Ssam	struct rt2560_tx_data *data;
1337170530Ssam
1338170530Ssam	if (ic->ic_opmode != IEEE80211_M_IBSS &&
1339170530Ssam	    ic->ic_opmode != IEEE80211_M_HOSTAP)
1340170530Ssam		return;
1341170530Ssam
1342170530Ssam	data = &sc->bcnq.data[sc->bcnq.next];
1343170530Ssam
1344170530Ssam	bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE);
1345170530Ssam	bus_dmamap_unload(sc->bcnq.data_dmat, data->map);
1346170530Ssam
1347170530Ssam	ieee80211_beacon_update(ic, data->ni, &sc->sc_bo, data->m, 1);
1348170530Ssam
1349170530Ssam	if (bpf_peers_present(ic->ic_rawbpf))
1350170530Ssam		bpf_mtap(ic->ic_rawbpf, data->m);
1351170530Ssam
1352170530Ssam	rt2560_tx_bcn(sc, data->m, data->ni);
1353170530Ssam
1354170530Ssam	DPRINTFN(15, ("beacon expired\n"));
1355170530Ssam
1356170530Ssam	sc->bcnq.next = (sc->bcnq.next + 1) % RT2560_BEACON_RING_COUNT;
1357170530Ssam}
1358170530Ssam
1359170530Ssam/* ARGSUSED */
1360170530Ssamstatic void
1361170530Ssamrt2560_wakeup_expire(struct rt2560_softc *sc)
1362170530Ssam{
1363170530Ssam	DPRINTFN(2, ("wakeup expired\n"));
1364170530Ssam}
1365170530Ssam
1366170530Ssamvoid
1367170530Ssamrt2560_intr(void *arg)
1368170530Ssam{
1369173273Ssam	struct rt2560_softc *sc = arg;
1370173273Ssam	struct ifnet *ifp = sc->sc_ifp;
1371173273Ssam	uint32_t r;
1372170530Ssam
1373170530Ssam	RAL_LOCK(sc);
1374170530Ssam
1375170530Ssam	/* disable interrupts */
1376170530Ssam	RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
1377170530Ssam
1378170530Ssam	/* don't re-enable interrupts if we're shutting down */
1379170530Ssam	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1380170530Ssam		RAL_UNLOCK(sc);
1381170530Ssam		return;
1382170530Ssam	}
1383170530Ssam
1384170530Ssam	r = RAL_READ(sc, RT2560_CSR7);
1385170530Ssam	RAL_WRITE(sc, RT2560_CSR7, r);
1386170530Ssam
1387170530Ssam	if (r & RT2560_BEACON_EXPIRE)
1388170530Ssam		rt2560_beacon_expire(sc);
1389170530Ssam
1390170530Ssam	if (r & RT2560_WAKEUP_EXPIRE)
1391170530Ssam		rt2560_wakeup_expire(sc);
1392170530Ssam
1393170530Ssam	if (r & RT2560_ENCRYPTION_DONE)
1394170530Ssam		rt2560_encryption_intr(sc);
1395170530Ssam
1396170530Ssam	if (r & RT2560_TX_DONE)
1397170530Ssam		rt2560_tx_intr(sc);
1398170530Ssam
1399170530Ssam	if (r & RT2560_PRIO_DONE)
1400170530Ssam		rt2560_prio_intr(sc);
1401170530Ssam
1402178354Ssam	if (r & RT2560_DECRYPTION_DONE)
1403170530Ssam		rt2560_decryption_intr(sc);
1404170530Ssam
1405170530Ssam	if (r & RT2560_RX_DONE)
1406170530Ssam		rt2560_rx_intr(sc);
1407170530Ssam
1408170530Ssam	/* re-enable interrupts */
1409170530Ssam	RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
1410170530Ssam
1411170530Ssam	RAL_UNLOCK(sc);
1412170530Ssam}
1413170530Ssam
1414170530Ssam/* quickly determine if a given rate is CCK or OFDM */
1415170530Ssam#define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
1416170530Ssam
1417170530Ssam#define RAL_ACK_SIZE	14	/* 10 + 4(FCS) */
1418170530Ssam#define RAL_CTS_SIZE	14	/* 10 + 4(FCS) */
1419170530Ssam
1420170530Ssam#define RAL_SIFS		10	/* us */
1421170530Ssam
1422170530Ssam#define RT2560_TXRX_TURNAROUND	10	/* us */
1423170530Ssam
1424178354Ssam/*
1425170530Ssam * This function is only used by the Rx radiotap code.
1426170530Ssam */
1427170530Ssamstatic uint8_t
1428173273Ssamrt2560_rxrate(struct rt2560_rx_desc *desc)
1429173273Ssam{
1430173273Ssam	if (le32toh(desc->flags) & RT2560_RX_OFDM) {
1431173273Ssam		/* reverse function of rt2560_plcp_signal */
1432170530Ssam		switch (desc->rate) {
1433170530Ssam		case 0xb:	return 12;
1434170530Ssam		case 0xf:	return 18;
1435170530Ssam		case 0xa:	return 24;
1436170530Ssam		case 0xe:	return 36;
1437173273Ssam		case 0x9:	return 48;
1438173273Ssam		case 0xd:	return 72;
1439173273Ssam		case 0x8:	return 96;
1440173273Ssam		case 0xc:	return 108;
1441173273Ssam		}
1442173273Ssam	} else {
1443178354Ssam		if (desc->rate == 10)
1444170530Ssam			return 2;
1445170530Ssam		if (desc->rate == 20)
1446170530Ssam			return 4;
1447170530Ssam		if (desc->rate == 55)
1448173273Ssam			return 11;
1449178354Ssam		if (desc->rate == 110)
1450173273Ssam			return 22;
1451173273Ssam	}
1452173273Ssam	return 2;	/* should not get there */
1453173273Ssam}
1454173273Ssam
1455178354Ssam/*
1456170530Ssam * Return the expected ack rate for a frame transmitted at rate `rate'.
1457173273Ssam * XXX: this should depend on the destination node basic rate set.
1458170530Ssam */
1459170530Ssamstatic int
1460170530Ssamrt2560_ack_rate(struct ieee80211com *ic, int rate)
1461170530Ssam{
1462170530Ssam	switch (rate) {
1463170530Ssam	/* CCK rates */
1464170530Ssam	case 2:
1465170530Ssam		return 2;
1466170530Ssam	case 4:
1467170530Ssam	case 11:
1468170530Ssam	case 22:
1469170530Ssam		return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
1470170530Ssam
1471170530Ssam	/* OFDM rates */
1472170530Ssam	case 12:
1473170530Ssam	case 18:
1474170530Ssam		return 12;
1475170530Ssam	case 24:
1476173273Ssam	case 36:
1477173273Ssam		return 24;
1478175877Ssam	case 48:
1479178354Ssam	case 72:
1480173273Ssam	case 96:
1481173273Ssam	case 108:
1482173273Ssam		return 48;
1483173273Ssam	}
1484178354Ssam
1485173273Ssam	/* default to 1Mbps */
1486173273Ssam	return 2;
1487173273Ssam}
1488178354Ssam
1489173273Ssam/*
1490173273Ssam * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
1491173273Ssam * The function automatically determines the operating mode depending on the
1492173273Ssam * given rate. `flags' indicates whether short preamble is in use or not.
1493173273Ssam */
1494178354Ssamstatic uint16_t
1495173273Ssamrt2560_txtime(int len, int rate, uint32_t flags)
1496173273Ssam{
1497173273Ssam	uint16_t txtime;
1498178354Ssam
1499170530Ssam	if (RAL_RATE_IS_OFDM(rate)) {
1500170530Ssam		/* IEEE Std 802.11a-1999, pp. 37 */
1501170530Ssam		txtime = (8 + 4 * len + 3 + rate - 1) / rate;
1502170530Ssam		txtime = 16 + 4 + 4 * txtime + 6;
1503170530Ssam	} else {
1504170530Ssam		/* IEEE Std 802.11b-1999, pp. 28 */
1505170530Ssam		txtime = (16 * len + rate - 1) / rate;
1506170530Ssam		if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
1507170530Ssam			txtime +=  72 + 24;
1508170530Ssam		else
1509170530Ssam			txtime += 144 + 48;
1510170530Ssam	}
1511170530Ssam
1512170530Ssam	return txtime;
1513170530Ssam}
1514178354Ssam
1515170530Ssamstatic uint8_t
1516170530Ssamrt2560_plcp_signal(int rate)
1517170530Ssam{
1518170530Ssam	switch (rate) {
1519170530Ssam	/* CCK rates (returned values are device-dependent) */
1520170530Ssam	case 2:		return 0x0;
1521170530Ssam	case 4:		return 0x1;
1522170530Ssam	case 11:	return 0x2;
1523170530Ssam	case 22:	return 0x3;
1524170530Ssam
1525170530Ssam	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
1526170530Ssam	case 12:	return 0xb;
1527170530Ssam	case 18:	return 0xf;
1528170530Ssam	case 24:	return 0xa;
1529170530Ssam	case 36:	return 0xe;
1530170530Ssam	case 48:	return 0x9;
1531170530Ssam	case 72:	return 0xd;
1532173273Ssam	case 96:	return 0x8;
1533170530Ssam	case 108:	return 0xc;
1534170530Ssam
1535170530Ssam	/* unsupported rates (should not get there) */
1536170530Ssam	default:	return 0xff;
1537170530Ssam	}
1538170530Ssam}
1539170530Ssam
1540170530Ssamstatic void
1541170530Ssamrt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
1542170530Ssam    uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr)
1543170530Ssam{
1544170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1545178354Ssam	uint16_t plcp_length;
1546170530Ssam	int remainder;
1547170530Ssam
1548170530Ssam	desc->flags = htole32(flags);
1549170530Ssam	desc->flags |= htole32(len << 16);
1550170530Ssam	desc->flags |= encrypt ? htole32(RT2560_TX_CIPHER_BUSY) :
1551170530Ssam	    htole32(RT2560_TX_BUSY | RT2560_TX_VALID);
1552178354Ssam
1553170530Ssam	desc->physaddr = htole32(physaddr);
1554170530Ssam	desc->wme = htole16(
1555170530Ssam	    RT2560_AIFSN(2) |
1556178354Ssam	    RT2560_LOGCWMIN(3) |
1557170530Ssam	    RT2560_LOGCWMAX(8));
1558170530Ssam
1559170530Ssam	/* setup PLCP fields */
1560170530Ssam	desc->plcp_signal  = rt2560_plcp_signal(rate);
1561170530Ssam	desc->plcp_service = 4;
1562170530Ssam
1563170530Ssam	len += IEEE80211_CRC_LEN;
1564170530Ssam	if (RAL_RATE_IS_OFDM(rate)) {
1565170530Ssam		desc->flags |= htole32(RT2560_TX_OFDM);
1566178354Ssam
1567170530Ssam		plcp_length = len & 0xfff;
1568173273Ssam		desc->plcp_length_hi = plcp_length >> 6;
1569170530Ssam		desc->plcp_length_lo = plcp_length & 0x3f;
1570170530Ssam	} else {
1571170530Ssam		plcp_length = (16 * len + rate - 1) / rate;
1572170530Ssam		if (rate == 22) {
1573173273Ssam			remainder = (16 * len) % 22;
1574178354Ssam			if (remainder != 0 && remainder < 7)
1575173273Ssam				desc->plcp_service |= RT2560_PLCP_LENGEXT;
1576173273Ssam		}
1577173273Ssam		desc->plcp_length_hi = plcp_length >> 8;
1578170530Ssam		desc->plcp_length_lo = plcp_length & 0xff;
1579178354Ssam
1580170530Ssam		if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
1581170530Ssam			desc->plcp_signal |= 0x08;
1582170530Ssam	}
1583178354Ssam}
1584170530Ssam
1585170530Ssamstatic int
1586170530Ssamrt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0,
1587170530Ssam    struct ieee80211_node *ni)
1588178354Ssam{
1589170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1590170530Ssam	struct rt2560_tx_desc *desc;
1591170530Ssam	struct rt2560_tx_data *data;
1592178354Ssam	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
1593170530Ssam	int nsegs, rate, error;
1594170530Ssam
1595170530Ssam	desc = &sc->bcnq.desc[sc->bcnq.cur];
1596170530Ssam	data = &sc->bcnq.data[sc->bcnq.cur];
1597170530Ssam
1598170530Ssam	rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
1599170530Ssam
1600170530Ssam	error = bus_dmamap_load_mbuf_sg(sc->bcnq.data_dmat, data->map, m0,
1601170530Ssam	    segs, &nsegs, BUS_DMA_NOWAIT);
1602178354Ssam	if (error != 0) {
1603178354Ssam		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
1604178354Ssam		    error);
1605178354Ssam		m_freem(m0);
1606178354Ssam		return error;
1607178354Ssam	}
1608178354Ssam
1609178354Ssam	if (bpf_peers_present(sc->sc_drvbpf)) {
1610178354Ssam		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
1611178354Ssam
1612178354Ssam		tap->wt_flags = 0;
1613178354Ssam		tap->wt_rate = rate;
1614178354Ssam		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
1615178354Ssam		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
1616178354Ssam		tap->wt_antenna = sc->tx_ant;
1617178354Ssam
1618178354Ssam		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
1619178354Ssam	}
1620178354Ssam
1621178354Ssam	data->m = m0;
1622178354Ssam	data->ni = ni;
1623178354Ssam
1624178354Ssam	rt2560_setup_tx_desc(sc, desc, RT2560_TX_IFS_NEWBACKOFF |
1625178354Ssam	    RT2560_TX_TIMESTAMP, m0->m_pkthdr.len, rate, 0, segs->ds_addr);
1626178354Ssam
1627178354Ssam	DPRINTFN(10, ("sending beacon frame len=%u idx=%u rate=%u\n",
1628178354Ssam	    m0->m_pkthdr.len, sc->bcnq.cur, rate));
1629178354Ssam
1630178354Ssam	bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
1631178354Ssam	bus_dmamap_sync(sc->bcnq.desc_dmat, sc->bcnq.desc_map,
1632178354Ssam	    BUS_DMASYNC_PREWRITE);
1633178354Ssam
1634178354Ssam	sc->bcnq.cur = (sc->bcnq.cur + 1) % RT2560_BEACON_RING_COUNT;
1635170530Ssam
1636170530Ssam	return 0;
1637170530Ssam}
1638170530Ssam
1639170530Ssamstatic int
1640170530Ssamrt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0,
1641170530Ssam    struct ieee80211_node *ni)
1642170530Ssam{
1643170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1644170530Ssam	struct rt2560_tx_desc *desc;
1645170530Ssam	struct rt2560_tx_data *data;
1646170530Ssam	struct ieee80211_frame *wh;
1647170530Ssam	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
1648170530Ssam	uint16_t dur;
1649170530Ssam	uint32_t flags = 0;
1650170530Ssam	int nsegs, rate, error;
1651170530Ssam
1652170530Ssam	desc = &sc->prioq.desc[sc->prioq.cur];
1653170530Ssam	data = &sc->prioq.data[sc->prioq.cur];
1654173273Ssam
1655173273Ssam	rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
1656173273Ssam
1657170530Ssam	error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0,
1658170530Ssam	    segs, &nsegs, 0);
1659170530Ssam	if (error != 0) {
1660170530Ssam		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
1661170530Ssam		    error);
1662170530Ssam		m_freem(m0);
1663170530Ssam		return error;
1664170530Ssam	}
1665170530Ssam
1666170530Ssam	if (bpf_peers_present(sc->sc_drvbpf)) {
1667170530Ssam		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
1668170530Ssam
1669178354Ssam		tap->wt_flags = 0;
1670173273Ssam		tap->wt_rate = rate;
1671173273Ssam		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
1672173273Ssam		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
1673178354Ssam		tap->wt_antenna = sc->tx_ant;
1674178354Ssam
1675178354Ssam		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
1676178354Ssam	}
1677170530Ssam
1678170530Ssam	data->m = m0;
1679170530Ssam	data->ni = ni;
1680178953Ssam
1681178953Ssam	wh = mtod(m0, struct ieee80211_frame *);
1682178953Ssam
1683178953Ssam	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1684170530Ssam		flags |= RT2560_TX_ACK;
1685170530Ssam
1686170530Ssam		dur = rt2560_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) +
1687170530Ssam		      RAL_SIFS;
1688170530Ssam		*(uint16_t *)wh->i_dur = htole16(dur);
1689173273Ssam
1690173273Ssam		/* tell hardware to add timestamp for probe responses */
1691173273Ssam		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
1692173273Ssam		    IEEE80211_FC0_TYPE_MGT &&
1693173273Ssam		    (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
1694173273Ssam		    IEEE80211_FC0_SUBTYPE_PROBE_RESP)
1695173273Ssam			flags |= RT2560_TX_TIMESTAMP;
1696178354Ssam	}
1697173273Ssam
1698173273Ssam	rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 0,
1699173273Ssam	    segs->ds_addr);
1700173273Ssam
1701178354Ssam	bus_dmamap_sync(sc->prioq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
1702173273Ssam	bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map,
1703178354Ssam	    BUS_DMASYNC_PREWRITE);
1704173273Ssam
1705173273Ssam	DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n",
1706173273Ssam	    m0->m_pkthdr.len, sc->prioq.cur, rate));
1707173273Ssam
1708173273Ssam	/* kick prio */
1709173273Ssam	sc->prioq.queued++;
1710173273Ssam	sc->prioq.cur = (sc->prioq.cur + 1) % RT2560_PRIO_RING_COUNT;
1711173273Ssam	RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_PRIO);
1712178354Ssam
1713173273Ssam	return 0;
1714173273Ssam}
1715178354Ssam
1716173273Ssam/*
1717173273Ssam * Build a RTS control frame.
1718173273Ssam */
1719173273Ssamstatic struct mbuf *
1720170530Ssamrt2560_get_rts(struct rt2560_softc *sc, struct ieee80211_frame *wh,
1721170530Ssam    uint16_t dur)
1722170530Ssam{
1723170530Ssam	struct ieee80211_frame_rts *rts;
1724170530Ssam	struct mbuf *m;
1725170530Ssam
1726170530Ssam	MGETHDR(m, M_DONTWAIT, MT_DATA);
1727170530Ssam	if (m == NULL) {
1728178354Ssam		sc->sc_ic.ic_stats.is_tx_nobuf++;
1729170530Ssam		device_printf(sc->sc_dev, "could not allocate RTS frame\n");
1730170530Ssam		return NULL;
1731170530Ssam	}
1732170530Ssam
1733170530Ssam	rts = mtod(m, struct ieee80211_frame_rts *);
1734178354Ssam
1735170530Ssam	rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL |
1736170530Ssam	    IEEE80211_FC0_SUBTYPE_RTS;
1737170530Ssam	rts->i_fc[1] = IEEE80211_FC1_DIR_NODS;
1738170530Ssam	*(uint16_t *)rts->i_dur = htole16(dur);
1739170530Ssam	IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1);
1740170530Ssam	IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2);
1741170530Ssam
1742170530Ssam	m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_rts);
1743170530Ssam
1744170530Ssam	return m;
1745170530Ssam}
1746170530Ssam
1747170530Ssamstatic int
1748170530Ssamrt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
1749170530Ssam    struct ieee80211_node *ni)
1750170530Ssam{
1751170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1752170530Ssam	struct rt2560_tx_desc *desc;
1753170530Ssam	struct rt2560_tx_data *data;
1754170530Ssam	struct rt2560_node *rn;
1755170530Ssam	struct ieee80211_rateset *rs;
1756178354Ssam	struct ieee80211_frame *wh;
1757170530Ssam	struct ieee80211_key *k;
1758170530Ssam	struct mbuf *mnew;
1759170530Ssam	bus_dma_segment_t segs[RT2560_MAX_SCATTER];
1760170530Ssam	uint16_t dur;
1761170530Ssam	uint32_t flags = 0;
1762170530Ssam	int nsegs, rate, error;
1763170530Ssam
1764170530Ssam	wh = mtod(m0, struct ieee80211_frame *);
1765170530Ssam
1766170530Ssam	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
1767170530Ssam		rs = &ic->ic_sup_rates[ic->ic_curmode];
1768170530Ssam		rate = rs->rs_rates[ic->ic_fixed_rate];
1769170530Ssam	} else {
1770170530Ssam		rs = &ni->ni_rates;
1771170530Ssam		rn = (struct rt2560_node *)ni;
1772178354Ssam		ni->ni_txrate = ral_rssadapt_choose(&rn->rssadapt, rs, wh,
1773178354Ssam		    m0->m_pkthdr.len, NULL, 0);
1774170530Ssam		rate = rs->rs_rates[ni->ni_txrate];
1775170530Ssam	}
1776178354Ssam	rate &= IEEE80211_RATE_VAL;
1777173273Ssam
1778173273Ssam	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
1779170530Ssam		k = ieee80211_crypto_encap(ic, ni, m0);
1780178354Ssam		if (k == NULL) {
1781170530Ssam			m_freem(m0);
1782170530Ssam			return ENOBUFS;
1783170530Ssam		}
1784170530Ssam
1785170530Ssam		/* packet header may have moved, reset our local pointer */
1786170530Ssam		wh = mtod(m0, struct ieee80211_frame *);
1787170530Ssam	}
1788170530Ssam
1789170530Ssam	/*
1790170530Ssam	 * IEEE Std 802.11-1999, pp 82: "A STA shall use an RTS/CTS exchange
1791170530Ssam	 * for directed frames only when the length of the MPDU is greater
1792170530Ssam	 * than the length threshold indicated by [...]" ic_rtsthreshold.
1793170530Ssam	 */
1794170530Ssam	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
1795170530Ssam	    m0->m_pkthdr.len > ic->ic_rtsthreshold) {
1796170530Ssam		struct mbuf *m;
1797178354Ssam		uint16_t dur;
1798170530Ssam		int rtsrate, ackrate;
1799170530Ssam
1800170530Ssam		rtsrate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
1801170530Ssam		ackrate = rt2560_ack_rate(ic, rate);
1802170530Ssam
1803178354Ssam		dur = rt2560_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) +
1804170530Ssam		      rt2560_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) +
1805170530Ssam		      rt2560_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) +
1806170530Ssam		      3 * RAL_SIFS;
1807170530Ssam
1808170530Ssam		m = rt2560_get_rts(sc, wh, dur);
1809170530Ssam
1810170530Ssam		desc = &sc->txq.desc[sc->txq.cur_encrypt];
1811170530Ssam		data = &sc->txq.data[sc->txq.cur_encrypt];
1812170530Ssam
1813170530Ssam		error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map,
1814170530Ssam		    m, segs, &nsegs, 0);
1815170530Ssam		if (error != 0) {
1816170530Ssam			device_printf(sc->sc_dev,
1817178354Ssam			    "could not map mbuf (error %d)\n", error);
1818170530Ssam			m_freem(m);
1819170530Ssam			m_freem(m0);
1820170530Ssam			return error;
1821170530Ssam		}
1822170530Ssam
1823170530Ssam		/* avoid multiple free() of the same node for each fragment */
1824170530Ssam		ieee80211_ref_node(ni);
1825170530Ssam
1826170530Ssam		data->m = m;
1827170530Ssam		data->ni = ni;
1828170530Ssam
1829170530Ssam		/* RTS frames are not taken into account for rssadapt */
1830170530Ssam		data->id.id_node = NULL;
1831170530Ssam
1832170530Ssam		rt2560_setup_tx_desc(sc, desc, RT2560_TX_ACK |
1833170530Ssam		    RT2560_TX_MORE_FRAG, m->m_pkthdr.len, rtsrate, 1,
1834170530Ssam		    segs->ds_addr);
1835170530Ssam
1836170530Ssam		bus_dmamap_sync(sc->txq.data_dmat, data->map,
1837170530Ssam		    BUS_DMASYNC_PREWRITE);
1838170530Ssam
1839178354Ssam		sc->txq.queued++;
1840170530Ssam		sc->txq.cur_encrypt =
1841173273Ssam		    (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT;
1842173273Ssam
1843173273Ssam		/*
1844173273Ssam		 * IEEE Std 802.11-1999: when an RTS/CTS exchange is used, the
1845170530Ssam		 * asynchronous data frame shall be transmitted after the CTS
1846170530Ssam		 * frame and a SIFS period.
1847170530Ssam		 */
1848170530Ssam		flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
1849170530Ssam	}
1850170530Ssam
1851170530Ssam	data = &sc->txq.data[sc->txq.cur_encrypt];
1852178354Ssam	desc = &sc->txq.desc[sc->txq.cur_encrypt];
1853170530Ssam
1854170530Ssam	error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, m0,
1855170530Ssam	    segs, &nsegs, 0);
1856170530Ssam	if (error != 0 && error != EFBIG) {
1857170530Ssam		device_printf(sc->sc_dev, "could not map mbuf (error %d)\n",
1858170530Ssam		    error);
1859170530Ssam		m_freem(m0);
1860170530Ssam		return error;
1861170530Ssam	}
1862170530Ssam	if (error != 0) {
1863170530Ssam		mnew = m_defrag(m0, M_DONTWAIT);
1864170530Ssam		if (mnew == NULL) {
1865170530Ssam			device_printf(sc->sc_dev,
1866170530Ssam			    "could not defragment mbuf\n");
1867180309Ssam			m_freem(m0);
1868170530Ssam			return ENOBUFS;
1869170530Ssam		}
1870170530Ssam		m0 = mnew;
1871170530Ssam
1872178354Ssam		error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map,
1873170530Ssam		    m0, segs, &nsegs, 0);
1874170530Ssam		if (error != 0) {
1875170530Ssam			device_printf(sc->sc_dev,
1876170530Ssam			    "could not map mbuf (error %d)\n", error);
1877170530Ssam			m_freem(m0);
1878170530Ssam			return error;
1879170530Ssam		}
1880170530Ssam
1881170530Ssam		/* packet header may have moved, reset our local pointer */
1882170530Ssam		wh = mtod(m0, struct ieee80211_frame *);
1883170530Ssam	}
1884178354Ssam
1885170530Ssam	if (bpf_peers_present(sc->sc_drvbpf)) {
1886170530Ssam		struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
1887178354Ssam
1888170530Ssam		tap->wt_flags = 0;
1889178354Ssam		tap->wt_rate = rate;
1890170530Ssam		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
1891170530Ssam		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
1892170530Ssam		tap->wt_antenna = sc->tx_ant;
1893170530Ssam
1894170530Ssam		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
1895170530Ssam	}
1896170530Ssam
1897170530Ssam	data->m = m0;
1898170530Ssam	data->ni = ni;
1899178354Ssam
1900170530Ssam	/* remember link conditions for rate adaptation algorithm */
1901170530Ssam	if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
1902170530Ssam		data->id.id_len = m0->m_pkthdr.len;
1903170530Ssam		data->id.id_rateidx = ni->ni_txrate;
1904170530Ssam		data->id.id_node = ni;
1905170530Ssam		data->id.id_rssi = ni->ni_rssi;
1906170530Ssam	} else
1907170530Ssam		data->id.id_node = NULL;
1908178354Ssam
1909170530Ssam	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
1910170530Ssam		flags |= RT2560_TX_ACK;
1911178354Ssam
1912178354Ssam		dur = rt2560_txtime(RAL_ACK_SIZE, rt2560_ack_rate(ic, rate),
1913170530Ssam		    ic->ic_flags) + RAL_SIFS;
1914170530Ssam		*(uint16_t *)wh->i_dur = htole16(dur);
1915170530Ssam	}
1916170530Ssam
1917170530Ssam	rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 1,
1918170530Ssam	    segs->ds_addr);
1919170530Ssam
1920170530Ssam	bus_dmamap_sync(sc->txq.data_dmat, data->map, BUS_DMASYNC_PREWRITE);
1921170530Ssam	bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
1922170530Ssam	    BUS_DMASYNC_PREWRITE);
1923170530Ssam
1924170530Ssam	DPRINTFN(10, ("sending data frame len=%u idx=%u rate=%u\n",
1925170530Ssam	    m0->m_pkthdr.len, sc->txq.cur_encrypt, rate));
1926170530Ssam
1927170530Ssam	/* kick encrypt */
1928170530Ssam	sc->txq.queued++;
1929170530Ssam	sc->txq.cur_encrypt = (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT;
1930170530Ssam	RAL_WRITE(sc, RT2560_SECCSR1, RT2560_KICK_ENCRYPT);
1931170530Ssam
1932170530Ssam	return 0;
1933170530Ssam}
1934170530Ssam
1935170530Ssamstatic void
1936170530Ssamrt2560_start(struct ifnet *ifp)
1937170530Ssam{
1938170530Ssam	struct rt2560_softc *sc = ifp->if_softc;
1939170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
1940170530Ssam	struct mbuf *m0;
1941170530Ssam	struct ether_header *eh;
1942170530Ssam	struct ieee80211_node *ni;
1943170530Ssam
1944170530Ssam	RAL_LOCK(sc);
1945170530Ssam
1946170530Ssam	/* prevent management frames from being sent if we're not ready */
1947178354Ssam	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1948170530Ssam		RAL_UNLOCK(sc);
1949173865Ssam		return;
1950170530Ssam	}
1951170530Ssam
1952178354Ssam	for (;;) {
1953173273Ssam		IF_POLL(&ic->ic_mgtq, m0);
1954173273Ssam		if (m0 != NULL) {
1955173273Ssam			if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
1956173273Ssam				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1957173273Ssam				break;
1958173273Ssam			}
1959173273Ssam			IF_DEQUEUE(&ic->ic_mgtq, m0);
1960173273Ssam
1961178354Ssam			ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
1962173273Ssam			m0->m_pkthdr.rcvif = NULL;
1963178354Ssam
1964173273Ssam			if (bpf_peers_present(ic->ic_rawbpf))
1965173273Ssam				bpf_mtap(ic->ic_rawbpf, m0);
1966173273Ssam
1967173865Ssam			if (rt2560_tx_mgt(sc, m0, ni) != 0)
1968173865Ssam				break;
1969173865Ssam
1970173273Ssam		} else {
1971173273Ssam			if (ic->ic_state != IEEE80211_S_RUN)
1972178354Ssam				break;
1973173273Ssam			IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
1974173273Ssam			if (m0 == NULL)
1975173273Ssam				break;
1976178354Ssam			if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) {
1977178354Ssam				IFQ_DRV_PREPEND(&ifp->if_snd, m0);
1978173273Ssam				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1979170530Ssam				break;
1980178354Ssam			}
1981170530Ssam
1982178354Ssam			if (m0->m_len < sizeof (struct ether_header) &&
1983170530Ssam			    !(m0 = m_pullup(m0, sizeof (struct ether_header))))
1984170530Ssam				continue;
1985170530Ssam
1986170530Ssam			eh = mtod(m0, struct ether_header *);
1987170530Ssam			ni = ieee80211_find_txnode(ic, eh->ether_dhost);
1988173865Ssam			if (ni == NULL) {
1989173865Ssam				m_freem(m0);
1990173273Ssam				continue;
1991170530Ssam			}
1992170530Ssam			BPF_MTAP(ifp, m0);
1993170530Ssam
1994170530Ssam			m0 = ieee80211_encap(ic, m0, ni);
1995170530Ssam			if (m0 == NULL) {
1996170530Ssam				ieee80211_free_node(ni);
1997170530Ssam				continue;
1998173273Ssam			}
1999173273Ssam
2000173273Ssam			if (bpf_peers_present(ic->ic_rawbpf))
2001173273Ssam				bpf_mtap(ic->ic_rawbpf, m0);
2002173273Ssam
2003173273Ssam			if (rt2560_tx_data(sc, m0, ni) != 0) {
2004173273Ssam				ieee80211_free_node(ni);
2005170530Ssam				ifp->if_oerrors++;
2006170530Ssam				break;
2007170530Ssam			}
2008170530Ssam		}
2009170530Ssam
2010170530Ssam		sc->sc_tx_timer = 5;
2011170530Ssam		ifp->if_timer = 1;
2012170530Ssam	}
2013170530Ssam
2014170530Ssam	RAL_UNLOCK(sc);
2015170530Ssam}
2016170530Ssam
2017170530Ssamstatic void
2018170530Ssamrt2560_watchdog(struct ifnet *ifp)
2019170530Ssam{
2020170530Ssam	struct rt2560_softc *sc = ifp->if_softc;
2021170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
2022170530Ssam
2023170530Ssam	RAL_LOCK(sc);
2024170530Ssam
2025170530Ssam	ifp->if_timer = 0;
2026170530Ssam
2027170530Ssam	if (sc->sc_tx_timer > 0) {
2028170530Ssam		if (--sc->sc_tx_timer == 0) {
2029170530Ssam			device_printf(sc->sc_dev, "device timeout\n");
2030170530Ssam			rt2560_init(sc);
2031170530Ssam			ifp->if_oerrors++;
2032170530Ssam			RAL_UNLOCK(sc);
2033170530Ssam			return;
2034170530Ssam		}
2035170530Ssam		ifp->if_timer = 1;
2036170530Ssam	}
2037170530Ssam
2038170530Ssam	ieee80211_watchdog(ic);
2039170530Ssam
2040170530Ssam	RAL_UNLOCK(sc);
2041170530Ssam}
2042170530Ssam
2043170530Ssam/*
2044170530Ssam * This function allows for fast channel switching in monitor mode (used by
2045170530Ssam * net-mgmt/kismet). In IBSS mode, we must explicitly reset the interface to
2046170530Ssam * generate a new beacon frame.
2047170530Ssam */
2048170530Ssamstatic int
2049170530Ssamrt2560_reset(struct ifnet *ifp)
2050170530Ssam{
2051170530Ssam	struct rt2560_softc *sc = ifp->if_softc;
2052170530Ssam	struct ieee80211com *ic = &sc->sc_ic;
2053170530Ssam
2054170530Ssam	if (ic->ic_opmode != IEEE80211_M_MONITOR)
2055170530Ssam		return ENETRESET;
2056170530Ssam
2057170530Ssam	rt2560_set_chan(sc, ic->ic_curchan);
2058170530Ssam
2059172211Ssam	return 0;
2060172211Ssam}
2061172211Ssam
2062178354Ssamstatic int
2063172211Ssamrt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
2064172211Ssam{
2065172211Ssam	struct rt2560_softc *sc = ifp->if_softc;
2066178354Ssam	struct ieee80211com *ic = &sc->sc_ic;
2067178354Ssam	int error = 0;
2068172211Ssam
2069172211Ssam	RAL_LOCK(sc);
2070172211Ssam
2071172211Ssam	switch (cmd) {
2072178354Ssam	case SIOCSIFFLAGS:
2073172211Ssam		if (ifp->if_flags & IFF_UP) {
2074178354Ssam			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2075172211Ssam				rt2560_update_promisc(sc);
2076178354Ssam			else
2077172211Ssam				rt2560_init(sc);
2078172211Ssam		} else {
2079172211Ssam			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2080178354Ssam				rt2560_stop(sc);
2081172211Ssam		}
2082172211Ssam		break;
2083172211Ssam
2084172211Ssam	default:
2085172211Ssam		error = ieee80211_ioctl(ic, cmd, data);
2086172211Ssam	}
2087172211Ssam
2088172211Ssam	if (error == ENETRESET) {
2089172211Ssam		if ((ifp->if_flags & IFF_UP) &&
2090172211Ssam		    (ifp->if_drv_flags & IFF_DRV_RUNNING) &&
2091170530Ssam		    (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
2092173273Ssam			rt2560_init(sc);
2093173273Ssam		error = 0;
2094173273Ssam	}
2095173273Ssam
2096170530Ssam	RAL_UNLOCK(sc);
2097170530Ssam
2098170530Ssam	return error;
2099170530Ssam}
2100170530Ssam
2101170530Ssamstatic void
2102170530Ssamrt2560_bbp_write(struct rt2560_softc *sc, uint8_t reg, uint8_t val)
2103170530Ssam{
2104170530Ssam	uint32_t tmp;
2105170530Ssam	int ntries;
2106178354Ssam
2107170530Ssam	for (ntries = 0; ntries < 100; ntries++) {
2108170530Ssam		if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY))
2109178354Ssam			break;
2110170530Ssam		DELAY(1);
2111178354Ssam	}
2112170530Ssam	if (ntries == 100) {
2113170530Ssam		device_printf(sc->sc_dev, "could not write to BBP\n");
2114170530Ssam		return;
2115178354Ssam	}
2116170530Ssam
2117170530Ssam	tmp = RT2560_BBP_WRITE | RT2560_BBP_BUSY | reg << 8 | val;
2118172211Ssam	RAL_WRITE(sc, RT2560_BBPCSR, tmp);
2119170530Ssam
2120170530Ssam	DPRINTFN(15, ("BBP R%u <- 0x%02x\n", reg, val));
2121170530Ssam}
2122170530Ssam
2123170530Ssamstatic uint8_t
2124170530Ssamrt2560_bbp_read(struct rt2560_softc *sc, uint8_t reg)
2125170530Ssam{
2126170530Ssam	uint32_t val;
2127170530Ssam	int ntries;
2128170530Ssam
2129170530Ssam	val = RT2560_BBP_BUSY | reg << 8;
2130170530Ssam	RAL_WRITE(sc, RT2560_BBPCSR, val);
2131170530Ssam
2132170530Ssam	for (ntries = 0; ntries < 100; ntries++) {
2133170530Ssam		val = RAL_READ(sc, RT2560_BBPCSR);
2134170530Ssam		if (!(val & RT2560_BBP_BUSY))
2135170530Ssam			return val & 0xff;
2136170530Ssam		DELAY(1);
2137170530Ssam	}
2138170530Ssam
2139170530Ssam	device_printf(sc->sc_dev, "could not read from BBP\n");
2140170530Ssam	return 0;
2141170530Ssam}
2142170530Ssam
2143170530Ssamstatic void
2144170530Ssamrt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val)
2145170530Ssam{
2146170530Ssam	uint32_t tmp;
2147170530Ssam	int ntries;
2148170530Ssam
2149170530Ssam	for (ntries = 0; ntries < 100; ntries++) {
2150170530Ssam		if (!(RAL_READ(sc, RT2560_RFCSR) & RT2560_RF_BUSY))
2151170530Ssam			break;
2152170530Ssam		DELAY(1);
2153170530Ssam	}
2154170530Ssam	if (ntries == 100) {
2155		device_printf(sc->sc_dev, "could not write to RF\n");
2156		return;
2157	}
2158
2159	tmp = RT2560_RF_BUSY | RT2560_RF_20BIT | (val & 0xfffff) << 2 |
2160	    (reg & 0x3);
2161	RAL_WRITE(sc, RT2560_RFCSR, tmp);
2162
2163	/* remember last written value in sc */
2164	sc->rf_regs[reg] = val;
2165
2166	DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff));
2167}
2168
2169static void
2170rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
2171{
2172	struct ieee80211com *ic = &sc->sc_ic;
2173	uint8_t power, tmp;
2174	u_int i, chan;
2175
2176	chan = ieee80211_chan2ieee(ic, c);
2177	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
2178		return;
2179
2180	if (IEEE80211_IS_CHAN_2GHZ(c))
2181		power = min(sc->txpow[chan - 1], 31);
2182	else
2183		power = 31;
2184
2185	/* adjust txpower using ifconfig settings */
2186	power -= (100 - ic->ic_txpowlimit) / 8;
2187
2188	DPRINTFN(2, ("setting channel to %u, txpower to %u\n", chan, power));
2189
2190	switch (sc->rf_rev) {
2191	case RT2560_RF_2522:
2192		rt2560_rf_write(sc, RAL_RF1, 0x00814);
2193		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2522_r2[chan - 1]);
2194		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
2195		break;
2196
2197	case RT2560_RF_2523:
2198		rt2560_rf_write(sc, RAL_RF1, 0x08804);
2199		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2523_r2[chan - 1]);
2200		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x38044);
2201		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2202		break;
2203
2204	case RT2560_RF_2524:
2205		rt2560_rf_write(sc, RAL_RF1, 0x0c808);
2206		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2524_r2[chan - 1]);
2207		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
2208		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2209		break;
2210
2211	case RT2560_RF_2525:
2212		rt2560_rf_write(sc, RAL_RF1, 0x08808);
2213		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_hi_r2[chan - 1]);
2214		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2215		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2216
2217		rt2560_rf_write(sc, RAL_RF1, 0x08808);
2218		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_r2[chan - 1]);
2219		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2220		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
2221		break;
2222
2223	case RT2560_RF_2525E:
2224		rt2560_rf_write(sc, RAL_RF1, 0x08808);
2225		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525e_r2[chan - 1]);
2226		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2227		rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282);
2228		break;
2229
2230	case RT2560_RF_2526:
2231		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_hi_r2[chan - 1]);
2232		rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
2233		rt2560_rf_write(sc, RAL_RF1, 0x08804);
2234
2235		rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_r2[chan - 1]);
2236		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
2237		rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
2238		break;
2239
2240	/* dual-band RF */
2241	case RT2560_RF_5222:
2242		for (i = 0; rt2560_rf5222[i].chan != chan; i++);
2243
2244		rt2560_rf_write(sc, RAL_RF1, rt2560_rf5222[i].r1);
2245		rt2560_rf_write(sc, RAL_RF2, rt2560_rf5222[i].r2);
2246		rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
2247		rt2560_rf_write(sc, RAL_RF4, rt2560_rf5222[i].r4);
2248		break;
2249	}
2250
2251	if (ic->ic_state != IEEE80211_S_SCAN) {
2252		/* set Japan filter bit for channel 14 */
2253		tmp = rt2560_bbp_read(sc, 70);
2254
2255		tmp &= ~RT2560_JAPAN_FILTER;
2256		if (chan == 14)
2257			tmp |= RT2560_JAPAN_FILTER;
2258
2259		rt2560_bbp_write(sc, 70, tmp);
2260
2261		/* clear CRC errors */
2262		RAL_READ(sc, RT2560_CNT0);
2263	}
2264}
2265
2266#if 0
2267/*
2268 * Disable RF auto-tuning.
2269 */
2270static void
2271rt2560_disable_rf_tune(struct rt2560_softc *sc)
2272{
2273	uint32_t tmp;
2274
2275	if (sc->rf_rev != RT2560_RF_2523) {
2276		tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE;
2277		rt2560_rf_write(sc, RAL_RF1, tmp);
2278	}
2279
2280	tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE;
2281	rt2560_rf_write(sc, RAL_RF3, tmp);
2282
2283	DPRINTFN(2, ("disabling RF autotune\n"));
2284}
2285#endif
2286
2287/*
2288 * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
2289 * synchronization.
2290 */
2291static void
2292rt2560_enable_tsf_sync(struct rt2560_softc *sc)
2293{
2294	struct ieee80211com *ic = &sc->sc_ic;
2295	uint16_t logcwmin, preload;
2296	uint32_t tmp;
2297
2298	/* first, disable TSF synchronization */
2299	RAL_WRITE(sc, RT2560_CSR14, 0);
2300
2301	tmp = 16 * ic->ic_bss->ni_intval;
2302	RAL_WRITE(sc, RT2560_CSR12, tmp);
2303
2304	RAL_WRITE(sc, RT2560_CSR13, 0);
2305
2306	logcwmin = 5;
2307	preload = (ic->ic_opmode == IEEE80211_M_STA) ? 384 : 1024;
2308	tmp = logcwmin << 16 | preload;
2309	RAL_WRITE(sc, RT2560_BCNOCSR, tmp);
2310
2311	/* finally, enable TSF synchronization */
2312	tmp = RT2560_ENABLE_TSF | RT2560_ENABLE_TBCN;
2313	if (ic->ic_opmode == IEEE80211_M_STA)
2314		tmp |= RT2560_ENABLE_TSF_SYNC(1);
2315	else
2316		tmp |= RT2560_ENABLE_TSF_SYNC(2) |
2317		       RT2560_ENABLE_BEACON_GENERATOR;
2318	RAL_WRITE(sc, RT2560_CSR14, tmp);
2319
2320	DPRINTF(("enabling TSF synchronization\n"));
2321}
2322
2323static void
2324rt2560_update_plcp(struct rt2560_softc *sc)
2325{
2326	struct ieee80211com *ic = &sc->sc_ic;
2327
2328	/* no short preamble for 1Mbps */
2329	RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400);
2330
2331	if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) {
2332		/* values taken from the reference driver */
2333		RAL_WRITE(sc, RT2560_PLCP2MCSR,   0x00380401);
2334		RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x00150402);
2335		RAL_WRITE(sc, RT2560_PLCP11MCSR,  0x000b8403);
2336	} else {
2337		/* same values as above or'ed 0x8 */
2338		RAL_WRITE(sc, RT2560_PLCP2MCSR,   0x00380409);
2339		RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x0015040a);
2340		RAL_WRITE(sc, RT2560_PLCP11MCSR,  0x000b840b);
2341	}
2342
2343	DPRINTF(("updating PLCP for %s preamble\n",
2344	    (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long"));
2345}
2346
2347/*
2348 * This function can be called by ieee80211_set_shortslottime(). Refer to
2349 * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
2350 */
2351static void
2352rt2560_update_slot(struct ifnet *ifp)
2353{
2354	struct rt2560_softc *sc = ifp->if_softc;
2355	struct ieee80211com *ic = &sc->sc_ic;
2356	uint8_t slottime;
2357	uint16_t tx_sifs, tx_pifs, tx_difs, eifs;
2358	uint32_t tmp;
2359
2360	slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
2361
2362	/* update the MAC slot boundaries */
2363	tx_sifs = RAL_SIFS - RT2560_TXRX_TURNAROUND;
2364	tx_pifs = tx_sifs + slottime;
2365	tx_difs = tx_sifs + 2 * slottime;
2366	eifs = (ic->ic_curmode == IEEE80211_MODE_11B) ? 364 : 60;
2367
2368	tmp = RAL_READ(sc, RT2560_CSR11);
2369	tmp = (tmp & ~0x1f00) | slottime << 8;
2370	RAL_WRITE(sc, RT2560_CSR11, tmp);
2371
2372	tmp = tx_pifs << 16 | tx_sifs;
2373	RAL_WRITE(sc, RT2560_CSR18, tmp);
2374
2375	tmp = eifs << 16 | tx_difs;
2376	RAL_WRITE(sc, RT2560_CSR19, tmp);
2377
2378	DPRINTF(("setting slottime to %uus\n", slottime));
2379}
2380
2381static void
2382rt2560_set_basicrates(struct rt2560_softc *sc)
2383{
2384	struct ieee80211com *ic = &sc->sc_ic;
2385
2386	/* update basic rate set */
2387	if (ic->ic_curmode == IEEE80211_MODE_11B) {
2388		/* 11b basic rates: 1, 2Mbps */
2389		RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x3);
2390	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) {
2391		/* 11a basic rates: 6, 12, 24Mbps */
2392		RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x150);
2393	} else {
2394		/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
2395		RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x15f);
2396	}
2397}
2398
2399static void
2400rt2560_update_led(struct rt2560_softc *sc, int led1, int led2)
2401{
2402	uint32_t tmp;
2403
2404	/* set ON period to 70ms and OFF period to 30ms */
2405	tmp = led1 << 16 | led2 << 17 | 70 << 8 | 30;
2406	RAL_WRITE(sc, RT2560_LEDCSR, tmp);
2407}
2408
2409static void
2410rt2560_set_bssid(struct rt2560_softc *sc, uint8_t *bssid)
2411{
2412	uint32_t tmp;
2413
2414	tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
2415	RAL_WRITE(sc, RT2560_CSR5, tmp);
2416
2417	tmp = bssid[4] | bssid[5] << 8;
2418	RAL_WRITE(sc, RT2560_CSR6, tmp);
2419
2420	DPRINTF(("setting BSSID to %6D\n", bssid, ":"));
2421}
2422
2423static void
2424rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr)
2425{
2426	uint32_t tmp;
2427
2428	tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
2429	RAL_WRITE(sc, RT2560_CSR3, tmp);
2430
2431	tmp = addr[4] | addr[5] << 8;
2432	RAL_WRITE(sc, RT2560_CSR4, tmp);
2433
2434	DPRINTF(("setting MAC address to %6D\n", addr, ":"));
2435}
2436
2437static void
2438rt2560_get_macaddr(struct rt2560_softc *sc, uint8_t *addr)
2439{
2440	uint32_t tmp;
2441
2442	tmp = RAL_READ(sc, RT2560_CSR3);
2443	addr[0] = tmp & 0xff;
2444	addr[1] = (tmp >>  8) & 0xff;
2445	addr[2] = (tmp >> 16) & 0xff;
2446	addr[3] = (tmp >> 24);
2447
2448	tmp = RAL_READ(sc, RT2560_CSR4);
2449	addr[4] = tmp & 0xff;
2450	addr[5] = (tmp >> 8) & 0xff;
2451}
2452
2453static void
2454rt2560_update_promisc(struct rt2560_softc *sc)
2455{
2456	struct ifnet *ifp = sc->sc_ic.ic_ifp;
2457	uint32_t tmp;
2458
2459	tmp = RAL_READ(sc, RT2560_RXCSR0);
2460
2461	tmp &= ~RT2560_DROP_NOT_TO_ME;
2462	if (!(ifp->if_flags & IFF_PROMISC))
2463		tmp |= RT2560_DROP_NOT_TO_ME;
2464
2465	RAL_WRITE(sc, RT2560_RXCSR0, tmp);
2466
2467	DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
2468	    "entering" : "leaving"));
2469}
2470
2471static const char *
2472rt2560_get_rf(int rev)
2473{
2474	switch (rev) {
2475	case RT2560_RF_2522:	return "RT2522";
2476	case RT2560_RF_2523:	return "RT2523";
2477	case RT2560_RF_2524:	return "RT2524";
2478	case RT2560_RF_2525:	return "RT2525";
2479	case RT2560_RF_2525E:	return "RT2525e";
2480	case RT2560_RF_2526:	return "RT2526";
2481	case RT2560_RF_5222:	return "RT5222";
2482	default:		return "unknown";
2483	}
2484}
2485
2486static void
2487rt2560_read_eeprom(struct rt2560_softc *sc)
2488{
2489	uint16_t val;
2490	int i;
2491
2492	val = rt2560_eeprom_read(sc, RT2560_EEPROM_CONFIG0);
2493	sc->rf_rev =   (val >> 11) & 0x7;
2494	sc->hw_radio = (val >> 10) & 0x1;
2495	sc->led_mode = (val >> 6)  & 0x7;
2496	sc->rx_ant =   (val >> 4)  & 0x3;
2497	sc->tx_ant =   (val >> 2)  & 0x3;
2498	sc->nb_ant =   val & 0x3;
2499
2500	/* read default values for BBP registers */
2501	for (i = 0; i < 16; i++) {
2502		val = rt2560_eeprom_read(sc, RT2560_EEPROM_BBP_BASE + i);
2503		sc->bbp_prom[i].reg = val >> 8;
2504		sc->bbp_prom[i].val = val & 0xff;
2505	}
2506
2507	/* read Tx power for all b/g channels */
2508	for (i = 0; i < 14 / 2; i++) {
2509		val = rt2560_eeprom_read(sc, RT2560_EEPROM_TXPOWER + i);
2510		sc->txpow[i * 2] = val >> 8;
2511		sc->txpow[i * 2 + 1] = val & 0xff;
2512	}
2513}
2514
2515static int
2516rt2560_bbp_init(struct rt2560_softc *sc)
2517{
2518#define N(a)	(sizeof (a) / sizeof ((a)[0]))
2519	int i, ntries;
2520
2521	/* wait for BBP to be ready */
2522	for (ntries = 0; ntries < 100; ntries++) {
2523		if (rt2560_bbp_read(sc, RT2560_BBP_VERSION) != 0)
2524			break;
2525		DELAY(1);
2526	}
2527	if (ntries == 100) {
2528		device_printf(sc->sc_dev, "timeout waiting for BBP\n");
2529		return EIO;
2530	}
2531
2532	/* initialize BBP registers to default values */
2533	for (i = 0; i < N(rt2560_def_bbp); i++) {
2534		rt2560_bbp_write(sc, rt2560_def_bbp[i].reg,
2535		    rt2560_def_bbp[i].val);
2536	}
2537#if 0
2538	/* initialize BBP registers to values stored in EEPROM */
2539	for (i = 0; i < 16; i++) {
2540		if (sc->bbp_prom[i].reg == 0xff)
2541			continue;
2542		rt2560_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
2543	}
2544#endif
2545
2546	return 0;
2547#undef N
2548}
2549
2550static void
2551rt2560_set_txantenna(struct rt2560_softc *sc, int antenna)
2552{
2553	uint32_t tmp;
2554	uint8_t tx;
2555
2556	tx = rt2560_bbp_read(sc, RT2560_BBP_TX) & ~RT2560_BBP_ANTMASK;
2557	if (antenna == 1)
2558		tx |= RT2560_BBP_ANTA;
2559	else if (antenna == 2)
2560		tx |= RT2560_BBP_ANTB;
2561	else
2562		tx |= RT2560_BBP_DIVERSITY;
2563
2564	/* need to force I/Q flip for RF 2525e, 2526 and 5222 */
2565	if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526 ||
2566	    sc->rf_rev == RT2560_RF_5222)
2567		tx |= RT2560_BBP_FLIPIQ;
2568
2569	rt2560_bbp_write(sc, RT2560_BBP_TX, tx);
2570
2571	/* update values for CCK and OFDM in BBPCSR1 */
2572	tmp = RAL_READ(sc, RT2560_BBPCSR1) & ~0x00070007;
2573	tmp |= (tx & 0x7) << 16 | (tx & 0x7);
2574	RAL_WRITE(sc, RT2560_BBPCSR1, tmp);
2575}
2576
2577static void
2578rt2560_set_rxantenna(struct rt2560_softc *sc, int antenna)
2579{
2580	uint8_t rx;
2581
2582	rx = rt2560_bbp_read(sc, RT2560_BBP_RX) & ~RT2560_BBP_ANTMASK;
2583	if (antenna == 1)
2584		rx |= RT2560_BBP_ANTA;
2585	else if (antenna == 2)
2586		rx |= RT2560_BBP_ANTB;
2587	else
2588		rx |= RT2560_BBP_DIVERSITY;
2589
2590	/* need to force no I/Q flip for RF 2525e and 2526 */
2591	if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526)
2592		rx &= ~RT2560_BBP_FLIPIQ;
2593
2594	rt2560_bbp_write(sc, RT2560_BBP_RX, rx);
2595}
2596
2597static void
2598rt2560_init(void *priv)
2599{
2600#define N(a)	(sizeof (a) / sizeof ((a)[0]))
2601	struct rt2560_softc *sc = priv;
2602	struct ieee80211com *ic = &sc->sc_ic;
2603	struct ifnet *ifp = ic->ic_ifp;
2604	uint32_t tmp;
2605	int i;
2606
2607	RAL_LOCK(sc);
2608
2609	rt2560_stop(sc);
2610
2611	/* setup tx rings */
2612	tmp = RT2560_PRIO_RING_COUNT << 24 |
2613	      RT2560_ATIM_RING_COUNT << 16 |
2614	      RT2560_TX_RING_COUNT   <<  8 |
2615	      RT2560_TX_DESC_SIZE;
2616
2617	/* rings must be initialized in this exact order */
2618	RAL_WRITE(sc, RT2560_TXCSR2, tmp);
2619	RAL_WRITE(sc, RT2560_TXCSR3, sc->txq.physaddr);
2620	RAL_WRITE(sc, RT2560_TXCSR5, sc->prioq.physaddr);
2621	RAL_WRITE(sc, RT2560_TXCSR4, sc->atimq.physaddr);
2622	RAL_WRITE(sc, RT2560_TXCSR6, sc->bcnq.physaddr);
2623
2624	/* setup rx ring */
2625	tmp = RT2560_RX_RING_COUNT << 8 | RT2560_RX_DESC_SIZE;
2626
2627	RAL_WRITE(sc, RT2560_RXCSR1, tmp);
2628	RAL_WRITE(sc, RT2560_RXCSR2, sc->rxq.physaddr);
2629
2630	/* initialize MAC registers to default values */
2631	for (i = 0; i < N(rt2560_def_mac); i++)
2632		RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
2633
2634	IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
2635	rt2560_set_macaddr(sc, ic->ic_myaddr);
2636
2637	/* set basic rate set (will be updated later) */
2638	RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
2639
2640	rt2560_set_txantenna(sc, sc->tx_ant);
2641	rt2560_set_rxantenna(sc, sc->rx_ant);
2642	rt2560_update_slot(ifp);
2643	rt2560_update_plcp(sc);
2644	rt2560_update_led(sc, 0, 0);
2645
2646	RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC);
2647	RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY);
2648
2649	if (rt2560_bbp_init(sc) != 0) {
2650		rt2560_stop(sc);
2651		RAL_UNLOCK(sc);
2652		return;
2653	}
2654
2655	/* set default BSS channel */
2656	rt2560_set_chan(sc, ic->ic_curchan);
2657
2658	/* kick Rx */
2659	tmp = RT2560_DROP_PHY_ERROR | RT2560_DROP_CRC_ERROR;
2660	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2661		tmp |= RT2560_DROP_CTL | RT2560_DROP_VERSION_ERROR;
2662		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2663			tmp |= RT2560_DROP_TODS;
2664		if (!(ifp->if_flags & IFF_PROMISC))
2665			tmp |= RT2560_DROP_NOT_TO_ME;
2666	}
2667	RAL_WRITE(sc, RT2560_RXCSR0, tmp);
2668
2669	/* clear old FCS and Rx FIFO errors */
2670	RAL_READ(sc, RT2560_CNT0);
2671	RAL_READ(sc, RT2560_CNT4);
2672
2673	/* clear any pending interrupts */
2674	RAL_WRITE(sc, RT2560_CSR7, 0xffffffff);
2675
2676	/* enable interrupts */
2677	RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
2678
2679	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2680	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2681
2682	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
2683		if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
2684			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
2685	} else
2686		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
2687
2688	RAL_UNLOCK(sc);
2689#undef N
2690}
2691
2692void
2693rt2560_stop(void *priv)
2694{
2695	struct rt2560_softc *sc = priv;
2696	struct ieee80211com *ic = &sc->sc_ic;
2697	struct ifnet *ifp = ic->ic_ifp;
2698
2699	sc->sc_tx_timer = 0;
2700	ifp->if_timer = 0;
2701	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
2702
2703	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
2704
2705	/* abort Tx */
2706	RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX);
2707
2708	/* disable Rx */
2709	RAL_WRITE(sc, RT2560_RXCSR0, RT2560_DISABLE_RX);
2710
2711	/* reset ASIC (imply reset BBP) */
2712	RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC);
2713	RAL_WRITE(sc, RT2560_CSR1, 0);
2714
2715	/* disable interrupts */
2716	RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
2717
2718	/* reset Tx and Rx rings */
2719	rt2560_reset_tx_ring(sc, &sc->txq);
2720	rt2560_reset_tx_ring(sc, &sc->atimq);
2721	rt2560_reset_tx_ring(sc, &sc->prioq);
2722	rt2560_reset_tx_ring(sc, &sc->bcnq);
2723	rt2560_reset_rx_ring(sc, &sc->rxq);
2724}
2725