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