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