xref: /illumos-gate/usr/src/uts/common/io/rwd/rt2661.c (revision d3351b34)
110115c80Sfei feng - Sun Microsystems - Beijing China /*
20dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
310115c80Sfei feng - Sun Microsystems - Beijing China  * Use is subject to license terms.
410115c80Sfei feng - Sun Microsystems - Beijing China  */
510115c80Sfei feng - Sun Microsystems - Beijing China 
610115c80Sfei feng - Sun Microsystems - Beijing China /*
710115c80Sfei feng - Sun Microsystems - Beijing China  * Copyright (c) 2006
810115c80Sfei feng - Sun Microsystems - Beijing China  *	Damien Bergamini <damien.bergamini@free.fr>
910115c80Sfei feng - Sun Microsystems - Beijing China  *
1010115c80Sfei feng - Sun Microsystems - Beijing China  * Permission to use, copy, modify, and distribute this software for any
1110115c80Sfei feng - Sun Microsystems - Beijing China  * purpose with or without fee is hereby granted, provided that the above
1210115c80Sfei feng - Sun Microsystems - Beijing China  * copyright notice and this permission notice appear in all copies.
1310115c80Sfei feng - Sun Microsystems - Beijing China  *
1410115c80Sfei feng - Sun Microsystems - Beijing China  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1510115c80Sfei feng - Sun Microsystems - Beijing China  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1610115c80Sfei feng - Sun Microsystems - Beijing China  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1710115c80Sfei feng - Sun Microsystems - Beijing China  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1810115c80Sfei feng - Sun Microsystems - Beijing China  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1910115c80Sfei feng - Sun Microsystems - Beijing China  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2010115c80Sfei feng - Sun Microsystems - Beijing China  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2110115c80Sfei feng - Sun Microsystems - Beijing China  */
2210115c80Sfei feng - Sun Microsystems - Beijing China 
2310115c80Sfei feng - Sun Microsystems - Beijing China /*
2410115c80Sfei feng - Sun Microsystems - Beijing China  * Ralink Technology RT2561, RT2561S and RT2661  chipset driver
2510115c80Sfei feng - Sun Microsystems - Beijing China  * http://www.ralinktech.com/
2610115c80Sfei feng - Sun Microsystems - Beijing China  */
2710115c80Sfei feng - Sun Microsystems - Beijing China 
28*d3351b34SJohn Levon /*
29*d3351b34SJohn Levon  * Copyright 2019 Joyent, Inc.
30*d3351b34SJohn Levon  */
31*d3351b34SJohn Levon 
3210115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/types.h>
3310115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/byteorder.h>
3410115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/conf.h>
3510115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/cmn_err.h>
3610115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/stat.h>
3710115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/ddi.h>
3810115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/sunddi.h>
3910115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/strsubr.h>
4010115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/ethernet.h>
4110115c80Sfei feng - Sun Microsystems - Beijing China #include <inet/common.h>
4210115c80Sfei feng - Sun Microsystems - Beijing China #include <inet/nd.h>
4310115c80Sfei feng - Sun Microsystems - Beijing China #include <inet/mi.h>
4410115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/note.h>
4510115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/stream.h>
4610115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/strsun.h>
4710115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/modctl.h>
4810115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/devops.h>
4910115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/dlpi.h>
5010115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/mac_provider.h>
5110115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/mac_wifi.h>
5210115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/net80211.h>
5310115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/net80211_proto.h>
5410115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/varargs.h>
5510115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/policy.h>
5610115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/pci.h>
5710115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/crypto/common.h>
5810115c80Sfei feng - Sun Microsystems - Beijing China #include <sys/crypto/api.h>
5910115c80Sfei feng - Sun Microsystems - Beijing China #include <inet/wifi_ioctl.h>
6010115c80Sfei feng - Sun Microsystems - Beijing China 
6110115c80Sfei feng - Sun Microsystems - Beijing China #include "rt2661_reg.h"
6210115c80Sfei feng - Sun Microsystems - Beijing China #include "rt2661_var.h"
6310115c80Sfei feng - Sun Microsystems - Beijing China #include "rt2661_ucode.h"
6410115c80Sfei feng - Sun Microsystems - Beijing China 
6510115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_80211	(1 << 0)
6610115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_DMA		(1 << 1)
6710115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_EEPROM	(1 << 2)
6810115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_FW		(1 << 3)
6910115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_HW		(1 << 4)
7010115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_INTR		(1 << 5)
7110115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_RX		(1 << 6)
7210115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_SCAN		(1 << 7)
7310115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_TX		(1 << 8)
7410115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_RADIO	(1 << 9)
7510115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_RESUME	(1 << 10)
7610115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_DBG_MSG		(1 << 11)
7710115c80Sfei feng - Sun Microsystems - Beijing China 
7810115c80Sfei feng - Sun Microsystems - Beijing China uint32_t rt2661_dbg_flags = 0;
7910115c80Sfei feng - Sun Microsystems - Beijing China 
8010115c80Sfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
8110115c80Sfei feng - Sun Microsystems - Beijing China #define	RWD_DEBUG \
8210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_debug
8310115c80Sfei feng - Sun Microsystems - Beijing China #else
84*d3351b34SJohn Levon #define	RWD_DEBUG(...) (void)(0)
8510115c80Sfei feng - Sun Microsystems - Beijing China #endif
8610115c80Sfei feng - Sun Microsystems - Beijing China 
8710115c80Sfei feng - Sun Microsystems - Beijing China static void *rt2661_soft_state_p = NULL;
8810115c80Sfei feng - Sun Microsystems - Beijing China 
8910115c80Sfei feng - Sun Microsystems - Beijing China static const uint8_t *ucode = NULL;
9010115c80Sfei feng - Sun Microsystems - Beijing China int usize;
9110115c80Sfei feng - Sun Microsystems - Beijing China 
9210115c80Sfei feng - Sun Microsystems - Beijing China static const struct {
9310115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t	reg;
9410115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t	val;
9510115c80Sfei feng - Sun Microsystems - Beijing China } rt2661_def_mac[] = {
9610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_DEF_MAC
9710115c80Sfei feng - Sun Microsystems - Beijing China };
9810115c80Sfei feng - Sun Microsystems - Beijing China 
9910115c80Sfei feng - Sun Microsystems - Beijing China static const struct {
10010115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t	reg;
10110115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t	val;
10210115c80Sfei feng - Sun Microsystems - Beijing China } rt2661_def_bbp[] = {
10310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_DEF_BBP
10410115c80Sfei feng - Sun Microsystems - Beijing China };
10510115c80Sfei feng - Sun Microsystems - Beijing China 
10610115c80Sfei feng - Sun Microsystems - Beijing China static const struct rfprog {
10710115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t		chan;
10810115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t	r1, r2, r3, r4;
10910115c80Sfei feng - Sun Microsystems - Beijing China }  rt2661_rf5225_1[] = {
11010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_RF5225_1
11110115c80Sfei feng - Sun Microsystems - Beijing China }, rt2661_rf5225_2[] = {
11210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_RF5225_2
11310115c80Sfei feng - Sun Microsystems - Beijing China };
11410115c80Sfei feng - Sun Microsystems - Beijing China 
11510115c80Sfei feng - Sun Microsystems - Beijing China /*
11610115c80Sfei feng - Sun Microsystems - Beijing China  * PIO access attributes for registers
11710115c80Sfei feng - Sun Microsystems - Beijing China  */
11810115c80Sfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t rt2661_csr_accattr = {
11910115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,
12010115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_STRUCTURE_LE_ACC,
12110115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC
12210115c80Sfei feng - Sun Microsystems - Beijing China };
12310115c80Sfei feng - Sun Microsystems - Beijing China 
12410115c80Sfei feng - Sun Microsystems - Beijing China /*
12510115c80Sfei feng - Sun Microsystems - Beijing China  * DMA access attributes for descriptors: NOT to be byte swapped.
12610115c80Sfei feng - Sun Microsystems - Beijing China  */
12710115c80Sfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t rt2661_desc_accattr = {
12810115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,
12910115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_STRUCTURE_LE_ACC,
13010115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC
13110115c80Sfei feng - Sun Microsystems - Beijing China };
13210115c80Sfei feng - Sun Microsystems - Beijing China 
13310115c80Sfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t rt2661_buf_accattr = {
13410115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_DEVICE_ATTR_V0,
13510115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_NEVERSWAP_ACC,
13610115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_STRICTORDER_ACC,
13710115c80Sfei feng - Sun Microsystems - Beijing China 	DDI_DEFAULT_ACC
13810115c80Sfei feng - Sun Microsystems - Beijing China };
13910115c80Sfei feng - Sun Microsystems - Beijing China 
14010115c80Sfei feng - Sun Microsystems - Beijing China /*
14110115c80Sfei feng - Sun Microsystems - Beijing China  * Describes the chip's DMA engine
14210115c80Sfei feng - Sun Microsystems - Beijing China  */
14310115c80Sfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t rt2661_dma_attr = {
14410115c80Sfei feng - Sun Microsystems - Beijing China 	DMA_ATTR_V0,			/* dma_attr version */
14510115c80Sfei feng - Sun Microsystems - Beijing China 	0x0,				/* dma_attr_addr_lo */
14610115c80Sfei feng - Sun Microsystems - Beijing China 	0xffffffffU,			/* dma_attr_addr_hi */
14710115c80Sfei feng - Sun Microsystems - Beijing China 	0xffffffffU,			/* dma_attr_count_max */
14810115c80Sfei feng - Sun Microsystems - Beijing China 	1,				/* dma_attr_align */
14910115c80Sfei feng - Sun Microsystems - Beijing China 	0x00000fff,			/* dma_attr_burstsizes */
15010115c80Sfei feng - Sun Microsystems - Beijing China 	1,				/* dma_attr_minxfer */
15110115c80Sfei feng - Sun Microsystems - Beijing China 	0xffffffffU,			/* dma_attr_maxxfer */
15210115c80Sfei feng - Sun Microsystems - Beijing China 	0xffffffffU,			/* dma_attr_seg */
15310115c80Sfei feng - Sun Microsystems - Beijing China 	1,				/* dma_attr_sgllen */
15410115c80Sfei feng - Sun Microsystems - Beijing China 	1,				/* dma_attr_granular */
15510115c80Sfei feng - Sun Microsystems - Beijing China 	0				/* dma_attr_flags */
15610115c80Sfei feng - Sun Microsystems - Beijing China };
15710115c80Sfei feng - Sun Microsystems - Beijing China 
15810115c80Sfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset rt2661_rateset_11b =
15910115c80Sfei feng - Sun Microsystems - Beijing China 	{ 4, { 2, 4, 11, 22 } };
16010115c80Sfei feng - Sun Microsystems - Beijing China 
16110115c80Sfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset rt2661_rateset_11g =
16210115c80Sfei feng - Sun Microsystems - Beijing China 	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
16310115c80Sfei feng - Sun Microsystems - Beijing China 
16410115c80Sfei feng - Sun Microsystems - Beijing China 
16510115c80Sfei feng - Sun Microsystems - Beijing China static const char *rt2661_get_rf(int);
16610115c80Sfei feng - Sun Microsystems - Beijing China 
16710115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_read_eeprom(struct rt2661_softc *);
16810115c80Sfei feng - Sun Microsystems - Beijing China static uint16_t	rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
16910115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_load_microcode(struct rt2661_softc *,
17010115c80Sfei feng - Sun Microsystems - Beijing China 		    const uint8_t *, int);
17110115c80Sfei feng - Sun Microsystems - Beijing China 
17210115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_alloc_dma_mem(dev_info_t *, ddi_dma_attr_t *, size_t,
17310115c80Sfei feng - Sun Microsystems - Beijing China 		    ddi_device_acc_attr_t *, uint_t, uint_t, struct dma_area *);
17410115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_free_dma_mem(struct dma_area *);
17510115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_alloc_tx_ring(struct rt2661_softc *,
17610115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_tx_ring *, int);
17710115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_reset_tx_ring(struct rt2661_softc *,
17810115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_tx_ring *);
17910115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_free_tx_ring(struct rt2661_softc *,
18010115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_tx_ring *);
18110115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_alloc_rx_ring(struct rt2661_softc *,
18210115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_rx_ring *, int);
18310115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_reset_rx_ring(struct rt2661_softc *,
18410115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_rx_ring *);
18510115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_free_rx_ring(struct rt2661_softc *,
18610115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_rx_ring *);
18710115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_tx_dma_intr(struct rt2661_softc *,
18810115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_tx_ring *);
18910115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_tx_intr(struct rt2661_softc *);
19010115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_rx_intr(struct rt2661_softc *);
19110115c80Sfei feng - Sun Microsystems - Beijing China static uint_t	rt2661_softintr(caddr_t, caddr_t);
19210115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_mcu_wakeup(struct rt2661_softc *);
19310115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_mcu_cmd_intr(struct rt2661_softc *);
19410115c80Sfei feng - Sun Microsystems - Beijing China static uint_t	rt2661_intr(caddr_t, caddr_t);
19510115c80Sfei feng - Sun Microsystems - Beijing China 
19610115c80Sfei feng - Sun Microsystems - Beijing China static uint16_t	rt2661_txtime(int, int, uint32_t);
19710115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_ack_rate(struct ieee80211com *, int);
19810115c80Sfei feng - Sun Microsystems - Beijing China static uint8_t	rt2661_plcp_signal(int);
19910115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_setup_tx_desc(struct rt2661_softc *,
20010115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_tx_desc *, uint32_t, uint16_t, int,
20110115c80Sfei feng - Sun Microsystems - Beijing China 		    int, int);
20210115c80Sfei feng - Sun Microsystems - Beijing China 
20310115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_get_rssi(struct rt2661_softc *, uint8_t);
20410115c80Sfei feng - Sun Microsystems - Beijing China 
20510115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_send(ieee80211com_t *, mblk_t *);
20610115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_mgmt_send(ieee80211com_t *, mblk_t *, uint8_t);
20710115c80Sfei feng - Sun Microsystems - Beijing China 
20810115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_amrr_node_init(const struct rt2661_amrr *,
20910115c80Sfei feng - Sun Microsystems - Beijing China 		    struct rt2661_amrr_node *);
21010115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_amrr_choose(struct rt2661_amrr *,
21110115c80Sfei feng - Sun Microsystems - Beijing China 		    struct ieee80211_node *, struct rt2661_amrr_node *);
21210115c80Sfei feng - Sun Microsystems - Beijing China 
21310115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_update_promisc(struct rt2661_softc *);
21410115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_updateslot(struct ieee80211com *, int);
21510115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_set_slottime(struct rt2661_softc *);
21610115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_enable_mrr(struct rt2661_softc *);
21710115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_set_txpreamble(struct rt2661_softc *);
21810115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_set_basicrates(struct rt2661_softc *);
21910115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_set_bssid(struct rt2661_softc *, const uint8_t *);
22010115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_newassoc(struct ieee80211com *, struct ieee80211_node *);
22110115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_updatestats(void *);
22210115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_rx_tune(struct rt2661_softc *);
22310115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_enable_tsf_sync(struct rt2661_softc *);
22410115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_newstate(struct ieee80211com *,
22510115c80Sfei feng - Sun Microsystems - Beijing China 		    enum ieee80211_state, int);
22610115c80Sfei feng - Sun Microsystems - Beijing China 
22710115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_set_macaddr(struct rt2661_softc *, const uint8_t *);
22810115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_bbp_init(struct rt2661_softc *);
22910115c80Sfei feng - Sun Microsystems - Beijing China static uint8_t	rt2661_bbp_read(struct rt2661_softc *, uint8_t);
23010115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_bbp_write(struct rt2661_softc *, uint8_t, uint8_t);
23110115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_select_band(struct rt2661_softc *,
23210115c80Sfei feng - Sun Microsystems - Beijing China 		    struct ieee80211_channel *);
23310115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_select_antenna(struct rt2661_softc *);
23410115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_rf_write(struct rt2661_softc *, uint8_t, uint32_t);
23510115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_set_chan(struct rt2661_softc *,
23610115c80Sfei feng - Sun Microsystems - Beijing China 		    struct ieee80211_channel *);
23710115c80Sfei feng - Sun Microsystems - Beijing China 
23810115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_stop_locked(struct rt2661_softc *);
23910115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_init(struct rt2661_softc *);
24010115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_stop(struct rt2661_softc *);
24110115c80Sfei feng - Sun Microsystems - Beijing China /*
24210115c80Sfei feng - Sun Microsystems - Beijing China  * device operations
24310115c80Sfei feng - Sun Microsystems - Beijing China  */
24410115c80Sfei feng - Sun Microsystems - Beijing China static int rt2661_attach(dev_info_t *, ddi_attach_cmd_t);
24510115c80Sfei feng - Sun Microsystems - Beijing China static int rt2661_detach(dev_info_t *, ddi_detach_cmd_t);
24610115c80Sfei feng - Sun Microsystems - Beijing China static int rt2661_quiesce(dev_info_t *);
24710115c80Sfei feng - Sun Microsystems - Beijing China 
24810115c80Sfei feng - Sun Microsystems - Beijing China /*
24910115c80Sfei feng - Sun Microsystems - Beijing China  * Module Loading Data & Entry Points
25010115c80Sfei feng - Sun Microsystems - Beijing China  */
25110115c80Sfei feng - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(rwd_dev_ops, nulldev, nulldev, rt2661_attach,
25210115c80Sfei feng - Sun Microsystems - Beijing China     rt2661_detach, nodev, NULL, D_MP, NULL, rt2661_quiesce);
25310115c80Sfei feng - Sun Microsystems - Beijing China 
25410115c80Sfei feng - Sun Microsystems - Beijing China static struct modldrv rwd_modldrv = {
25510115c80Sfei feng - Sun Microsystems - Beijing China 	&mod_driverops,		/* Type of module.  This one is a driver */
25610115c80Sfei feng - Sun Microsystems - Beijing China 	"Ralink RT2661 driver v1.1",	/* short description */
25710115c80Sfei feng - Sun Microsystems - Beijing China 	&rwd_dev_ops		/* driver specific ops */
25810115c80Sfei feng - Sun Microsystems - Beijing China };
25910115c80Sfei feng - Sun Microsystems - Beijing China 
26010115c80Sfei feng - Sun Microsystems - Beijing China static struct modlinkage modlinkage = {
26110115c80Sfei feng - Sun Microsystems - Beijing China 	MODREV_1,
26210115c80Sfei feng - Sun Microsystems - Beijing China 	(void *)&rwd_modldrv,
26310115c80Sfei feng - Sun Microsystems - Beijing China 	NULL
26410115c80Sfei feng - Sun Microsystems - Beijing China };
26510115c80Sfei feng - Sun Microsystems - Beijing China 
26610115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_stat(void *,  uint_t, uint64_t *);
26710115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_start(void *);
26810115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_m_stop(void *);
26910115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_promisc(void *, boolean_t);
27010115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_multicst(void *, boolean_t, const uint8_t *);
27110115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_unicst(void *, const uint8_t *);
27210115c80Sfei feng - Sun Microsystems - Beijing China static mblk_t	*rt2661_m_tx(void *, mblk_t *);
27310115c80Sfei feng - Sun Microsystems - Beijing China static void	rt2661_m_ioctl(void *, queue_t *, mblk_t *);
27410115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_setprop(void *arg, const char *pr_name,
27510115c80Sfei feng - Sun Microsystems - Beijing China 		    mac_prop_id_t wldp_pr_num,
27610115c80Sfei feng - Sun Microsystems - Beijing China 		    uint_t wldp_length, const void *wldp_buf);
27710115c80Sfei feng - Sun Microsystems - Beijing China static int	rt2661_m_getprop(void *arg, const char *pr_name,
2780dc2366fSVenugopal Iyer 		    mac_prop_id_t wldp_pr_num, uint_t wldp_length,
2790dc2366fSVenugopal Iyer 		    void *wldp_buf);
2800dc2366fSVenugopal Iyer static void	rt2661_m_propinfo(void *arg, const char *pr_name,
2810dc2366fSVenugopal Iyer 		    mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t mph);
28210115c80Sfei feng - Sun Microsystems - Beijing China 
28310115c80Sfei feng - Sun Microsystems - Beijing China static mac_callbacks_t rt2661_m_callbacks = {
2840dc2366fSVenugopal Iyer 	MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
28510115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_stat,
28610115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_start,
28710115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_stop,
28810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_promisc,
28910115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_multicst,
29010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_unicst,
29110115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_tx,
2920dc2366fSVenugopal Iyer 	NULL,
29310115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_ioctl,
29410115c80Sfei feng - Sun Microsystems - Beijing China 	NULL,
29510115c80Sfei feng - Sun Microsystems - Beijing China 	NULL,
29610115c80Sfei feng - Sun Microsystems - Beijing China 	NULL,
29710115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_m_setprop,
2980dc2366fSVenugopal Iyer 	rt2661_m_getprop,
2990dc2366fSVenugopal Iyer 	rt2661_m_propinfo
30010115c80Sfei feng - Sun Microsystems - Beijing China };
30110115c80Sfei feng - Sun Microsystems - Beijing China 
30210115c80Sfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
30310115c80Sfei feng - Sun Microsystems - Beijing China void
rt2661_debug(uint32_t dbg_flags,const int8_t * fmt,...)30410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_debug(uint32_t dbg_flags, const int8_t *fmt, ...)
30510115c80Sfei feng - Sun Microsystems - Beijing China {
30610115c80Sfei feng - Sun Microsystems - Beijing China 	va_list args;
30710115c80Sfei feng - Sun Microsystems - Beijing China 
30810115c80Sfei feng - Sun Microsystems - Beijing China 	if (dbg_flags & rt2661_dbg_flags) {
30910115c80Sfei feng - Sun Microsystems - Beijing China 		va_start(args, fmt);
31010115c80Sfei feng - Sun Microsystems - Beijing China 		vcmn_err(CE_CONT, fmt, args);
31110115c80Sfei feng - Sun Microsystems - Beijing China 		va_end(args);
31210115c80Sfei feng - Sun Microsystems - Beijing China 	}
31310115c80Sfei feng - Sun Microsystems - Beijing China }
31410115c80Sfei feng - Sun Microsystems - Beijing China #endif
31510115c80Sfei feng - Sun Microsystems - Beijing China 
31610115c80Sfei feng - Sun Microsystems - Beijing China /*
31710115c80Sfei feng - Sun Microsystems - Beijing China  * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
31810115c80Sfei feng - Sun Microsystems - Beijing China  * 93C66).
31910115c80Sfei feng - Sun Microsystems - Beijing China  */
32010115c80Sfei feng - Sun Microsystems - Beijing China static uint16_t
rt2661_eeprom_read(struct rt2661_softc * sc,uint8_t addr)32110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
32210115c80Sfei feng - Sun Microsystems - Beijing China {
32310115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
32410115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t val;
32510115c80Sfei feng - Sun Microsystems - Beijing China 	int n;
32610115c80Sfei feng - Sun Microsystems - Beijing China 
32710115c80Sfei feng - Sun Microsystems - Beijing China 	/* clock C once before the first command */
32810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, 0);
32910115c80Sfei feng - Sun Microsystems - Beijing China 
33010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S);
33110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
33210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S);
33310115c80Sfei feng - Sun Microsystems - Beijing China 
33410115c80Sfei feng - Sun Microsystems - Beijing China 	/* write start bit (1) */
33510115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
33610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
33710115c80Sfei feng - Sun Microsystems - Beijing China 
33810115c80Sfei feng - Sun Microsystems - Beijing China 	/* write READ opcode (10) */
33910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
34010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
34110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S);
34210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
34310115c80Sfei feng - Sun Microsystems - Beijing China 
34410115c80Sfei feng - Sun Microsystems - Beijing China 	/* write address (A5-A0 or A7-A0) */
34510115c80Sfei feng - Sun Microsystems - Beijing China 	n = (RT2661_READ(sc, RT2661_E2PROM_CSR) & RT2661_93C46) ? 5 : 7;
34610115c80Sfei feng - Sun Microsystems - Beijing China 	for (; n >= 0; n--) {
34710115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_EEPROM_CTL(sc, RT2661_S |
34810115c80Sfei feng - Sun Microsystems - Beijing China 		    (((addr >> n) & 1) << RT2661_SHIFT_D));
34910115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_EEPROM_CTL(sc, RT2661_S |
35010115c80Sfei feng - Sun Microsystems - Beijing China 		    (((addr >> n) & 1) << RT2661_SHIFT_D) | RT2661_C);
35110115c80Sfei feng - Sun Microsystems - Beijing China 	}
35210115c80Sfei feng - Sun Microsystems - Beijing China 
35310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S);
35410115c80Sfei feng - Sun Microsystems - Beijing China 
35510115c80Sfei feng - Sun Microsystems - Beijing China 	/* read data Q15-Q0 */
35610115c80Sfei feng - Sun Microsystems - Beijing China 	val = 0;
35710115c80Sfei feng - Sun Microsystems - Beijing China 	for (n = 15; n >= 0; n--) {
35810115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
35910115c80Sfei feng - Sun Microsystems - Beijing China 		tmp = RT2661_READ(sc, RT2661_E2PROM_CSR);
36010115c80Sfei feng - Sun Microsystems - Beijing China 		val |= ((tmp & RT2661_Q) >> RT2661_SHIFT_Q) << n;
36110115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_EEPROM_CTL(sc, RT2661_S);
36210115c80Sfei feng - Sun Microsystems - Beijing China 	}
36310115c80Sfei feng - Sun Microsystems - Beijing China 
36410115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, 0);
36510115c80Sfei feng - Sun Microsystems - Beijing China 
36610115c80Sfei feng - Sun Microsystems - Beijing China 	/* clear Chip Select and clock C */
36710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_S);
36810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, 0);
36910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_EEPROM_CTL(sc, RT2661_C);
37010115c80Sfei feng - Sun Microsystems - Beijing China 
37110115c80Sfei feng - Sun Microsystems - Beijing China 	return (val);
37210115c80Sfei feng - Sun Microsystems - Beijing China }
37310115c80Sfei feng - Sun Microsystems - Beijing China 
37410115c80Sfei feng - Sun Microsystems - Beijing China 
37510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_read_eeprom(struct rt2661_softc * sc)37610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_read_eeprom(struct rt2661_softc *sc)
37710115c80Sfei feng - Sun Microsystems - Beijing China {
37810115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
37910115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t val;
38010115c80Sfei feng - Sun Microsystems - Beijing China 	int i;
38110115c80Sfei feng - Sun Microsystems - Beijing China 
38210115c80Sfei feng - Sun Microsystems - Beijing China 	/* read MAC address */
38310115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01);
38410115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_macaddr[0] = val & 0xff;
38510115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_macaddr[1] = val >> 8;
38610115c80Sfei feng - Sun Microsystems - Beijing China 
38710115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC23);
38810115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_macaddr[2] = val & 0xff;
38910115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_macaddr[3] = val >> 8;
39010115c80Sfei feng - Sun Microsystems - Beijing China 
39110115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC45);
39210115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_macaddr[4] = val & 0xff;
39310115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_macaddr[5] = val >> 8;
39410115c80Sfei feng - Sun Microsystems - Beijing China 
39510115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_ANTENNA);
39610115c80Sfei feng - Sun Microsystems - Beijing China 	/* XXX: test if different from 0xffff? */
39710115c80Sfei feng - Sun Microsystems - Beijing China 	sc->rf_rev   = (val >> 11) & 0x1f;
39810115c80Sfei feng - Sun Microsystems - Beijing China 	sc->hw_radio = (val >> 10) & 0x1;
39910115c80Sfei feng - Sun Microsystems - Beijing China 	sc->rx_ant   = (val >> 4)  & 0x3;
40010115c80Sfei feng - Sun Microsystems - Beijing China 	sc->tx_ant   = (val >> 2)  & 0x3;
40110115c80Sfei feng - Sun Microsystems - Beijing China 	sc->nb_ant   = val & 0x3;
40210115c80Sfei feng - Sun Microsystems - Beijing China 
40310115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
40410115c80Sfei feng - Sun Microsystems - Beijing China 	    "RF revision=%d\n", sc->rf_rev);
40510115c80Sfei feng - Sun Microsystems - Beijing China 
40610115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_CONFIG2);
40710115c80Sfei feng - Sun Microsystems - Beijing China 	sc->ext_5ghz_lna = (val >> 6) & 0x1;
40810115c80Sfei feng - Sun Microsystems - Beijing China 	sc->ext_2ghz_lna = (val >> 4) & 0x1;
40910115c80Sfei feng - Sun Microsystems - Beijing China 
41010115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
41110115c80Sfei feng - Sun Microsystems - Beijing China 	    "External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n",
41210115c80Sfei feng - Sun Microsystems - Beijing China 	    sc->ext_2ghz_lna, sc->ext_5ghz_lna);
41310115c80Sfei feng - Sun Microsystems - Beijing China 
41410115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_2GHZ_OFFSET);
41510115c80Sfei feng - Sun Microsystems - Beijing China 	if ((val & 0xff) != 0xff)
41610115c80Sfei feng - Sun Microsystems - Beijing China 		sc->rssi_2ghz_corr = (int8_t)(val & 0xff);
41710115c80Sfei feng - Sun Microsystems - Beijing China 
41810115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_5GHZ_OFFSET);
41910115c80Sfei feng - Sun Microsystems - Beijing China 	if ((val & 0xff) != 0xff)
42010115c80Sfei feng - Sun Microsystems - Beijing China 		sc->rssi_5ghz_corr = (int8_t)(val & 0xff);
42110115c80Sfei feng - Sun Microsystems - Beijing China 
42210115c80Sfei feng - Sun Microsystems - Beijing China 	/* adjust RSSI correction for external low-noise amplifier */
42310115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->ext_2ghz_lna)
42410115c80Sfei feng - Sun Microsystems - Beijing China 		sc->rssi_2ghz_corr -= 14;
42510115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->ext_5ghz_lna)
42610115c80Sfei feng - Sun Microsystems - Beijing China 		sc->rssi_5ghz_corr -= 14;
42710115c80Sfei feng - Sun Microsystems - Beijing China 
42810115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
42910115c80Sfei feng - Sun Microsystems - Beijing China 	    "RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n",
43010115c80Sfei feng - Sun Microsystems - Beijing China 	    sc->rssi_2ghz_corr, sc->rssi_5ghz_corr);
43110115c80Sfei feng - Sun Microsystems - Beijing China 
43210115c80Sfei feng - Sun Microsystems - Beijing China 	val = rt2661_eeprom_read(sc, RT2661_EEPROM_FREQ_OFFSET);
43310115c80Sfei feng - Sun Microsystems - Beijing China 	if ((val >> 8) != 0xff)
43410115c80Sfei feng - Sun Microsystems - Beijing China 		sc->rfprog = (val >> 8) & 0x3;
43510115c80Sfei feng - Sun Microsystems - Beijing China 	if ((val & 0xff) != 0xff)
43610115c80Sfei feng - Sun Microsystems - Beijing China 		sc->rffreq = val & 0xff;
43710115c80Sfei feng - Sun Microsystems - Beijing China 
43810115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
43910115c80Sfei feng - Sun Microsystems - Beijing China 	    "RF prog=%d\nRF freq=%d\n", sc->rfprog, sc->rffreq);
44010115c80Sfei feng - Sun Microsystems - Beijing China 
44110115c80Sfei feng - Sun Microsystems - Beijing China 	/* read Tx power for all a/b/g channels */
44210115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 19; i++) {
44310115c80Sfei feng - Sun Microsystems - Beijing China 		val = rt2661_eeprom_read(sc, RT2661_EEPROM_TXPOWER + i);
44410115c80Sfei feng - Sun Microsystems - Beijing China 		sc->txpow[i * 2] = (int8_t)(val >> 8);
44510115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
44610115c80Sfei feng - Sun Microsystems - Beijing China 		    "Channel=%d Tx power=%d\n",
44710115c80Sfei feng - Sun Microsystems - Beijing China 		    rt2661_rf5225_1[i * 2].chan, sc->txpow[i * 2]);
44810115c80Sfei feng - Sun Microsystems - Beijing China 		sc->txpow[i * 2 + 1] = (int8_t)(val & 0xff);
44910115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
45010115c80Sfei feng - Sun Microsystems - Beijing China 		    "Channel=%d Tx power=%d\n",
45110115c80Sfei feng - Sun Microsystems - Beijing China 		    rt2661_rf5225_1[i * 2 + 1].chan, sc->txpow[i * 2 + 1]);
45210115c80Sfei feng - Sun Microsystems - Beijing China 	}
45310115c80Sfei feng - Sun Microsystems - Beijing China 
45410115c80Sfei feng - Sun Microsystems - Beijing China 	/* read vendor-specific BBP values */
45510115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 16; i++) {
45610115c80Sfei feng - Sun Microsystems - Beijing China 		val = rt2661_eeprom_read(sc, RT2661_EEPROM_BBP_BASE + i);
45710115c80Sfei feng - Sun Microsystems - Beijing China 		if (val == 0 || val == 0xffff)
45810115c80Sfei feng - Sun Microsystems - Beijing China 			continue;
45910115c80Sfei feng - Sun Microsystems - Beijing China 		sc->bbp_prom[i].reg = val >> 8;
46010115c80Sfei feng - Sun Microsystems - Beijing China 		sc->bbp_prom[i].val = val & 0xff;
46110115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_read_eeprom(): "
46210115c80Sfei feng - Sun Microsystems - Beijing China 		    "BBP R%d=%02x\n", sc->bbp_prom[i].reg,
46310115c80Sfei feng - Sun Microsystems - Beijing China 		    sc->bbp_prom[i].val);
46410115c80Sfei feng - Sun Microsystems - Beijing China 	}
46510115c80Sfei feng - Sun Microsystems - Beijing China }
46610115c80Sfei feng - Sun Microsystems - Beijing China 
46710115c80Sfei feng - Sun Microsystems - Beijing China static const char *
rt2661_get_rf(int rev)46810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_get_rf(int rev)
46910115c80Sfei feng - Sun Microsystems - Beijing China {
47010115c80Sfei feng - Sun Microsystems - Beijing China 	switch (rev) {
47110115c80Sfei feng - Sun Microsystems - Beijing China 	case RT2661_RF_5225:	return "RT5225";
47210115c80Sfei feng - Sun Microsystems - Beijing China 	case RT2661_RF_5325:	return "RT5325 (MIMO XR)";
47310115c80Sfei feng - Sun Microsystems - Beijing China 	case RT2661_RF_2527:	return "RT2527";
47410115c80Sfei feng - Sun Microsystems - Beijing China 	case RT2661_RF_2529:	return "RT2529 (MIMO XR)";
47510115c80Sfei feng - Sun Microsystems - Beijing China 	default:		return "unknown";
47610115c80Sfei feng - Sun Microsystems - Beijing China 	}
47710115c80Sfei feng - Sun Microsystems - Beijing China }
47810115c80Sfei feng - Sun Microsystems - Beijing China 
47910115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_load_microcode(struct rt2661_softc * sc,const uint8_t * ucode_p,int size)48010115c80Sfei feng - Sun Microsystems - Beijing China rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode_p, int size)
48110115c80Sfei feng - Sun Microsystems - Beijing China {
48210115c80Sfei feng - Sun Microsystems - Beijing China 	int ntries;
48310115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t off, i;
48410115c80Sfei feng - Sun Microsystems - Beijing China 	const uint8_t *fptr;
48510115c80Sfei feng - Sun Microsystems - Beijing China 
48610115c80Sfei feng - Sun Microsystems - Beijing China 	fptr = ucode_p;
48710115c80Sfei feng - Sun Microsystems - Beijing China 	off = RT2661_MCU_CODE_BASE;
48810115c80Sfei feng - Sun Microsystems - Beijing China 
48910115c80Sfei feng - Sun Microsystems - Beijing China 	/* reset 8051 */
49010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
49110115c80Sfei feng - Sun Microsystems - Beijing China 
49210115c80Sfei feng - Sun Microsystems - Beijing China 	/* cancel any pending Host to MCU command */
49310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_H2M_MAILBOX_CSR, 0);
49410115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
49510115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_HOST_CMD_CSR, 0);
49610115c80Sfei feng - Sun Microsystems - Beijing China 
49710115c80Sfei feng - Sun Microsystems - Beijing China 	/* write 8051's microcode */
49810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR,
49910115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_MCU_RESET | RT2661_MCU_SEL);
50010115c80Sfei feng - Sun Microsystems - Beijing China 	/* RT2661_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, ucode, size); */
50110115c80Sfei feng - Sun Microsystems - Beijing China 
50210115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < size; i++) {
50310115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_MEM_WRITE1(sc, off++, *fptr++);
50410115c80Sfei feng - Sun Microsystems - Beijing China 	}
50510115c80Sfei feng - Sun Microsystems - Beijing China 
50610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
50710115c80Sfei feng - Sun Microsystems - Beijing China 
50810115c80Sfei feng - Sun Microsystems - Beijing China 	/* kick 8051's ass */
50910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_CNTL_CSR, 0);
51010115c80Sfei feng - Sun Microsystems - Beijing China 
51110115c80Sfei feng - Sun Microsystems - Beijing China 	/* wait for 8051 to initialize */
51210115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 500; ntries++) {
51310115c80Sfei feng - Sun Microsystems - Beijing China 		if (RT2661_READ(sc, RT2661_MCU_CNTL_CSR) & RT2661_MCU_READY)
51410115c80Sfei feng - Sun Microsystems - Beijing China 			break;
51510115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(100);
51610115c80Sfei feng - Sun Microsystems - Beijing China 	}
51710115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 500) {
51810115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_load_microcode(): "
51910115c80Sfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for MCU to initialize\n");
52010115c80Sfei feng - Sun Microsystems - Beijing China 		return (RT2661_FAILURE);
52110115c80Sfei feng - Sun Microsystems - Beijing China 	}
52210115c80Sfei feng - Sun Microsystems - Beijing China 
52310115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_load_microcode(): "
52410115c80Sfei feng - Sun Microsystems - Beijing China 	    "MCU initialized successfully\n");
52510115c80Sfei feng - Sun Microsystems - Beijing China 	return (RT2661_SUCCESS);
52610115c80Sfei feng - Sun Microsystems - Beijing China }
52710115c80Sfei feng - Sun Microsystems - Beijing China 
52810115c80Sfei feng - Sun Microsystems - Beijing China /*
52910115c80Sfei feng - Sun Microsystems - Beijing China  * Allocate an DMA memory and a DMA handle for accessing it
53010115c80Sfei feng - Sun Microsystems - Beijing China  */
53110115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_alloc_dma_mem(dev_info_t * devinfo,ddi_dma_attr_t * dma_attr,size_t memsize,ddi_device_acc_attr_t * attr_p,uint_t alloc_flags,uint_t bind_flags,struct dma_area * dma_p)53210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr,
53310115c80Sfei feng - Sun Microsystems - Beijing China 	size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
53410115c80Sfei feng - Sun Microsystems - Beijing China 	uint_t bind_flags, struct dma_area *dma_p)
53510115c80Sfei feng - Sun Microsystems - Beijing China {
53610115c80Sfei feng - Sun Microsystems - Beijing China 	int err;
53710115c80Sfei feng - Sun Microsystems - Beijing China 
53810115c80Sfei feng - Sun Microsystems - Beijing China 	/*
53910115c80Sfei feng - Sun Microsystems - Beijing China 	 * Allocate handle
54010115c80Sfei feng - Sun Microsystems - Beijing China 	 */
54110115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_dma_alloc_handle(devinfo, dma_attr,
54210115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
54310115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
54410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_allo_dma_mem(): "
54510115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc handle\n");
54610115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
54710115c80Sfei feng - Sun Microsystems - Beijing China 	}
54810115c80Sfei feng - Sun Microsystems - Beijing China 
54910115c80Sfei feng - Sun Microsystems - Beijing China 	/*
55010115c80Sfei feng - Sun Microsystems - Beijing China 	 * Allocate memory
55110115c80Sfei feng - Sun Microsystems - Beijing China 	 */
55210115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
55310115c80Sfei feng - Sun Microsystems - Beijing China 	    alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
55410115c80Sfei feng - Sun Microsystems - Beijing China 	    &dma_p->alength, &dma_p->acc_hdl);
55510115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
55610115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_alloc_dma_mem(): "
55710115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc mem\n");
55810115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
55910115c80Sfei feng - Sun Microsystems - Beijing China 	}
56010115c80Sfei feng - Sun Microsystems - Beijing China 
56110115c80Sfei feng - Sun Microsystems - Beijing China 	/*
56210115c80Sfei feng - Sun Microsystems - Beijing China 	 * Bind the two together
56310115c80Sfei feng - Sun Microsystems - Beijing China 	 */
56410115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
56510115c80Sfei feng - Sun Microsystems - Beijing China 	    dma_p->mem_va, dma_p->alength, bind_flags,
56610115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
56710115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_DMA_MAPPED) {
56810115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_alloc_dma_mem(): "
56910115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to bind handle\n");
57010115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail3;
57110115c80Sfei feng - Sun Microsystems - Beijing China 	}
57210115c80Sfei feng - Sun Microsystems - Beijing China 
57310115c80Sfei feng - Sun Microsystems - Beijing China 	if (dma_p->ncookies != 1) {
57410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rwd_alloc_dma_mem(): "
57510115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc cookies\n");
57610115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail4;
57710115c80Sfei feng - Sun Microsystems - Beijing China 	}
57810115c80Sfei feng - Sun Microsystems - Beijing China 
57910115c80Sfei feng - Sun Microsystems - Beijing China 	dma_p->nslots = ~0U;
58010115c80Sfei feng - Sun Microsystems - Beijing China 	dma_p->size = ~0U;
58110115c80Sfei feng - Sun Microsystems - Beijing China 	dma_p->token = ~0U;
58210115c80Sfei feng - Sun Microsystems - Beijing China 	dma_p->offset = 0;
58310115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
58410115c80Sfei feng - Sun Microsystems - Beijing China 
58510115c80Sfei feng - Sun Microsystems - Beijing China fail4:
58610115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
58710115c80Sfei feng - Sun Microsystems - Beijing China fail3:
58810115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_dma_mem_free(&dma_p->acc_hdl);
58910115c80Sfei feng - Sun Microsystems - Beijing China fail2:
59010115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_dma_free_handle(&dma_p->dma_hdl);
59110115c80Sfei feng - Sun Microsystems - Beijing China fail1:
59210115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
59310115c80Sfei feng - Sun Microsystems - Beijing China }
59410115c80Sfei feng - Sun Microsystems - Beijing China 
59510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_free_dma_mem(struct dma_area * dma_p)59610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_free_dma_mem(struct dma_area *dma_p)
59710115c80Sfei feng - Sun Microsystems - Beijing China {
59810115c80Sfei feng - Sun Microsystems - Beijing China 	if (dma_p->dma_hdl != NULL) {
59910115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_unbind_handle(dma_p->dma_hdl);
60010115c80Sfei feng - Sun Microsystems - Beijing China 		if (dma_p->acc_hdl != NULL) {
60110115c80Sfei feng - Sun Microsystems - Beijing China 			ddi_dma_mem_free(&dma_p->acc_hdl);
60210115c80Sfei feng - Sun Microsystems - Beijing China 			dma_p->acc_hdl = NULL;
60310115c80Sfei feng - Sun Microsystems - Beijing China 		}
60410115c80Sfei feng - Sun Microsystems - Beijing China 		ddi_dma_free_handle(&dma_p->dma_hdl);
60510115c80Sfei feng - Sun Microsystems - Beijing China 		dma_p->ncookies = 0;
60610115c80Sfei feng - Sun Microsystems - Beijing China 		dma_p->dma_hdl = NULL;
60710115c80Sfei feng - Sun Microsystems - Beijing China 	}
60810115c80Sfei feng - Sun Microsystems - Beijing China }
60910115c80Sfei feng - Sun Microsystems - Beijing China 
61010115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
61110115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_alloc_tx_ring(struct rt2661_softc * sc,struct rt2661_tx_ring * ring,int count)61210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_alloc_tx_ring(struct rt2661_softc *sc,
61310115c80Sfei feng - Sun Microsystems - Beijing China     struct rt2661_tx_ring *ring, int count)
61410115c80Sfei feng - Sun Microsystems - Beijing China {
61510115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_desc *desc;
61610115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
61710115c80Sfei feng - Sun Microsystems - Beijing China 	int i, err, size, len;
61810115c80Sfei feng - Sun Microsystems - Beijing China 
61910115c80Sfei feng - Sun Microsystems - Beijing China 	size = count * RT2661_TX_DESC_SIZE;
62010115c80Sfei feng - Sun Microsystems - Beijing China 	len = count * sizeof (struct rt2661_tx_data);
62110115c80Sfei feng - Sun Microsystems - Beijing China 
62210115c80Sfei feng - Sun Microsystems - Beijing China 	ring->count = count;
62310115c80Sfei feng - Sun Microsystems - Beijing China 	ring->queued = 0;
62410115c80Sfei feng - Sun Microsystems - Beijing China 	ring->cur = 0;
62510115c80Sfei feng - Sun Microsystems - Beijing China 	ring->next = 0;
62610115c80Sfei feng - Sun Microsystems - Beijing China 	ring->stat = 0;
62710115c80Sfei feng - Sun Microsystems - Beijing China 
62810115c80Sfei feng - Sun Microsystems - Beijing China 	err = rt2661_alloc_dma_mem(sc->sc_dev, &rt2661_dma_attr, size,
62910115c80Sfei feng - Sun Microsystems - Beijing China 	    &rt2661_desc_accattr, DDI_DMA_CONSISTENT,
63010115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
63110115c80Sfei feng - Sun Microsystems - Beijing China 	    &ring->txdesc_dma);
63210115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
63310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_alloc_tx_ring(): "
63410115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc dma mem\n");
63510115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
63610115c80Sfei feng - Sun Microsystems - Beijing China 	}
63710115c80Sfei feng - Sun Microsystems - Beijing China 
63810115c80Sfei feng - Sun Microsystems - Beijing China 	ring->desc = (struct rt2661_tx_desc *)ring->txdesc_dma.mem_va;
63910115c80Sfei feng - Sun Microsystems - Beijing China 	(void) bzero(ring->desc, size);
64010115c80Sfei feng - Sun Microsystems - Beijing China 	ring->paddr = ring->txdesc_dma.cookie.dmac_address;
64110115c80Sfei feng - Sun Microsystems - Beijing China 
64210115c80Sfei feng - Sun Microsystems - Beijing China 	ring->data = kmem_zalloc(len, KM_NOSLEEP);
64310115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->data == NULL) {
64410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_alloc_tx_ring(): "
64510115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc tx buffer\n");
64610115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
64710115c80Sfei feng - Sun Microsystems - Beijing China 	}
64810115c80Sfei feng - Sun Microsystems - Beijing China 
64910115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < count; i++) {
65010115c80Sfei feng - Sun Microsystems - Beijing China 		desc = &ring->desc[i];
65110115c80Sfei feng - Sun Microsystems - Beijing China 		data = &ring->data[i];
65210115c80Sfei feng - Sun Microsystems - Beijing China 		err = rt2661_alloc_dma_mem(sc->sc_dev,
65310115c80Sfei feng - Sun Microsystems - Beijing China 		    &rt2661_dma_attr, sc->sc_dmabuf_size,
65410115c80Sfei feng - Sun Microsystems - Beijing China 		    &rt2661_buf_accattr, DDI_DMA_CONSISTENT,
65510115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
65610115c80Sfei feng - Sun Microsystems - Beijing China 		    &data->txdata_dma);
65710115c80Sfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
65810115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_DMA,
65910115c80Sfei feng - Sun Microsystems - Beijing China 			    "rwd: rt2661_alloc_tx_ring(): "
66010115c80Sfei feng - Sun Microsystems - Beijing China 			    "failed to alloc tx buffer dma\n");
66110115c80Sfei feng - Sun Microsystems - Beijing China 			while (i >= 0) {
66210115c80Sfei feng - Sun Microsystems - Beijing China 				rt2661_free_dma_mem(&ring->data[i].txdata_dma);
66310115c80Sfei feng - Sun Microsystems - Beijing China 				i--;
66410115c80Sfei feng - Sun Microsystems - Beijing China 			}
66510115c80Sfei feng - Sun Microsystems - Beijing China 			goto fail3;
66610115c80Sfei feng - Sun Microsystems - Beijing China 		}
66710115c80Sfei feng - Sun Microsystems - Beijing China 		desc->addr[0] = data->txdata_dma.cookie.dmac_address;
66810115c80Sfei feng - Sun Microsystems - Beijing China 		data->buf = data->txdata_dma.mem_va;
66910115c80Sfei feng - Sun Microsystems - Beijing China 		data->paddr = data->txdata_dma.cookie.dmac_address;
67010115c80Sfei feng - Sun Microsystems - Beijing China 	}
67110115c80Sfei feng - Sun Microsystems - Beijing China 
67210115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
67310115c80Sfei feng - Sun Microsystems - Beijing China 	    0, size, DDI_DMA_SYNC_FORDEV);
67410115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
67510115c80Sfei feng - Sun Microsystems - Beijing China fail3:
67610115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->data)
67710115c80Sfei feng - Sun Microsystems - Beijing China 		kmem_free(ring->data,
67810115c80Sfei feng - Sun Microsystems - Beijing China 		    count * sizeof (struct rt2661_tx_data));
67910115c80Sfei feng - Sun Microsystems - Beijing China fail2:
68010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_dma_mem(&ring->txdesc_dma);
68110115c80Sfei feng - Sun Microsystems - Beijing China fail1:
68210115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
68310115c80Sfei feng - Sun Microsystems - Beijing China }
68410115c80Sfei feng - Sun Microsystems - Beijing China 
68510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_reset_tx_ring(struct rt2661_softc * sc,struct rt2661_tx_ring * ring)68610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
68710115c80Sfei feng - Sun Microsystems - Beijing China {
68810115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_desc *desc;
68910115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
69010115c80Sfei feng - Sun Microsystems - Beijing China 	int i;
69110115c80Sfei feng - Sun Microsystems - Beijing China 
69210115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < ring->count; i++) {
69310115c80Sfei feng - Sun Microsystems - Beijing China 		desc = &ring->desc[i];
69410115c80Sfei feng - Sun Microsystems - Beijing China 		data = &ring->data[i];
69510115c80Sfei feng - Sun Microsystems - Beijing China 
69610115c80Sfei feng - Sun Microsystems - Beijing China 		if (data->ni != NULL) {
69710115c80Sfei feng - Sun Microsystems - Beijing China 			ieee80211_free_node(data->ni);
69810115c80Sfei feng - Sun Microsystems - Beijing China 			data->ni = NULL;
69910115c80Sfei feng - Sun Microsystems - Beijing China 		}
70010115c80Sfei feng - Sun Microsystems - Beijing China 
70110115c80Sfei feng - Sun Microsystems - Beijing China 		desc->flags = 0;
70210115c80Sfei feng - Sun Microsystems - Beijing China 	}
70310115c80Sfei feng - Sun Microsystems - Beijing China 
70410115c80Sfei feng - Sun Microsystems - Beijing China 	if (!RT2661_IS_FASTREBOOT(sc))
70510115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 0,
70610115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->count * sizeof (struct rt2661_tx_desc),
70710115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORDEV);
70810115c80Sfei feng - Sun Microsystems - Beijing China 
70910115c80Sfei feng - Sun Microsystems - Beijing China 	ring->queued = 0;
71010115c80Sfei feng - Sun Microsystems - Beijing China 	ring->cur = ring->next = ring->stat = 0;
71110115c80Sfei feng - Sun Microsystems - Beijing China }
71210115c80Sfei feng - Sun Microsystems - Beijing China 
71310115c80Sfei feng - Sun Microsystems - Beijing China 
71410115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
71510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_free_tx_ring(struct rt2661_softc * sc,struct rt2661_tx_ring * ring)71610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
71710115c80Sfei feng - Sun Microsystems - Beijing China {
71810115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
71910115c80Sfei feng - Sun Microsystems - Beijing China 	int i;
72010115c80Sfei feng - Sun Microsystems - Beijing China 
72110115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->desc != NULL) {
72210115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_free_dma_mem(&ring->txdesc_dma);
72310115c80Sfei feng - Sun Microsystems - Beijing China 	}
72410115c80Sfei feng - Sun Microsystems - Beijing China 
72510115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->data != NULL) {
72610115c80Sfei feng - Sun Microsystems - Beijing China 		for (i = 0; i < ring->count; i++) {
72710115c80Sfei feng - Sun Microsystems - Beijing China 			data = &ring->data[i];
72810115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_free_dma_mem(&data->txdata_dma);
72910115c80Sfei feng - Sun Microsystems - Beijing China 			if (data->ni != NULL) {
73010115c80Sfei feng - Sun Microsystems - Beijing China 				ieee80211_free_node(data->ni);
73110115c80Sfei feng - Sun Microsystems - Beijing China 				data->ni = NULL;
73210115c80Sfei feng - Sun Microsystems - Beijing China 			}
73310115c80Sfei feng - Sun Microsystems - Beijing China 		}
73410115c80Sfei feng - Sun Microsystems - Beijing China 		kmem_free(ring->data,
73510115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->count * sizeof (struct rt2661_tx_data));
73610115c80Sfei feng - Sun Microsystems - Beijing China 	}
73710115c80Sfei feng - Sun Microsystems - Beijing China }
73810115c80Sfei feng - Sun Microsystems - Beijing China 
73910115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
74010115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_alloc_rx_ring(struct rt2661_softc * sc,struct rt2661_rx_ring * ring,int count)74110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_alloc_rx_ring(struct rt2661_softc *sc,
74210115c80Sfei feng - Sun Microsystems - Beijing China     struct rt2661_rx_ring *ring, int count)
74310115c80Sfei feng - Sun Microsystems - Beijing China {
74410115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_rx_desc *desc;
74510115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_rx_data *data;
74610115c80Sfei feng - Sun Microsystems - Beijing China 	int i, err, len, size;
74710115c80Sfei feng - Sun Microsystems - Beijing China 
74810115c80Sfei feng - Sun Microsystems - Beijing China 	size = count * RT2661_RX_DESC_SIZE;
74910115c80Sfei feng - Sun Microsystems - Beijing China 	len = count * sizeof (struct rt2661_rx_data);
75010115c80Sfei feng - Sun Microsystems - Beijing China 
75110115c80Sfei feng - Sun Microsystems - Beijing China 	ring->count = count;
75210115c80Sfei feng - Sun Microsystems - Beijing China 	ring->cur = 0;
75310115c80Sfei feng - Sun Microsystems - Beijing China 	ring->next = 0;
75410115c80Sfei feng - Sun Microsystems - Beijing China 
75510115c80Sfei feng - Sun Microsystems - Beijing China 	err = rt2661_alloc_dma_mem(sc->sc_dev, &rt2661_dma_attr, size,
75610115c80Sfei feng - Sun Microsystems - Beijing China 	    &rt2661_desc_accattr, DDI_DMA_CONSISTENT,
75710115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
75810115c80Sfei feng - Sun Microsystems - Beijing China 	    &ring->rxdesc_dma);
75910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
76010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_alloc_rx_ring(): "
76110115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc dma mem\n");
76210115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
76310115c80Sfei feng - Sun Microsystems - Beijing China 	}
76410115c80Sfei feng - Sun Microsystems - Beijing China 
76510115c80Sfei feng - Sun Microsystems - Beijing China 	ring->desc = (struct rt2661_rx_desc *)ring->rxdesc_dma.mem_va;
76610115c80Sfei feng - Sun Microsystems - Beijing China 	(void) bzero(ring->desc, size);
76710115c80Sfei feng - Sun Microsystems - Beijing China 	ring->paddr = ring->rxdesc_dma.cookie.dmac_address;
76810115c80Sfei feng - Sun Microsystems - Beijing China 
76910115c80Sfei feng - Sun Microsystems - Beijing China 	ring->data = kmem_zalloc(len, KM_NOSLEEP);
77010115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->data == NULL) {
77110115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_alloc_rx_ring(): "
77210115c80Sfei feng - Sun Microsystems - Beijing China 		    "failed to alloc rx buffer\n");
77310115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
77410115c80Sfei feng - Sun Microsystems - Beijing China 	}
77510115c80Sfei feng - Sun Microsystems - Beijing China 
77610115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < count; i++) {
77710115c80Sfei feng - Sun Microsystems - Beijing China 		desc = &ring->desc[i];
77810115c80Sfei feng - Sun Microsystems - Beijing China 		data = &ring->data[i];
77910115c80Sfei feng - Sun Microsystems - Beijing China 		err = rt2661_alloc_dma_mem(sc->sc_dev,
78010115c80Sfei feng - Sun Microsystems - Beijing China 		    &rt2661_dma_attr, sc->sc_dmabuf_size,
78110115c80Sfei feng - Sun Microsystems - Beijing China 		    &rt2661_buf_accattr, DDI_DMA_CONSISTENT,
78210115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
78310115c80Sfei feng - Sun Microsystems - Beijing China 		    &data->rxdata_dma);
78410115c80Sfei feng - Sun Microsystems - Beijing China 		if (err != DDI_SUCCESS) {
78510115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_DMA,
78610115c80Sfei feng - Sun Microsystems - Beijing China 			    "rwd: rt2661_alloc_rx_ring(): "
78710115c80Sfei feng - Sun Microsystems - Beijing China 			    "failed to alloc rx buffer dma\n");
78810115c80Sfei feng - Sun Microsystems - Beijing China 			while (i >= 0) {
78910115c80Sfei feng - Sun Microsystems - Beijing China 				rt2661_free_dma_mem(&ring->data[i].rxdata_dma);
79010115c80Sfei feng - Sun Microsystems - Beijing China 				i--;
79110115c80Sfei feng - Sun Microsystems - Beijing China 			}
79210115c80Sfei feng - Sun Microsystems - Beijing China 			goto fail3;
79310115c80Sfei feng - Sun Microsystems - Beijing China 		}
79410115c80Sfei feng - Sun Microsystems - Beijing China 		data->buf = data->rxdata_dma.mem_va;
79510115c80Sfei feng - Sun Microsystems - Beijing China 		data->paddr = data->rxdata_dma.cookie.dmac_address;
79610115c80Sfei feng - Sun Microsystems - Beijing China 		desc->flags = LE_32(RT2661_RX_BUSY);
79710115c80Sfei feng - Sun Microsystems - Beijing China 		desc->physaddr = LE_32(data->paddr);
79810115c80Sfei feng - Sun Microsystems - Beijing China 	}
79910115c80Sfei feng - Sun Microsystems - Beijing China 
80010115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl,
80110115c80Sfei feng - Sun Microsystems - Beijing China 	    0, size, DDI_DMA_SYNC_FORDEV);
80210115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
80310115c80Sfei feng - Sun Microsystems - Beijing China fail3:
80410115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->data)
80510115c80Sfei feng - Sun Microsystems - Beijing China 		kmem_free(ring->data,
80610115c80Sfei feng - Sun Microsystems - Beijing China 		    count * sizeof (struct rt2661_rx_data));
80710115c80Sfei feng - Sun Microsystems - Beijing China fail2:
80810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_dma_mem(&ring->rxdesc_dma);
80910115c80Sfei feng - Sun Microsystems - Beijing China fail1:
81010115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
81110115c80Sfei feng - Sun Microsystems - Beijing China }
81210115c80Sfei feng - Sun Microsystems - Beijing China 
81310115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_reset_rx_ring(struct rt2661_softc * sc,struct rt2661_rx_ring * ring)81410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_reset_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
81510115c80Sfei feng - Sun Microsystems - Beijing China {
81610115c80Sfei feng - Sun Microsystems - Beijing China 	int i;
81710115c80Sfei feng - Sun Microsystems - Beijing China 
81810115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < ring->count; i++)
81910115c80Sfei feng - Sun Microsystems - Beijing China 		ring->desc[i].flags = LE_32(RT2661_RX_BUSY);
82010115c80Sfei feng - Sun Microsystems - Beijing China 
82110115c80Sfei feng - Sun Microsystems - Beijing China 	if (!RT2661_IS_FASTREBOOT(sc))
82210115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl, 0,
82310115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->count * sizeof (struct rt2661_rx_ring),
82410115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORKERNEL);
82510115c80Sfei feng - Sun Microsystems - Beijing China 
82610115c80Sfei feng - Sun Microsystems - Beijing China 	ring->cur = ring->next = 0;
82710115c80Sfei feng - Sun Microsystems - Beijing China }
82810115c80Sfei feng - Sun Microsystems - Beijing China 
82910115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
83010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_free_rx_ring(struct rt2661_softc * sc,struct rt2661_rx_ring * ring)83110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
83210115c80Sfei feng - Sun Microsystems - Beijing China {
83310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_rx_data *data;
83410115c80Sfei feng - Sun Microsystems - Beijing China 	int i;
83510115c80Sfei feng - Sun Microsystems - Beijing China 
83610115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->desc != NULL) {
83710115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_free_dma_mem(&ring->rxdesc_dma);
83810115c80Sfei feng - Sun Microsystems - Beijing China 	}
83910115c80Sfei feng - Sun Microsystems - Beijing China 
84010115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->data != NULL) {
84110115c80Sfei feng - Sun Microsystems - Beijing China 		for (i = 0; i < ring->count; i++) {
84210115c80Sfei feng - Sun Microsystems - Beijing China 			data = &ring->data[i];
84310115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_free_dma_mem(&data->rxdata_dma);
84410115c80Sfei feng - Sun Microsystems - Beijing China 		}
84510115c80Sfei feng - Sun Microsystems - Beijing China 		kmem_free(ring->data,
84610115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->count * sizeof (struct rt2661_rx_data));
84710115c80Sfei feng - Sun Microsystems - Beijing China 	}
84810115c80Sfei feng - Sun Microsystems - Beijing China }
84910115c80Sfei feng - Sun Microsystems - Beijing China 
85010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_tx_dma_intr(struct rt2661_softc * sc,struct rt2661_tx_ring * ring)85110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
85210115c80Sfei feng - Sun Microsystems - Beijing China {
85310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_desc *desc;
85410115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
85510115c80Sfei feng - Sun Microsystems - Beijing China 
85610115c80Sfei feng - Sun Microsystems - Beijing China 	for (;;) {
85710115c80Sfei feng - Sun Microsystems - Beijing China 		desc = &ring->desc[ring->next];
85810115c80Sfei feng - Sun Microsystems - Beijing China 		data = &ring->data[ring->next];
85910115c80Sfei feng - Sun Microsystems - Beijing China 
86010115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
86110115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->next * RT2661_TX_DESC_SIZE,
86210115c80Sfei feng - Sun Microsystems - Beijing China 		    RT2661_TX_DESC_SIZE,
86310115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORKERNEL);
86410115c80Sfei feng - Sun Microsystems - Beijing China 
86510115c80Sfei feng - Sun Microsystems - Beijing China 		if ((LE_32(desc->flags) & RT2661_TX_BUSY) ||
86610115c80Sfei feng - Sun Microsystems - Beijing China 		    !(LE_32(desc->flags) & RT2661_TX_VALID))
86710115c80Sfei feng - Sun Microsystems - Beijing China 			break;
86810115c80Sfei feng - Sun Microsystems - Beijing China 
86910115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(data->txdata_dma.dma_hdl,
87010115c80Sfei feng - Sun Microsystems - Beijing China 		    0, sc->sc_dmabuf_size,
87110115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORDEV);
87210115c80Sfei feng - Sun Microsystems - Beijing China 
87310115c80Sfei feng - Sun Microsystems - Beijing China 		/* descriptor is no longer valid */
87410115c80Sfei feng - Sun Microsystems - Beijing China 		desc->flags &= ~LE_32(RT2661_TX_VALID);
87510115c80Sfei feng - Sun Microsystems - Beijing China 
87610115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
87710115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->next * RT2661_TX_DESC_SIZE,
87810115c80Sfei feng - Sun Microsystems - Beijing China 		    RT2661_TX_DESC_SIZE,
87910115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORDEV);
88010115c80Sfei feng - Sun Microsystems - Beijing China 
88110115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_dma_intr(): "
88210115c80Sfei feng - Sun Microsystems - Beijing China 		    "tx dma done q=%p idx=%u\n", ring, ring->next);
88310115c80Sfei feng - Sun Microsystems - Beijing China 
88410115c80Sfei feng - Sun Microsystems - Beijing China 		if (++ring->next >= ring->count) /* faster than % count */
88510115c80Sfei feng - Sun Microsystems - Beijing China 			ring->next = 0;
88610115c80Sfei feng - Sun Microsystems - Beijing China 	}
88710115c80Sfei feng - Sun Microsystems - Beijing China }
88810115c80Sfei feng - Sun Microsystems - Beijing China 
88910115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_tx_intr(struct rt2661_softc * sc)89010115c80Sfei feng - Sun Microsystems - Beijing China rt2661_tx_intr(struct rt2661_softc *sc)
89110115c80Sfei feng - Sun Microsystems - Beijing China {
89210115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
89310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_ring *ring;
89410115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
89510115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_node *rn;
89610115c80Sfei feng - Sun Microsystems - Beijing China 
89710115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t val;
89810115c80Sfei feng - Sun Microsystems - Beijing China 	int qid, retrycnt;
89910115c80Sfei feng - Sun Microsystems - Beijing China 
90010115c80Sfei feng - Sun Microsystems - Beijing China 	for (;;) {
90110115c80Sfei feng - Sun Microsystems - Beijing China 		val = RT2661_READ(sc, RT2661_STA_CSR4);
90210115c80Sfei feng - Sun Microsystems - Beijing China 		if (!(val & RT2661_TX_STAT_VALID))
90310115c80Sfei feng - Sun Microsystems - Beijing China 			break;
90410115c80Sfei feng - Sun Microsystems - Beijing China 
90510115c80Sfei feng - Sun Microsystems - Beijing China 		/* retrieve the queue in which this frame was send */
90610115c80Sfei feng - Sun Microsystems - Beijing China 		qid = RT2661_TX_QID(val);
90710115c80Sfei feng - Sun Microsystems - Beijing China 		ring = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq;
90810115c80Sfei feng - Sun Microsystems - Beijing China 
90910115c80Sfei feng - Sun Microsystems - Beijing China 		/* retrieve rate control algorithm context */
91010115c80Sfei feng - Sun Microsystems - Beijing China 		data = &ring->data[ring->stat];
91110115c80Sfei feng - Sun Microsystems - Beijing China 		rn = (struct rt2661_node *)data->ni;
91210115c80Sfei feng - Sun Microsystems - Beijing China 
91310115c80Sfei feng - Sun Microsystems - Beijing China 		/* if no frame has been sent, ignore */
91410115c80Sfei feng - Sun Microsystems - Beijing China 		if (rn == NULL) {
91510115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
91610115c80Sfei feng - Sun Microsystems - Beijing China 			    "no frame has been send, ignore\n");
91710115c80Sfei feng - Sun Microsystems - Beijing China 			continue;
91810115c80Sfei feng - Sun Microsystems - Beijing China 		}
91910115c80Sfei feng - Sun Microsystems - Beijing China 
92010115c80Sfei feng - Sun Microsystems - Beijing China 		switch (RT2661_TX_RESULT(val)) {
92110115c80Sfei feng - Sun Microsystems - Beijing China 		case RT2661_TX_SUCCESS:
92210115c80Sfei feng - Sun Microsystems - Beijing China 			retrycnt = RT2661_TX_RETRYCNT(val);
92310115c80Sfei feng - Sun Microsystems - Beijing China 
92410115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
92510115c80Sfei feng - Sun Microsystems - Beijing China 			    "data frame sent successfully after "
92610115c80Sfei feng - Sun Microsystems - Beijing China 			    "%d retries\n", retrycnt);
92710115c80Sfei feng - Sun Microsystems - Beijing China 			rn->amn.amn_txcnt++;
92810115c80Sfei feng - Sun Microsystems - Beijing China 			if (retrycnt > 0) {
92910115c80Sfei feng - Sun Microsystems - Beijing China 				rn->amn.amn_retrycnt++;
93010115c80Sfei feng - Sun Microsystems - Beijing China 				sc->sc_tx_retries++;
93110115c80Sfei feng - Sun Microsystems - Beijing China 			}
93210115c80Sfei feng - Sun Microsystems - Beijing China 			break;
93310115c80Sfei feng - Sun Microsystems - Beijing China 		case RT2661_TX_RETRY_FAIL:
93410115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
93510115c80Sfei feng - Sun Microsystems - Beijing China 			    "sending data frame failed (too much retries)\n");
93610115c80Sfei feng - Sun Microsystems - Beijing China 			rn->amn.amn_txcnt++;
93710115c80Sfei feng - Sun Microsystems - Beijing China 			rn->amn.amn_retrycnt++;
93810115c80Sfei feng - Sun Microsystems - Beijing China 			break;
93910115c80Sfei feng - Sun Microsystems - Beijing China 		default:
94010115c80Sfei feng - Sun Microsystems - Beijing China 			/* other failure */
94110115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr():"
94210115c80Sfei feng - Sun Microsystems - Beijing China 			    "sending data frame failed 0x%08x\n", val);
94310115c80Sfei feng - Sun Microsystems - Beijing China 		}
94410115c80Sfei feng - Sun Microsystems - Beijing China 
94510115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_intr(): "
94610115c80Sfei feng - Sun Microsystems - Beijing China 		    "tx done q=%d idx=%u\n", qid, ring->stat);
94710115c80Sfei feng - Sun Microsystems - Beijing China 
94810115c80Sfei feng - Sun Microsystems - Beijing China 		ieee80211_free_node(data->ni);
94910115c80Sfei feng - Sun Microsystems - Beijing China 		data->ni = NULL;
95010115c80Sfei feng - Sun Microsystems - Beijing China 
95110115c80Sfei feng - Sun Microsystems - Beijing China 		ring->queued--;
95210115c80Sfei feng - Sun Microsystems - Beijing China 
95310115c80Sfei feng - Sun Microsystems - Beijing China 		/* faster than % count */
95410115c80Sfei feng - Sun Microsystems - Beijing China 		if (++ring->stat >= ring->count)
95510115c80Sfei feng - Sun Microsystems - Beijing China 			ring->stat = 0;
95610115c80Sfei feng - Sun Microsystems - Beijing China 
95710115c80Sfei feng - Sun Microsystems - Beijing China 		if (sc->sc_need_sched) {
95810115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_need_sched = 0;
95910115c80Sfei feng - Sun Microsystems - Beijing China 			mac_tx_update(ic->ic_mach);
96010115c80Sfei feng - Sun Microsystems - Beijing China 		}
96110115c80Sfei feng - Sun Microsystems - Beijing China 	}
96210115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_tx_timer = 0;
96310115c80Sfei feng - Sun Microsystems - Beijing China }
96410115c80Sfei feng - Sun Microsystems - Beijing China 
96510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_rx_intr(struct rt2661_softc * sc)96610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_rx_intr(struct rt2661_softc *sc)
96710115c80Sfei feng - Sun Microsystems - Beijing China {
96810115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
96910115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_rx_ring *ring;
97010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_rx_desc *desc;
97110115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_rx_data *data;
97210115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
97310115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni;
97410115c80Sfei feng - Sun Microsystems - Beijing China 
97510115c80Sfei feng - Sun Microsystems - Beijing China 	mblk_t *m;
97610115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t *rxbuf;
97710115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t pktlen;
97810115c80Sfei feng - Sun Microsystems - Beijing China 
97910115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_rxlock);
98010115c80Sfei feng - Sun Microsystems - Beijing China 	ring = &sc->rxq;
98110115c80Sfei feng - Sun Microsystems - Beijing China 
98210115c80Sfei feng - Sun Microsystems - Beijing China 	for (;;) {
98310115c80Sfei feng - Sun Microsystems - Beijing China 		int rssi;
98410115c80Sfei feng - Sun Microsystems - Beijing China 
98510115c80Sfei feng - Sun Microsystems - Beijing China 		desc = &ring->desc[ring->cur];
98610115c80Sfei feng - Sun Microsystems - Beijing China 		data = &ring->data[ring->cur];
98710115c80Sfei feng - Sun Microsystems - Beijing China 
98810115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl,
98910115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->cur * RT2661_RX_DESC_SIZE,
99010115c80Sfei feng - Sun Microsystems - Beijing China 		    RT2661_RX_DESC_SIZE,
99110115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORKERNEL);
99210115c80Sfei feng - Sun Microsystems - Beijing China 
99310115c80Sfei feng - Sun Microsystems - Beijing China 
99410115c80Sfei feng - Sun Microsystems - Beijing China 		if (LE_32(desc->flags) & RT2661_RX_BUSY)
99510115c80Sfei feng - Sun Microsystems - Beijing China 			break;
99610115c80Sfei feng - Sun Microsystems - Beijing China 
99710115c80Sfei feng - Sun Microsystems - Beijing China 		if ((LE_32(desc->flags) & RT2661_RX_PHY_ERROR) ||
99810115c80Sfei feng - Sun Microsystems - Beijing China 		    (LE_32(desc->flags) & RT2661_RX_CRC_ERROR)) {
99910115c80Sfei feng - Sun Microsystems - Beijing China 			/*
100010115c80Sfei feng - Sun Microsystems - Beijing China 			 * This should not happen since we did not request
100110115c80Sfei feng - Sun Microsystems - Beijing China 			 * to receive those frames when we filled TXRX_CSR0.
100210115c80Sfei feng - Sun Microsystems - Beijing China 			 */
100310115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_intr(): "
100410115c80Sfei feng - Sun Microsystems - Beijing China 			    "PHY or CRC error flags 0x%08x\n",
100510115c80Sfei feng - Sun Microsystems - Beijing China 			    LE_32(desc->flags));
100610115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_rx_err++;
100710115c80Sfei feng - Sun Microsystems - Beijing China 			goto skip;
100810115c80Sfei feng - Sun Microsystems - Beijing China 		}
100910115c80Sfei feng - Sun Microsystems - Beijing China 
101010115c80Sfei feng - Sun Microsystems - Beijing China 		if ((LE_32(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
101110115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_rx_err++;
101210115c80Sfei feng - Sun Microsystems - Beijing China 			goto skip;
101310115c80Sfei feng - Sun Microsystems - Beijing China 		}
101410115c80Sfei feng - Sun Microsystems - Beijing China 
101510115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(data->rxdata_dma.dma_hdl,
101610115c80Sfei feng - Sun Microsystems - Beijing China 		    0, sc->sc_dmabuf_size,
101710115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORCPU);
101810115c80Sfei feng - Sun Microsystems - Beijing China 
101910115c80Sfei feng - Sun Microsystems - Beijing China 		rxbuf = (uint8_t *)data->rxdata_dma.mem_va;
102010115c80Sfei feng - Sun Microsystems - Beijing China 		desc->physaddr = LE_32(data->rxdata_dma.cookie.dmac_address);
102110115c80Sfei feng - Sun Microsystems - Beijing China 		pktlen = (LE_32(desc->flags) >> 16) & 0xfff;
102210115c80Sfei feng - Sun Microsystems - Beijing China 		if ((pktlen < sizeof (struct ieee80211_frame_min)) ||
102310115c80Sfei feng - Sun Microsystems - Beijing China 		    (pktlen > sc->sc_dmabuf_size)) {
102410115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_intr(): "
102510115c80Sfei feng - Sun Microsystems - Beijing China 			    "bad fram length=%u\n", pktlen);
102610115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_rx_err++;
102710115c80Sfei feng - Sun Microsystems - Beijing China 			goto skip;
102810115c80Sfei feng - Sun Microsystems - Beijing China 		}
102910115c80Sfei feng - Sun Microsystems - Beijing China 
103010115c80Sfei feng - Sun Microsystems - Beijing China 		if ((m = allocb(pktlen, BPRI_MED)) == NULL) {
103110115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_intr(): "
103210115c80Sfei feng - Sun Microsystems - Beijing China 			    "allocate mblk failed.\n");
103310115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_rx_nobuf++;
103410115c80Sfei feng - Sun Microsystems - Beijing China 			goto skip;
103510115c80Sfei feng - Sun Microsystems - Beijing China 		}
103610115c80Sfei feng - Sun Microsystems - Beijing China 
103710115c80Sfei feng - Sun Microsystems - Beijing China 		bcopy(rxbuf, m->b_rptr, pktlen);
103810115c80Sfei feng - Sun Microsystems - Beijing China 		m->b_wptr += pktlen;
103910115c80Sfei feng - Sun Microsystems - Beijing China 
104010115c80Sfei feng - Sun Microsystems - Beijing China 		wh = (struct ieee80211_frame *)m->b_rptr;
104110115c80Sfei feng - Sun Microsystems - Beijing China 		ni = ieee80211_find_rxnode(ic, wh);
104210115c80Sfei feng - Sun Microsystems - Beijing China 
104310115c80Sfei feng - Sun Microsystems - Beijing China 		rssi = rt2661_get_rssi(sc, desc->rssi);
104410115c80Sfei feng - Sun Microsystems - Beijing China 		/* send the frame to the 802.11 layer */
1045c1374a13SSurya Prakki 		(void) ieee80211_input(ic, m, ni, rssi + 95, 0);
104610115c80Sfei feng - Sun Microsystems - Beijing China 
104710115c80Sfei feng - Sun Microsystems - Beijing China 		sc->avg_rssi = (rssi + 7 * sc->avg_rssi) / 8;
104810115c80Sfei feng - Sun Microsystems - Beijing China 
104910115c80Sfei feng - Sun Microsystems - Beijing China 		/* node is no longer needed */
105010115c80Sfei feng - Sun Microsystems - Beijing China 		ieee80211_free_node(ni);
105110115c80Sfei feng - Sun Microsystems - Beijing China skip:
105210115c80Sfei feng - Sun Microsystems - Beijing China 		desc->flags |= LE_32(RT2661_RX_BUSY);
105310115c80Sfei feng - Sun Microsystems - Beijing China 
105410115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_dma_sync(ring->rxdesc_dma.dma_hdl,
105510115c80Sfei feng - Sun Microsystems - Beijing China 		    ring->cur * RT2661_RX_DESC_SIZE,
105610115c80Sfei feng - Sun Microsystems - Beijing China 		    RT2661_RX_DESC_SIZE,
105710115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_DMA_SYNC_FORDEV);
105810115c80Sfei feng - Sun Microsystems - Beijing China 
105910115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_rx_intr(): "
106010115c80Sfei feng - Sun Microsystems - Beijing China 		    "rx intr idx=%u\n", sc->rxq.cur);
106110115c80Sfei feng - Sun Microsystems - Beijing China 		ring->cur = (ring->cur + 1) % RT2661_RX_RING_COUNT;
106210115c80Sfei feng - Sun Microsystems - Beijing China 	}
106310115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_rxlock);
106410115c80Sfei feng - Sun Microsystems - Beijing China }
106510115c80Sfei feng - Sun Microsystems - Beijing China 
106610115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
106710115c80Sfei feng - Sun Microsystems - Beijing China static uint_t
rt2661_softintr(caddr_t data,caddr_t unused)106810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_softintr(caddr_t data, caddr_t unused)
106910115c80Sfei feng - Sun Microsystems - Beijing China {
107010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)data;
107110115c80Sfei feng - Sun Microsystems - Beijing China 
107210115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_rx_pend) {
107310115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_pend = 0;
107410115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_rx_intr(sc);
107510115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_INTR_CLAIMED);
107610115c80Sfei feng - Sun Microsystems - Beijing China 	}
107710115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_INTR_UNCLAIMED);
107810115c80Sfei feng - Sun Microsystems - Beijing China }
107910115c80Sfei feng - Sun Microsystems - Beijing China 
108010115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_tx_cmd(struct rt2661_softc * sc,uint8_t cmd,uint16_t arg)108110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_tx_cmd(struct rt2661_softc *sc, uint8_t cmd, uint16_t arg)
108210115c80Sfei feng - Sun Microsystems - Beijing China {
108310115c80Sfei feng - Sun Microsystems - Beijing China 	if (RT2661_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY)
108410115c80Sfei feng - Sun Microsystems - Beijing China 		return (EIO);	/* there is already a command pending */
108510115c80Sfei feng - Sun Microsystems - Beijing China 
108610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_H2M_MAILBOX_CSR,
108710115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | arg);
108810115c80Sfei feng - Sun Microsystems - Beijing China 
108910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | cmd);
109010115c80Sfei feng - Sun Microsystems - Beijing China 
109110115c80Sfei feng - Sun Microsystems - Beijing China 	return (0);
109210115c80Sfei feng - Sun Microsystems - Beijing China }
109310115c80Sfei feng - Sun Microsystems - Beijing China 
109410115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_mcu_wakeup(struct rt2661_softc * sc)109510115c80Sfei feng - Sun Microsystems - Beijing China rt2661_mcu_wakeup(struct rt2661_softc *sc)
109610115c80Sfei feng - Sun Microsystems - Beijing China {
109710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR11, 5 << 16);
109810115c80Sfei feng - Sun Microsystems - Beijing China 
109910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_SOFT_RESET_CSR, 0x7);
110010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_IO_CNTL_CSR, 0x18);
110110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_PCI_USEC_CSR, 0x20);
110210115c80Sfei feng - Sun Microsystems - Beijing China 
110310115c80Sfei feng - Sun Microsystems - Beijing China 	/* send wakeup command to MCU */
110410115c80Sfei feng - Sun Microsystems - Beijing China 	(void) rt2661_tx_cmd(sc, RT2661_MCU_CMD_WAKEUP, 0);
110510115c80Sfei feng - Sun Microsystems - Beijing China }
110610115c80Sfei feng - Sun Microsystems - Beijing China 
110710115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_mcu_cmd_intr(struct rt2661_softc * sc)110810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_mcu_cmd_intr(struct rt2661_softc *sc)
110910115c80Sfei feng - Sun Microsystems - Beijing China {
111010115c80Sfei feng - Sun Microsystems - Beijing China 	(void) RT2661_READ(sc, RT2661_M2H_CMD_DONE_CSR);
111110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
111210115c80Sfei feng - Sun Microsystems - Beijing China }
111310115c80Sfei feng - Sun Microsystems - Beijing China 
111410115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
111510115c80Sfei feng - Sun Microsystems - Beijing China static uint_t
rt2661_intr(caddr_t arg,caddr_t unused)111610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_intr(caddr_t arg, caddr_t unused)
111710115c80Sfei feng - Sun Microsystems - Beijing China {
111810115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
111910115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t r1, r2;
112010115c80Sfei feng - Sun Microsystems - Beijing China 
112110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
112210115c80Sfei feng - Sun Microsystems - Beijing China 
112310115c80Sfei feng - Sun Microsystems - Beijing China 	if (!RT2661_IS_RUNNING(sc) || RT2661_IS_SUSPEND(sc)) {
112410115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
112510115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_INTR_UNCLAIMED);
112610115c80Sfei feng - Sun Microsystems - Beijing China 	}
112710115c80Sfei feng - Sun Microsystems - Beijing China 
112810115c80Sfei feng - Sun Microsystems - Beijing China 	r1 = RT2661_READ(sc, RT2661_INT_SOURCE_CSR);
112910115c80Sfei feng - Sun Microsystems - Beijing China 	r2 = RT2661_READ(sc, RT2661_MCU_INT_SOURCE_CSR);
113010115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 == 0 && r2 == 0) {
113110115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
113210115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_INTR_UNCLAIMED);	/* not for us */
113310115c80Sfei feng - Sun Microsystems - Beijing China 	}
113410115c80Sfei feng - Sun Microsystems - Beijing China 
113510115c80Sfei feng - Sun Microsystems - Beijing China 	/* disable MAC and MCU interrupts */
113610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
113710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
113810115c80Sfei feng - Sun Microsystems - Beijing China 
113910115c80Sfei feng - Sun Microsystems - Beijing China 	/* acknowledge interrupts */
114010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_INT_SOURCE_CSR, r1);
114110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, r2);
114210115c80Sfei feng - Sun Microsystems - Beijing China 
114310115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_MGT_DONE) {
114410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
114510115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_MGT_DONE\n");
114610115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_tx_dma_intr(sc, &sc->mgtq);
114710115c80Sfei feng - Sun Microsystems - Beijing China 	}
114810115c80Sfei feng - Sun Microsystems - Beijing China 
114910115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_RX_DONE) {
115010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
115110115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_RX_DONE\n");
115210115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rx_pend = 1;
115310115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ddi_intr_trigger_softint(sc->sc_softintr_hdl, NULL);
115410115c80Sfei feng - Sun Microsystems - Beijing China 	}
115510115c80Sfei feng - Sun Microsystems - Beijing China 
115610115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_TX0_DMA_DONE) {
115710115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
115810115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_TX0_DMA_DONE\n");
115910115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_tx_dma_intr(sc, &sc->txq[0]);
116010115c80Sfei feng - Sun Microsystems - Beijing China 	}
116110115c80Sfei feng - Sun Microsystems - Beijing China 
116210115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_TX1_DMA_DONE) {
116310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
116410115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_TX1_DMA_DONE\n");
116510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_tx_dma_intr(sc, &sc->txq[1]);
116610115c80Sfei feng - Sun Microsystems - Beijing China 	}
116710115c80Sfei feng - Sun Microsystems - Beijing China 
116810115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_TX2_DMA_DONE) {
116910115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
117010115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_TX2_DMA_DONE\n");
117110115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_tx_dma_intr(sc, &sc->txq[2]);
117210115c80Sfei feng - Sun Microsystems - Beijing China 	}
117310115c80Sfei feng - Sun Microsystems - Beijing China 
117410115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_TX3_DMA_DONE) {
117510115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
117610115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_TX3_DMA_DONE\n");
117710115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_tx_dma_intr(sc, &sc->txq[3]);
117810115c80Sfei feng - Sun Microsystems - Beijing China 	}
117910115c80Sfei feng - Sun Microsystems - Beijing China 
118010115c80Sfei feng - Sun Microsystems - Beijing China 	if (r1 & RT2661_TX_DONE) {
118110115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
118210115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_TX_DONE\n");
118310115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_tx_intr(sc);
118410115c80Sfei feng - Sun Microsystems - Beijing China 	}
118510115c80Sfei feng - Sun Microsystems - Beijing China 
118610115c80Sfei feng - Sun Microsystems - Beijing China 	if (r2 & RT2661_MCU_CMD_DONE) {
118710115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
118810115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_MCU_CMD_DONE\n");
118910115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_mcu_cmd_intr(sc);
119010115c80Sfei feng - Sun Microsystems - Beijing China 	}
119110115c80Sfei feng - Sun Microsystems - Beijing China 
119210115c80Sfei feng - Sun Microsystems - Beijing China 	if (r2 & RT2661_MCU_WAKEUP) {
119310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_intr(): "
119410115c80Sfei feng - Sun Microsystems - Beijing China 		    "RT2661_MCU_WAKEUP\n");
119510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_mcu_wakeup(sc);
119610115c80Sfei feng - Sun Microsystems - Beijing China 	}
119710115c80Sfei feng - Sun Microsystems - Beijing China 
119810115c80Sfei feng - Sun Microsystems - Beijing China 	/* re-enable MAC and MCU interrupts */
119910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
120010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
120110115c80Sfei feng - Sun Microsystems - Beijing China 
120210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
120310115c80Sfei feng - Sun Microsystems - Beijing China 	return (RT2661_SUCCESS);
120410115c80Sfei feng - Sun Microsystems - Beijing China }
120510115c80Sfei feng - Sun Microsystems - Beijing China 
120610115c80Sfei feng - Sun Microsystems - Beijing China /*
120710115c80Sfei feng - Sun Microsystems - Beijing China  * Retrieve the "Received Signal Strength Indicator" from the raw values
120810115c80Sfei feng - Sun Microsystems - Beijing China  * contained in Rx descriptors.  The computation depends on which band the
120910115c80Sfei feng - Sun Microsystems - Beijing China  * frame was received.  Correction values taken from the reference driver.
121010115c80Sfei feng - Sun Microsystems - Beijing China  */
121110115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_get_rssi(struct rt2661_softc * sc,uint8_t raw)121210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
121310115c80Sfei feng - Sun Microsystems - Beijing China {
121410115c80Sfei feng - Sun Microsystems - Beijing China 	int lna, agc, rssi;
121510115c80Sfei feng - Sun Microsystems - Beijing China 
121610115c80Sfei feng - Sun Microsystems - Beijing China 	lna = (raw >> 5) & 0x3;
121710115c80Sfei feng - Sun Microsystems - Beijing China 	agc = raw & 0x1f;
121810115c80Sfei feng - Sun Microsystems - Beijing China 
121910115c80Sfei feng - Sun Microsystems - Beijing China 	rssi = 2 * agc;
122010115c80Sfei feng - Sun Microsystems - Beijing China 
122110115c80Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)) {
122210115c80Sfei feng - Sun Microsystems - Beijing China 		rssi += sc->rssi_2ghz_corr;
122310115c80Sfei feng - Sun Microsystems - Beijing China 
122410115c80Sfei feng - Sun Microsystems - Beijing China 		if (lna == 1)
122510115c80Sfei feng - Sun Microsystems - Beijing China 			rssi -= 64;
122610115c80Sfei feng - Sun Microsystems - Beijing China 		else if (lna == 2)
122710115c80Sfei feng - Sun Microsystems - Beijing China 			rssi -= 74;
122810115c80Sfei feng - Sun Microsystems - Beijing China 		else if (lna == 3)
122910115c80Sfei feng - Sun Microsystems - Beijing China 			rssi -= 90;
123010115c80Sfei feng - Sun Microsystems - Beijing China 	} else {
123110115c80Sfei feng - Sun Microsystems - Beijing China 		rssi += sc->rssi_5ghz_corr;
123210115c80Sfei feng - Sun Microsystems - Beijing China 
123310115c80Sfei feng - Sun Microsystems - Beijing China 		if (lna == 1)
123410115c80Sfei feng - Sun Microsystems - Beijing China 			rssi -= 64;
123510115c80Sfei feng - Sun Microsystems - Beijing China 		else if (lna == 2)
123610115c80Sfei feng - Sun Microsystems - Beijing China 			rssi -= 86;
123710115c80Sfei feng - Sun Microsystems - Beijing China 		else if (lna == 3)
123810115c80Sfei feng - Sun Microsystems - Beijing China 			rssi -= 100;
123910115c80Sfei feng - Sun Microsystems - Beijing China 	}
124010115c80Sfei feng - Sun Microsystems - Beijing China 	return (rssi);
124110115c80Sfei feng - Sun Microsystems - Beijing China }
124210115c80Sfei feng - Sun Microsystems - Beijing China 
124310115c80Sfei feng - Sun Microsystems - Beijing China /* quickly determine if a given rate is CCK or OFDM */
124410115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
124510115c80Sfei feng - Sun Microsystems - Beijing China 
124610115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_ACK_SIZE	14	/* 10 + 4(FCS) */
124710115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_CTS_SIZE	14	/* 10 + 4(FCS) */
124810115c80Sfei feng - Sun Microsystems - Beijing China 
124910115c80Sfei feng - Sun Microsystems - Beijing China #define	RT2661_SIFS	10	/* us */
125010115c80Sfei feng - Sun Microsystems - Beijing China 
125110115c80Sfei feng - Sun Microsystems - Beijing China /*
125210115c80Sfei feng - Sun Microsystems - Beijing China  * Return the expected ack rate for a frame transmitted at rate `rate'.
125310115c80Sfei feng - Sun Microsystems - Beijing China  * XXX: this should depend on the destination node basic rate set.
125410115c80Sfei feng - Sun Microsystems - Beijing China  */
125510115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_ack_rate(struct ieee80211com * ic,int rate)125610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_ack_rate(struct ieee80211com *ic, int rate)
125710115c80Sfei feng - Sun Microsystems - Beijing China {
125810115c80Sfei feng - Sun Microsystems - Beijing China 	switch (rate) {
125910115c80Sfei feng - Sun Microsystems - Beijing China 	/* CCK rates */
126010115c80Sfei feng - Sun Microsystems - Beijing China 	case 2:
126110115c80Sfei feng - Sun Microsystems - Beijing China 		return (2);
126210115c80Sfei feng - Sun Microsystems - Beijing China 	case 4:
126310115c80Sfei feng - Sun Microsystems - Beijing China 	case 11:
126410115c80Sfei feng - Sun Microsystems - Beijing China 	case 22:
126510115c80Sfei feng - Sun Microsystems - Beijing China 		return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate);
126610115c80Sfei feng - Sun Microsystems - Beijing China 
126710115c80Sfei feng - Sun Microsystems - Beijing China 	/* OFDM rates */
126810115c80Sfei feng - Sun Microsystems - Beijing China 	case 12:
126910115c80Sfei feng - Sun Microsystems - Beijing China 	case 18:
127010115c80Sfei feng - Sun Microsystems - Beijing China 		return (12);
127110115c80Sfei feng - Sun Microsystems - Beijing China 	case 24:
127210115c80Sfei feng - Sun Microsystems - Beijing China 	case 36:
127310115c80Sfei feng - Sun Microsystems - Beijing China 		return (24);
127410115c80Sfei feng - Sun Microsystems - Beijing China 	case 48:
127510115c80Sfei feng - Sun Microsystems - Beijing China 	case 72:
127610115c80Sfei feng - Sun Microsystems - Beijing China 	case 96:
127710115c80Sfei feng - Sun Microsystems - Beijing China 	case 108:
127810115c80Sfei feng - Sun Microsystems - Beijing China 		return (48);
127910115c80Sfei feng - Sun Microsystems - Beijing China 	}
128010115c80Sfei feng - Sun Microsystems - Beijing China 
128110115c80Sfei feng - Sun Microsystems - Beijing China 	/* default to 1Mbps */
128210115c80Sfei feng - Sun Microsystems - Beijing China 	return (2);
128310115c80Sfei feng - Sun Microsystems - Beijing China }
128410115c80Sfei feng - Sun Microsystems - Beijing China 
128510115c80Sfei feng - Sun Microsystems - Beijing China /*
128610115c80Sfei feng - Sun Microsystems - Beijing China  * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
128710115c80Sfei feng - Sun Microsystems - Beijing China  * The function automatically determines the operating mode depending on the
128810115c80Sfei feng - Sun Microsystems - Beijing China  * given rate. `flags' indicates whether short preamble is in use or not.
128910115c80Sfei feng - Sun Microsystems - Beijing China  */
129010115c80Sfei feng - Sun Microsystems - Beijing China static uint16_t
rt2661_txtime(int len,int rate,uint32_t flags)129110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_txtime(int len, int rate, uint32_t flags)
129210115c80Sfei feng - Sun Microsystems - Beijing China {
129310115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t txtime;
129410115c80Sfei feng - Sun Microsystems - Beijing China 
129510115c80Sfei feng - Sun Microsystems - Beijing China 	if (RT2661_RATE_IS_OFDM(rate)) {
129610115c80Sfei feng - Sun Microsystems - Beijing China 		/* IEEE Std 802.11a-1999, pp. 37 */
129710115c80Sfei feng - Sun Microsystems - Beijing China 		txtime = (8 + 4 * len + 3 + rate - 1) / rate;
129810115c80Sfei feng - Sun Microsystems - Beijing China 		txtime = 16 + 4 + 4 * txtime + 6;
129910115c80Sfei feng - Sun Microsystems - Beijing China 	} else {
130010115c80Sfei feng - Sun Microsystems - Beijing China 		/* IEEE Std 802.11b-1999, pp. 28 */
130110115c80Sfei feng - Sun Microsystems - Beijing China 		txtime = (16 * len + rate - 1) / rate;
130210115c80Sfei feng - Sun Microsystems - Beijing China 		if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
130310115c80Sfei feng - Sun Microsystems - Beijing China 			txtime +=  72 + 24;
130410115c80Sfei feng - Sun Microsystems - Beijing China 		else
130510115c80Sfei feng - Sun Microsystems - Beijing China 			txtime += 144 + 48;
130610115c80Sfei feng - Sun Microsystems - Beijing China 	}
130710115c80Sfei feng - Sun Microsystems - Beijing China 
130810115c80Sfei feng - Sun Microsystems - Beijing China 	return (txtime);
130910115c80Sfei feng - Sun Microsystems - Beijing China }
131010115c80Sfei feng - Sun Microsystems - Beijing China 
131110115c80Sfei feng - Sun Microsystems - Beijing China static uint8_t
rt2661_plcp_signal(int rate)131210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_plcp_signal(int rate)
131310115c80Sfei feng - Sun Microsystems - Beijing China {
131410115c80Sfei feng - Sun Microsystems - Beijing China 	switch (rate) {
131510115c80Sfei feng - Sun Microsystems - Beijing China 	/* CCK rates (returned values are device-dependent) */
131610115c80Sfei feng - Sun Microsystems - Beijing China 	case 2:
131710115c80Sfei feng - Sun Microsystems - Beijing China 		return (0x0);
131810115c80Sfei feng - Sun Microsystems - Beijing China 	case 4:
131910115c80Sfei feng - Sun Microsystems - Beijing China 		return (0x1);
132010115c80Sfei feng - Sun Microsystems - Beijing China 	case 11:
132110115c80Sfei feng - Sun Microsystems - Beijing China 		return (0x2);
132210115c80Sfei feng - Sun Microsystems - Beijing China 	case 22:
132310115c80Sfei feng - Sun Microsystems - Beijing China 		return (0x3);
132410115c80Sfei feng - Sun Microsystems - Beijing China 
132510115c80Sfei feng - Sun Microsystems - Beijing China 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
132610115c80Sfei feng - Sun Microsystems - Beijing China 	case 12:
132710115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xb);
132810115c80Sfei feng - Sun Microsystems - Beijing China 	case 18:
132910115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xf);
133010115c80Sfei feng - Sun Microsystems - Beijing China 	case 24:
133110115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xa);
133210115c80Sfei feng - Sun Microsystems - Beijing China 	case 36:
133310115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xe);
133410115c80Sfei feng - Sun Microsystems - Beijing China 	case 48:
133510115c80Sfei feng - Sun Microsystems - Beijing China 		return (0x9);
133610115c80Sfei feng - Sun Microsystems - Beijing China 	case 72:
133710115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xd);
133810115c80Sfei feng - Sun Microsystems - Beijing China 	case 96:
133910115c80Sfei feng - Sun Microsystems - Beijing China 		return (0x8);
134010115c80Sfei feng - Sun Microsystems - Beijing China 	case 108:
134110115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xc);
134210115c80Sfei feng - Sun Microsystems - Beijing China 
134310115c80Sfei feng - Sun Microsystems - Beijing China 	/* unsupported rates (should not get there) */
134410115c80Sfei feng - Sun Microsystems - Beijing China 	default:
134510115c80Sfei feng - Sun Microsystems - Beijing China 		return (0xff);
134610115c80Sfei feng - Sun Microsystems - Beijing China 	}
134710115c80Sfei feng - Sun Microsystems - Beijing China }
134810115c80Sfei feng - Sun Microsystems - Beijing China 
134910115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_setup_tx_desc(struct rt2661_softc * sc,struct rt2661_tx_desc * desc,uint32_t flags,uint16_t xflags,int len,int rate,int ac)135010115c80Sfei feng - Sun Microsystems - Beijing China rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
135110115c80Sfei feng - Sun Microsystems - Beijing China     uint32_t flags, uint16_t xflags, int len, int rate, int ac)
135210115c80Sfei feng - Sun Microsystems - Beijing China {
135310115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
135410115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t plcp_length;
135510115c80Sfei feng - Sun Microsystems - Beijing China 	int remainder;
135610115c80Sfei feng - Sun Microsystems - Beijing China 
135710115c80Sfei feng - Sun Microsystems - Beijing China 	desc->flags = LE_32(flags);
135810115c80Sfei feng - Sun Microsystems - Beijing China 	desc->flags |= LE_32(len << 16);
135910115c80Sfei feng - Sun Microsystems - Beijing China 	desc->flags |= LE_32(RT2661_TX_BUSY | RT2661_TX_VALID);
136010115c80Sfei feng - Sun Microsystems - Beijing China 
136110115c80Sfei feng - Sun Microsystems - Beijing China 	desc->xflags = LE_16(xflags);
136210115c80Sfei feng - Sun Microsystems - Beijing China 	desc->xflags |= LE_16(1 << 13);
136310115c80Sfei feng - Sun Microsystems - Beijing China 
136410115c80Sfei feng - Sun Microsystems - Beijing China 	desc->wme = LE_16(
136510115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_QID(ac) |
136610115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_AIFSN(2) |
136710115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_LOGCWMIN(4) |
136810115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_LOGCWMAX(10));
136910115c80Sfei feng - Sun Microsystems - Beijing China 
137010115c80Sfei feng - Sun Microsystems - Beijing China 	/*
137110115c80Sfei feng - Sun Microsystems - Beijing China 	 * Remember in which queue this frame was sent. This field is driver
137210115c80Sfei feng - Sun Microsystems - Beijing China 	 * private data only. It will be made available by the NIC in STA_CSR4
137310115c80Sfei feng - Sun Microsystems - Beijing China 	 * on Tx interrupts.
137410115c80Sfei feng - Sun Microsystems - Beijing China 	 */
137510115c80Sfei feng - Sun Microsystems - Beijing China 	desc->qid = (uint8_t)ac;
137610115c80Sfei feng - Sun Microsystems - Beijing China 
137710115c80Sfei feng - Sun Microsystems - Beijing China 	/* setup PLCP fields */
137810115c80Sfei feng - Sun Microsystems - Beijing China 	desc->plcp_signal  = rt2661_plcp_signal(rate);
137910115c80Sfei feng - Sun Microsystems - Beijing China 	desc->plcp_service = 4;
138010115c80Sfei feng - Sun Microsystems - Beijing China 
138110115c80Sfei feng - Sun Microsystems - Beijing China 	len += IEEE80211_CRC_LEN;
138210115c80Sfei feng - Sun Microsystems - Beijing China 
138310115c80Sfei feng - Sun Microsystems - Beijing China 	if (RT2661_RATE_IS_OFDM(rate)) {
138410115c80Sfei feng - Sun Microsystems - Beijing China 		desc->flags |= LE_32(RT2661_TX_OFDM);
138510115c80Sfei feng - Sun Microsystems - Beijing China 
138610115c80Sfei feng - Sun Microsystems - Beijing China 		plcp_length = len & 0xfff;
138710115c80Sfei feng - Sun Microsystems - Beijing China 		desc->plcp_length_hi = plcp_length >> 6;
138810115c80Sfei feng - Sun Microsystems - Beijing China 		desc->plcp_length_lo = plcp_length & 0x3f;
138910115c80Sfei feng - Sun Microsystems - Beijing China 	} else {
139010115c80Sfei feng - Sun Microsystems - Beijing China 		plcp_length = (16 * len + rate - 1) / rate;
139110115c80Sfei feng - Sun Microsystems - Beijing China 		if (rate == 22) {
139210115c80Sfei feng - Sun Microsystems - Beijing China 			remainder = (16 * len) % 22;
139310115c80Sfei feng - Sun Microsystems - Beijing China 			if (remainder != 0 && remainder < 7)
139410115c80Sfei feng - Sun Microsystems - Beijing China 				desc->plcp_service |= RT2661_PLCP_LENGEXT;
139510115c80Sfei feng - Sun Microsystems - Beijing China 		}
139610115c80Sfei feng - Sun Microsystems - Beijing China 		desc->plcp_length_hi = plcp_length >> 8;
139710115c80Sfei feng - Sun Microsystems - Beijing China 		desc->plcp_length_lo = plcp_length & 0xff;
139810115c80Sfei feng - Sun Microsystems - Beijing China 
139910115c80Sfei feng - Sun Microsystems - Beijing China 		if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
140010115c80Sfei feng - Sun Microsystems - Beijing China 			desc->plcp_signal |= 0x08;
140110115c80Sfei feng - Sun Microsystems - Beijing China 	}
140210115c80Sfei feng - Sun Microsystems - Beijing China 
140310115c80Sfei feng - Sun Microsystems - Beijing China 	/* RT2x61 supports scatter with up to 5 segments */
140410115c80Sfei feng - Sun Microsystems - Beijing China 	desc->len [0] = LE_16(len);
140510115c80Sfei feng - Sun Microsystems - Beijing China }
140610115c80Sfei feng - Sun Microsystems - Beijing China 
140710115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_send(ieee80211com_t * ic,mblk_t * mp)140810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_send(ieee80211com_t *ic, mblk_t *mp)
140910115c80Sfei feng - Sun Microsystems - Beijing China {
141010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)ic;
141110115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_ring *ring;
141210115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_desc *desc;
141310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
141410115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
141510115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni;
141610115c80Sfei feng - Sun Microsystems - Beijing China 
141710115c80Sfei feng - Sun Microsystems - Beijing China 	int err, off, rate;
141810115c80Sfei feng - Sun Microsystems - Beijing China 	int mblen, pktlen;
141910115c80Sfei feng - Sun Microsystems - Beijing China 	mblk_t *m, *m0;
142010115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t dur;
142110115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t flags = 0;
142210115c80Sfei feng - Sun Microsystems - Beijing China 
142310115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_enter(&sc->sc_txlock);
142410115c80Sfei feng - Sun Microsystems - Beijing China 	ring = &sc->txq[0];
142510115c80Sfei feng - Sun Microsystems - Beijing China 	err = DDI_SUCCESS;
142610115c80Sfei feng - Sun Microsystems - Beijing China 
142710115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->queued > RT2661_TX_RING_COUNT - 8) {
142810115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_need_sched = 1;
142910115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_nobuf++;
143010115c80Sfei feng - Sun Microsystems - Beijing China 		err = ENOMEM;
143110115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
143210115c80Sfei feng - Sun Microsystems - Beijing China 	}
143310115c80Sfei feng - Sun Microsystems - Beijing China 
143410115c80Sfei feng - Sun Microsystems - Beijing China 	m = allocb(msgdsize(mp) + 32, BPRI_MED);
143510115c80Sfei feng - Sun Microsystems - Beijing China 	if (m == NULL) {
143610115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_send():"
143710115c80Sfei feng - Sun Microsystems - Beijing China 		    "can't alloc mblk.\n");
143810115c80Sfei feng - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
143910115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
144010115c80Sfei feng - Sun Microsystems - Beijing China 	}
144110115c80Sfei feng - Sun Microsystems - Beijing China 
144210115c80Sfei feng - Sun Microsystems - Beijing China 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
144310115c80Sfei feng - Sun Microsystems - Beijing China 		mblen = MBLKL(m0);
144410115c80Sfei feng - Sun Microsystems - Beijing China 		(void) bcopy(m0->b_rptr, m->b_rptr + off, mblen);
144510115c80Sfei feng - Sun Microsystems - Beijing China 		off += mblen;
144610115c80Sfei feng - Sun Microsystems - Beijing China 	}
144710115c80Sfei feng - Sun Microsystems - Beijing China 	m->b_wptr += off;
144810115c80Sfei feng - Sun Microsystems - Beijing China 
144910115c80Sfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
145010115c80Sfei feng - Sun Microsystems - Beijing China 	ni = ieee80211_find_txnode(ic, wh->i_addr1);
145110115c80Sfei feng - Sun Microsystems - Beijing China 	if (ni == NULL) {
145210115c80Sfei feng - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
145310115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_err++;
145410115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
145510115c80Sfei feng - Sun Microsystems - Beijing China 	}
145610115c80Sfei feng - Sun Microsystems - Beijing China 
145710115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ieee80211_encap(ic, m, ni);
145810115c80Sfei feng - Sun Microsystems - Beijing China 
145910115c80Sfei feng - Sun Microsystems - Beijing China 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
146010115c80Sfei feng - Sun Microsystems - Beijing China 		struct ieee80211_key *k;
146110115c80Sfei feng - Sun Microsystems - Beijing China 		k = ieee80211_crypto_encap(ic, m);
146210115c80Sfei feng - Sun Microsystems - Beijing China 		if (k == NULL) {
146310115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_tx_err++;
146410115c80Sfei feng - Sun Microsystems - Beijing China 			err = DDI_FAILURE;
146510115c80Sfei feng - Sun Microsystems - Beijing China 			goto fail3;
146610115c80Sfei feng - Sun Microsystems - Beijing China 		}
146710115c80Sfei feng - Sun Microsystems - Beijing China 		/* packet header may have moved, reset our local pointer */
146810115c80Sfei feng - Sun Microsystems - Beijing China 		wh = (struct ieee80211_frame *)m->b_rptr;
146910115c80Sfei feng - Sun Microsystems - Beijing China 	}
147010115c80Sfei feng - Sun Microsystems - Beijing China 
147110115c80Sfei feng - Sun Microsystems - Beijing China 	pktlen = msgdsize(m);
147210115c80Sfei feng - Sun Microsystems - Beijing China 
147310115c80Sfei feng - Sun Microsystems - Beijing China 	desc = &ring->desc[ring->cur];
147410115c80Sfei feng - Sun Microsystems - Beijing China 	data = &ring->data[ring->cur];
147510115c80Sfei feng - Sun Microsystems - Beijing China 	data->ni = ieee80211_ref_node(ni);
147610115c80Sfei feng - Sun Microsystems - Beijing China 
147710115c80Sfei feng - Sun Microsystems - Beijing China 	/* pickup a rate */
147810115c80Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
147910115c80Sfei feng - Sun Microsystems - Beijing China 		/* multicast frames are sent at the lowest avail. rate */
148010115c80Sfei feng - Sun Microsystems - Beijing China 		rate = ni->in_rates.ir_rates[0];
148110115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
148210115c80Sfei feng - Sun Microsystems - Beijing China 		rate = ic->ic_sup_rates[ic->ic_curmode].
148310115c80Sfei feng - Sun Microsystems - Beijing China 		    ir_rates[ic->ic_fixed_rate];
148410115c80Sfei feng - Sun Microsystems - Beijing China 	} else
148510115c80Sfei feng - Sun Microsystems - Beijing China 		rate = ni->in_rates.ir_rates[ni->in_txrate];
148610115c80Sfei feng - Sun Microsystems - Beijing China 	if (rate == 0)
148710115c80Sfei feng - Sun Microsystems - Beijing China 		rate = 2;	/* XXX should not happen */
148810115c80Sfei feng - Sun Microsystems - Beijing China 	rate &= IEEE80211_RATE_VAL;
148910115c80Sfei feng - Sun Microsystems - Beijing China 
149010115c80Sfei feng - Sun Microsystems - Beijing China 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
149110115c80Sfei feng - Sun Microsystems - Beijing China 		flags |= RT2661_TX_NEED_ACK;
149210115c80Sfei feng - Sun Microsystems - Beijing China 
149310115c80Sfei feng - Sun Microsystems - Beijing China 		dur = rt2661_txtime(RT2661_ACK_SIZE,
149410115c80Sfei feng - Sun Microsystems - Beijing China 		    rt2661_ack_rate(ic, rate), ic->ic_flags) + sc->sifs;
149510115c80Sfei feng - Sun Microsystems - Beijing China 		*(uint16_t *)wh->i_dur = LE_16(dur);
149610115c80Sfei feng - Sun Microsystems - Beijing China 	}
149710115c80Sfei feng - Sun Microsystems - Beijing China 
149810115c80Sfei feng - Sun Microsystems - Beijing China 	bcopy(m->b_rptr, data->buf, pktlen);
149910115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_setup_tx_desc(sc, desc, flags, 0, pktlen, rate, 0);
150010115c80Sfei feng - Sun Microsystems - Beijing China 
150110115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(data->txdata_dma.dma_hdl,
150210115c80Sfei feng - Sun Microsystems - Beijing China 	    0, pktlen,
150310115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SYNC_FORDEV);
150410115c80Sfei feng - Sun Microsystems - Beijing China 
150510115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
150610115c80Sfei feng - Sun Microsystems - Beijing China 	    ring->cur * RT2661_TX_DESC_SIZE,
150710115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_DESC_SIZE,
150810115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SYNC_FORDEV);
150910115c80Sfei feng - Sun Microsystems - Beijing China 
151010115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_send(): "
151110115c80Sfei feng - Sun Microsystems - Beijing China 	    "sending data frame len=%u idx=%u rate=%u\n",
151210115c80Sfei feng - Sun Microsystems - Beijing China 	    pktlen, ring->cur, rate);
151310115c80Sfei feng - Sun Microsystems - Beijing China 
151410115c80Sfei feng - Sun Microsystems - Beijing China 	/* kick Tx */
151510115c80Sfei feng - Sun Microsystems - Beijing China 	ring->queued++;
151610115c80Sfei feng - Sun Microsystems - Beijing China 	ring->cur = (ring->cur + 1) % RT2661_TX_RING_COUNT;
151710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TX_CNTL_CSR, 1 << 0);
151810115c80Sfei feng - Sun Microsystems - Beijing China 
151910115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_frags++;
152010115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_bytes += pktlen;
152110115c80Sfei feng - Sun Microsystems - Beijing China fail3:
152210115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_free_node(ni);
152310115c80Sfei feng - Sun Microsystems - Beijing China fail2:
152410115c80Sfei feng - Sun Microsystems - Beijing China 	freemsg(m);
152510115c80Sfei feng - Sun Microsystems - Beijing China fail1:
152610115c80Sfei feng - Sun Microsystems - Beijing China 	if (err == DDI_SUCCESS)
152710115c80Sfei feng - Sun Microsystems - Beijing China 		freemsg(mp);
152810115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_exit(&sc->sc_txlock);
152910115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
153010115c80Sfei feng - Sun Microsystems - Beijing China }
153110115c80Sfei feng - Sun Microsystems - Beijing China 
153210115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
153310115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_mgmt_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)153410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_mgmt_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
153510115c80Sfei feng - Sun Microsystems - Beijing China {
153610115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)ic;
153710115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_ring *ring;
153810115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_desc *desc;
153910115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_tx_data *data;
154010115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_frame *wh;
154110115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni;
154210115c80Sfei feng - Sun Microsystems - Beijing China 
154310115c80Sfei feng - Sun Microsystems - Beijing China 	int err, off, rate;
154410115c80Sfei feng - Sun Microsystems - Beijing China 	int mblen, pktlen;
154510115c80Sfei feng - Sun Microsystems - Beijing China 	mblk_t *m, *m0;
154610115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t dur;
154710115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t flags = 0;
154810115c80Sfei feng - Sun Microsystems - Beijing China 
154910115c80Sfei feng - Sun Microsystems - Beijing China 	if ((!RT2661_IS_RUNNING(sc)) || RT2661_IS_SUSPEND(sc)) {
155010115c80Sfei feng - Sun Microsystems - Beijing China 		err = ENXIO;
155110115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
155210115c80Sfei feng - Sun Microsystems - Beijing China 	}
155310115c80Sfei feng - Sun Microsystems - Beijing China 
155410115c80Sfei feng - Sun Microsystems - Beijing China 	ring = &sc->mgtq;
155510115c80Sfei feng - Sun Microsystems - Beijing China 	err = DDI_SUCCESS;
155610115c80Sfei feng - Sun Microsystems - Beijing China 
155710115c80Sfei feng - Sun Microsystems - Beijing China 	if (ring->queued >= RT2661_MGT_RING_COUNT) {
155810115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_nobuf++;
155910115c80Sfei feng - Sun Microsystems - Beijing China 		err = ENOMEM;
156010115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
156110115c80Sfei feng - Sun Microsystems - Beijing China 	}
156210115c80Sfei feng - Sun Microsystems - Beijing China 
156310115c80Sfei feng - Sun Microsystems - Beijing China 	m = allocb(msgdsize(mp) + 32, BPRI_MED);
156410115c80Sfei feng - Sun Microsystems - Beijing China 	if (m == NULL) {
156510115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_mgmt_send():"
156610115c80Sfei feng - Sun Microsystems - Beijing China 		    "can't alloc mblk.\n");
156710115c80Sfei feng - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
156810115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
156910115c80Sfei feng - Sun Microsystems - Beijing China 	}
157010115c80Sfei feng - Sun Microsystems - Beijing China 
157110115c80Sfei feng - Sun Microsystems - Beijing China 	for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
157210115c80Sfei feng - Sun Microsystems - Beijing China 		mblen = MBLKL(m0);
157310115c80Sfei feng - Sun Microsystems - Beijing China 		(void) bcopy(m0->b_rptr, m->b_rptr + off, mblen);
157410115c80Sfei feng - Sun Microsystems - Beijing China 		off += mblen;
157510115c80Sfei feng - Sun Microsystems - Beijing China 	}
157610115c80Sfei feng - Sun Microsystems - Beijing China 	m->b_wptr += off;
157710115c80Sfei feng - Sun Microsystems - Beijing China 
157810115c80Sfei feng - Sun Microsystems - Beijing China 	wh = (struct ieee80211_frame *)m->b_rptr;
157910115c80Sfei feng - Sun Microsystems - Beijing China 	ni = ieee80211_find_txnode(ic, wh->i_addr1);
158010115c80Sfei feng - Sun Microsystems - Beijing China 	if (ni == NULL) {
158110115c80Sfei feng - Sun Microsystems - Beijing China 		err = DDI_FAILURE;
158210115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_err++;
158310115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
158410115c80Sfei feng - Sun Microsystems - Beijing China 	}
158510115c80Sfei feng - Sun Microsystems - Beijing China 
158610115c80Sfei feng - Sun Microsystems - Beijing China 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
158710115c80Sfei feng - Sun Microsystems - Beijing China 		struct ieee80211_key *k;
158810115c80Sfei feng - Sun Microsystems - Beijing China 		k = ieee80211_crypto_encap(ic, m);
158910115c80Sfei feng - Sun Microsystems - Beijing China 		if (k == NULL) {
159010115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_tx_err++;
159110115c80Sfei feng - Sun Microsystems - Beijing China 			err = DDI_FAILURE;
159210115c80Sfei feng - Sun Microsystems - Beijing China 			goto fail3;
159310115c80Sfei feng - Sun Microsystems - Beijing China 		}
159410115c80Sfei feng - Sun Microsystems - Beijing China 		/* packet header may have moved, reset our local pointer */
159510115c80Sfei feng - Sun Microsystems - Beijing China 		wh = (struct ieee80211_frame *)m->b_rptr;
159610115c80Sfei feng - Sun Microsystems - Beijing China 	}
159710115c80Sfei feng - Sun Microsystems - Beijing China 
159810115c80Sfei feng - Sun Microsystems - Beijing China 	pktlen = msgdsize(m);
159910115c80Sfei feng - Sun Microsystems - Beijing China 
160010115c80Sfei feng - Sun Microsystems - Beijing China 	desc = &ring->desc[ring->cur];
160110115c80Sfei feng - Sun Microsystems - Beijing China 	data = &ring->data[ring->cur];
160210115c80Sfei feng - Sun Microsystems - Beijing China 	data->ni = ieee80211_ref_node(ni);
160310115c80Sfei feng - Sun Microsystems - Beijing China 
160410115c80Sfei feng - Sun Microsystems - Beijing China 	/* send mgt frames at the lowest available rate */
160510115c80Sfei feng - Sun Microsystems - Beijing China 	rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
160610115c80Sfei feng - Sun Microsystems - Beijing China 
160710115c80Sfei feng - Sun Microsystems - Beijing China 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
160810115c80Sfei feng - Sun Microsystems - Beijing China 		flags |= RT2661_TX_NEED_ACK;
160910115c80Sfei feng - Sun Microsystems - Beijing China 
161010115c80Sfei feng - Sun Microsystems - Beijing China 		dur = rt2661_txtime(RT2661_ACK_SIZE,
161110115c80Sfei feng - Sun Microsystems - Beijing China 		    rate, ic->ic_flags) + sc->sifs;
161210115c80Sfei feng - Sun Microsystems - Beijing China 		*(uint16_t *)wh->i_dur = LE_16(dur);
161310115c80Sfei feng - Sun Microsystems - Beijing China 
161410115c80Sfei feng - Sun Microsystems - Beijing China 		/* tell hardware to add timestamp in probe responses */
161510115c80Sfei feng - Sun Microsystems - Beijing China 		if ((wh->i_fc[0] &
161610115c80Sfei feng - Sun Microsystems - Beijing China 		    (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
161710115c80Sfei feng - Sun Microsystems - Beijing China 		    (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
161810115c80Sfei feng - Sun Microsystems - Beijing China 			flags |= RT2661_TX_TIMESTAMP;
161910115c80Sfei feng - Sun Microsystems - Beijing China 	}
162010115c80Sfei feng - Sun Microsystems - Beijing China 
162110115c80Sfei feng - Sun Microsystems - Beijing China 	bcopy(m->b_rptr, data->buf, pktlen);
162210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_setup_tx_desc(sc, desc, flags, 0, pktlen, rate, RT2661_QID_MGT);
162310115c80Sfei feng - Sun Microsystems - Beijing China 
162410115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(data->txdata_dma.dma_hdl,
162510115c80Sfei feng - Sun Microsystems - Beijing China 	    0, pktlen,
162610115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SYNC_FORDEV);
162710115c80Sfei feng - Sun Microsystems - Beijing China 
162810115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_dma_sync(ring->txdesc_dma.dma_hdl,
162910115c80Sfei feng - Sun Microsystems - Beijing China 	    ring->cur * RT2661_TX_DESC_SIZE,
163010115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_DESC_SIZE,
163110115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_DMA_SYNC_FORDEV);
163210115c80Sfei feng - Sun Microsystems - Beijing China 
163310115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_mgmt_send(): "
163410115c80Sfei feng - Sun Microsystems - Beijing China 	    "sending mgmt frame len=%u idx=%u rate=%u\n",
163510115c80Sfei feng - Sun Microsystems - Beijing China 	    pktlen, ring->cur, rate);
163610115c80Sfei feng - Sun Microsystems - Beijing China 
163710115c80Sfei feng - Sun Microsystems - Beijing China 	/* kick Tx */
163810115c80Sfei feng - Sun Microsystems - Beijing China 	ring->queued++;
163910115c80Sfei feng - Sun Microsystems - Beijing China 	ring->cur = (ring->cur + 1) % RT2661_MGT_RING_COUNT;
164010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TX_CNTL_CSR, RT2661_KICK_MGT);
164110115c80Sfei feng - Sun Microsystems - Beijing China 
164210115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_frags++;
164310115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_stats.is_tx_bytes += pktlen;
164410115c80Sfei feng - Sun Microsystems - Beijing China 
164510115c80Sfei feng - Sun Microsystems - Beijing China fail3:
164610115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_free_node(ni);
164710115c80Sfei feng - Sun Microsystems - Beijing China fail2:
164810115c80Sfei feng - Sun Microsystems - Beijing China 	freemsg(m);
164910115c80Sfei feng - Sun Microsystems - Beijing China fail1:
165010115c80Sfei feng - Sun Microsystems - Beijing China 	freemsg(mp);
165110115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
165210115c80Sfei feng - Sun Microsystems - Beijing China }
165310115c80Sfei feng - Sun Microsystems - Beijing China 
165410115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_amrr_node_init(const struct rt2661_amrr * amrr,struct rt2661_amrr_node * amn)165510115c80Sfei feng - Sun Microsystems - Beijing China rt2661_amrr_node_init(const struct rt2661_amrr *amrr,
165610115c80Sfei feng - Sun Microsystems - Beijing China     struct rt2661_amrr_node *amn)
165710115c80Sfei feng - Sun Microsystems - Beijing China {
165810115c80Sfei feng - Sun Microsystems - Beijing China 	amn->amn_success = 0;
165910115c80Sfei feng - Sun Microsystems - Beijing China 	amn->amn_recovery = 0;
166010115c80Sfei feng - Sun Microsystems - Beijing China 	amn->amn_txcnt = amn->amn_retrycnt = 0;
166110115c80Sfei feng - Sun Microsystems - Beijing China 	amn->amn_success_threshold = amrr->amrr_min_success_threshold;
166210115c80Sfei feng - Sun Microsystems - Beijing China }
166310115c80Sfei feng - Sun Microsystems - Beijing China 
166410115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_amrr_choose(struct rt2661_amrr * amrr,struct ieee80211_node * ni,struct rt2661_amrr_node * amn)166510115c80Sfei feng - Sun Microsystems - Beijing China rt2661_amrr_choose(struct rt2661_amrr *amrr, struct ieee80211_node *ni,
166610115c80Sfei feng - Sun Microsystems - Beijing China     struct rt2661_amrr_node *amn)
166710115c80Sfei feng - Sun Microsystems - Beijing China {
166810115c80Sfei feng - Sun Microsystems - Beijing China #define	RV(rate)	((rate) & IEEE80211_RATE_VAL)
166910115c80Sfei feng - Sun Microsystems - Beijing China #define	is_success(amn)	\
167010115c80Sfei feng - Sun Microsystems - Beijing China 	((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
167110115c80Sfei feng - Sun Microsystems - Beijing China #define	is_failure(amn)	\
167210115c80Sfei feng - Sun Microsystems - Beijing China 	((amn)->amn_retrycnt > (amn)->amn_txcnt / 3)
167310115c80Sfei feng - Sun Microsystems - Beijing China #define	is_enough(amn)		\
167410115c80Sfei feng - Sun Microsystems - Beijing China 	((amn)->amn_txcnt > 10)
167510115c80Sfei feng - Sun Microsystems - Beijing China #define	is_min_rate(ni)		\
167610115c80Sfei feng - Sun Microsystems - Beijing China 	((ni)->in_txrate == 0)
167710115c80Sfei feng - Sun Microsystems - Beijing China #define	is_max_rate(ni)		\
167810115c80Sfei feng - Sun Microsystems - Beijing China 	((ni)->in_txrate == (ni)->in_rates.ir_nrates - 1)
167910115c80Sfei feng - Sun Microsystems - Beijing China #define	increase_rate(ni)	\
168010115c80Sfei feng - Sun Microsystems - Beijing China 	((ni)->in_txrate++)
168110115c80Sfei feng - Sun Microsystems - Beijing China #define	decrease_rate(ni)	\
168210115c80Sfei feng - Sun Microsystems - Beijing China 	((ni)->in_txrate--)
168310115c80Sfei feng - Sun Microsystems - Beijing China #define	reset_cnt(amn)		\
168410115c80Sfei feng - Sun Microsystems - Beijing China 	{ (amn)->amn_txcnt = (amn)->amn_retrycnt = 0; }
168510115c80Sfei feng - Sun Microsystems - Beijing China 
168610115c80Sfei feng - Sun Microsystems - Beijing China 	int need_change = 0;
168710115c80Sfei feng - Sun Microsystems - Beijing China 
168810115c80Sfei feng - Sun Microsystems - Beijing China 	if (is_success(amn) && is_enough(amn)) {
168910115c80Sfei feng - Sun Microsystems - Beijing China 		amn->amn_success++;
169010115c80Sfei feng - Sun Microsystems - Beijing China 		if (amn->amn_success >= amn->amn_success_threshold &&
169110115c80Sfei feng - Sun Microsystems - Beijing China 		    !is_max_rate(ni)) {
169210115c80Sfei feng - Sun Microsystems - Beijing China 			amn->amn_recovery = 1;
169310115c80Sfei feng - Sun Microsystems - Beijing China 			amn->amn_success = 0;
169410115c80Sfei feng - Sun Microsystems - Beijing China 			increase_rate(ni);
169510115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_amrr_choose(): "
169610115c80Sfei feng - Sun Microsystems - Beijing China 			    "increase rate = %d, #tx = %d, #retries = %d\n",
169710115c80Sfei feng - Sun Microsystems - Beijing China 			    RV(ni->in_rates.ir_rates[ni->in_txrate]),
169810115c80Sfei feng - Sun Microsystems - Beijing China 			    amn->amn_txcnt, amn->amn_retrycnt);
169910115c80Sfei feng - Sun Microsystems - Beijing China 			need_change = 1;
170010115c80Sfei feng - Sun Microsystems - Beijing China 		} else
170110115c80Sfei feng - Sun Microsystems - Beijing China 			amn->amn_recovery = 0;
170210115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (is_failure(amn)) {
170310115c80Sfei feng - Sun Microsystems - Beijing China 		amn->amn_success = 0;
170410115c80Sfei feng - Sun Microsystems - Beijing China 		if (!is_min_rate(ni)) {
170510115c80Sfei feng - Sun Microsystems - Beijing China 			if (amn->amn_recovery) {
170610115c80Sfei feng - Sun Microsystems - Beijing China 				amn->amn_success_threshold *= 2;
170710115c80Sfei feng - Sun Microsystems - Beijing China 				if (amn->amn_success_threshold >
170810115c80Sfei feng - Sun Microsystems - Beijing China 				    amrr->amrr_max_success_threshold)
170910115c80Sfei feng - Sun Microsystems - Beijing China 					amn->amn_success_threshold =
171010115c80Sfei feng - Sun Microsystems - Beijing China 					    amrr->amrr_max_success_threshold;
171110115c80Sfei feng - Sun Microsystems - Beijing China 			} else {
171210115c80Sfei feng - Sun Microsystems - Beijing China 				amn->amn_success_threshold =
171310115c80Sfei feng - Sun Microsystems - Beijing China 				    amrr->amrr_min_success_threshold;
171410115c80Sfei feng - Sun Microsystems - Beijing China 			}
171510115c80Sfei feng - Sun Microsystems - Beijing China 			decrease_rate(ni);
171610115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_amrr_choose(): "
171710115c80Sfei feng - Sun Microsystems - Beijing China 			    "decrease rate = %d, #tx = %d, #retries = %d\n",
171810115c80Sfei feng - Sun Microsystems - Beijing China 			    RV(ni->in_rates.ir_rates[ni->in_txrate]),
171910115c80Sfei feng - Sun Microsystems - Beijing China 			    amn->amn_txcnt, amn->amn_retrycnt);
172010115c80Sfei feng - Sun Microsystems - Beijing China 			need_change = 1;
172110115c80Sfei feng - Sun Microsystems - Beijing China 		}
172210115c80Sfei feng - Sun Microsystems - Beijing China 		amn->amn_recovery = 0;
172310115c80Sfei feng - Sun Microsystems - Beijing China 	}
172410115c80Sfei feng - Sun Microsystems - Beijing China 
172510115c80Sfei feng - Sun Microsystems - Beijing China 	if (is_enough(amn) || need_change)
172610115c80Sfei feng - Sun Microsystems - Beijing China 		reset_cnt(amn);
172710115c80Sfei feng - Sun Microsystems - Beijing China #undef RV
172810115c80Sfei feng - Sun Microsystems - Beijing China 
172910115c80Sfei feng - Sun Microsystems - Beijing China }
173010115c80Sfei feng - Sun Microsystems - Beijing China 
173110115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_update_promisc(struct rt2661_softc * sc)173210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_update_promisc(struct rt2661_softc *sc)
173310115c80Sfei feng - Sun Microsystems - Beijing China {
173410115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
173510115c80Sfei feng - Sun Microsystems - Beijing China 
173610115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_TXRX_CSR0);
173710115c80Sfei feng - Sun Microsystems - Beijing China 
173810115c80Sfei feng - Sun Microsystems - Beijing China 	tmp &= ~RT2661_DROP_NOT_TO_ME;
173910115c80Sfei feng - Sun Microsystems - Beijing China 	if (!(sc->sc_rcr & RT2661_RCR_PROMISC))
174010115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_DROP_NOT_TO_ME;
174110115c80Sfei feng - Sun Microsystems - Beijing China 
174210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp);
174310115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_update_promisc(): "
174410115c80Sfei feng - Sun Microsystems - Beijing China 	    "%s promiscuous mode\n",
174510115c80Sfei feng - Sun Microsystems - Beijing China 	    (sc->sc_rcr & RT2661_RCR_PROMISC) ? "entering" : "leaving");
174610115c80Sfei feng - Sun Microsystems - Beijing China }
174710115c80Sfei feng - Sun Microsystems - Beijing China 
174810115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_updateslot(struct ieee80211com * ic,int onoff)174910115c80Sfei feng - Sun Microsystems - Beijing China rt2661_updateslot(struct ieee80211com *ic, int onoff)
175010115c80Sfei feng - Sun Microsystems - Beijing China {
175110115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)ic;
175210115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t slottime;
175310115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
175410115c80Sfei feng - Sun Microsystems - Beijing China 
175510115c80Sfei feng - Sun Microsystems - Beijing China 	slottime = (onoff ? 9 : 20);
175610115c80Sfei feng - Sun Microsystems - Beijing China 
175710115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_MAC_CSR9);
175810115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = (tmp & ~0xff) | slottime;
175910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR9, tmp);
176010115c80Sfei feng - Sun Microsystems - Beijing China 
176110115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_updateslot(): "
176210115c80Sfei feng - Sun Microsystems - Beijing China 	    "setting slot time to %uus\n", slottime);
176310115c80Sfei feng - Sun Microsystems - Beijing China }
176410115c80Sfei feng - Sun Microsystems - Beijing China 
176510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_set_slottime(struct rt2661_softc * sc)176610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_set_slottime(struct rt2661_softc *sc)
176710115c80Sfei feng - Sun Microsystems - Beijing China {
176810115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
176910115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t slottime;
177010115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
177110115c80Sfei feng - Sun Microsystems - Beijing China 
177210115c80Sfei feng - Sun Microsystems - Beijing China 	slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
177310115c80Sfei feng - Sun Microsystems - Beijing China 
177410115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_MAC_CSR9);
177510115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = (tmp & ~0xff) | slottime;
177610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR9, tmp);
177710115c80Sfei feng - Sun Microsystems - Beijing China 
177810115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_set_slottime(): "
177910115c80Sfei feng - Sun Microsystems - Beijing China 	    "setting slot time to %uus\n", slottime);
178010115c80Sfei feng - Sun Microsystems - Beijing China }
178110115c80Sfei feng - Sun Microsystems - Beijing China 
178210115c80Sfei feng - Sun Microsystems - Beijing China 
178310115c80Sfei feng - Sun Microsystems - Beijing China /*
178410115c80Sfei feng - Sun Microsystems - Beijing China  * Enable multi-rate retries for frames sent at OFDM rates.
178510115c80Sfei feng - Sun Microsystems - Beijing China  * In 802.11b/g mode, allow fallback to CCK rates.
178610115c80Sfei feng - Sun Microsystems - Beijing China  */
178710115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_enable_mrr(struct rt2661_softc * sc)178810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_enable_mrr(struct rt2661_softc *sc)
178910115c80Sfei feng - Sun Microsystems - Beijing China {
179010115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
179110115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
179210115c80Sfei feng - Sun Microsystems - Beijing China 
179310115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_TXRX_CSR4);
179410115c80Sfei feng - Sun Microsystems - Beijing China 
179510115c80Sfei feng - Sun Microsystems - Beijing China 	tmp &= ~RT2661_MRR_CCK_FALLBACK;
179610115c80Sfei feng - Sun Microsystems - Beijing China 	if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
179710115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_MRR_CCK_FALLBACK;
179810115c80Sfei feng - Sun Microsystems - Beijing China 	tmp |= RT2661_MRR_ENABLED;
179910115c80Sfei feng - Sun Microsystems - Beijing China 
180010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR4, tmp);
180110115c80Sfei feng - Sun Microsystems - Beijing China }
180210115c80Sfei feng - Sun Microsystems - Beijing China 
180310115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_set_txpreamble(struct rt2661_softc * sc)180410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_set_txpreamble(struct rt2661_softc *sc)
180510115c80Sfei feng - Sun Microsystems - Beijing China {
180610115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
180710115c80Sfei feng - Sun Microsystems - Beijing China 
180810115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_TXRX_CSR4);
180910115c80Sfei feng - Sun Microsystems - Beijing China 
181010115c80Sfei feng - Sun Microsystems - Beijing China 	tmp &= ~RT2661_SHORT_PREAMBLE;
181110115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
181210115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_SHORT_PREAMBLE;
181310115c80Sfei feng - Sun Microsystems - Beijing China 
181410115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR4, tmp);
181510115c80Sfei feng - Sun Microsystems - Beijing China }
181610115c80Sfei feng - Sun Microsystems - Beijing China 
181710115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_set_basicrates(struct rt2661_softc * sc)181810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_set_basicrates(struct rt2661_softc *sc)
181910115c80Sfei feng - Sun Microsystems - Beijing China {
182010115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
182110115c80Sfei feng - Sun Microsystems - Beijing China 
182210115c80Sfei feng - Sun Microsystems - Beijing China 	/* update basic rate set */
182310115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_curmode == IEEE80211_MODE_11B) {
182410115c80Sfei feng - Sun Microsystems - Beijing China 		/* 11b basic rates: 1, 2Mbps */
182510115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_TXRX_CSR5, 0x3);
182610115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (ic->ic_curmode == IEEE80211_MODE_11A) {
182710115c80Sfei feng - Sun Microsystems - Beijing China 		/* 11a basic rates: 6, 12, 24Mbps */
182810115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_TXRX_CSR5, 0x150);
182910115c80Sfei feng - Sun Microsystems - Beijing China 	} else {
183010115c80Sfei feng - Sun Microsystems - Beijing China 		/* 11b/g basic rates: 1, 2, 5.5, 11Mbps */
183110115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_TXRX_CSR5, 0xf);
183210115c80Sfei feng - Sun Microsystems - Beijing China 	}
183310115c80Sfei feng - Sun Microsystems - Beijing China }
183410115c80Sfei feng - Sun Microsystems - Beijing China 
183510115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_set_bssid(struct rt2661_softc * sc,const uint8_t * bssid)183610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_set_bssid(struct rt2661_softc *sc, const uint8_t *bssid)
183710115c80Sfei feng - Sun Microsystems - Beijing China {
183810115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
183910115c80Sfei feng - Sun Microsystems - Beijing China 
184010115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
184110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR4, tmp);
184210115c80Sfei feng - Sun Microsystems - Beijing China 
184310115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = bssid[4] | bssid[5] << 8 | RT2661_ONE_BSSID << 16;
184410115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR5, tmp);
184510115c80Sfei feng - Sun Microsystems - Beijing China }
184610115c80Sfei feng - Sun Microsystems - Beijing China 
184710115c80Sfei feng - Sun Microsystems - Beijing China /*
184810115c80Sfei feng - Sun Microsystems - Beijing China  * Enable TSF synchronization and tell h/w to start sending beacons for IBSS
184910115c80Sfei feng - Sun Microsystems - Beijing China  * and HostAP operating modes.
185010115c80Sfei feng - Sun Microsystems - Beijing China  */
185110115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_enable_tsf_sync(struct rt2661_softc * sc)185210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_enable_tsf_sync(struct rt2661_softc *sc)
185310115c80Sfei feng - Sun Microsystems - Beijing China {
185410115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
185510115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
185610115c80Sfei feng - Sun Microsystems - Beijing China 
185710115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_TXRX_CSR9) & 0xff000000;
185810115c80Sfei feng - Sun Microsystems - Beijing China 
185910115c80Sfei feng - Sun Microsystems - Beijing China 	/* set beacon interval (in 1/16ms unit) */
186010115c80Sfei feng - Sun Microsystems - Beijing China 	tmp |= ic->ic_bss->in_intval * 16;
186110115c80Sfei feng - Sun Microsystems - Beijing China 
186210115c80Sfei feng - Sun Microsystems - Beijing China 	tmp |= RT2661_TSF_TICKING | RT2661_ENABLE_TBTT;
186310115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_opmode == IEEE80211_M_STA)
186410115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_TSF_MODE(1);
186510115c80Sfei feng - Sun Microsystems - Beijing China 
186610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR9, tmp);
186710115c80Sfei feng - Sun Microsystems - Beijing China }
186810115c80Sfei feng - Sun Microsystems - Beijing China 
186910115c80Sfei feng - Sun Microsystems - Beijing China 
187010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_next_scan(void * arg)187110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_next_scan(void *arg)
187210115c80Sfei feng - Sun Microsystems - Beijing China {
187310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = arg;
187410115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
187510115c80Sfei feng - Sun Microsystems - Beijing China 
187610115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_state == IEEE80211_S_SCAN)
187710115c80Sfei feng - Sun Microsystems - Beijing China 		(void) ieee80211_next_scan(ic);
187810115c80Sfei feng - Sun Microsystems - Beijing China }
187910115c80Sfei feng - Sun Microsystems - Beijing China 
188010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_newassoc(struct ieee80211com * ic,struct ieee80211_node * ni)188110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni)
188210115c80Sfei feng - Sun Microsystems - Beijing China {
188310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)ic;
188410115c80Sfei feng - Sun Microsystems - Beijing China 	int i;
188510115c80Sfei feng - Sun Microsystems - Beijing China 
188610115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_amrr_node_init(&sc->amrr, &((struct rt2661_node *)ni)->amn);
188710115c80Sfei feng - Sun Microsystems - Beijing China 
188810115c80Sfei feng - Sun Microsystems - Beijing China 	/* set rate to some reasonable initial value */
188910115c80Sfei feng - Sun Microsystems - Beijing China 	i = ni->in_rates.ir_nrates - 1;
189010115c80Sfei feng - Sun Microsystems - Beijing China 	while (i > 0 && ((ni->in_rates.ir_rates[i] & IEEE80211_RATE_VAL) > 72))
189110115c80Sfei feng - Sun Microsystems - Beijing China 		i--;
189210115c80Sfei feng - Sun Microsystems - Beijing China 
189310115c80Sfei feng - Sun Microsystems - Beijing China 	ni->in_txrate = i;
189410115c80Sfei feng - Sun Microsystems - Beijing China }
189510115c80Sfei feng - Sun Microsystems - Beijing China 
189610115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_iter_func(void * arg,struct ieee80211_node * ni)189710115c80Sfei feng - Sun Microsystems - Beijing China rt2661_iter_func(void *arg, struct ieee80211_node *ni)
189810115c80Sfei feng - Sun Microsystems - Beijing China {
189910115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = arg;
190010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_node *rn = (struct rt2661_node *)ni;
190110115c80Sfei feng - Sun Microsystems - Beijing China 
190210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_amrr_choose(&sc->amrr, ni, &rn->amn);
190310115c80Sfei feng - Sun Microsystems - Beijing China 
190410115c80Sfei feng - Sun Microsystems - Beijing China }
190510115c80Sfei feng - Sun Microsystems - Beijing China 
190610115c80Sfei feng - Sun Microsystems - Beijing China /*
190710115c80Sfei feng - Sun Microsystems - Beijing China  * Dynamically tune Rx sensitivity (BBP register 17) based on average RSSI and
190810115c80Sfei feng - Sun Microsystems - Beijing China  * false CCA count.  This function is called periodically (every seconds) when
190910115c80Sfei feng - Sun Microsystems - Beijing China  * in the RUN state.  Values taken from the reference driver.
191010115c80Sfei feng - Sun Microsystems - Beijing China  */
191110115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_rx_tune(struct rt2661_softc * sc)191210115c80Sfei feng - Sun Microsystems - Beijing China rt2661_rx_tune(struct rt2661_softc *sc)
191310115c80Sfei feng - Sun Microsystems - Beijing China {
191410115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t	bbp17;
191510115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t cca;
191610115c80Sfei feng - Sun Microsystems - Beijing China 	int lo, hi, dbm;
191710115c80Sfei feng - Sun Microsystems - Beijing China 
191810115c80Sfei feng - Sun Microsystems - Beijing China 	/*
191910115c80Sfei feng - Sun Microsystems - Beijing China 	 * Tuning range depends on operating band and on the presence of an
192010115c80Sfei feng - Sun Microsystems - Beijing China 	 * external low-noise amplifier.
192110115c80Sfei feng - Sun Microsystems - Beijing China 	 */
192210115c80Sfei feng - Sun Microsystems - Beijing China 	lo = 0x20;
192310115c80Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan))
192410115c80Sfei feng - Sun Microsystems - Beijing China 		lo += 0x08;
192510115c80Sfei feng - Sun Microsystems - Beijing China 	if ((IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) && sc->ext_2ghz_lna) ||
192610115c80Sfei feng - Sun Microsystems - Beijing China 	    (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan) && sc->ext_5ghz_lna))
192710115c80Sfei feng - Sun Microsystems - Beijing China 		lo += 0x10;
192810115c80Sfei feng - Sun Microsystems - Beijing China 	hi = lo + 0x20;
192910115c80Sfei feng - Sun Microsystems - Beijing China 
193010115c80Sfei feng - Sun Microsystems - Beijing China 	dbm = sc->avg_rssi;
193110115c80Sfei feng - Sun Microsystems - Beijing China 	/* retrieve false CCA count since last call (clear on read) */
193210115c80Sfei feng - Sun Microsystems - Beijing China 	cca = RT2661_READ(sc, RT2661_STA_CSR1) & 0xffff;
193310115c80Sfei feng - Sun Microsystems - Beijing China 
193410115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_INTR, "rwd: rt2661_rx_tune(): "
193510115c80Sfei feng - Sun Microsystems - Beijing China 	    "RSSI=%ddBm false CCA=%d\n", dbm, cca);
193610115c80Sfei feng - Sun Microsystems - Beijing China 
193710115c80Sfei feng - Sun Microsystems - Beijing China 	if (dbm < -74) {
193810115c80Sfei feng - Sun Microsystems - Beijing China 		/* very bad RSSI, tune using false CCA count */
193910115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 = sc->bbp17; /* current value */
194010115c80Sfei feng - Sun Microsystems - Beijing China 
194110115c80Sfei feng - Sun Microsystems - Beijing China 		hi -= 2 * (-74 - dbm);
194210115c80Sfei feng - Sun Microsystems - Beijing China 		if (hi < lo)
194310115c80Sfei feng - Sun Microsystems - Beijing China 			hi = lo;
194410115c80Sfei feng - Sun Microsystems - Beijing China 
194510115c80Sfei feng - Sun Microsystems - Beijing China 		if (bbp17 > hi)
194610115c80Sfei feng - Sun Microsystems - Beijing China 			bbp17 = (uint8_t)hi;
194710115c80Sfei feng - Sun Microsystems - Beijing China 		else if (cca > 512)
194810115c80Sfei feng - Sun Microsystems - Beijing China 			bbp17 = (uint8_t)min(bbp17 + 1, hi);
194910115c80Sfei feng - Sun Microsystems - Beijing China 		else if (cca < 100)
195010115c80Sfei feng - Sun Microsystems - Beijing China 			bbp17 = (uint8_t)max(bbp17 - 1, lo);
195110115c80Sfei feng - Sun Microsystems - Beijing China 
195210115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (dbm < -66) {
195310115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 = lo + 0x08;
195410115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (dbm < -58) {
195510115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 = lo + 0x10;
195610115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (dbm < -35) {
195710115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 = (uint8_t)hi;
195810115c80Sfei feng - Sun Microsystems - Beijing China 	} else {	/* very good RSSI >= -35dBm */
195910115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 = 0x60;	/* very low sensitivity */
196010115c80Sfei feng - Sun Microsystems - Beijing China 	}
196110115c80Sfei feng - Sun Microsystems - Beijing China 
196210115c80Sfei feng - Sun Microsystems - Beijing China 	if (bbp17 != sc->bbp17) {
196310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rx_tune(): "
196410115c80Sfei feng - Sun Microsystems - Beijing China 		    "BBP17 %x->%x\n", sc->bbp17, bbp17);
196510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, 17, bbp17);
196610115c80Sfei feng - Sun Microsystems - Beijing China 		sc->bbp17 = bbp17;
196710115c80Sfei feng - Sun Microsystems - Beijing China 	}
196810115c80Sfei feng - Sun Microsystems - Beijing China }
196910115c80Sfei feng - Sun Microsystems - Beijing China 
197010115c80Sfei feng - Sun Microsystems - Beijing China /*
197110115c80Sfei feng - Sun Microsystems - Beijing China  * This function is called periodically (every 500ms) in RUN state to update
197210115c80Sfei feng - Sun Microsystems - Beijing China  * various settings like rate control statistics or Rx sensitivity.
197310115c80Sfei feng - Sun Microsystems - Beijing China  */
197410115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_updatestats(void * arg)197510115c80Sfei feng - Sun Microsystems - Beijing China rt2661_updatestats(void *arg)
197610115c80Sfei feng - Sun Microsystems - Beijing China {
197710115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = arg;
197810115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
197910115c80Sfei feng - Sun Microsystems - Beijing China 
198010115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_opmode == IEEE80211_M_STA)
198110115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_iter_func(sc, ic->ic_bss);
198210115c80Sfei feng - Sun Microsystems - Beijing China 	else
198310115c80Sfei feng - Sun Microsystems - Beijing China 		ieee80211_iterate_nodes(&ic->ic_sta, rt2661_iter_func, arg);
198410115c80Sfei feng - Sun Microsystems - Beijing China 
198510115c80Sfei feng - Sun Microsystems - Beijing China 	/* update rx sensitivity every 1 sec */
198610115c80Sfei feng - Sun Microsystems - Beijing China 	if (++sc->ncalls & 1)
198710115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_rx_tune(sc);
198810115c80Sfei feng - Sun Microsystems - Beijing China 
198910115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_rssadapt_id = timeout(rt2661_updatestats, (void *)sc,
199010115c80Sfei feng - Sun Microsystems - Beijing China 	    drv_usectohz(200 * 1000));
199110115c80Sfei feng - Sun Microsystems - Beijing China }
199210115c80Sfei feng - Sun Microsystems - Beijing China 
199310115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)199410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
199510115c80Sfei feng - Sun Microsystems - Beijing China {
199610115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)ic;
199710115c80Sfei feng - Sun Microsystems - Beijing China 	enum ieee80211_state ostate;
199810115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni;
199910115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
200010115c80Sfei feng - Sun Microsystems - Beijing China 	int err;
200110115c80Sfei feng - Sun Microsystems - Beijing China 
200210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
200310115c80Sfei feng - Sun Microsystems - Beijing China 
200410115c80Sfei feng - Sun Microsystems - Beijing China 	ostate = ic->ic_state;
200510115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_ostate = ostate;
200610115c80Sfei feng - Sun Microsystems - Beijing China 
200710115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt26661_newstate(): "
200810115c80Sfei feng - Sun Microsystems - Beijing China 	    "%x -> %x\n", ostate, nstate);
200910115c80Sfei feng - Sun Microsystems - Beijing China 
201010115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_scan_id != 0) {
201110115c80Sfei feng - Sun Microsystems - Beijing China 		(void) untimeout(sc->sc_scan_id);
201210115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_scan_id = 0;
201310115c80Sfei feng - Sun Microsystems - Beijing China 	}
201410115c80Sfei feng - Sun Microsystems - Beijing China 
201510115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->sc_rssadapt_id) {
201610115c80Sfei feng - Sun Microsystems - Beijing China 		(void) untimeout(sc->sc_rssadapt_id);
201710115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rssadapt_id = 0;
201810115c80Sfei feng - Sun Microsystems - Beijing China 	}
201910115c80Sfei feng - Sun Microsystems - Beijing China 
202010115c80Sfei feng - Sun Microsystems - Beijing China 	switch (nstate) {
202110115c80Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_INIT:
202210115c80Sfei feng - Sun Microsystems - Beijing China 		if (ostate == IEEE80211_S_RUN) {
202310115c80Sfei feng - Sun Microsystems - Beijing China 			/* abort TSF synchronization */
202410115c80Sfei feng - Sun Microsystems - Beijing China 			tmp = RT2661_READ(sc, RT2661_TXRX_CSR9);
202510115c80Sfei feng - Sun Microsystems - Beijing China 			RT2661_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0x00ffffff);
202610115c80Sfei feng - Sun Microsystems - Beijing China 		}
202710115c80Sfei feng - Sun Microsystems - Beijing China 		break;
202810115c80Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_SCAN:
202910115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_set_chan(sc, ic->ic_curchan);
203010115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_scan_id = timeout(rt2661_next_scan, (void *)sc,
203110115c80Sfei feng - Sun Microsystems - Beijing China 		    drv_usectohz(200000));
203210115c80Sfei feng - Sun Microsystems - Beijing China 		break;
203310115c80Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_AUTH:
203410115c80Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_ASSOC:
203510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_set_chan(sc, ic->ic_curchan);
203610115c80Sfei feng - Sun Microsystems - Beijing China 		break;
203710115c80Sfei feng - Sun Microsystems - Beijing China 	case IEEE80211_S_RUN:
203810115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_set_chan(sc, ic->ic_curchan);
203910115c80Sfei feng - Sun Microsystems - Beijing China 
204010115c80Sfei feng - Sun Microsystems - Beijing China 		ni = ic->ic_bss;
204110115c80Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
204210115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_set_slottime(sc);
204310115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_enable_mrr(sc);
204410115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_set_txpreamble(sc);
204510115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_set_basicrates(sc);
204610115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_set_bssid(sc, ni->in_bssid);
204710115c80Sfei feng - Sun Microsystems - Beijing China 		}
204810115c80Sfei feng - Sun Microsystems - Beijing China 
204910115c80Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_opmode == IEEE80211_M_STA) {
205010115c80Sfei feng - Sun Microsystems - Beijing China 			/* fake a join to init the tx rate */
205110115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_newassoc(ic, ni);
205210115c80Sfei feng - Sun Microsystems - Beijing China 		}
205310115c80Sfei feng - Sun Microsystems - Beijing China 
205410115c80Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
205510115c80Sfei feng - Sun Microsystems - Beijing China 			sc->ncalls = 0;
205610115c80Sfei feng - Sun Microsystems - Beijing China 			sc->avg_rssi = -95;	/* reset EMA */
205710115c80Sfei feng - Sun Microsystems - Beijing China 			sc->sc_rssadapt_id = timeout(rt2661_updatestats,
205810115c80Sfei feng - Sun Microsystems - Beijing China 			    (void *)sc, drv_usectohz(200 * 1000));
205910115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_enable_tsf_sync(sc);
206010115c80Sfei feng - Sun Microsystems - Beijing China 		}
206110115c80Sfei feng - Sun Microsystems - Beijing China 		break;
206210115c80Sfei feng - Sun Microsystems - Beijing China 	default:
206310115c80Sfei feng - Sun Microsystems - Beijing China 		break;
206410115c80Sfei feng - Sun Microsystems - Beijing China 	}
206510115c80Sfei feng - Sun Microsystems - Beijing China 
206610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
206710115c80Sfei feng - Sun Microsystems - Beijing China 
206810115c80Sfei feng - Sun Microsystems - Beijing China 	err = sc->sc_newstate(ic, nstate, arg);
206910115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
207010115c80Sfei feng - Sun Microsystems - Beijing China }
207110115c80Sfei feng - Sun Microsystems - Beijing China 
207210115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
207310115c80Sfei feng - Sun Microsystems - Beijing China static struct ieee80211_node *
rt2661_node_alloc(ieee80211com_t * ic)207410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_node_alloc(ieee80211com_t *ic)
207510115c80Sfei feng - Sun Microsystems - Beijing China {
207610115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_node *rn;
207710115c80Sfei feng - Sun Microsystems - Beijing China 
207810115c80Sfei feng - Sun Microsystems - Beijing China 	rn = kmem_zalloc(sizeof (struct rt2661_node), KM_SLEEP);
207910115c80Sfei feng - Sun Microsystems - Beijing China 	return ((rn != NULL) ? &rn->ni : NULL);
208010115c80Sfei feng - Sun Microsystems - Beijing China }
208110115c80Sfei feng - Sun Microsystems - Beijing China 
208210115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_node_free(struct ieee80211_node * in)208310115c80Sfei feng - Sun Microsystems - Beijing China rt2661_node_free(struct ieee80211_node *in)
208410115c80Sfei feng - Sun Microsystems - Beijing China {
208510115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = in->in_ic;
208610115c80Sfei feng - Sun Microsystems - Beijing China 
208710115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_node_cleanup(in);
208810115c80Sfei feng - Sun Microsystems - Beijing China 	if (in->in_wpa_ie != NULL)
208910115c80Sfei feng - Sun Microsystems - Beijing China 		ieee80211_free(in->in_wpa_ie);
209010115c80Sfei feng - Sun Microsystems - Beijing China 	kmem_free(in, sizeof (struct rt2661_node));
209110115c80Sfei feng - Sun Microsystems - Beijing China }
209210115c80Sfei feng - Sun Microsystems - Beijing China 
209310115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_stop_locked(struct rt2661_softc * sc)209410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_stop_locked(struct rt2661_softc *sc)
209510115c80Sfei feng - Sun Microsystems - Beijing China {
209610115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
209710115c80Sfei feng - Sun Microsystems - Beijing China 
209810115c80Sfei feng - Sun Microsystems - Beijing China 	if (RT2661_IS_RUNNING(sc)) {
209910115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_tx_timer = 0;
210010115c80Sfei feng - Sun Microsystems - Beijing China 
210110115c80Sfei feng - Sun Microsystems - Beijing China 		/* abort Tx (for all 5 Tx rings) */
210210115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
210310115c80Sfei feng - Sun Microsystems - Beijing China 
210410115c80Sfei feng - Sun Microsystems - Beijing China 		/* disable Rx (value remains after reset!) */
210510115c80Sfei feng - Sun Microsystems - Beijing China 		tmp = RT2661_READ(sc, RT2661_TXRX_CSR0);
210610115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
210710115c80Sfei feng - Sun Microsystems - Beijing China 
210810115c80Sfei feng - Sun Microsystems - Beijing China 		/* reset ASIC */
210910115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_MAC_CSR1, 3);
211010115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_MAC_CSR1, 0);
211110115c80Sfei feng - Sun Microsystems - Beijing China 
211210115c80Sfei feng - Sun Microsystems - Beijing China 		/* disable interrupts */
211310115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
211410115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
211510115c80Sfei feng - Sun Microsystems - Beijing China 
211610115c80Sfei feng - Sun Microsystems - Beijing China 		/* clear any pending interrupt */
211710115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
211810115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff);
211910115c80Sfei feng - Sun Microsystems - Beijing China 
212010115c80Sfei feng - Sun Microsystems - Beijing China 		/* reset Tx and Rx rings */
212110115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_reset_tx_ring(sc, &sc->txq[0]);
212210115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_reset_tx_ring(sc, &sc->txq[1]);
212310115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_reset_tx_ring(sc, &sc->txq[2]);
212410115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_reset_tx_ring(sc, &sc->txq[3]);
212510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_reset_tx_ring(sc, &sc->mgtq);
212610115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_reset_rx_ring(sc, &sc->rxq);
212710115c80Sfei feng - Sun Microsystems - Beijing China 	}
212810115c80Sfei feng - Sun Microsystems - Beijing China }
212910115c80Sfei feng - Sun Microsystems - Beijing China 
213010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_set_macaddr(struct rt2661_softc * sc,const uint8_t * addr)213110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_set_macaddr(struct rt2661_softc *sc, const uint8_t *addr)
213210115c80Sfei feng - Sun Microsystems - Beijing China {
213310115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
213410115c80Sfei feng - Sun Microsystems - Beijing China 
213510115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
213610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR2, tmp);
213710115c80Sfei feng - Sun Microsystems - Beijing China 
213810115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = addr[4] | addr[5] << 8 | 0xff << 16;
213910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR3, tmp);
214010115c80Sfei feng - Sun Microsystems - Beijing China }
214110115c80Sfei feng - Sun Microsystems - Beijing China 
214210115c80Sfei feng - Sun Microsystems - Beijing China static uint8_t
rt2661_bbp_read(struct rt2661_softc * sc,uint8_t reg)214310115c80Sfei feng - Sun Microsystems - Beijing China rt2661_bbp_read(struct rt2661_softc *sc, uint8_t reg)
214410115c80Sfei feng - Sun Microsystems - Beijing China {
214510115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t val;
214610115c80Sfei feng - Sun Microsystems - Beijing China 	int ntries;
214710115c80Sfei feng - Sun Microsystems - Beijing China 
214810115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 100; ntries++) {
214910115c80Sfei feng - Sun Microsystems - Beijing China 		if (!(RT2661_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
215010115c80Sfei feng - Sun Microsystems - Beijing China 			break;
215110115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1);
215210115c80Sfei feng - Sun Microsystems - Beijing China 	}
215310115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 100) {
215410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_read(): "
215510115c80Sfei feng - Sun Microsystems - Beijing China 		    "could not read from BBP\n");
215610115c80Sfei feng - Sun Microsystems - Beijing China 		return (0);
215710115c80Sfei feng - Sun Microsystems - Beijing China 	}
215810115c80Sfei feng - Sun Microsystems - Beijing China 
215910115c80Sfei feng - Sun Microsystems - Beijing China 	val = RT2661_BBP_BUSY | RT2661_BBP_READ | reg << 8;
216010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_PHY_CSR3, val);
216110115c80Sfei feng - Sun Microsystems - Beijing China 
216210115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 100; ntries++) {
216310115c80Sfei feng - Sun Microsystems - Beijing China 		val = RT2661_READ(sc, RT2661_PHY_CSR3);
216410115c80Sfei feng - Sun Microsystems - Beijing China 		if (!(val & RT2661_BBP_BUSY))
216510115c80Sfei feng - Sun Microsystems - Beijing China 			return (val & 0xff);
216610115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1);
216710115c80Sfei feng - Sun Microsystems - Beijing China 	}
216810115c80Sfei feng - Sun Microsystems - Beijing China 
216910115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_read(): "
217010115c80Sfei feng - Sun Microsystems - Beijing China 	    "could not read from BBP\n");
217110115c80Sfei feng - Sun Microsystems - Beijing China 	return (0);
217210115c80Sfei feng - Sun Microsystems - Beijing China }
217310115c80Sfei feng - Sun Microsystems - Beijing China 
217410115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_bbp_init(struct rt2661_softc * sc)217510115c80Sfei feng - Sun Microsystems - Beijing China rt2661_bbp_init(struct rt2661_softc *sc)
217610115c80Sfei feng - Sun Microsystems - Beijing China {
217710115c80Sfei feng - Sun Microsystems - Beijing China #define	N(a)	(sizeof (a) / sizeof ((a)[0]))
217810115c80Sfei feng - Sun Microsystems - Beijing China 
217910115c80Sfei feng - Sun Microsystems - Beijing China 	int i, ntries;
218010115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t	val;
218110115c80Sfei feng - Sun Microsystems - Beijing China 
218210115c80Sfei feng - Sun Microsystems - Beijing China 	/* wait for BBP to be ready */
218310115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 100; ntries++) {
218410115c80Sfei feng - Sun Microsystems - Beijing China 		val = rt2661_bbp_read(sc, 0);
218510115c80Sfei feng - Sun Microsystems - Beijing China 		if (val != 0 && val != 0xff)
218610115c80Sfei feng - Sun Microsystems - Beijing China 			break;
218710115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(100);
218810115c80Sfei feng - Sun Microsystems - Beijing China 	}
218910115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 100) {
219010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_init(): "
219110115c80Sfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for BBP\n");
219210115c80Sfei feng - Sun Microsystems - Beijing China 		return (RT2661_FAILURE);
219310115c80Sfei feng - Sun Microsystems - Beijing China 	}
219410115c80Sfei feng - Sun Microsystems - Beijing China 
219510115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize BBP registers to default values */
219610115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < N(rt2661_def_bbp); i++) {
219710115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, rt2661_def_bbp[i].reg,
219810115c80Sfei feng - Sun Microsystems - Beijing China 		    rt2661_def_bbp[i].val);
219910115c80Sfei feng - Sun Microsystems - Beijing China 	}
220010115c80Sfei feng - Sun Microsystems - Beijing China 
220110115c80Sfei feng - Sun Microsystems - Beijing China 	/* write vendor-specific BBP values (from EEPROM) */
220210115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 16; i++) {
220310115c80Sfei feng - Sun Microsystems - Beijing China 		if (sc->bbp_prom[i].reg == 0)
220410115c80Sfei feng - Sun Microsystems - Beijing China 			continue;
220510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
220610115c80Sfei feng - Sun Microsystems - Beijing China 	}
220710115c80Sfei feng - Sun Microsystems - Beijing China 
220810115c80Sfei feng - Sun Microsystems - Beijing China 	return (RT2661_SUCCESS);
220910115c80Sfei feng - Sun Microsystems - Beijing China #undef N
221010115c80Sfei feng - Sun Microsystems - Beijing China }
221110115c80Sfei feng - Sun Microsystems - Beijing China 
221210115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_bbp_write(struct rt2661_softc * sc,uint8_t reg,uint8_t val)221310115c80Sfei feng - Sun Microsystems - Beijing China rt2661_bbp_write(struct rt2661_softc *sc, uint8_t reg, uint8_t val)
221410115c80Sfei feng - Sun Microsystems - Beijing China {
221510115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
221610115c80Sfei feng - Sun Microsystems - Beijing China 	int ntries;
221710115c80Sfei feng - Sun Microsystems - Beijing China 
221810115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 100; ntries++) {
221910115c80Sfei feng - Sun Microsystems - Beijing China 		if (!(RT2661_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
222010115c80Sfei feng - Sun Microsystems - Beijing China 			break;
222110115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1);
222210115c80Sfei feng - Sun Microsystems - Beijing China 	}
222310115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 100) {
222410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_bbp_write(): "
222510115c80Sfei feng - Sun Microsystems - Beijing China 		    "could not write to BBP\n");
222610115c80Sfei feng - Sun Microsystems - Beijing China 		return;
222710115c80Sfei feng - Sun Microsystems - Beijing China 	}
222810115c80Sfei feng - Sun Microsystems - Beijing China 
222910115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_BBP_BUSY | (reg & 0x7f) << 8 | val;
223010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_PHY_CSR3, tmp);
223110115c80Sfei feng - Sun Microsystems - Beijing China 
223210115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_HW, "rwd: rt2661_bbp_write(): "
223310115c80Sfei feng - Sun Microsystems - Beijing China 	    "BBP R%u <- 0x%02x\n", reg, val);
223410115c80Sfei feng - Sun Microsystems - Beijing China }
223510115c80Sfei feng - Sun Microsystems - Beijing China 
223610115c80Sfei feng - Sun Microsystems - Beijing China /*
223710115c80Sfei feng - Sun Microsystems - Beijing China  * Reprogram MAC/BBP to switch to a new band.  Values taken from the reference
223810115c80Sfei feng - Sun Microsystems - Beijing China  * driver.
223910115c80Sfei feng - Sun Microsystems - Beijing China  */
224010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_select_band(struct rt2661_softc * sc,struct ieee80211_channel * c)224110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
224210115c80Sfei feng - Sun Microsystems - Beijing China {
224310115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
224410115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
224510115c80Sfei feng - Sun Microsystems - Beijing China 
224610115c80Sfei feng - Sun Microsystems - Beijing China 	/* update all BBP registers that depend on the band */
224710115c80Sfei feng - Sun Microsystems - Beijing China 	bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
224810115c80Sfei feng - Sun Microsystems - Beijing China 	bbp35 = 0x50; bbp97 = 0x48; bbp98  = 0x48;
224910115c80Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_5GHZ(c)) {
225010115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c;
225110115c80Sfei feng - Sun Microsystems - Beijing China 		bbp35 += 0x10; bbp97 += 0x10; bbp98  += 0x10;
225210115c80Sfei feng - Sun Microsystems - Beijing China 	}
225310115c80Sfei feng - Sun Microsystems - Beijing China 	if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
225410115c80Sfei feng - Sun Microsystems - Beijing China 	    (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
225510115c80Sfei feng - Sun Microsystems - Beijing China 		bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10;
225610115c80Sfei feng - Sun Microsystems - Beijing China 	}
225710115c80Sfei feng - Sun Microsystems - Beijing China 
225810115c80Sfei feng - Sun Microsystems - Beijing China 	sc->bbp17 = bbp17;
225910115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc,  17, bbp17);
226010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc,  96, bbp96);
226110115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc, 104, bbp104);
226210115c80Sfei feng - Sun Microsystems - Beijing China 
226310115c80Sfei feng - Sun Microsystems - Beijing China 	if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
226410115c80Sfei feng - Sun Microsystems - Beijing China 	    (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
226510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, 75, 0x80);
226610115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, 86, 0x80);
226710115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, 88, 0x80);
226810115c80Sfei feng - Sun Microsystems - Beijing China 	}
226910115c80Sfei feng - Sun Microsystems - Beijing China 
227010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc, 35, bbp35);
227110115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc, 97, bbp97);
227210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc, 98, bbp98);
227310115c80Sfei feng - Sun Microsystems - Beijing China 
227410115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_PHY_CSR0);
227510115c80Sfei feng - Sun Microsystems - Beijing China 	tmp &= ~(RT2661_PA_PE_2GHZ | RT2661_PA_PE_5GHZ);
227610115c80Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_2GHZ(c))
227710115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_PA_PE_2GHZ;
227810115c80Sfei feng - Sun Microsystems - Beijing China 	else
227910115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_PA_PE_5GHZ;
228010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_PHY_CSR0, tmp);
228110115c80Sfei feng - Sun Microsystems - Beijing China 
228210115c80Sfei feng - Sun Microsystems - Beijing China 	/* 802.11a uses a 16 microseconds short interframe space */
228310115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10;
228410115c80Sfei feng - Sun Microsystems - Beijing China }
228510115c80Sfei feng - Sun Microsystems - Beijing China 
228610115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_select_antenna(struct rt2661_softc * sc)228710115c80Sfei feng - Sun Microsystems - Beijing China rt2661_select_antenna(struct rt2661_softc *sc)
228810115c80Sfei feng - Sun Microsystems - Beijing China {
228910115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t bbp4, bbp77;
229010115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
229110115c80Sfei feng - Sun Microsystems - Beijing China 
229210115c80Sfei feng - Sun Microsystems - Beijing China 	bbp4  = rt2661_bbp_read(sc,  4);
229310115c80Sfei feng - Sun Microsystems - Beijing China 	bbp77 = rt2661_bbp_read(sc, 77);
229410115c80Sfei feng - Sun Microsystems - Beijing China 
229510115c80Sfei feng - Sun Microsystems - Beijing China 	/* TBD */
229610115c80Sfei feng - Sun Microsystems - Beijing China 
229710115c80Sfei feng - Sun Microsystems - Beijing China 	/* make sure Rx is disabled before switching antenna */
229810115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_TXRX_CSR0);
229910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
230010115c80Sfei feng - Sun Microsystems - Beijing China 
230110115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc,  4, bbp4);
230210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc, 77, bbp77);
230310115c80Sfei feng - Sun Microsystems - Beijing China 
230410115c80Sfei feng - Sun Microsystems - Beijing China 	/* restore Rx filter */
230510115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp);
230610115c80Sfei feng - Sun Microsystems - Beijing China }
230710115c80Sfei feng - Sun Microsystems - Beijing China 
230810115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_rf_write(struct rt2661_softc * sc,uint8_t reg,uint32_t val)230910115c80Sfei feng - Sun Microsystems - Beijing China rt2661_rf_write(struct rt2661_softc *sc, uint8_t reg, uint32_t val)
231010115c80Sfei feng - Sun Microsystems - Beijing China {
231110115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp;
231210115c80Sfei feng - Sun Microsystems - Beijing China 	int ntries;
231310115c80Sfei feng - Sun Microsystems - Beijing China 
231410115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 100; ntries++) {
231510115c80Sfei feng - Sun Microsystems - Beijing China 		if (!(RT2661_READ(sc, RT2661_PHY_CSR4) & RT2661_RF_BUSY))
231610115c80Sfei feng - Sun Microsystems - Beijing China 			break;
231710115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1);
231810115c80Sfei feng - Sun Microsystems - Beijing China 	}
231910115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 100) {
232010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_rf_write(): "
232110115c80Sfei feng - Sun Microsystems - Beijing China 		    "could not write to RF\n");
232210115c80Sfei feng - Sun Microsystems - Beijing China 		return;
232310115c80Sfei feng - Sun Microsystems - Beijing China 	}
232410115c80Sfei feng - Sun Microsystems - Beijing China 
232510115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_RF_BUSY | RT2661_RF_21BIT | (val & 0x1fffff) << 2 |
232610115c80Sfei feng - Sun Microsystems - Beijing China 	    (reg & 3);
232710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_PHY_CSR4, tmp);
232810115c80Sfei feng - Sun Microsystems - Beijing China 
232910115c80Sfei feng - Sun Microsystems - Beijing China 	/* remember last written value in sc */
233010115c80Sfei feng - Sun Microsystems - Beijing China 	sc->rf_regs[reg] = val;
233110115c80Sfei feng - Sun Microsystems - Beijing China 
233210115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_FW, "rwd: rt2661_rf_write(): "
233310115c80Sfei feng - Sun Microsystems - Beijing China 	    "RF R[%u] <- 0x%05x\n", reg & 3, val & 0x1fffff);
233410115c80Sfei feng - Sun Microsystems - Beijing China }
233510115c80Sfei feng - Sun Microsystems - Beijing China 
233610115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_set_chan(struct rt2661_softc * sc,struct ieee80211_channel * c)233710115c80Sfei feng - Sun Microsystems - Beijing China rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
233810115c80Sfei feng - Sun Microsystems - Beijing China {
233910115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
234010115c80Sfei feng - Sun Microsystems - Beijing China 	const struct rfprog *rfprog;
234110115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
234210115c80Sfei feng - Sun Microsystems - Beijing China 	int8_t power;
234310115c80Sfei feng - Sun Microsystems - Beijing China 	uint_t i, chan;
234410115c80Sfei feng - Sun Microsystems - Beijing China 
234510115c80Sfei feng - Sun Microsystems - Beijing China 	chan = ieee80211_chan2ieee(ic, c);
234610115c80Sfei feng - Sun Microsystems - Beijing China 	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
234710115c80Sfei feng - Sun Microsystems - Beijing China 		return;
234810115c80Sfei feng - Sun Microsystems - Beijing China 
234910115c80Sfei feng - Sun Microsystems - Beijing China 	/* select the appropriate RF settings based on what EEPROM says */
235010115c80Sfei feng - Sun Microsystems - Beijing China 	rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2;
235110115c80Sfei feng - Sun Microsystems - Beijing China 
235210115c80Sfei feng - Sun Microsystems - Beijing China 	/* find the settings for this channel (we know it exists) */
235310115c80Sfei feng - Sun Microsystems - Beijing China 	i = 0;
235410115c80Sfei feng - Sun Microsystems - Beijing China 	while (rfprog[i].chan != chan)
235510115c80Sfei feng - Sun Microsystems - Beijing China 		i++;
235610115c80Sfei feng - Sun Microsystems - Beijing China 
235710115c80Sfei feng - Sun Microsystems - Beijing China 	power = sc->txpow[i];
235810115c80Sfei feng - Sun Microsystems - Beijing China 	if (power < 0) {
235910115c80Sfei feng - Sun Microsystems - Beijing China 		bbp94 += power;
236010115c80Sfei feng - Sun Microsystems - Beijing China 		power = 0;
236110115c80Sfei feng - Sun Microsystems - Beijing China 	} else if (power > 31) {
236210115c80Sfei feng - Sun Microsystems - Beijing China 		bbp94 += power - 31;
236310115c80Sfei feng - Sun Microsystems - Beijing China 		power = 31;
236410115c80Sfei feng - Sun Microsystems - Beijing China 	}
236510115c80Sfei feng - Sun Microsystems - Beijing China 
236610115c80Sfei feng - Sun Microsystems - Beijing China 	/*
236710115c80Sfei feng - Sun Microsystems - Beijing China 	 * If we are switching from the 2GHz band to the 5GHz band or
236810115c80Sfei feng - Sun Microsystems - Beijing China 	 * vice-versa, BBP registers need to be reprogrammed.
236910115c80Sfei feng - Sun Microsystems - Beijing China 	 */
237010115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_flags != sc->sc_curchan->ich_flags) {
237110115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_select_band(sc, c);
237210115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_select_antenna(sc);
237310115c80Sfei feng - Sun Microsystems - Beijing China 	}
237410115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_curchan = c;
237510115c80Sfei feng - Sun Microsystems - Beijing China 
237610115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF1, rfprog[i].r1);
237710115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF2, rfprog[i].r2);
237810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF3, rfprog[i].r3 | power << 7);
237910115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF4, rfprog[i].r4 | sc->rffreq << 10);
238010115c80Sfei feng - Sun Microsystems - Beijing China 
238110115c80Sfei feng - Sun Microsystems - Beijing China 	DELAY(200);
238210115c80Sfei feng - Sun Microsystems - Beijing China 
238310115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF1, rfprog[i].r1);
238410115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF2, rfprog[i].r2);
238510115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF3, rfprog[i].r3 | power << 7 | 1);
238610115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF4, rfprog[i].r4 | sc->rffreq << 10);
238710115c80Sfei feng - Sun Microsystems - Beijing China 
238810115c80Sfei feng - Sun Microsystems - Beijing China 	DELAY(200);
238910115c80Sfei feng - Sun Microsystems - Beijing China 
239010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF1, rfprog[i].r1);
239110115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF2, rfprog[i].r2);
239210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF3, rfprog[i].r3 | power << 7);
239310115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_rf_write(sc, RT2661_RF4, rfprog[i].r4 | sc->rffreq << 10);
239410115c80Sfei feng - Sun Microsystems - Beijing China 
239510115c80Sfei feng - Sun Microsystems - Beijing China 	/* enable smart mode for MIMO-capable RFs */
239610115c80Sfei feng - Sun Microsystems - Beijing China 	bbp3 = rt2661_bbp_read(sc, 3);
239710115c80Sfei feng - Sun Microsystems - Beijing China 
239810115c80Sfei feng - Sun Microsystems - Beijing China 	bbp3 &= ~RT2661_SMART_MODE;
239910115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc->rf_rev == RT2661_RF_5325 || sc->rf_rev == RT2661_RF_2529)
240010115c80Sfei feng - Sun Microsystems - Beijing China 		bbp3 |= RT2661_SMART_MODE;
240110115c80Sfei feng - Sun Microsystems - Beijing China 
240210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_bbp_write(sc, 3, bbp3);
240310115c80Sfei feng - Sun Microsystems - Beijing China 
240410115c80Sfei feng - Sun Microsystems - Beijing China 	if (bbp94 != RT2661_BBPR94_DEFAULT)
240510115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_bbp_write(sc, 94, bbp94);
240610115c80Sfei feng - Sun Microsystems - Beijing China 
240710115c80Sfei feng - Sun Microsystems - Beijing China 	/* 5GHz radio needs a 1ms delay here */
240810115c80Sfei feng - Sun Microsystems - Beijing China 	if (IEEE80211_IS_CHAN_5GHZ(c))
240910115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1000);
241010115c80Sfei feng - Sun Microsystems - Beijing China }
241110115c80Sfei feng - Sun Microsystems - Beijing China 
241210115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_init(struct rt2661_softc * sc)241310115c80Sfei feng - Sun Microsystems - Beijing China rt2661_init(struct rt2661_softc *sc)
241410115c80Sfei feng - Sun Microsystems - Beijing China {
241510115c80Sfei feng - Sun Microsystems - Beijing China #define	N(a)	(sizeof (a) / sizeof ((a)[0]))
241610115c80Sfei feng - Sun Microsystems - Beijing China 
241710115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
241810115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t tmp, sta[3], *fptr;
241910115c80Sfei feng - Sun Microsystems - Beijing China 	int i, err, off, ntries;
242010115c80Sfei feng - Sun Microsystems - Beijing China 
242110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
242210115c80Sfei feng - Sun Microsystems - Beijing China 
242310115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_stop_locked(sc);
242410115c80Sfei feng - Sun Microsystems - Beijing China 
242510115c80Sfei feng - Sun Microsystems - Beijing China 	if (!RT2661_IS_FWLOADED(sc)) {
242610115c80Sfei feng - Sun Microsystems - Beijing China 		err = rt2661_load_microcode(sc, ucode, usize);
242710115c80Sfei feng - Sun Microsystems - Beijing China 		if (err != RT2661_SUCCESS) {
242810115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
242910115c80Sfei feng - Sun Microsystems - Beijing China 			    "could not load 8051 microcode\n");
243010115c80Sfei feng - Sun Microsystems - Beijing China 			return (DDI_FAILURE);
243110115c80Sfei feng - Sun Microsystems - Beijing China 		}
243210115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags |= RT2661_F_FWLOADED;
243310115c80Sfei feng - Sun Microsystems - Beijing China 	}
243410115c80Sfei feng - Sun Microsystems - Beijing China 
243510115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize Tx rings */
243610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_AC1_BASE_CSR, sc->txq[1].paddr);
243710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_AC0_BASE_CSR, sc->txq[0].paddr);
243810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_AC2_BASE_CSR, sc->txq[2].paddr);
243910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_AC3_BASE_CSR, sc->txq[3].paddr);
244010115c80Sfei feng - Sun Microsystems - Beijing China 
244110115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize Mgt ring */
244210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MGT_BASE_CSR, sc->mgtq.paddr);
244310115c80Sfei feng - Sun Microsystems - Beijing China 
244410115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize Rx ring */
244510115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_RX_BASE_CSR, sc->rxq.paddr);
244610115c80Sfei feng - Sun Microsystems - Beijing China 
244710115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize Tx rings sizes */
244810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TX_RING_CSR0,
244910115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_RING_COUNT << 24 |
245010115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_RING_COUNT << 16 |
245110115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_RING_COUNT <<  8 |
245210115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_RING_COUNT);
245310115c80Sfei feng - Sun Microsystems - Beijing China 
245410115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TX_RING_CSR1,
245510115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_DESC_WSIZE << 16 |
245610115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_TX_RING_COUNT <<  8 |
245710115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_MGT_RING_COUNT);
245810115c80Sfei feng - Sun Microsystems - Beijing China 
245910115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize Rx rings */
246010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_RX_RING_CSR,
246110115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_RX_DESC_BACK  << 16 |
246210115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_RX_DESC_WSIZE <<  8 |
246310115c80Sfei feng - Sun Microsystems - Beijing China 	    RT2661_RX_RING_COUNT);
246410115c80Sfei feng - Sun Microsystems - Beijing China 
246510115c80Sfei feng - Sun Microsystems - Beijing China 	/* XXX: some magic here */
246610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TX_DMA_DST_CSR, 0xaa);
246710115c80Sfei feng - Sun Microsystems - Beijing China 
246810115c80Sfei feng - Sun Microsystems - Beijing China 	/* load base addresses of all 5 Tx rings (4 data + 1 mgt) */
246910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_LOAD_TX_RING_CSR, 0x1f);
247010115c80Sfei feng - Sun Microsystems - Beijing China 
247110115c80Sfei feng - Sun Microsystems - Beijing China 	/* load base address of Rx ring */
247210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_RX_CNTL_CSR, 2);
247310115c80Sfei feng - Sun Microsystems - Beijing China 
247410115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize MAC registers to default values */
247510115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < N(rt2661_def_mac); i++)
247610115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
247710115c80Sfei feng - Sun Microsystems - Beijing China 
247810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_set_macaddr(sc, ic->ic_macaddr);
247910115c80Sfei feng - Sun Microsystems - Beijing China 
248010115c80Sfei feng - Sun Microsystems - Beijing China 	/* set host ready */
248110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR1, 3);
248210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR1, 0);
248310115c80Sfei feng - Sun Microsystems - Beijing China 
248410115c80Sfei feng - Sun Microsystems - Beijing China 	/* wait for BBP/RF to wakeup */
248510115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 1000; ntries++) {
248610115c80Sfei feng - Sun Microsystems - Beijing China 		if (RT2661_READ(sc, RT2661_MAC_CSR12) & 8)
248710115c80Sfei feng - Sun Microsystems - Beijing China 			break;
248810115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1000);
248910115c80Sfei feng - Sun Microsystems - Beijing China 	}
249010115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 1000) {
249110115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
249210115c80Sfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for BBP/RF to wakeup\n");
249310115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_stop_locked(sc);
249410115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
249510115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
249610115c80Sfei feng - Sun Microsystems - Beijing China 	}
249710115c80Sfei feng - Sun Microsystems - Beijing China 
249810115c80Sfei feng - Sun Microsystems - Beijing China 	if (rt2661_bbp_init(sc) != RT2661_SUCCESS) {
249910115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_stop_locked(sc);
250010115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
250110115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
250210115c80Sfei feng - Sun Microsystems - Beijing China 	}
250310115c80Sfei feng - Sun Microsystems - Beijing China 
250410115c80Sfei feng - Sun Microsystems - Beijing China 	/* select default channel */
250510115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_curchan = ic->ic_bss->in_chan = ic->ic_curchan;
250610115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_select_band(sc, sc->sc_curchan);
250710115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_select_antenna(sc);
250810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_set_chan(sc, sc->sc_curchan);
250910115c80Sfei feng - Sun Microsystems - Beijing China 
251010115c80Sfei feng - Sun Microsystems - Beijing China 	/* update Rx filter */
251110115c80Sfei feng - Sun Microsystems - Beijing China 	tmp = RT2661_READ(sc, RT2661_TXRX_CSR0) & 0xffff;
251210115c80Sfei feng - Sun Microsystems - Beijing China 
251310115c80Sfei feng - Sun Microsystems - Beijing China 	tmp |= RT2661_DROP_PHY_ERROR | RT2661_DROP_CRC_ERROR;
251410115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
251510115c80Sfei feng - Sun Microsystems - Beijing China 		tmp |= RT2661_DROP_CTL | RT2661_DROP_VER_ERROR |
251610115c80Sfei feng - Sun Microsystems - Beijing China 		    RT2661_DROP_ACKCTS;
251710115c80Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_opmode != IEEE80211_M_HOSTAP)
251810115c80Sfei feng - Sun Microsystems - Beijing China 			tmp |= RT2661_DROP_TODS;
251910115c80Sfei feng - Sun Microsystems - Beijing China 		if (!(sc->sc_rcr & RT2661_RCR_PROMISC))
252010115c80Sfei feng - Sun Microsystems - Beijing China 			tmp |= RT2661_DROP_NOT_TO_ME;
252110115c80Sfei feng - Sun Microsystems - Beijing China 	}
252210115c80Sfei feng - Sun Microsystems - Beijing China 
252310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_TXRX_CSR0, tmp);
252410115c80Sfei feng - Sun Microsystems - Beijing China 
252510115c80Sfei feng - Sun Microsystems - Beijing China 	/* clear STA registers */
252610115c80Sfei feng - Sun Microsystems - Beijing China 	off = RT2661_STA_CSR0;
252710115c80Sfei feng - Sun Microsystems - Beijing China 	fptr = sta;
252810115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < N(sta); i++) {
252910115c80Sfei feng - Sun Microsystems - Beijing China 		*fptr = RT2661_MEM_READ1(sc, off++);
253010115c80Sfei feng - Sun Microsystems - Beijing China 	}
253110115c80Sfei feng - Sun Microsystems - Beijing China 
253210115c80Sfei feng - Sun Microsystems - Beijing China 	/* initialize ASIC */
253310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MAC_CSR1, 4);
253410115c80Sfei feng - Sun Microsystems - Beijing China 
253510115c80Sfei feng - Sun Microsystems - Beijing China 	/* clear any pending interrupt */
253610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
253710115c80Sfei feng - Sun Microsystems - Beijing China 
253810115c80Sfei feng - Sun Microsystems - Beijing China 	/* enable interrupts */
253910115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
254010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
254110115c80Sfei feng - Sun Microsystems - Beijing China 
254210115c80Sfei feng - Sun Microsystems - Beijing China 	/* kick Rx */
254310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
254410115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
254510115c80Sfei feng - Sun Microsystems - Beijing China 
254610115c80Sfei feng - Sun Microsystems - Beijing China #undef N
254710115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
254810115c80Sfei feng - Sun Microsystems - Beijing China }
254910115c80Sfei feng - Sun Microsystems - Beijing China 
255010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_stop(struct rt2661_softc * sc)255110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_stop(struct rt2661_softc *sc)
255210115c80Sfei feng - Sun Microsystems - Beijing China {
255310115c80Sfei feng - Sun Microsystems - Beijing China 	if (!RT2661_IS_FASTREBOOT(sc))
255410115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GLOCK(sc);
255510115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_stop_locked(sc);
255610115c80Sfei feng - Sun Microsystems - Beijing China 	if (!RT2661_IS_FASTREBOOT(sc))
255710115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
255810115c80Sfei feng - Sun Microsystems - Beijing China }
255910115c80Sfei feng - Sun Microsystems - Beijing China 
256010115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_start(void * arg)256110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_start(void *arg)
256210115c80Sfei feng - Sun Microsystems - Beijing China {
256310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
256410115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
256510115c80Sfei feng - Sun Microsystems - Beijing China 	int err;
256610115c80Sfei feng - Sun Microsystems - Beijing China 
256710115c80Sfei feng - Sun Microsystems - Beijing China 	err = rt2661_init(sc);
256810115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
256910115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_m_start():"
257010115c80Sfei feng - Sun Microsystems - Beijing China 		    "Hardware initialization failed\n");
257110115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
257210115c80Sfei feng - Sun Microsystems - Beijing China 	}
257310115c80Sfei feng - Sun Microsystems - Beijing China 
257410115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
257510115c80Sfei feng - Sun Microsystems - Beijing China 
257610115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
257710115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags |= RT2661_F_RUNNING;
257810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
257910115c80Sfei feng - Sun Microsystems - Beijing China 
258010115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
258110115c80Sfei feng - Sun Microsystems - Beijing China fail1:
258210115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_stop(sc);
258310115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
258410115c80Sfei feng - Sun Microsystems - Beijing China }
258510115c80Sfei feng - Sun Microsystems - Beijing China 
258610115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_m_stop(void * arg)258710115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_stop(void *arg)
258810115c80Sfei feng - Sun Microsystems - Beijing China {
258910115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
259010115c80Sfei feng - Sun Microsystems - Beijing China 
259110115c80Sfei feng - Sun Microsystems - Beijing China 	(void) rt2661_stop(sc);
259210115c80Sfei feng - Sun Microsystems - Beijing China 
259310115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
259410115c80Sfei feng - Sun Microsystems - Beijing China 
259510115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
259610115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags &= ~RT2661_F_RUNNING;
259710115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
259810115c80Sfei feng - Sun Microsystems - Beijing China }
259910115c80Sfei feng - Sun Microsystems - Beijing China 
260010115c80Sfei feng - Sun Microsystems - Beijing China static void
rt2661_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)260110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
260210115c80Sfei feng - Sun Microsystems - Beijing China {
260310115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
260410115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
260510115c80Sfei feng - Sun Microsystems - Beijing China 	int err;
260610115c80Sfei feng - Sun Microsystems - Beijing China 
260710115c80Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_ioctl(ic, wq, mp);
260810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
260910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err == ENETRESET) {
261010115c80Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen) {
261110115c80Sfei feng - Sun Microsystems - Beijing China 			if (RT2661_IS_RUNNING(sc)) {
261210115c80Sfei feng - Sun Microsystems - Beijing China 				RT2661_GUNLOCK(sc);
261310115c80Sfei feng - Sun Microsystems - Beijing China 				(void) rt2661_init(sc);
261410115c80Sfei feng - Sun Microsystems - Beijing China 				(void) ieee80211_new_state(ic,
261510115c80Sfei feng - Sun Microsystems - Beijing China 				    IEEE80211_S_SCAN, -1);
261610115c80Sfei feng - Sun Microsystems - Beijing China 				RT2661_GLOCK(sc);
261710115c80Sfei feng - Sun Microsystems - Beijing China 			}
261810115c80Sfei feng - Sun Microsystems - Beijing China 		}
261910115c80Sfei feng - Sun Microsystems - Beijing China 	}
262010115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
262110115c80Sfei feng - Sun Microsystems - Beijing China }
262210115c80Sfei feng - Sun Microsystems - Beijing China 
262310115c80Sfei feng - Sun Microsystems - Beijing China /*
262410115c80Sfei feng - Sun Microsystems - Beijing China  * Call back function for get/set proporty
262510115c80Sfei feng - Sun Microsystems - Beijing China  */
262610115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)262710115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
26280dc2366fSVenugopal Iyer     uint_t wldp_length, void *wldp_buf)
262910115c80Sfei feng - Sun Microsystems - Beijing China {
263010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
263110115c80Sfei feng - Sun Microsystems - Beijing China 	int err = 0;
263210115c80Sfei feng - Sun Microsystems - Beijing China 
263310115c80Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
26340dc2366fSVenugopal Iyer 	    wldp_length, wldp_buf);
263510115c80Sfei feng - Sun Microsystems - Beijing China 
263610115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
263710115c80Sfei feng - Sun Microsystems - Beijing China }
263810115c80Sfei feng - Sun Microsystems - Beijing China 
26390dc2366fSVenugopal Iyer static void
rt2661_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t mph)26400dc2366fSVenugopal Iyer rt2661_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
26410dc2366fSVenugopal Iyer     mac_prop_info_handle_t mph)
26420dc2366fSVenugopal Iyer {
26430dc2366fSVenugopal Iyer 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
26440dc2366fSVenugopal Iyer 
26450dc2366fSVenugopal Iyer 	ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph);
26460dc2366fSVenugopal Iyer }
26470dc2366fSVenugopal Iyer 
264810115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)264910115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
265010115c80Sfei feng - Sun Microsystems - Beijing China     uint_t wldp_length, const void *wldp_buf)
265110115c80Sfei feng - Sun Microsystems - Beijing China {
265210115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
265310115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211com_t *ic = &sc->sc_ic;
265410115c80Sfei feng - Sun Microsystems - Beijing China 	int err;
265510115c80Sfei feng - Sun Microsystems - Beijing China 
265610115c80Sfei feng - Sun Microsystems - Beijing China 	err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
265710115c80Sfei feng - Sun Microsystems - Beijing China 	    wldp_buf);
265810115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
265910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err == ENETRESET) {
266010115c80Sfei feng - Sun Microsystems - Beijing China 		if (ic->ic_des_esslen) {
266110115c80Sfei feng - Sun Microsystems - Beijing China 			if (RT2661_IS_RUNNING(sc)) {
266210115c80Sfei feng - Sun Microsystems - Beijing China 				RT2661_GUNLOCK(sc);
266310115c80Sfei feng - Sun Microsystems - Beijing China 				(void) rt2661_init(sc);
266410115c80Sfei feng - Sun Microsystems - Beijing China 				(void) ieee80211_new_state(ic,
266510115c80Sfei feng - Sun Microsystems - Beijing China 				    IEEE80211_S_SCAN, -1);
266610115c80Sfei feng - Sun Microsystems - Beijing China 				RT2661_GLOCK(sc);
266710115c80Sfei feng - Sun Microsystems - Beijing China 			}
266810115c80Sfei feng - Sun Microsystems - Beijing China 		}
266910115c80Sfei feng - Sun Microsystems - Beijing China 		err = 0;
267010115c80Sfei feng - Sun Microsystems - Beijing China 	}
267110115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
267210115c80Sfei feng - Sun Microsystems - Beijing China 	return (err);
267310115c80Sfei feng - Sun Microsystems - Beijing China }
267410115c80Sfei feng - Sun Microsystems - Beijing China 
267510115c80Sfei feng - Sun Microsystems - Beijing China static mblk_t *
rt2661_m_tx(void * arg,mblk_t * mp)267610115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_tx(void *arg, mblk_t *mp)
267710115c80Sfei feng - Sun Microsystems - Beijing China {
267810115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
267910115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
268010115c80Sfei feng - Sun Microsystems - Beijing China 	mblk_t *next;
268110115c80Sfei feng - Sun Microsystems - Beijing China 
268210115c80Sfei feng - Sun Microsystems - Beijing China 	if (RT2661_IS_SUSPEND(sc)) {
268310115c80Sfei feng - Sun Microsystems - Beijing China 		freemsgchain(mp);
268410115c80Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
268510115c80Sfei feng - Sun Microsystems - Beijing China 	}
268610115c80Sfei feng - Sun Microsystems - Beijing China 
268710115c80Sfei feng - Sun Microsystems - Beijing China 	/*
268810115c80Sfei feng - Sun Microsystems - Beijing China 	 * No data frames go out unless we're associated; this
268910115c80Sfei feng - Sun Microsystems - Beijing China 	 * should not happen as the 802.11 layer does not enable
269010115c80Sfei feng - Sun Microsystems - Beijing China 	 * the xmit queue until we enter the RUN state.
269110115c80Sfei feng - Sun Microsystems - Beijing China 	 */
269210115c80Sfei feng - Sun Microsystems - Beijing China 	if (ic->ic_state != IEEE80211_S_RUN) {
269310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_TX, "rwd: rt2661_tx_data(): "
269410115c80Sfei feng - Sun Microsystems - Beijing China 		    "discard, state %u\n", ic->ic_state);
269510115c80Sfei feng - Sun Microsystems - Beijing China 		freemsgchain(mp);
269610115c80Sfei feng - Sun Microsystems - Beijing China 		return (NULL);
269710115c80Sfei feng - Sun Microsystems - Beijing China 	}
269810115c80Sfei feng - Sun Microsystems - Beijing China 
269910115c80Sfei feng - Sun Microsystems - Beijing China 	while (mp != NULL) {
270010115c80Sfei feng - Sun Microsystems - Beijing China 		next = mp->b_next;
270110115c80Sfei feng - Sun Microsystems - Beijing China 		mp->b_next = NULL;
270210115c80Sfei feng - Sun Microsystems - Beijing China 		if (rt2661_send(ic, mp) !=
270310115c80Sfei feng - Sun Microsystems - Beijing China 		    DDI_SUCCESS) {
270410115c80Sfei feng - Sun Microsystems - Beijing China 			mp->b_next = next;
270510115c80Sfei feng - Sun Microsystems - Beijing China 			break;
270610115c80Sfei feng - Sun Microsystems - Beijing China 		}
270710115c80Sfei feng - Sun Microsystems - Beijing China 		mp = next;
270810115c80Sfei feng - Sun Microsystems - Beijing China 	}
270910115c80Sfei feng - Sun Microsystems - Beijing China 	return (mp);
271010115c80Sfei feng - Sun Microsystems - Beijing China }
271110115c80Sfei feng - Sun Microsystems - Beijing China 
271210115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
271310115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_unicst(void * arg,const uint8_t * macaddr)271410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_unicst(void *arg, const uint8_t *macaddr)
271510115c80Sfei feng - Sun Microsystems - Beijing China {
271610115c80Sfei feng - Sun Microsystems - Beijing China 	return (ENOTSUP);
271710115c80Sfei feng - Sun Microsystems - Beijing China }
271810115c80Sfei feng - Sun Microsystems - Beijing China 
271910115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
272010115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_multicst(void * arg,boolean_t add,const uint8_t * mca)272110115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
272210115c80Sfei feng - Sun Microsystems - Beijing China {
272310115c80Sfei feng - Sun Microsystems - Beijing China 	return (ENOTSUP);
272410115c80Sfei feng - Sun Microsystems - Beijing China }
272510115c80Sfei feng - Sun Microsystems - Beijing China 
272610115c80Sfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/
272710115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_promisc(void * arg,boolean_t on)272810115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_promisc(void *arg, boolean_t on)
272910115c80Sfei feng - Sun Microsystems - Beijing China {
273010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc = (struct rt2661_softc *)arg;
273110115c80Sfei feng - Sun Microsystems - Beijing China 
273210115c80Sfei feng - Sun Microsystems - Beijing China 	if (on) {
273310115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rcr |= RT2661_RCR_PROMISC;
273410115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rcr |= RT2661_RCR_MULTI;
273510115c80Sfei feng - Sun Microsystems - Beijing China 	} else {
273610115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rcr &= ~RT2661_RCR_PROMISC;
273710115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_rcr &= ~RT2661_RCR_MULTI;
273810115c80Sfei feng - Sun Microsystems - Beijing China 	}
273910115c80Sfei feng - Sun Microsystems - Beijing China 
274010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_update_promisc(sc);
274110115c80Sfei feng - Sun Microsystems - Beijing China 	return (0);
274210115c80Sfei feng - Sun Microsystems - Beijing China }
274310115c80Sfei feng - Sun Microsystems - Beijing China 
274410115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_m_stat(void * arg,uint_t stat,uint64_t * val)274510115c80Sfei feng - Sun Microsystems - Beijing China rt2661_m_stat(void *arg, uint_t stat, uint64_t *val)
274610115c80Sfei feng - Sun Microsystems - Beijing China {
274710115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc  = (struct rt2661_softc *)arg;
274810115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic = &sc->sc_ic;
274910115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_node *ni = ic->ic_bss;
275010115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211_rateset *rs = &ni->in_rates;
275110115c80Sfei feng - Sun Microsystems - Beijing China 
275210115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GLOCK(sc);
275310115c80Sfei feng - Sun Microsystems - Beijing China 	switch (stat) {
275410115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IFSPEED:
275510115c80Sfei feng - Sun Microsystems - Beijing China 		*val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
275610115c80Sfei feng - Sun Microsystems - Beijing China 		    (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL)
275710115c80Sfei feng - Sun Microsystems - Beijing China 		    : ic->ic_fixed_rate) / 2 * 1000000;
275810115c80Sfei feng - Sun Microsystems - Beijing China 		break;
275910115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_NOXMTBUF:
276010115c80Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_nobuf;
276110115c80Sfei feng - Sun Microsystems - Beijing China 		break;
276210115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_NORCVBUF:
276310115c80Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_rx_nobuf;
276410115c80Sfei feng - Sun Microsystems - Beijing China 		break;
276510115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IERRORS:
276610115c80Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_rx_err;
276710115c80Sfei feng - Sun Microsystems - Beijing China 		break;
276810115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_RBYTES:
276910115c80Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_bytes;
277010115c80Sfei feng - Sun Microsystems - Beijing China 		break;
277110115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_IPACKETS:
277210115c80Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_rx_frags;
277310115c80Sfei feng - Sun Microsystems - Beijing China 		break;
277410115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OBYTES:
277510115c80Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_bytes;
277610115c80Sfei feng - Sun Microsystems - Beijing China 		break;
277710115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OPACKETS:
277810115c80Sfei feng - Sun Microsystems - Beijing China 		*val = ic->ic_stats.is_tx_frags;
277910115c80Sfei feng - Sun Microsystems - Beijing China 		break;
278010115c80Sfei feng - Sun Microsystems - Beijing China 	case MAC_STAT_OERRORS:
278110115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FAILED:
278210115c80Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_err;
278310115c80Sfei feng - Sun Microsystems - Beijing China 		break;
278410115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_RETRANS:
278510115c80Sfei feng - Sun Microsystems - Beijing China 		*val = sc->sc_tx_retries;
278610115c80Sfei feng - Sun Microsystems - Beijing China 		break;
278710115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_FCS_ERRORS:
278810115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_WEP_ERRORS:
278910115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_TX_FRAGS:
279010115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_TX:
279110115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_SUCCESS:
279210115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RTS_FAILURE:
279310115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_ACK_FAILURE:
279410115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_FRAGS:
279510115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_MCAST_RX:
279610115c80Sfei feng - Sun Microsystems - Beijing China 	case WIFI_STAT_RX_DUPS:
279710115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
279810115c80Sfei feng - Sun Microsystems - Beijing China 		return (ieee80211_stat(ic, stat, val));
279910115c80Sfei feng - Sun Microsystems - Beijing China 	default:
280010115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
280110115c80Sfei feng - Sun Microsystems - Beijing China 		return (ENOTSUP);
280210115c80Sfei feng - Sun Microsystems - Beijing China 	}
280310115c80Sfei feng - Sun Microsystems - Beijing China 	RT2661_GUNLOCK(sc);
280410115c80Sfei feng - Sun Microsystems - Beijing China 
280510115c80Sfei feng - Sun Microsystems - Beijing China 	return (0);
280610115c80Sfei feng - Sun Microsystems - Beijing China }
280710115c80Sfei feng - Sun Microsystems - Beijing China 
280810115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)280910115c80Sfei feng - Sun Microsystems - Beijing China rt2661_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
281010115c80Sfei feng - Sun Microsystems - Beijing China {
281110115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc;
281210115c80Sfei feng - Sun Microsystems - Beijing China 	struct ieee80211com *ic;
281310115c80Sfei feng - Sun Microsystems - Beijing China 
281410115c80Sfei feng - Sun Microsystems - Beijing China 	int i, ac, err, ntries, instance;
281510115c80Sfei feng - Sun Microsystems - Beijing China 	int intr_type, intr_count, intr_actual;
281610115c80Sfei feng - Sun Microsystems - Beijing China 	char strbuf[32];
281710115c80Sfei feng - Sun Microsystems - Beijing China 	uint8_t cachelsz;
281810115c80Sfei feng - Sun Microsystems - Beijing China 	uint16_t command, vendor_id, device_id;
281910115c80Sfei feng - Sun Microsystems - Beijing China 	uint32_t val;
282010115c80Sfei feng - Sun Microsystems - Beijing China 
282110115c80Sfei feng - Sun Microsystems - Beijing China 	wifi_data_t wd = { 0 };
282210115c80Sfei feng - Sun Microsystems - Beijing China 	mac_register_t *macp;
282310115c80Sfei feng - Sun Microsystems - Beijing China 
282410115c80Sfei feng - Sun Microsystems - Beijing China 	switch (cmd) {
282510115c80Sfei feng - Sun Microsystems - Beijing China 	case DDI_ATTACH:
282610115c80Sfei feng - Sun Microsystems - Beijing China 		break;
282710115c80Sfei feng - Sun Microsystems - Beijing China 	case DDI_RESUME:
282810115c80Sfei feng - Sun Microsystems - Beijing China 		sc = ddi_get_soft_state(rt2661_soft_state_p,
282910115c80Sfei feng - Sun Microsystems - Beijing China 		    ddi_get_instance(devinfo));
283010115c80Sfei feng - Sun Microsystems - Beijing China 		ASSERT(sc != NULL);
283110115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GLOCK(sc);
283210115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags &= ~RT2661_F_SUSPEND;
283310115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
283410115c80Sfei feng - Sun Microsystems - Beijing China 		if (RT2661_IS_RUNNING(sc))
283510115c80Sfei feng - Sun Microsystems - Beijing China 			(void) rt2661_init(sc);
283610115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
283710115c80Sfei feng - Sun Microsystems - Beijing China 		    "resume now\n");
283810115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
283910115c80Sfei feng - Sun Microsystems - Beijing China 	default:
284010115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
284110115c80Sfei feng - Sun Microsystems - Beijing China 	}
284210115c80Sfei feng - Sun Microsystems - Beijing China 
284310115c80Sfei feng - Sun Microsystems - Beijing China 	instance = ddi_get_instance(devinfo);
284410115c80Sfei feng - Sun Microsystems - Beijing China 
284510115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_soft_state_zalloc(rt2661_soft_state_p, instance);
284610115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
284710115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
284810115c80Sfei feng - Sun Microsystems - Beijing China 		    "unable to alloc soft_state_p\n");
284910115c80Sfei feng - Sun Microsystems - Beijing China 		return (err);
285010115c80Sfei feng - Sun Microsystems - Beijing China 	}
285110115c80Sfei feng - Sun Microsystems - Beijing China 
285210115c80Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(rt2661_soft_state_p, instance);
285310115c80Sfei feng - Sun Microsystems - Beijing China 	ic = (struct ieee80211com *)&sc->sc_ic;
285410115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_dev = devinfo;
285510115c80Sfei feng - Sun Microsystems - Beijing China 
285610115c80Sfei feng - Sun Microsystems - Beijing China 	/* PCI configuration */
285710115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_regs_map_setup(devinfo, 0, &sc->sc_cfg_base, 0, 0,
285810115c80Sfei feng - Sun Microsystems - Beijing China 	    &rt2661_csr_accattr, &sc->sc_cfg_handle);
285910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
286010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
286110115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_regs_map_setup() failed");
286210115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail1;
286310115c80Sfei feng - Sun Microsystems - Beijing China 	}
286410115c80Sfei feng - Sun Microsystems - Beijing China 
286510115c80Sfei feng - Sun Microsystems - Beijing China 	cachelsz = ddi_get8(sc->sc_cfg_handle,
286610115c80Sfei feng - Sun Microsystems - Beijing China 	    (uint8_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
286710115c80Sfei feng - Sun Microsystems - Beijing China 	if (cachelsz == 0)
286810115c80Sfei feng - Sun Microsystems - Beijing China 		cachelsz = 0x10;
286910115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_cachelsz = cachelsz << 2;
287010115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_dmabuf_size = roundup(IEEE80211_MAX_LEN, sc->sc_cachelsz);
287110115c80Sfei feng - Sun Microsystems - Beijing China 
287210115c80Sfei feng - Sun Microsystems - Beijing China 	vendor_id = ddi_get16(sc->sc_cfg_handle,
287310115c80Sfei feng - Sun Microsystems - Beijing China 	    (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_VENID));
287410115c80Sfei feng - Sun Microsystems - Beijing China 	device_id = ddi_get16(sc->sc_cfg_handle,
287510115c80Sfei feng - Sun Microsystems - Beijing China 	    (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_DEVID));
287610115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
287710115c80Sfei feng - Sun Microsystems - Beijing China 	    "vendor 0x%x, device id 0x%x, cache size %d\n",
287810115c80Sfei feng - Sun Microsystems - Beijing China 	    vendor_id, device_id, cachelsz);
287910115c80Sfei feng - Sun Microsystems - Beijing China 
288010115c80Sfei feng - Sun Microsystems - Beijing China 	/*
288110115c80Sfei feng - Sun Microsystems - Beijing China 	 * Enable response to memory space accesses,
288210115c80Sfei feng - Sun Microsystems - Beijing China 	 * and enabe bus master.
288310115c80Sfei feng - Sun Microsystems - Beijing China 	 */
288410115c80Sfei feng - Sun Microsystems - Beijing China 	command = PCI_COMM_MAE | PCI_COMM_ME;
288510115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_put16(sc->sc_cfg_handle,
288610115c80Sfei feng - Sun Microsystems - Beijing China 	    (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_COMM),
288710115c80Sfei feng - Sun Microsystems - Beijing China 	    command);
288810115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_put8(sc->sc_cfg_handle,
288910115c80Sfei feng - Sun Microsystems - Beijing China 	    (uint8_t *)(sc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8);
289010115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_put8(sc->sc_cfg_handle,
289110115c80Sfei feng - Sun Microsystems - Beijing China 	    (uint8_t *)(sc->sc_cfg_base + PCI_CONF_ILINE), 0x10);
289210115c80Sfei feng - Sun Microsystems - Beijing China 
289310115c80Sfei feng - Sun Microsystems - Beijing China 	/* pci i/o space */
289410115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_regs_map_setup(devinfo, 1,
289510115c80Sfei feng - Sun Microsystems - Beijing China 	    &sc->sc_io_base, 0, 0, &rt2661_csr_accattr, &sc->sc_io_handle);
289610115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
289710115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
289810115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_regs_map_setup() failed");
289910115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail2;
290010115c80Sfei feng - Sun Microsystems - Beijing China 	}
290110115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
290210115c80Sfei feng - Sun Microsystems - Beijing China 	    "PCI configuration is done successfully\n");
290310115c80Sfei feng - Sun Microsystems - Beijing China 
290410115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_get_supported_types(devinfo, &intr_type);
290510115c80Sfei feng - Sun Microsystems - Beijing China 	if ((err != DDI_SUCCESS) || (!(intr_type & DDI_INTR_TYPE_FIXED))) {
290610115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
290710115c80Sfei feng - Sun Microsystems - Beijing China 		    "fixed type interrupt is not supported\n");
290810115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail3;
290910115c80Sfei feng - Sun Microsystems - Beijing China 	}
291010115c80Sfei feng - Sun Microsystems - Beijing China 
291110115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_get_nintrs(devinfo, DDI_INTR_TYPE_FIXED, &intr_count);
291210115c80Sfei feng - Sun Microsystems - Beijing China 	if ((err != DDI_SUCCESS) || (intr_count != 1)) {
291310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
291410115c80Sfei feng - Sun Microsystems - Beijing China 		    "no fixed interrupts\n");
291510115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail3;
291610115c80Sfei feng - Sun Microsystems - Beijing China 	}
291710115c80Sfei feng - Sun Microsystems - Beijing China 
291810115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
291910115c80Sfei feng - Sun Microsystems - Beijing China 
292010115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_alloc(devinfo, sc->sc_intr_htable,
292110115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_INTR_TYPE_FIXED, 0, intr_count, &intr_actual, 0);
292210115c80Sfei feng - Sun Microsystems - Beijing China 	if ((err != DDI_SUCCESS) || (intr_actual != 1)) {
292310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
292410115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_alloc() failed 0x%x\n", err);
292510115c80Sfei feng - Sun Microsystems - Beijing China 		goto faili4;
292610115c80Sfei feng - Sun Microsystems - Beijing China 	}
292710115c80Sfei feng - Sun Microsystems - Beijing China 
292810115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_pri);
292910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
293010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
293110115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_get_pri() failed 0x%x\n", err);
293210115c80Sfei feng - Sun Microsystems - Beijing China 		goto faili5;
293310115c80Sfei feng - Sun Microsystems - Beijing China 	}
293410115c80Sfei feng - Sun Microsystems - Beijing China 
293510115c80Sfei feng - Sun Microsystems - Beijing China 	sc->amrr.amrr_min_success_threshold =  1;
293610115c80Sfei feng - Sun Microsystems - Beijing China 	sc->amrr.amrr_max_success_threshold = 15;
293710115c80Sfei feng - Sun Microsystems - Beijing China 
293810115c80Sfei feng - Sun Microsystems - Beijing China 	/* wait for NIC to initialize */
293910115c80Sfei feng - Sun Microsystems - Beijing China 	for (ntries = 0; ntries < 1000; ntries++) {
294010115c80Sfei feng - Sun Microsystems - Beijing China 		if ((val = RT2661_READ(sc, RT2661_MAC_CSR0)) != 0)
294110115c80Sfei feng - Sun Microsystems - Beijing China 			break;
294210115c80Sfei feng - Sun Microsystems - Beijing China 		DELAY(1000);
294310115c80Sfei feng - Sun Microsystems - Beijing China 	}
294410115c80Sfei feng - Sun Microsystems - Beijing China 	if (ntries == 1000) {
294510115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
294610115c80Sfei feng - Sun Microsystems - Beijing China 		    "timeout waiting for NIC to initialize\n");
294710115c80Sfei feng - Sun Microsystems - Beijing China 		goto faili5;
294810115c80Sfei feng - Sun Microsystems - Beijing China 	}
294910115c80Sfei feng - Sun Microsystems - Beijing China 
295010115c80Sfei feng - Sun Microsystems - Beijing China 	/* retrieve RF rev. no and various other things from EEPROM */
295110115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_read_eeprom(sc);
295210115c80Sfei feng - Sun Microsystems - Beijing China 
295310115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
295410115c80Sfei feng - Sun Microsystems - Beijing China 	    "MAC/BBP RT%X, RF %s\n"
295510115c80Sfei feng - Sun Microsystems - Beijing China 	    "MAC address is: %x:%x:%x:%x:%x:%x\n", val,
295610115c80Sfei feng - Sun Microsystems - Beijing China 	    rt2661_get_rf(sc->rf_rev),
295710115c80Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
295810115c80Sfei feng - Sun Microsystems - Beijing China 	    ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]);
295910115c80Sfei feng - Sun Microsystems - Beijing China 
296010115c80Sfei feng - Sun Microsystems - Beijing China 	/*
296110115c80Sfei feng - Sun Microsystems - Beijing China 	 * Load 8051 microcode into NIC.
296210115c80Sfei feng - Sun Microsystems - Beijing China 	 */
296310115c80Sfei feng - Sun Microsystems - Beijing China 	switch (device_id) {
296410115c80Sfei feng - Sun Microsystems - Beijing China 	case 0x0301:
296510115c80Sfei feng - Sun Microsystems - Beijing China 		ucode = rt2561s_ucode;
296610115c80Sfei feng - Sun Microsystems - Beijing China 		usize = sizeof (rt2561s_ucode);
296710115c80Sfei feng - Sun Microsystems - Beijing China 		break;
296810115c80Sfei feng - Sun Microsystems - Beijing China 	case 0x0302:
296910115c80Sfei feng - Sun Microsystems - Beijing China 		ucode = rt2561_ucode;
297010115c80Sfei feng - Sun Microsystems - Beijing China 		usize = sizeof (rt2561_ucode);
297110115c80Sfei feng - Sun Microsystems - Beijing China 		break;
297210115c80Sfei feng - Sun Microsystems - Beijing China 	case 0x0401:
297310115c80Sfei feng - Sun Microsystems - Beijing China 		ucode = rt2661_ucode;
297410115c80Sfei feng - Sun Microsystems - Beijing China 		usize = sizeof (rt2661_ucode);
297510115c80Sfei feng - Sun Microsystems - Beijing China 		break;
297610115c80Sfei feng - Sun Microsystems - Beijing China 	}
297710115c80Sfei feng - Sun Microsystems - Beijing China 
297810115c80Sfei feng - Sun Microsystems - Beijing China 	err = rt2661_load_microcode(sc, ucode, usize);
297910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != RT2661_SUCCESS) {
298010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
298110115c80Sfei feng - Sun Microsystems - Beijing China 		    "could not load 8051 microcode\n");
298210115c80Sfei feng - Sun Microsystems - Beijing China 		goto faili5;
298310115c80Sfei feng - Sun Microsystems - Beijing China 	}
298410115c80Sfei feng - Sun Microsystems - Beijing China 
298510115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags = 0;
298610115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags |= RT2661_F_FWLOADED;
298710115c80Sfei feng - Sun Microsystems - Beijing China 
298810115c80Sfei feng - Sun Microsystems - Beijing China 	/*
298910115c80Sfei feng - Sun Microsystems - Beijing China 	 * Allocate Tx and Rx rings.
299010115c80Sfei feng - Sun Microsystems - Beijing China 	 */
299110115c80Sfei feng - Sun Microsystems - Beijing China 	for (ac = 0; ac < 4; ac++) {
299210115c80Sfei feng - Sun Microsystems - Beijing China 		err = rt2661_alloc_tx_ring(sc, &sc->txq[ac],
299310115c80Sfei feng - Sun Microsystems - Beijing China 		    RT2661_TX_RING_COUNT);
299410115c80Sfei feng - Sun Microsystems - Beijing China 		if (err != RT2661_SUCCESS) {
299510115c80Sfei feng - Sun Microsystems - Beijing China 			RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_attach(): "
299610115c80Sfei feng - Sun Microsystems - Beijing China 			    "could not allocate Tx ring %d\n", ac);
299710115c80Sfei feng - Sun Microsystems - Beijing China 			goto fail4;
299810115c80Sfei feng - Sun Microsystems - Beijing China 		}
299910115c80Sfei feng - Sun Microsystems - Beijing China 	}
300010115c80Sfei feng - Sun Microsystems - Beijing China 
300110115c80Sfei feng - Sun Microsystems - Beijing China 	err = rt2661_alloc_tx_ring(sc, &sc->mgtq, RT2661_MGT_RING_COUNT);
300210115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != RT2661_SUCCESS) {
300310115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_attach(): "
300410115c80Sfei feng - Sun Microsystems - Beijing China 		    "could not allocate Mgt ring\n");
300510115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail5;
300610115c80Sfei feng - Sun Microsystems - Beijing China 	}
300710115c80Sfei feng - Sun Microsystems - Beijing China 
300810115c80Sfei feng - Sun Microsystems - Beijing China 	err = rt2661_alloc_rx_ring(sc, &sc->rxq, RT2661_RX_RING_COUNT);
300910115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != RT2661_SUCCESS) {
301010115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_DMA, "rwd: rt2661_attach(): "
301110115c80Sfei feng - Sun Microsystems - Beijing China 		    "could not allocate Rx ring\n");
301210115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail6;
301310115c80Sfei feng - Sun Microsystems - Beijing China 	}
301410115c80Sfei feng - Sun Microsystems - Beijing China 
301510115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
301610115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL);
301710115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL);
301810115c80Sfei feng - Sun Microsystems - Beijing China 
301910115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_phytype = IEEE80211_T_OFDM;
302010115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_opmode = IEEE80211_M_STA;
302110115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_state = IEEE80211_S_INIT;
302210115c80Sfei feng - Sun Microsystems - Beijing China 
302310115c80Sfei feng - Sun Microsystems - Beijing China 	/* set device capabilities */
302410115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_caps =
302510115c80Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_TXPMGT |
302610115c80Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_SHPREAMBLE |
302710115c80Sfei feng - Sun Microsystems - Beijing China 	    IEEE80211_C_SHSLOT;
302810115c80Sfei feng - Sun Microsystems - Beijing China 
302910115c80Sfei feng - Sun Microsystems - Beijing China 	/* WPA/WPA2 support */
303010115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_caps |= IEEE80211_C_WPA;
303110115c80Sfei feng - Sun Microsystems - Beijing China 
303210115c80Sfei feng - Sun Microsystems - Beijing China 	/* set supported .11b and .11g rates */
303310115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11B] = rt2661_rateset_11b;
303410115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_sup_rates[IEEE80211_MODE_11G] = rt2661_rateset_11g;
303510115c80Sfei feng - Sun Microsystems - Beijing China 
303610115c80Sfei feng - Sun Microsystems - Beijing China 	/* set supported .11b and .11g channels (1 through 14) */
303710115c80Sfei feng - Sun Microsystems - Beijing China 	for (i = 1; i <= 14; i++) {
303810115c80Sfei feng - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_freq =
303910115c80Sfei feng - Sun Microsystems - Beijing China 		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
304010115c80Sfei feng - Sun Microsystems - Beijing China 		ic->ic_sup_channels[i].ich_flags =
304110115c80Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
304210115c80Sfei feng - Sun Microsystems - Beijing China 		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
304310115c80Sfei feng - Sun Microsystems - Beijing China 	}
304410115c80Sfei feng - Sun Microsystems - Beijing China 
304510115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_maxrssi = 63;
304610115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_xmit = rt2661_mgmt_send;
304710115c80Sfei feng - Sun Microsystems - Beijing China 
304810115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_attach(ic);
304910115c80Sfei feng - Sun Microsystems - Beijing China 
305010115c80Sfei feng - Sun Microsystems - Beijing China 	/* register WPA door */
305110115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_register_door(ic, ddi_driver_name(devinfo),
305210115c80Sfei feng - Sun Microsystems - Beijing China 	    ddi_get_instance(devinfo));
305310115c80Sfei feng - Sun Microsystems - Beijing China 
305410115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_node_alloc = rt2661_node_alloc;
305510115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_node_free = rt2661_node_free;
305610115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_set_shortslot = rt2661_updateslot;
305710115c80Sfei feng - Sun Microsystems - Beijing China 
305810115c80Sfei feng - Sun Microsystems - Beijing China 	/* override state transition machine */
305910115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_newstate = ic->ic_newstate;
306010115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_newstate = rt2661_newstate;
306110115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_media_init(ic);
306210115c80Sfei feng - Sun Microsystems - Beijing China 	ic->ic_def_txkey = 0;
306310115c80Sfei feng - Sun Microsystems - Beijing China 
306410115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_add_softint(devinfo, &sc->sc_softintr_hdl,
306510115c80Sfei feng - Sun Microsystems - Beijing China 	    DDI_INTR_SOFTPRI_MAX, rt2661_softintr, (caddr_t)sc);
306610115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
306710115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
306810115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_add_softintr() failed");
306910115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail7;
307010115c80Sfei feng - Sun Microsystems - Beijing China 	}
307110115c80Sfei feng - Sun Microsystems - Beijing China 
307210115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_add_handler(sc->sc_intr_htable[0], rt2661_intr,
307310115c80Sfei feng - Sun Microsystems - Beijing China 	    (caddr_t)sc, NULL);
307410115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
307510115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
307610115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_addr_handle() failed\n");
307710115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail8;
307810115c80Sfei feng - Sun Microsystems - Beijing China 	}
307910115c80Sfei feng - Sun Microsystems - Beijing China 
308010115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_intr_enable(sc->sc_intr_htable[0]);
308110115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != DDI_SUCCESS) {
308210115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd; rt2661_attach(): "
308310115c80Sfei feng - Sun Microsystems - Beijing China 		    "ddi_intr_enable() failed\n");
308410115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail9;
308510115c80Sfei feng - Sun Microsystems - Beijing China 	}
308610115c80Sfei feng - Sun Microsystems - Beijing China 
308710115c80Sfei feng - Sun Microsystems - Beijing China 	/*
308810115c80Sfei feng - Sun Microsystems - Beijing China 	 * Provide initial settings for the WiFi plugin; whenever this
308910115c80Sfei feng - Sun Microsystems - Beijing China 	 * information changes, we need to call mac_plugindata_update()
309010115c80Sfei feng - Sun Microsystems - Beijing China 	 */
309110115c80Sfei feng - Sun Microsystems - Beijing China 	wd.wd_opmode = ic->ic_opmode;
309210115c80Sfei feng - Sun Microsystems - Beijing China 	wd.wd_secalloc = WIFI_SEC_NONE;
309310115c80Sfei feng - Sun Microsystems - Beijing China 	IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
309410115c80Sfei feng - Sun Microsystems - Beijing China 
309510115c80Sfei feng - Sun Microsystems - Beijing China 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
309610115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
309710115c80Sfei feng - Sun Microsystems - Beijing China 		    "MAC version mismatch\n");
309810115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail10;
309910115c80Sfei feng - Sun Microsystems - Beijing China 	}
310010115c80Sfei feng - Sun Microsystems - Beijing China 
310110115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_type_ident	= MAC_PLUGIN_IDENT_WIFI;
310210115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_driver		= sc;
310310115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_dip		= devinfo;
310410115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_src_addr	= ic->ic_macaddr;
310510115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_callbacks	= &rt2661_m_callbacks;
310610115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_min_sdu		= 0;
310710115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_max_sdu		= IEEE80211_MTU;
310810115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_pdata		= &wd;
310910115c80Sfei feng - Sun Microsystems - Beijing China 	macp->m_pdata_size	= sizeof (wd);
311010115c80Sfei feng - Sun Microsystems - Beijing China 
311110115c80Sfei feng - Sun Microsystems - Beijing China 	err = mac_register(macp, &ic->ic_mach);
311210115c80Sfei feng - Sun Microsystems - Beijing China 	mac_free(macp);
311310115c80Sfei feng - Sun Microsystems - Beijing China 	if (err != 0) {
311410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
311510115c80Sfei feng - Sun Microsystems - Beijing China 		    "mac_register err %x\n", err);
311610115c80Sfei feng - Sun Microsystems - Beijing China 		goto fail10;
311710115c80Sfei feng - Sun Microsystems - Beijing China 	}
311810115c80Sfei feng - Sun Microsystems - Beijing China 
311910115c80Sfei feng - Sun Microsystems - Beijing China 	/*
312010115c80Sfei feng - Sun Microsystems - Beijing China 	 * Create minor node of type DDI_NT_NET_WIFI
312110115c80Sfei feng - Sun Microsystems - Beijing China 	 */
312210115c80Sfei feng - Sun Microsystems - Beijing China 	(void) snprintf(strbuf, sizeof (strbuf), "%s%d",
312310115c80Sfei feng - Sun Microsystems - Beijing China 	    "rwd", instance);
312410115c80Sfei feng - Sun Microsystems - Beijing China 	err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
312510115c80Sfei feng - Sun Microsystems - Beijing China 	    instance + 1, DDI_NT_NET_WIFI, 0);
312610115c80Sfei feng - Sun Microsystems - Beijing China 
312710115c80Sfei feng - Sun Microsystems - Beijing China 	/*
312810115c80Sfei feng - Sun Microsystems - Beijing China 	 * Notify link is down now
312910115c80Sfei feng - Sun Microsystems - Beijing China 	 */
313010115c80Sfei feng - Sun Microsystems - Beijing China 	mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
313110115c80Sfei feng - Sun Microsystems - Beijing China 
313210115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_attach(): "
313310115c80Sfei feng - Sun Microsystems - Beijing China 	    "attach successfully\n");
313410115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
313510115c80Sfei feng - Sun Microsystems - Beijing China 
313610115c80Sfei feng - Sun Microsystems - Beijing China fail10:
313710115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_disable(sc->sc_intr_htable[0]);
313810115c80Sfei feng - Sun Microsystems - Beijing China fail9:
313910115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
314010115c80Sfei feng - Sun Microsystems - Beijing China fail8:
314110115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_softint(sc->sc_softintr_hdl);
314210115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_softintr_hdl = NULL;
314310115c80Sfei feng - Sun Microsystems - Beijing China fail7:
314410115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_genlock);
314510115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_txlock);
314610115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_rxlock);
314710115c80Sfei feng - Sun Microsystems - Beijing China fail6:
314810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_rx_ring(sc, &sc->rxq);
314910115c80Sfei feng - Sun Microsystems - Beijing China fail5:
315010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_tx_ring(sc, &sc->mgtq);
315110115c80Sfei feng - Sun Microsystems - Beijing China fail4:
315210115c80Sfei feng - Sun Microsystems - Beijing China 	while (--ac >= 0)
315310115c80Sfei feng - Sun Microsystems - Beijing China 		rt2661_free_tx_ring(sc, &sc->txq[ac]);
315410115c80Sfei feng - Sun Microsystems - Beijing China faili5:
315510115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_free(sc->sc_intr_htable[0]);
315610115c80Sfei feng - Sun Microsystems - Beijing China faili4:
315710115c80Sfei feng - Sun Microsystems - Beijing China 	kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
315810115c80Sfei feng - Sun Microsystems - Beijing China fail3:
315910115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_io_handle);
316010115c80Sfei feng - Sun Microsystems - Beijing China fail2:
316110115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_cfg_handle);
316210115c80Sfei feng - Sun Microsystems - Beijing China fail1:
316310115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_FAILURE);
316410115c80Sfei feng - Sun Microsystems - Beijing China }
316510115c80Sfei feng - Sun Microsystems - Beijing China 
316610115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)316710115c80Sfei feng - Sun Microsystems - Beijing China rt2661_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
316810115c80Sfei feng - Sun Microsystems - Beijing China {
316910115c80Sfei feng - Sun Microsystems - Beijing China 
317010115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc;
317110115c80Sfei feng - Sun Microsystems - Beijing China 
317210115c80Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(rt2661_soft_state_p, ddi_get_instance(devinfo));
317310115c80Sfei feng - Sun Microsystems - Beijing China 
317410115c80Sfei feng - Sun Microsystems - Beijing China 	switch (cmd) {
317510115c80Sfei feng - Sun Microsystems - Beijing China 	case DDI_DETACH:
317610115c80Sfei feng - Sun Microsystems - Beijing China 		break;
317710115c80Sfei feng - Sun Microsystems - Beijing China 	case DDI_SUSPEND:
317810115c80Sfei feng - Sun Microsystems - Beijing China 		if (RT2661_IS_RUNNING(sc))
317910115c80Sfei feng - Sun Microsystems - Beijing China 			rt2661_stop(sc);
318010115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GLOCK(sc);
318110115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags |= RT2661_F_SUSPEND;
318210115c80Sfei feng - Sun Microsystems - Beijing China 		sc->sc_flags &= ~RT2661_F_FWLOADED;
318310115c80Sfei feng - Sun Microsystems - Beijing China 		RT2661_GUNLOCK(sc);
318410115c80Sfei feng - Sun Microsystems - Beijing China 		RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_detach(): "
318510115c80Sfei feng - Sun Microsystems - Beijing China 		    "suspend now\n");
318610115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_SUCCESS);
318710115c80Sfei feng - Sun Microsystems - Beijing China 	default:
318810115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
318910115c80Sfei feng - Sun Microsystems - Beijing China 	}
319010115c80Sfei feng - Sun Microsystems - Beijing China 
319110115c80Sfei feng - Sun Microsystems - Beijing China 	if (mac_disable(sc->sc_ic.ic_mach) != 0)
319210115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
319310115c80Sfei feng - Sun Microsystems - Beijing China 
319410115c80Sfei feng - Sun Microsystems - Beijing China 	/*
319510115c80Sfei feng - Sun Microsystems - Beijing China 	 * Unregister from the MAC layer subsystem
319610115c80Sfei feng - Sun Microsystems - Beijing China 	 */
319710115c80Sfei feng - Sun Microsystems - Beijing China 	(void) mac_unregister(sc->sc_ic.ic_mach);
319810115c80Sfei feng - Sun Microsystems - Beijing China 
319910115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_softint(sc->sc_softintr_hdl);
320010115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_softintr_hdl = NULL;
320110115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_disable(sc->sc_intr_htable[0]);
320210115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_remove_handler(sc->sc_intr_htable[0]);
320310115c80Sfei feng - Sun Microsystems - Beijing China 	(void) ddi_intr_free(sc->sc_intr_htable[0]);
320410115c80Sfei feng - Sun Microsystems - Beijing China 	kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t));
320510115c80Sfei feng - Sun Microsystems - Beijing China 
320610115c80Sfei feng - Sun Microsystems - Beijing China 	/*
320710115c80Sfei feng - Sun Microsystems - Beijing China 	 * detach ieee80211 layer
320810115c80Sfei feng - Sun Microsystems - Beijing China 	 */
320910115c80Sfei feng - Sun Microsystems - Beijing China 	ieee80211_detach(&sc->sc_ic);
321010115c80Sfei feng - Sun Microsystems - Beijing China 
321110115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_genlock);
321210115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_txlock);
321310115c80Sfei feng - Sun Microsystems - Beijing China 	mutex_destroy(&sc->sc_rxlock);
321410115c80Sfei feng - Sun Microsystems - Beijing China 
321510115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_tx_ring(sc, &sc->txq[0]);
321610115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_tx_ring(sc, &sc->txq[1]);
321710115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_tx_ring(sc, &sc->txq[2]);
321810115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_tx_ring(sc, &sc->txq[3]);
321910115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_tx_ring(sc, &sc->mgtq);
322010115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_free_rx_ring(sc, &sc->rxq);
322110115c80Sfei feng - Sun Microsystems - Beijing China 
322210115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_io_handle);
322310115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_regs_map_free(&sc->sc_cfg_handle);
322410115c80Sfei feng - Sun Microsystems - Beijing China 
322510115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_remove_minor_node(devinfo, NULL);
322610115c80Sfei feng - Sun Microsystems - Beijing China 	ddi_soft_state_free(rt2661_soft_state_p, ddi_get_instance(devinfo));
322710115c80Sfei feng - Sun Microsystems - Beijing China 
322810115c80Sfei feng - Sun Microsystems - Beijing China 	RWD_DEBUG(RT2661_DBG_MSG, "rwd: rt2661_detach(): "
322910115c80Sfei feng - Sun Microsystems - Beijing China 	    "detach successfully\n");
323010115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
323110115c80Sfei feng - Sun Microsystems - Beijing China }
323210115c80Sfei feng - Sun Microsystems - Beijing China 
323310115c80Sfei feng - Sun Microsystems - Beijing China static int
rt2661_quiesce(dev_info_t * dip)323410115c80Sfei feng - Sun Microsystems - Beijing China rt2661_quiesce(dev_info_t *dip)
323510115c80Sfei feng - Sun Microsystems - Beijing China {
323610115c80Sfei feng - Sun Microsystems - Beijing China 	struct rt2661_softc *sc;
323710115c80Sfei feng - Sun Microsystems - Beijing China 
323810115c80Sfei feng - Sun Microsystems - Beijing China 	sc = ddi_get_soft_state(rt2661_soft_state_p, ddi_get_instance(dip));
323910115c80Sfei feng - Sun Microsystems - Beijing China 	if (sc == NULL)
324010115c80Sfei feng - Sun Microsystems - Beijing China 		return (DDI_FAILURE);
324110115c80Sfei feng - Sun Microsystems - Beijing China 
324210115c80Sfei feng - Sun Microsystems - Beijing China #ifdef DEBUG
324310115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_dbg_flags = 0;
324410115c80Sfei feng - Sun Microsystems - Beijing China #endif
324510115c80Sfei feng - Sun Microsystems - Beijing China 
324610115c80Sfei feng - Sun Microsystems - Beijing China 	/*
324710115c80Sfei feng - Sun Microsystems - Beijing China 	 * No more blocking is allowed while we are in quiesce(9E) entry point
324810115c80Sfei feng - Sun Microsystems - Beijing China 	 */
324910115c80Sfei feng - Sun Microsystems - Beijing China 	sc->sc_flags |= RT2661_F_QUIESCE;
325010115c80Sfei feng - Sun Microsystems - Beijing China 
325110115c80Sfei feng - Sun Microsystems - Beijing China 	/*
325210115c80Sfei feng - Sun Microsystems - Beijing China 	 * Disable all interrupts
325310115c80Sfei feng - Sun Microsystems - Beijing China 	 */
325410115c80Sfei feng - Sun Microsystems - Beijing China 	rt2661_stop(sc);
325510115c80Sfei feng - Sun Microsystems - Beijing China 	return (DDI_SUCCESS);
325610115c80Sfei feng - Sun Microsystems - Beijing China }
325710115c80Sfei feng - Sun Microsystems - Beijing China 
325810115c80Sfei feng - Sun Microsystems - Beijing China int
_info(struct modinfo * modinfop)325910115c80Sfei feng - Sun Microsystems - Beijing China _info(struct modinfo *modinfop)
326010115c80Sfei feng - Sun Microsystems - Beijing China {
326110115c80Sfei feng - Sun Microsystems - Beijing China 	return (mod_info(&modlinkage, modinfop));
326210115c80Sfei feng - Sun Microsystems - Beijing China }
326310115c80Sfei feng - Sun Microsystems - Beijing China 
326410115c80Sfei feng - Sun Microsystems - Beijing China int
_init(void)326510115c80Sfei feng - Sun Microsystems - Beijing China _init(void)
326610115c80Sfei feng - Sun Microsystems - Beijing China {
326710115c80Sfei feng - Sun Microsystems - Beijing China 	int status;
326810115c80Sfei feng - Sun Microsystems - Beijing China 
326910115c80Sfei feng - Sun Microsystems - Beijing China 	status = ddi_soft_state_init(&rt2661_soft_state_p,
327010115c80Sfei feng - Sun Microsystems - Beijing China 	    sizeof (struct rt2661_softc), 1);
327110115c80Sfei feng - Sun Microsystems - Beijing China 	if (status != 0)
327210115c80Sfei feng - Sun Microsystems - Beijing China 		return (status);
327310115c80Sfei feng - Sun Microsystems - Beijing China 
327410115c80Sfei feng - Sun Microsystems - Beijing China 	mac_init_ops(&rwd_dev_ops, "rwd");
327510115c80Sfei feng - Sun Microsystems - Beijing China 	status = mod_install(&modlinkage);
327610115c80Sfei feng - Sun Microsystems - Beijing China 	if (status != 0) {
327710115c80Sfei feng - Sun Microsystems - Beijing China 		mac_fini_ops(&rwd_dev_ops);
327810115c80Sfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&rt2661_soft_state_p);
327910115c80Sfei feng - Sun Microsystems - Beijing China 	}
328010115c80Sfei feng - Sun Microsystems - Beijing China 	return (status);
328110115c80Sfei feng - Sun Microsystems - Beijing China }
328210115c80Sfei feng - Sun Microsystems - Beijing China 
328310115c80Sfei feng - Sun Microsystems - Beijing China int
_fini(void)328410115c80Sfei feng - Sun Microsystems - Beijing China _fini(void)
328510115c80Sfei feng - Sun Microsystems - Beijing China {
328610115c80Sfei feng - Sun Microsystems - Beijing China 	int status;
328710115c80Sfei feng - Sun Microsystems - Beijing China 
328810115c80Sfei feng - Sun Microsystems - Beijing China 	status = mod_remove(&modlinkage);
328910115c80Sfei feng - Sun Microsystems - Beijing China 	if (status == 0) {
329010115c80Sfei feng - Sun Microsystems - Beijing China 		mac_fini_ops(&rwd_dev_ops);
329110115c80Sfei feng - Sun Microsystems - Beijing China 		ddi_soft_state_fini(&rt2661_soft_state_p);
329210115c80Sfei feng - Sun Microsystems - Beijing China 	}
329310115c80Sfei feng - Sun Microsystems - Beijing China 	return (status);
329410115c80Sfei feng - Sun Microsystems - Beijing China }
3295