18a3c961bSfei feng - Sun Microsystems - Beijing China /* 2*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 38a3c961bSfei feng - Sun Microsystems - Beijing China * Use is subject to license terms. 48a3c961bSfei feng - Sun Microsystems - Beijing China */ 58a3c961bSfei feng - Sun Microsystems - Beijing China 68a3c961bSfei feng - Sun Microsystems - Beijing China /* 78a3c961bSfei feng - Sun Microsystems - Beijing China * Copyright (c) 2007, 2008 88a3c961bSfei feng - Sun Microsystems - Beijing China * Damien Bergamini <damien.bergamini@free.fr> 98a3c961bSfei feng - Sun Microsystems - Beijing China * 108a3c961bSfei feng - Sun Microsystems - Beijing China * Permission to use, copy, modify, and distribute this software for any 118a3c961bSfei feng - Sun Microsystems - Beijing China * purpose with or without fee is hereby granted, provided that the above 128a3c961bSfei feng - Sun Microsystems - Beijing China * copyright notice and this permission notice appear in all copies. 138a3c961bSfei feng - Sun Microsystems - Beijing China * 148a3c961bSfei feng - Sun Microsystems - Beijing China * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 158a3c961bSfei feng - Sun Microsystems - Beijing China * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 168a3c961bSfei feng - Sun Microsystems - Beijing China * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 178a3c961bSfei feng - Sun Microsystems - Beijing China * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 188a3c961bSfei feng - Sun Microsystems - Beijing China * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 198a3c961bSfei feng - Sun Microsystems - Beijing China * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 208a3c961bSfei feng - Sun Microsystems - Beijing China * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 218a3c961bSfei feng - Sun Microsystems - Beijing China */ 228a3c961bSfei feng - Sun Microsystems - Beijing China 238a3c961bSfei feng - Sun Microsystems - Beijing China /* 248a3c961bSfei feng - Sun Microsystems - Beijing China * Ralink Technology RT2860 chipset driver 258a3c961bSfei feng - Sun Microsystems - Beijing China * http://www.ralinktech.com/ 268a3c961bSfei feng - Sun Microsystems - Beijing China */ 278a3c961bSfei feng - Sun Microsystems - Beijing China 288a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/types.h> 298a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/byteorder.h> 308a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/conf.h> 318a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/cmn_err.h> 328a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/stat.h> 338a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/ddi.h> 348a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/sunddi.h> 358a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/strsubr.h> 368a3c961bSfei feng - Sun Microsystems - Beijing China #include <inet/common.h> 378a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/note.h> 388a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/stream.h> 398a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/strsun.h> 408a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/modctl.h> 418a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/devops.h> 428a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/mac_provider.h> 438a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/mac_wifi.h> 448a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/net80211.h> 458a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/net80211_proto.h> 468a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/varargs.h> 478a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/pci.h> 488a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/crypto/common.h> 498a3c961bSfei feng - Sun Microsystems - Beijing China #include <sys/crypto/api.h> 508a3c961bSfei feng - Sun Microsystems - Beijing China #include <inet/wifi_ioctl.h> 518a3c961bSfei feng - Sun Microsystems - Beijing China 528a3c961bSfei feng - Sun Microsystems - Beijing China #include "rt2860_reg.h" 538a3c961bSfei feng - Sun Microsystems - Beijing China #include "rt2860_var.h" 548a3c961bSfei feng - Sun Microsystems - Beijing China 558a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_80211 (1 << 0) 568a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_DMA (1 << 1) 578a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_EEPROM (1 << 2) 588a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_FW (1 << 3) 598a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_HW (1 << 4) 608a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_INTR (1 << 5) 618a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_RX (1 << 6) 628a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_SCAN (1 << 7) 638a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_TX (1 << 8) 648a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_RADIO (1 << 9) 658a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_RESUME (1 << 10) 668a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_DBG_MSG (1 << 11) 678a3c961bSfei feng - Sun Microsystems - Beijing China 688a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t rt2860_dbg_flags = 0x0; 698a3c961bSfei feng - Sun Microsystems - Beijing China 708a3c961bSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG 718a3c961bSfei feng - Sun Microsystems - Beijing China #define RWN_DEBUG \ 728a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_debug 738a3c961bSfei feng - Sun Microsystems - Beijing China #else 748a3c961bSfei feng - Sun Microsystems - Beijing China #define RWN_DEBUG 758a3c961bSfei feng - Sun Microsystems - Beijing China #endif 768a3c961bSfei feng - Sun Microsystems - Beijing China 778a3c961bSfei feng - Sun Microsystems - Beijing China static void *rt2860_soft_state_p = NULL; 788a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t rt2860_fw_bin [] = { 798a3c961bSfei feng - Sun Microsystems - Beijing China #include "fw-rt2860/rt2860.ucode" 808a3c961bSfei feng - Sun Microsystems - Beijing China }; 818a3c961bSfei feng - Sun Microsystems - Beijing China 82860387ebSfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset rt2860_rateset_11b = 838a3c961bSfei feng - Sun Microsystems - Beijing China { 4, { 2, 4, 11, 22 } }; 848a3c961bSfei feng - Sun Microsystems - Beijing China 85860387ebSfei feng - Sun Microsystems - Beijing China static const struct ieee80211_rateset rt2860_rateset_11g = 868a3c961bSfei feng - Sun Microsystems - Beijing China { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 878a3c961bSfei feng - Sun Microsystems - Beijing China 888a3c961bSfei feng - Sun Microsystems - Beijing China static const struct { 898a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t reg; 908a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t val; 918a3c961bSfei feng - Sun Microsystems - Beijing China } rt2860_def_mac[] = { 928a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DEF_MAC 938a3c961bSfei feng - Sun Microsystems - Beijing China }; 948a3c961bSfei feng - Sun Microsystems - Beijing China 958a3c961bSfei feng - Sun Microsystems - Beijing China static const struct { 968a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t reg; 978a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t val; 988a3c961bSfei feng - Sun Microsystems - Beijing China } rt2860_def_bbp[] = { 998a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DEF_BBP 1008a3c961bSfei feng - Sun Microsystems - Beijing China }; 1018a3c961bSfei feng - Sun Microsystems - Beijing China 1028a3c961bSfei feng - Sun Microsystems - Beijing China static const struct rfprog { 1038a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t chan; 1048a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t r1, r2, r3, r4; 1058a3c961bSfei feng - Sun Microsystems - Beijing China } rt2860_rf2850[] = { 1068a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_RF2850 1078a3c961bSfei feng - Sun Microsystems - Beijing China }; 1088a3c961bSfei feng - Sun Microsystems - Beijing China 1098a3c961bSfei feng - Sun Microsystems - Beijing China /* 1108a3c961bSfei feng - Sun Microsystems - Beijing China * PIO access attributes for registers 1118a3c961bSfei feng - Sun Microsystems - Beijing China */ 1128a3c961bSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t rwn_csr_accattr = { 1138a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, 1148a3c961bSfei feng - Sun Microsystems - Beijing China DDI_STRUCTURE_LE_ACC, 1158a3c961bSfei feng - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC 1168a3c961bSfei feng - Sun Microsystems - Beijing China }; 1178a3c961bSfei feng - Sun Microsystems - Beijing China 1188a3c961bSfei feng - Sun Microsystems - Beijing China /* 1198a3c961bSfei feng - Sun Microsystems - Beijing China * DMA access attributes for descriptors: NOT to be byte swapped. 1208a3c961bSfei feng - Sun Microsystems - Beijing China */ 1218a3c961bSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t rt2860_desc_accattr = { 1228a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, 1238a3c961bSfei feng - Sun Microsystems - Beijing China DDI_STRUCTURE_LE_ACC, 1248a3c961bSfei feng - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC 1258a3c961bSfei feng - Sun Microsystems - Beijing China }; 1268a3c961bSfei feng - Sun Microsystems - Beijing China 1278a3c961bSfei feng - Sun Microsystems - Beijing China static ddi_device_acc_attr_t rt2860_buf_accattr = { 1288a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DEVICE_ATTR_V0, 1298a3c961bSfei feng - Sun Microsystems - Beijing China DDI_NEVERSWAP_ACC, 1308a3c961bSfei feng - Sun Microsystems - Beijing China DDI_STRICTORDER_ACC, 1318a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DEFAULT_ACC 1328a3c961bSfei feng - Sun Microsystems - Beijing China }; 1338a3c961bSfei feng - Sun Microsystems - Beijing China 1348a3c961bSfei feng - Sun Microsystems - Beijing China /* 1358a3c961bSfei feng - Sun Microsystems - Beijing China * Describes the chip's DMA engine 1368a3c961bSfei feng - Sun Microsystems - Beijing China */ 1378a3c961bSfei feng - Sun Microsystems - Beijing China static ddi_dma_attr_t rt2860_dma_attr = { 1388a3c961bSfei feng - Sun Microsystems - Beijing China DMA_ATTR_V0, /* dma_attr version */ 1398a3c961bSfei feng - Sun Microsystems - Beijing China 0x0, /* dma_attr_addr_lo */ 1408a3c961bSfei feng - Sun Microsystems - Beijing China 0xffffffffU, /* dma_attr_addr_hi */ 1418a3c961bSfei feng - Sun Microsystems - Beijing China 0xffffffffU, /* dma_attr_count_max */ 1428a3c961bSfei feng - Sun Microsystems - Beijing China 16, /* dma_attr_align */ 1438a3c961bSfei feng - Sun Microsystems - Beijing China 0x00000fff, /* dma_attr_burstsizes */ 1448a3c961bSfei feng - Sun Microsystems - Beijing China 1, /* dma_attr_minxfer */ 1458a3c961bSfei feng - Sun Microsystems - Beijing China 0xffffffffU, /* dma_attr_maxxfer */ 1468a3c961bSfei feng - Sun Microsystems - Beijing China 0xffffffffU, /* dma_attr_seg */ 1478a3c961bSfei feng - Sun Microsystems - Beijing China 1, /* dma_attr_sgllen */ 1488a3c961bSfei feng - Sun Microsystems - Beijing China 1, /* dma_attr_granular */ 1498a3c961bSfei feng - Sun Microsystems - Beijing China 0 /* dma_attr_flags */ 1508a3c961bSfei feng - Sun Microsystems - Beijing China }; 1518a3c961bSfei feng - Sun Microsystems - Beijing China 1528a3c961bSfei feng - Sun Microsystems - Beijing China static uint16_t rt2860_eeprom_read(struct rt2860_softc *, uint8_t); 1538a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_read_eeprom(struct rt2860_softc *); 1548a3c961bSfei feng - Sun Microsystems - Beijing China const char *rt2860_get_rf(uint8_t); 1558a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_alloc_dma_mem(dev_info_t *, ddi_dma_attr_t *, size_t, 1568a3c961bSfei feng - Sun Microsystems - Beijing China ddi_device_acc_attr_t *, uint_t, uint_t, struct dma_area *); 1578a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_free_dma_mem(struct dma_area *); 1588a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_alloc_tx_ring(struct rt2860_softc *, 1598a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_ring *); 1608a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_free_tx_ring(struct rt2860_softc *, 1618a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_ring *); 1628a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_alloc_rx_ring(struct rt2860_softc *, 1638a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rx_ring *); 1648a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_free_rx_ring(struct rt2860_softc *, 1658a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rx_ring *); 1668a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_alloc_tx_pool(struct rt2860_softc *); 1678a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_free_tx_pool(struct rt2860_softc *); 1688a3c961bSfei feng - Sun Microsystems - Beijing China static uint16_t rt2860_txtime(int, int, uint32_t); 1698a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_ack_rate(struct ieee80211com *, int); 1708a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_send(ieee80211com_t *, mblk_t *, uint8_t); 1718a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t rt2860_maxrssi_chain(struct rt2860_softc *, 1728a3c961bSfei feng - Sun Microsystems - Beijing China const struct rt2860_rxwi *); 1738a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_drain_stats_fifo(struct rt2860_softc *); 1748a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_tx_intr(struct rt2860_softc *, int); 1758a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_rx_intr(struct rt2860_softc *); 1768a3c961bSfei feng - Sun Microsystems - Beijing China static uint_t rt2860_softintr(caddr_t); 1778a3c961bSfei feng - Sun Microsystems - Beijing China static uint_t rt2860_intr(caddr_t); 1788a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_region_4(struct rt2860_softc *, 1798a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t, uint32_t, int); 1808a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_load_microcode(struct rt2860_softc *); 1818a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); 1828a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_bbp_init(struct rt2860_softc *); 1838a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t); 1848a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); 1858a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_mcu_cmd(struct rt2860_softc *, uint8_t, uint16_t); 1868a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t); 1878a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_select_chan_group(struct rt2860_softc *, int); 1888a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_chan(struct rt2860_softc *, 1898a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_channel *); 1908a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_updateprot(struct ieee80211com *); 1918a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_leds(struct rt2860_softc *, uint16_t); 1928a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_next_scan(void *); 1938a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_iter_func(void *, struct ieee80211_node *); 1948a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_updateslot(struct rt2860_softc *); 1958a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t rt2860_rate2mcs(uint8_t); 1968a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_enable_mrr(struct rt2860_softc *); 1978a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_txpreamble(struct rt2860_softc *); 1988a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_basicrates(struct rt2860_softc *); 1998a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *); 2008a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_amrr_node_init(const struct rt2860_amrr *, 2018a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_amrr_node *); 2028a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_amrr_choose(struct rt2860_amrr *, 2038a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *, struct rt2860_amrr_node *); 2048a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_newassoc(struct ieee80211com *, struct ieee80211_node *, 2058a3c961bSfei feng - Sun Microsystems - Beijing China int); 2068a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_enable_tsf_sync(struct rt2860_softc *); 2078a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_newstate(struct ieee80211com *, 2088a3c961bSfei feng - Sun Microsystems - Beijing China enum ieee80211_state, int); 2098a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_init(struct rt2860_softc *); 2108a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_stop(struct rt2860_softc *); 2118a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_quiesce(dev_info_t *t); 2128a3c961bSfei feng - Sun Microsystems - Beijing China 2138a3c961bSfei feng - Sun Microsystems - Beijing China /* 2148a3c961bSfei feng - Sun Microsystems - Beijing China * device operations 2158a3c961bSfei feng - Sun Microsystems - Beijing China */ 2168a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_attach(dev_info_t *, ddi_attach_cmd_t); 2178a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_detach(dev_info_t *, ddi_detach_cmd_t); 2188a3c961bSfei feng - Sun Microsystems - Beijing China 2198a3c961bSfei feng - Sun Microsystems - Beijing China /* 2208a3c961bSfei feng - Sun Microsystems - Beijing China * Module Loading Data & Entry Points 2218a3c961bSfei feng - Sun Microsystems - Beijing China */ 2228a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DEFINE_STREAM_OPS(rwn_dev_ops, nulldev, nulldev, rt2860_attach, 2238a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_detach, nodev, NULL, D_MP, NULL, rt2860_quiesce); 2248a3c961bSfei feng - Sun Microsystems - Beijing China 2258a3c961bSfei feng - Sun Microsystems - Beijing China static struct modldrv rwn_modldrv = { 2268a3c961bSfei feng - Sun Microsystems - Beijing China &mod_driverops, /* Type of module. This one is a driver */ 227860387ebSfei feng - Sun Microsystems - Beijing China "Ralink RT2700/2800 driver v1.2", /* short description */ 2288a3c961bSfei feng - Sun Microsystems - Beijing China &rwn_dev_ops /* driver specific ops */ 2298a3c961bSfei feng - Sun Microsystems - Beijing China }; 2308a3c961bSfei feng - Sun Microsystems - Beijing China 2318a3c961bSfei feng - Sun Microsystems - Beijing China static struct modlinkage modlinkage = { 2328a3c961bSfei feng - Sun Microsystems - Beijing China MODREV_1, 2338a3c961bSfei feng - Sun Microsystems - Beijing China (void *)&rwn_modldrv, 2348a3c961bSfei feng - Sun Microsystems - Beijing China NULL 2358a3c961bSfei feng - Sun Microsystems - Beijing China }; 2368a3c961bSfei feng - Sun Microsystems - Beijing China 2378a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_stat(void *, uint_t, uint64_t *); 2388a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_start(void *); 2398a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_m_stop(void *); 2408a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_promisc(void *, boolean_t); 2418a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_multicst(void *, boolean_t, const uint8_t *); 2428a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_unicst(void *, const uint8_t *); 2438a3c961bSfei feng - Sun Microsystems - Beijing China static mblk_t *rt2860_m_tx(void *, mblk_t *); 2448a3c961bSfei feng - Sun Microsystems - Beijing China static void rt2860_m_ioctl(void *, queue_t *, mblk_t *); 2458a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_setprop(void *arg, const char *pr_name, 2468a3c961bSfei feng - Sun Microsystems - Beijing China mac_prop_id_t wldp_pr_num, 2478a3c961bSfei feng - Sun Microsystems - Beijing China uint_t wldp_length, const void *wldp_buf); 248*0dc2366fSVenugopal Iyer static void rt2860_m_propinfo(void *arg, const char *pr_name, 249*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_num, mac_prop_info_handle_t prh); 2508a3c961bSfei feng - Sun Microsystems - Beijing China static int rt2860_m_getprop(void *arg, const char *pr_name, 251*0dc2366fSVenugopal Iyer mac_prop_id_t wldp_pr_num, uint_t wldp_length, 252*0dc2366fSVenugopal Iyer void *wldp_buf); 2538a3c961bSfei feng - Sun Microsystems - Beijing China 2548a3c961bSfei feng - Sun Microsystems - Beijing China static mac_callbacks_t rt2860_m_callbacks = { 255*0dc2366fSVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 2568a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_stat, 2578a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_start, 2588a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_stop, 2598a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_promisc, 2608a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_multicst, 2618a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_unicst, 2628a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_tx, 263*0dc2366fSVenugopal Iyer NULL, 2648a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_ioctl, 2658a3c961bSfei feng - Sun Microsystems - Beijing China NULL, 2668a3c961bSfei feng - Sun Microsystems - Beijing China NULL, 2678a3c961bSfei feng - Sun Microsystems - Beijing China NULL, 2688a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_setprop, 269*0dc2366fSVenugopal Iyer rt2860_m_getprop, 270*0dc2366fSVenugopal Iyer rt2860_m_propinfo 2718a3c961bSfei feng - Sun Microsystems - Beijing China }; 2728a3c961bSfei feng - Sun Microsystems - Beijing China 2738a3c961bSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG 2748a3c961bSfei feng - Sun Microsystems - Beijing China void 2758a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_debug(uint32_t dbg_flags, const int8_t *fmt, ...) 2768a3c961bSfei feng - Sun Microsystems - Beijing China { 2778a3c961bSfei feng - Sun Microsystems - Beijing China va_list args; 2788a3c961bSfei feng - Sun Microsystems - Beijing China 2798a3c961bSfei feng - Sun Microsystems - Beijing China if (dbg_flags & rt2860_dbg_flags) { 2808a3c961bSfei feng - Sun Microsystems - Beijing China va_start(args, fmt); 2818a3c961bSfei feng - Sun Microsystems - Beijing China vcmn_err(CE_CONT, fmt, args); 2828a3c961bSfei feng - Sun Microsystems - Beijing China va_end(args); 2838a3c961bSfei feng - Sun Microsystems - Beijing China } 2848a3c961bSfei feng - Sun Microsystems - Beijing China } 2858a3c961bSfei feng - Sun Microsystems - Beijing China #endif 2868a3c961bSfei feng - Sun Microsystems - Beijing China 2878a3c961bSfei feng - Sun Microsystems - Beijing China const char * 2888a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_get_rf(uint8_t rev) 2898a3c961bSfei feng - Sun Microsystems - Beijing China { 2908a3c961bSfei feng - Sun Microsystems - Beijing China switch (rev) { 2918a3c961bSfei feng - Sun Microsystems - Beijing China case RT2860_RF_2820: return "RT2820"; 2928a3c961bSfei feng - Sun Microsystems - Beijing China case RT2860_RF_2850: return "RT2850"; 2938a3c961bSfei feng - Sun Microsystems - Beijing China case RT2860_RF_2720: return "RT2720"; 2948a3c961bSfei feng - Sun Microsystems - Beijing China case RT2860_RF_2750: return "RT2750"; 2958a3c961bSfei feng - Sun Microsystems - Beijing China default: return "unknown"; 2968a3c961bSfei feng - Sun Microsystems - Beijing China } 2978a3c961bSfei feng - Sun Microsystems - Beijing China } 2988a3c961bSfei feng - Sun Microsystems - Beijing China 2998a3c961bSfei feng - Sun Microsystems - Beijing China /* 3008a3c961bSfei feng - Sun Microsystems - Beijing China * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46, 3018a3c961bSfei feng - Sun Microsystems - Beijing China * 93C66 or 93C86). 3028a3c961bSfei feng - Sun Microsystems - Beijing China */ 3038a3c961bSfei feng - Sun Microsystems - Beijing China static uint16_t 3048a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_eeprom_read(struct rt2860_softc *sc, uint8_t addr) 3058a3c961bSfei feng - Sun Microsystems - Beijing China { 3068a3c961bSfei feng - Sun Microsystems - Beijing China int n; 3078a3c961bSfei feng - Sun Microsystems - Beijing China uint16_t val; 3088a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 3098a3c961bSfei feng - Sun Microsystems - Beijing China 3108a3c961bSfei feng - Sun Microsystems - Beijing China /* clock C once before the first command */ 3118a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, 0); 3128a3c961bSfei feng - Sun Microsystems - Beijing China 3138a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S); 3148a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); 3158a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S); 3168a3c961bSfei feng - Sun Microsystems - Beijing China 3178a3c961bSfei feng - Sun Microsystems - Beijing China /* write start bit (1) */ 3188a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); 3198a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); 3208a3c961bSfei feng - Sun Microsystems - Beijing China 3218a3c961bSfei feng - Sun Microsystems - Beijing China /* write READ opcode (10) */ 3228a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); 3238a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); 3248a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S); 3258a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); 3268a3c961bSfei feng - Sun Microsystems - Beijing China 3278a3c961bSfei feng - Sun Microsystems - Beijing China /* write address (A5-A0 or A7-A0) */ 3288a3c961bSfei feng - Sun Microsystems - Beijing China n = ((RT2860_READ(sc, RT2860_PCI_EECTRL) & 0x30) == 0) ? 5 : 7; 3298a3c961bSfei feng - Sun Microsystems - Beijing China for (; n >= 0; n--) { 3308a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | 3318a3c961bSfei feng - Sun Microsystems - Beijing China (((addr >> n) & 1) << RT2860_SHIFT_D)); 3328a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | 3338a3c961bSfei feng - Sun Microsystems - Beijing China (((addr >> n) & 1) << RT2860_SHIFT_D) | RT2860_C); 3348a3c961bSfei feng - Sun Microsystems - Beijing China } 3358a3c961bSfei feng - Sun Microsystems - Beijing China 3368a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S); 3378a3c961bSfei feng - Sun Microsystems - Beijing China 3388a3c961bSfei feng - Sun Microsystems - Beijing China /* read data Q15-Q0 */ 3398a3c961bSfei feng - Sun Microsystems - Beijing China val = 0; 3408a3c961bSfei feng - Sun Microsystems - Beijing China for (n = 15; n >= 0; n--) { 3418a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); 3428a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_PCI_EECTRL); 3438a3c961bSfei feng - Sun Microsystems - Beijing China val |= ((tmp & RT2860_Q) >> RT2860_SHIFT_Q) << n; 3448a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S); 3458a3c961bSfei feng - Sun Microsystems - Beijing China } 3468a3c961bSfei feng - Sun Microsystems - Beijing China 3478a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, 0); 3488a3c961bSfei feng - Sun Microsystems - Beijing China 3498a3c961bSfei feng - Sun Microsystems - Beijing China /* clear Chip Select and clock C */ 3508a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_S); 3518a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, 0); 3528a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_CTL(sc, RT2860_C); 3538a3c961bSfei feng - Sun Microsystems - Beijing China 3548a3c961bSfei feng - Sun Microsystems - Beijing China return (val); 3558a3c961bSfei feng - Sun Microsystems - Beijing China } 3568a3c961bSfei feng - Sun Microsystems - Beijing China 3578a3c961bSfei feng - Sun Microsystems - Beijing China /* 3588a3c961bSfei feng - Sun Microsystems - Beijing China * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word. 3598a3c961bSfei feng - Sun Microsystems - Beijing China * Used to adjust per-rate Tx power registers. 3608a3c961bSfei feng - Sun Microsystems - Beijing China */ 3618a3c961bSfei feng - Sun Microsystems - Beijing China static inline uint32_t 3628a3c961bSfei feng - Sun Microsystems - Beijing China b4inc(uint32_t b32, int8_t delta) 3638a3c961bSfei feng - Sun Microsystems - Beijing China { 3648a3c961bSfei feng - Sun Microsystems - Beijing China int8_t i, b4; 3658a3c961bSfei feng - Sun Microsystems - Beijing China 3668a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 8; i++) { 3678a3c961bSfei feng - Sun Microsystems - Beijing China b4 = b32 & 0xf; 3688a3c961bSfei feng - Sun Microsystems - Beijing China b4 += delta; 3698a3c961bSfei feng - Sun Microsystems - Beijing China if (b4 < 0) 3708a3c961bSfei feng - Sun Microsystems - Beijing China b4 = 0; 3718a3c961bSfei feng - Sun Microsystems - Beijing China else if (b4 > 0xf) 3728a3c961bSfei feng - Sun Microsystems - Beijing China b4 = 0xf; 3738a3c961bSfei feng - Sun Microsystems - Beijing China b32 = b32 >> 4 | b4 << 28; 3748a3c961bSfei feng - Sun Microsystems - Beijing China } 3758a3c961bSfei feng - Sun Microsystems - Beijing China return (b32); 3768a3c961bSfei feng - Sun Microsystems - Beijing China } 3778a3c961bSfei feng - Sun Microsystems - Beijing China 3788a3c961bSfei feng - Sun Microsystems - Beijing China static int 3798a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_read_eeprom(struct rt2860_softc *sc) 3808a3c961bSfei feng - Sun Microsystems - Beijing China { 3818a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 3828a3c961bSfei feng - Sun Microsystems - Beijing China int ridx, ant, i; 3838a3c961bSfei feng - Sun Microsystems - Beijing China int8_t delta_2ghz, delta_5ghz; 3848a3c961bSfei feng - Sun Microsystems - Beijing China uint16_t val; 3858a3c961bSfei feng - Sun Microsystems - Beijing China 3868a3c961bSfei feng - Sun Microsystems - Beijing China /* read EEPROM version */ 3878a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_VERSION); 3888a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 3898a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM rev=%d, FAE=%d\n", 3908a3c961bSfei feng - Sun Microsystems - Beijing China val & 0xff, val >> 8); 3918a3c961bSfei feng - Sun Microsystems - Beijing China 3928a3c961bSfei feng - Sun Microsystems - Beijing China /* read MAC address */ 3938a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_MAC01); 3948a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[0] = val & 0xff; 3958a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[1] = val >> 8; 3968a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_MAC23); 3978a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[2] = val & 0xff; 3988a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[3] = val >> 8; 3998a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_MAC45); 4008a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[4] = val & 0xff; 4018a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[5] = val >> 8; 4028a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4038a3c961bSfei feng - Sun Microsystems - Beijing China "MAC address is: %x:%x:%x:%x:%x:%x\n", 4048a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[0], ic->ic_macaddr[1], 4058a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[2], ic->ic_macaddr[3], 4068a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_macaddr[4], ic->ic_macaddr[5]); 4078a3c961bSfei feng - Sun Microsystems - Beijing China 4088a3c961bSfei feng - Sun Microsystems - Beijing China /* read country code */ 4098a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_COUNTRY); 4108a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4118a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM region code=0x%04x\n", val); 4128a3c961bSfei feng - Sun Microsystems - Beijing China 4138a3c961bSfei feng - Sun Microsystems - Beijing China /* read default BBP settings */ 4148a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 8; i++) { 4158a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_BBP_BASE + i); 4168a3c961bSfei feng - Sun Microsystems - Beijing China sc->bbp[i].val = val & 0xff; 4178a3c961bSfei feng - Sun Microsystems - Beijing China sc->bbp[i].reg = val >> 8; 4188a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4198a3c961bSfei feng - Sun Microsystems - Beijing China "BBP%d=0x%02x\n", 4208a3c961bSfei feng - Sun Microsystems - Beijing China sc->bbp[i].reg, sc->bbp[i].val); 4218a3c961bSfei feng - Sun Microsystems - Beijing China } 4228a3c961bSfei feng - Sun Microsystems - Beijing China 4238a3c961bSfei feng - Sun Microsystems - Beijing China /* read RF frequency offset from EEPROM */ 4248a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_FREQ_LEDS); 4258a3c961bSfei feng - Sun Microsystems - Beijing China sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; 4268a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4278a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM freq offset %d\n", sc->freq & 0xff); 4288a3c961bSfei feng - Sun Microsystems - Beijing China 4298a3c961bSfei feng - Sun Microsystems - Beijing China if ((sc->leds = val >> 8) != 0xff) { 4308a3c961bSfei feng - Sun Microsystems - Beijing China /* read LEDs operating mode */ 4318a3c961bSfei feng - Sun Microsystems - Beijing China sc->led[0] = rt2860_eeprom_read(sc, RT2860_EEPROM_LED1); 4328a3c961bSfei feng - Sun Microsystems - Beijing China sc->led[1] = rt2860_eeprom_read(sc, RT2860_EEPROM_LED2); 4338a3c961bSfei feng - Sun Microsystems - Beijing China sc->led[2] = rt2860_eeprom_read(sc, RT2860_EEPROM_LED3); 4348a3c961bSfei feng - Sun Microsystems - Beijing China } else { 4358a3c961bSfei feng - Sun Microsystems - Beijing China /* broken EEPROM, use default settings */ 4368a3c961bSfei feng - Sun Microsystems - Beijing China sc->leds = 0x01; 4378a3c961bSfei feng - Sun Microsystems - Beijing China sc->led[0] = 0x5555; 4388a3c961bSfei feng - Sun Microsystems - Beijing China sc->led[1] = 0x2221; 4398a3c961bSfei feng - Sun Microsystems - Beijing China sc->led[2] = 0xa9f8; 4408a3c961bSfei feng - Sun Microsystems - Beijing China } 4418a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4428a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", 4438a3c961bSfei feng - Sun Microsystems - Beijing China sc->leds, sc->led[0], sc->led[1], sc->led[2]); 4448a3c961bSfei feng - Sun Microsystems - Beijing China 4458a3c961bSfei feng - Sun Microsystems - Beijing China /* read RF information */ 4468a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_ANTENNA); 4478a3c961bSfei feng - Sun Microsystems - Beijing China if (val == 0xffff) { 4488a3c961bSfei feng - Sun Microsystems - Beijing China /* broken EEPROM, default to RF2820 1T2R */ 4498a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4508a3c961bSfei feng - Sun Microsystems - Beijing China "invalid EEPROM antenna info, using default\n"); 4518a3c961bSfei feng - Sun Microsystems - Beijing China sc->rf_rev = RT2860_RF_2820; 4528a3c961bSfei feng - Sun Microsystems - Beijing China sc->ntxchains = 1; 4538a3c961bSfei feng - Sun Microsystems - Beijing China sc->nrxchains = 2; 4548a3c961bSfei feng - Sun Microsystems - Beijing China } else { 4558a3c961bSfei feng - Sun Microsystems - Beijing China sc->rf_rev = (val >> 8) & 0xf; 4568a3c961bSfei feng - Sun Microsystems - Beijing China sc->ntxchains = (val >> 4) & 0xf; 4578a3c961bSfei feng - Sun Microsystems - Beijing China sc->nrxchains = val & 0xf; 4588a3c961bSfei feng - Sun Microsystems - Beijing China } 4598a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4608a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM RF rev=0x%02x chains=%dT%dR\n", 4618a3c961bSfei feng - Sun Microsystems - Beijing China sc->rf_rev, sc->ntxchains, sc->nrxchains); 4628a3c961bSfei feng - Sun Microsystems - Beijing China 4638a3c961bSfei feng - Sun Microsystems - Beijing China /* check if RF supports automatic Tx access gain control */ 4648a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_CONFIG); 4658a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 4668a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM CFG 0x%04x\n", val); 4678a3c961bSfei feng - Sun Microsystems - Beijing China if ((val & 0xff) != 0xff) 4688a3c961bSfei feng - Sun Microsystems - Beijing China sc->calib_2ghz = sc->calib_5ghz = 0; /* XXX (val >> 1) & 1 */; 4698a3c961bSfei feng - Sun Microsystems - Beijing China 4708a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_flags & RT2860_ADVANCED_PS) { 4718a3c961bSfei feng - Sun Microsystems - Beijing China /* read PCIe power save level */ 4728a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_PCIE_PSLEVEL); 4738a3c961bSfei feng - Sun Microsystems - Beijing China if ((val & 0xff) != 0xff) { 4748a3c961bSfei feng - Sun Microsystems - Beijing China sc->pslevel = val & 0x3; 4758a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_REV); 4768a3c961bSfei feng - Sun Microsystems - Beijing China if (val >> 8 != 0x92 || !(val & 0x80)) 4778a3c961bSfei feng - Sun Microsystems - Beijing China sc->pslevel = MIN(sc->pslevel, 1); 4788a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, 4798a3c961bSfei feng - Sun Microsystems - Beijing China "rwn: rt2860_read_eeprom(): " 4808a3c961bSfei feng - Sun Microsystems - Beijing China "EEPROM PCIe PS Level=%d\n", 4818a3c961bSfei feng - Sun Microsystems - Beijing China sc->pslevel); 4828a3c961bSfei feng - Sun Microsystems - Beijing China } 4838a3c961bSfei feng - Sun Microsystems - Beijing China } 4848a3c961bSfei feng - Sun Microsystems - Beijing China /* read power settings for 2GHz channels */ 4858a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 14; i += 2) { 4868a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, 4878a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2); 4888a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow1[i + 0] = (int8_t)(val & 0xff); 4898a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow1[i + 1] = (int8_t)(val >> 8); 4908a3c961bSfei feng - Sun Microsystems - Beijing China 4918a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, 4928a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2); 4938a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[i + 0] = (int8_t)(val & 0xff); 4948a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[i + 1] = (int8_t)(val >> 8); 4958a3c961bSfei feng - Sun Microsystems - Beijing China } 4968a3c961bSfei feng - Sun Microsystems - Beijing China /* fix broken Tx power entries */ 4978a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 14; i++) { 4988a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31) 4998a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow1[i] = 5; 5008a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) 5018a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[i] = 5; 5028a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 5038a3c961bSfei feng - Sun Microsystems - Beijing China "chan %d: power1=%d, power2=%d\n", 5048a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]); 5058a3c961bSfei feng - Sun Microsystems - Beijing China } 5068a3c961bSfei feng - Sun Microsystems - Beijing China /* read power settings for 5GHz channels */ 5078a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 36; i += 2) { 5088a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, 5098a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2); 5108a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow1[i + 14] = (int8_t)(val & 0xff); 5118a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow1[i + 15] = (int8_t)(val >> 8); 5128a3c961bSfei feng - Sun Microsystems - Beijing China 5138a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, 5148a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2); 5158a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[i + 14] = (int8_t)(val & 0xff); 5168a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[i + 15] = (int8_t)(val >> 8); 5178a3c961bSfei feng - Sun Microsystems - Beijing China } 5188a3c961bSfei feng - Sun Microsystems - Beijing China /* fix broken Tx power entries */ 5198a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 36; i++) { 5208a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) 5218a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow1[14 + i] = 5; 5228a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) 5238a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[14 + i] = 5; 5248a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 5258a3c961bSfei feng - Sun Microsystems - Beijing China "chan %d: power1=%d, power2=%d\n", 5268a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], 5278a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow2[14 + i]); 5288a3c961bSfei feng - Sun Microsystems - Beijing China } 5298a3c961bSfei feng - Sun Microsystems - Beijing China 5308a3c961bSfei feng - Sun Microsystems - Beijing China /* read Tx power compensation for each Tx rate */ 5318a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_DELTAPWR); 5328a3c961bSfei feng - Sun Microsystems - Beijing China delta_2ghz = delta_5ghz = 0; 5338a3c961bSfei feng - Sun Microsystems - Beijing China if ((val & 0xff) != 0xff && (val & 0x80)) { 5348a3c961bSfei feng - Sun Microsystems - Beijing China delta_2ghz = val & 0xf; 5358a3c961bSfei feng - Sun Microsystems - Beijing China if (!(val & 0x40)) /* negative number */ 5368a3c961bSfei feng - Sun Microsystems - Beijing China delta_2ghz = -delta_2ghz; 5378a3c961bSfei feng - Sun Microsystems - Beijing China } 5388a3c961bSfei feng - Sun Microsystems - Beijing China val >>= 8; 5398a3c961bSfei feng - Sun Microsystems - Beijing China if ((val & 0xff) != 0xff && (val & 0x80)) { 5408a3c961bSfei feng - Sun Microsystems - Beijing China delta_5ghz = val & 0xf; 5418a3c961bSfei feng - Sun Microsystems - Beijing China if (!(val & 0x40)) /* negative number */ 5428a3c961bSfei feng - Sun Microsystems - Beijing China delta_5ghz = -delta_5ghz; 5438a3c961bSfei feng - Sun Microsystems - Beijing China } 5448a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 5458a3c961bSfei feng - Sun Microsystems - Beijing China "power compensation=%d (2GHz), %d (5GHz) \n", 5468a3c961bSfei feng - Sun Microsystems - Beijing China delta_2ghz, delta_5ghz); 5478a3c961bSfei feng - Sun Microsystems - Beijing China 5488a3c961bSfei feng - Sun Microsystems - Beijing China for (ridx = 0; ridx < 5; ridx++) { 5498a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t reg; 5508a3c961bSfei feng - Sun Microsystems - Beijing China 5518a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_RPWR + ridx); 5528a3c961bSfei feng - Sun Microsystems - Beijing China reg = (uint32_t)val << 16; 5538a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_RPWR + ridx + 1); 5548a3c961bSfei feng - Sun Microsystems - Beijing China reg |= val; 5558a3c961bSfei feng - Sun Microsystems - Beijing China 5568a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow20mhz[ridx] = reg; 5578a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); 5588a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); 5598a3c961bSfei feng - Sun Microsystems - Beijing China 5608a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 5618a3c961bSfei feng - Sun Microsystems - Beijing China "ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " 5628a3c961bSfei feng - Sun Microsystems - Beijing China "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], 5638a3c961bSfei feng - Sun Microsystems - Beijing China sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]); 5648a3c961bSfei feng - Sun Microsystems - Beijing China } 5658a3c961bSfei feng - Sun Microsystems - Beijing China 5668a3c961bSfei feng - Sun Microsystems - Beijing China /* read factory-calibrated samples for temperature compensation */ 5678a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI1_2GHZ); 5688a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[0] = val & 0xff; /* [-4] */ 5698a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[1] = val >> 8; /* [-3] */ 5708a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI2_2GHZ); 5718a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[2] = val & 0xff; /* [-2] */ 5728a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[3] = val >> 8; /* [-1] */ 5738a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI3_2GHZ); 5748a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[4] = val & 0xff; /* [+0] */ 5758a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[5] = val >> 8; /* [+1] */ 5768a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI4_2GHZ); 5778a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[6] = val & 0xff; /* [+2] */ 5788a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[7] = val >> 8; /* [+3] */ 5798a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI5_2GHZ); 5808a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[8] = val & 0xff; /* [+4] */ 5818a3c961bSfei feng - Sun Microsystems - Beijing China sc->step_2ghz = val >> 8; 5828a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 5838a3c961bSfei feng - Sun Microsystems - Beijing China "TSSI 2GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " 5848a3c961bSfei feng - Sun Microsystems - Beijing China "0x%02x 0x%02x step=%d\n", sc->tssi_2ghz[0], sc->tssi_2ghz[1], 5858a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[2], sc->tssi_2ghz[3], sc->tssi_2ghz[4], 5868a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[5], sc->tssi_2ghz[6], sc->tssi_2ghz[7], 5878a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_2ghz[8], sc->step_2ghz); 5888a3c961bSfei feng - Sun Microsystems - Beijing China /* check that ref value is correct, otherwise disable calibration */ 5898a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->tssi_2ghz[4] == 0xff) 5908a3c961bSfei feng - Sun Microsystems - Beijing China sc->calib_2ghz = 0; 5918a3c961bSfei feng - Sun Microsystems - Beijing China 5928a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI1_5GHZ); 5938a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[0] = val & 0xff; /* [-4] */ 5948a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[1] = val >> 8; /* [-3] */ 5958a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI2_5GHZ); 5968a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[2] = val & 0xff; /* [-2] */ 5978a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[3] = val >> 8; /* [-1] */ 5988a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI3_5GHZ); 5998a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[4] = val & 0xff; /* [+0] */ 6008a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[5] = val >> 8; /* [+1] */ 6018a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI4_5GHZ); 6028a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[6] = val & 0xff; /* [+2] */ 6038a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[7] = val >> 8; /* [+3] */ 6048a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_TSSI5_5GHZ); 6058a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[8] = val & 0xff; /* [+4] */ 6068a3c961bSfei feng - Sun Microsystems - Beijing China sc->step_5ghz = val >> 8; 6078a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 6088a3c961bSfei feng - Sun Microsystems - Beijing China "TSSI 5GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " 6098a3c961bSfei feng - Sun Microsystems - Beijing China "0x%02x 0x%02x step=%d\n", sc->tssi_5ghz[0], sc->tssi_5ghz[1], 6108a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[2], sc->tssi_5ghz[3], sc->tssi_5ghz[4], 6118a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[5], sc->tssi_5ghz[6], sc->tssi_5ghz[7], 6128a3c961bSfei feng - Sun Microsystems - Beijing China sc->tssi_5ghz[8], sc->step_5ghz); 6138a3c961bSfei feng - Sun Microsystems - Beijing China /* check that ref value is correct, otherwise disable calibration */ 6148a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->tssi_5ghz[4] == 0xff) 6158a3c961bSfei feng - Sun Microsystems - Beijing China sc->calib_5ghz = 0; 6168a3c961bSfei feng - Sun Microsystems - Beijing China 6178a3c961bSfei feng - Sun Microsystems - Beijing China /* read RSSI offsets and LNA gains from EEPROM */ 6188a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_RSSI1_2GHZ); 6198a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ 6208a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_2ghz[1] = val >> 8; /* Ant B */ 6218a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_RSSI2_2GHZ); 6228a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ 6238a3c961bSfei feng - Sun Microsystems - Beijing China sc->lna[2] = val >> 8; /* channel group 2 */ 6248a3c961bSfei feng - Sun Microsystems - Beijing China 6258a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_RSSI1_5GHZ); 6268a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ 6278a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_5ghz[1] = val >> 8; /* Ant B */ 6288a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_RSSI2_5GHZ); 6298a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ 6308a3c961bSfei feng - Sun Microsystems - Beijing China sc->lna[3] = val >> 8; /* channel group 3 */ 6318a3c961bSfei feng - Sun Microsystems - Beijing China 6328a3c961bSfei feng - Sun Microsystems - Beijing China val = rt2860_eeprom_read(sc, RT2860_EEPROM_LNA); 6338a3c961bSfei feng - Sun Microsystems - Beijing China sc->lna[0] = val & 0xff; /* channel group 0 */ 6348a3c961bSfei feng - Sun Microsystems - Beijing China sc->lna[1] = val >> 8; /* channel group 1 */ 6358a3c961bSfei feng - Sun Microsystems - Beijing China 6368a3c961bSfei feng - Sun Microsystems - Beijing China /* fix broken 5GHz LNA entries */ 6378a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { 6388a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 6398a3c961bSfei feng - Sun Microsystems - Beijing China "invalid LNA for channel group %d\n", 2); 6408a3c961bSfei feng - Sun Microsystems - Beijing China sc->lna[2] = sc->lna[1]; 6418a3c961bSfei feng - Sun Microsystems - Beijing China } 6428a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { 6438a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, "rwn: rt2860_read_eeprom(): " 6448a3c961bSfei feng - Sun Microsystems - Beijing China "invalid LNA for channel group %d\n", 3); 6458a3c961bSfei feng - Sun Microsystems - Beijing China sc->lna[3] = sc->lna[1]; 6468a3c961bSfei feng - Sun Microsystems - Beijing China } 6478a3c961bSfei feng - Sun Microsystems - Beijing China 6488a3c961bSfei feng - Sun Microsystems - Beijing China /* fix broken RSSI offset entries */ 6498a3c961bSfei feng - Sun Microsystems - Beijing China for (ant = 0; ant < 3; ant++) { 6508a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { 6518a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, 6528a3c961bSfei feng - Sun Microsystems - Beijing China "rwn: rt2860_read_eeprom(): " 6538a3c961bSfei feng - Sun Microsystems - Beijing China "invalid RSSI%d offset: %d (2GHz)\n", 6548a3c961bSfei feng - Sun Microsystems - Beijing China ant + 1, sc->rssi_2ghz[ant]); 6558a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_2ghz[ant] = 0; 6568a3c961bSfei feng - Sun Microsystems - Beijing China } 6578a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { 6588a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_EEPROM, 6598a3c961bSfei feng - Sun Microsystems - Beijing China "rwn: rt2860_read_eeprom(): " 6608a3c961bSfei feng - Sun Microsystems - Beijing China "invalid RSSI%d offset: %d (2GHz)\n", 6618a3c961bSfei feng - Sun Microsystems - Beijing China ant + 1, sc->rssi_5ghz[ant]); 6628a3c961bSfei feng - Sun Microsystems - Beijing China sc->rssi_5ghz[ant] = 0; 6638a3c961bSfei feng - Sun Microsystems - Beijing China } 6648a3c961bSfei feng - Sun Microsystems - Beijing China } 6658a3c961bSfei feng - Sun Microsystems - Beijing China 6668a3c961bSfei feng - Sun Microsystems - Beijing China return (RT2860_SUCCESS); 6678a3c961bSfei feng - Sun Microsystems - Beijing China } 6688a3c961bSfei feng - Sun Microsystems - Beijing China 6698a3c961bSfei feng - Sun Microsystems - Beijing China /* 6708a3c961bSfei feng - Sun Microsystems - Beijing China * Allocate an DMA memory and a DMA handle for accessing it 6718a3c961bSfei feng - Sun Microsystems - Beijing China */ 6728a3c961bSfei feng - Sun Microsystems - Beijing China static int 6738a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr, 6748a3c961bSfei feng - Sun Microsystems - Beijing China size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags, 6758a3c961bSfei feng - Sun Microsystems - Beijing China uint_t bind_flags, struct dma_area *dma_p) 6768a3c961bSfei feng - Sun Microsystems - Beijing China { 6778a3c961bSfei feng - Sun Microsystems - Beijing China int err; 6788a3c961bSfei feng - Sun Microsystems - Beijing China 6798a3c961bSfei feng - Sun Microsystems - Beijing China /* 6808a3c961bSfei feng - Sun Microsystems - Beijing China * Allocate handle 6818a3c961bSfei feng - Sun Microsystems - Beijing China */ 6828a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_dma_alloc_handle(devinfo, dma_attr, 6838a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl); 6848a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 6858a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rwn_allo_dma_mem(): " 6868a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc handle\n"); 6878a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 6888a3c961bSfei feng - Sun Microsystems - Beijing China } 6898a3c961bSfei feng - Sun Microsystems - Beijing China 6908a3c961bSfei feng - Sun Microsystems - Beijing China /* 6918a3c961bSfei feng - Sun Microsystems - Beijing China * Allocate memory 6928a3c961bSfei feng - Sun Microsystems - Beijing China */ 6938a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 6948a3c961bSfei feng - Sun Microsystems - Beijing China alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va, 6958a3c961bSfei feng - Sun Microsystems - Beijing China &dma_p->alength, &dma_p->acc_hdl); 6968a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 6978a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rwn_alloc_dma_mem(): " 6988a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc mem\n"); 6998a3c961bSfei feng - Sun Microsystems - Beijing China goto fail2; 7008a3c961bSfei feng - Sun Microsystems - Beijing China } 7018a3c961bSfei feng - Sun Microsystems - Beijing China 7028a3c961bSfei feng - Sun Microsystems - Beijing China /* 7038a3c961bSfei feng - Sun Microsystems - Beijing China * Bind the two together 7048a3c961bSfei feng - Sun Microsystems - Beijing China */ 7058a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 7068a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->mem_va, dma_p->alength, bind_flags, 7078a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies); 7088a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_DMA_MAPPED) { 7098a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rwn_alloc_dma_mem(): " 7108a3c961bSfei feng - Sun Microsystems - Beijing China "failed to bind handle\n"); 7118a3c961bSfei feng - Sun Microsystems - Beijing China goto fail3; 7128a3c961bSfei feng - Sun Microsystems - Beijing China } 7138a3c961bSfei feng - Sun Microsystems - Beijing China 7148a3c961bSfei feng - Sun Microsystems - Beijing China if (dma_p->ncookies != 1) { 7158a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rwn_alloc_dma_mem(): " 7168a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc cookies\n"); 7178a3c961bSfei feng - Sun Microsystems - Beijing China goto fail4; 7188a3c961bSfei feng - Sun Microsystems - Beijing China } 7198a3c961bSfei feng - Sun Microsystems - Beijing China 7208a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->nslots = ~0U; 7218a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->size = ~0U; 7228a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->token = ~0U; 7238a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->offset = 0; 7248a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 7258a3c961bSfei feng - Sun Microsystems - Beijing China 7268a3c961bSfei feng - Sun Microsystems - Beijing China fail4: 7278a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 7288a3c961bSfei feng - Sun Microsystems - Beijing China fail3: 7298a3c961bSfei feng - Sun Microsystems - Beijing China ddi_dma_mem_free(&dma_p->acc_hdl); 7308a3c961bSfei feng - Sun Microsystems - Beijing China fail2: 7318a3c961bSfei feng - Sun Microsystems - Beijing China ddi_dma_free_handle(&dma_p->dma_hdl); 7328a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 7338a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 7348a3c961bSfei feng - Sun Microsystems - Beijing China } 7358a3c961bSfei feng - Sun Microsystems - Beijing China 7368a3c961bSfei feng - Sun Microsystems - Beijing China static void 7378a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(struct dma_area *dma_p) 7388a3c961bSfei feng - Sun Microsystems - Beijing China { 7398a3c961bSfei feng - Sun Microsystems - Beijing China if (dma_p->dma_hdl != NULL) { 7408a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 7418a3c961bSfei feng - Sun Microsystems - Beijing China if (dma_p->acc_hdl != NULL) { 7428a3c961bSfei feng - Sun Microsystems - Beijing China ddi_dma_mem_free(&dma_p->acc_hdl); 7438a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->acc_hdl = NULL; 7448a3c961bSfei feng - Sun Microsystems - Beijing China } 7458a3c961bSfei feng - Sun Microsystems - Beijing China ddi_dma_free_handle(&dma_p->dma_hdl); 7468a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->ncookies = 0; 7478a3c961bSfei feng - Sun Microsystems - Beijing China dma_p->dma_hdl = NULL; 7488a3c961bSfei feng - Sun Microsystems - Beijing China } 7498a3c961bSfei feng - Sun Microsystems - Beijing China } 7508a3c961bSfei feng - Sun Microsystems - Beijing China 7518a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 7528a3c961bSfei feng - Sun Microsystems - Beijing China static int 7538a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_alloc_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) 7548a3c961bSfei feng - Sun Microsystems - Beijing China { 7558a3c961bSfei feng - Sun Microsystems - Beijing China int size, err; 7568a3c961bSfei feng - Sun Microsystems - Beijing China 7578a3c961bSfei feng - Sun Microsystems - Beijing China size = RT2860_TX_RING_COUNT * sizeof (struct rt2860_txd); 7588a3c961bSfei feng - Sun Microsystems - Beijing China 7598a3c961bSfei feng - Sun Microsystems - Beijing China err = rt2860_alloc_dma_mem(sc->sc_dev, &rt2860_dma_attr, size, 7608a3c961bSfei feng - Sun Microsystems - Beijing China &rt2860_desc_accattr, DDI_DMA_CONSISTENT, 7618a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 7628a3c961bSfei feng - Sun Microsystems - Beijing China &ring->txdesc_dma); 7638a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 7648a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rt2860_alloc_tx_ring(): " 7658a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc dma mem\n"); 7668a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 7678a3c961bSfei feng - Sun Microsystems - Beijing China } 7688a3c961bSfei feng - Sun Microsystems - Beijing China 7698a3c961bSfei feng - Sun Microsystems - Beijing China ring->txd = (struct rt2860_txd *)ring->txdesc_dma.mem_va; 7708a3c961bSfei feng - Sun Microsystems - Beijing China ring->paddr = ring->txdesc_dma.cookie.dmac_address; 7718a3c961bSfei feng - Sun Microsystems - Beijing China 7728a3c961bSfei feng - Sun Microsystems - Beijing China ring->cur = 0; 7738a3c961bSfei feng - Sun Microsystems - Beijing China ring->next = 0; 7748a3c961bSfei feng - Sun Microsystems - Beijing China ring->queued = 0; 7758a3c961bSfei feng - Sun Microsystems - Beijing China 7768a3c961bSfei feng - Sun Microsystems - Beijing China (void) bzero(ring->txd, size); 7778a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(ring->txdesc_dma, DDI_DMA_SYNC_FORDEV); 7788a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 7798a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 7808a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 7818a3c961bSfei feng - Sun Microsystems - Beijing China } 7828a3c961bSfei feng - Sun Microsystems - Beijing China 7838a3c961bSfei feng - Sun Microsystems - Beijing China void 7848a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_reset_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) 7858a3c961bSfei feng - Sun Microsystems - Beijing China { 7868a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_data *data; 7878a3c961bSfei feng - Sun Microsystems - Beijing China int i; 7888a3c961bSfei feng - Sun Microsystems - Beijing China 7898a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RT2860_TX_RING_COUNT; i++) { 7908a3c961bSfei feng - Sun Microsystems - Beijing China ring->txd[i].sdl0 &= ~LE_16(RT2860_TX_DDONE); 7918a3c961bSfei feng - Sun Microsystems - Beijing China 7928a3c961bSfei feng - Sun Microsystems - Beijing China if ((data = ring->data[i]) == NULL) 7938a3c961bSfei feng - Sun Microsystems - Beijing China continue; /* nothing mapped in this slot */ 7948a3c961bSfei feng - Sun Microsystems - Beijing China 7958a3c961bSfei feng - Sun Microsystems - Beijing China /* by pass if it's quiesced */ 7968a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_F_QUIESCE)) 7978a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(data->txbuf_dma, DDI_DMA_SYNC_FORDEV); 7988a3c961bSfei feng - Sun Microsystems - Beijing China 7998a3c961bSfei feng - Sun Microsystems - Beijing China if (data->ni != NULL) { 8008a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_free_node(data->ni); 8018a3c961bSfei feng - Sun Microsystems - Beijing China data->ni = NULL; /* node already freed */ 8028a3c961bSfei feng - Sun Microsystems - Beijing China } 8038a3c961bSfei feng - Sun Microsystems - Beijing China 8048a3c961bSfei feng - Sun Microsystems - Beijing China SLIST_INSERT_HEAD(&sc->data_pool, data, next); 8058a3c961bSfei feng - Sun Microsystems - Beijing China ring->data[i] = NULL; 8068a3c961bSfei feng - Sun Microsystems - Beijing China } 8078a3c961bSfei feng - Sun Microsystems - Beijing China 8088a3c961bSfei feng - Sun Microsystems - Beijing China /* by pass if it's quiesced */ 8098a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_F_QUIESCE)) 8108a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(ring->txdesc_dma, DDI_DMA_SYNC_FORDEV); 8118a3c961bSfei feng - Sun Microsystems - Beijing China 8128a3c961bSfei feng - Sun Microsystems - Beijing China ring->queued = 0; 8138a3c961bSfei feng - Sun Microsystems - Beijing China ring->cur = ring->next = 0; 8148a3c961bSfei feng - Sun Microsystems - Beijing China } 8158a3c961bSfei feng - Sun Microsystems - Beijing China 8168a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 8178a3c961bSfei feng - Sun Microsystems - Beijing China static void 8188a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) 8198a3c961bSfei feng - Sun Microsystems - Beijing China { 8208a3c961bSfei feng - Sun Microsystems - Beijing China if (ring->txd != NULL) { 8218a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&ring->txdesc_dma); 8228a3c961bSfei feng - Sun Microsystems - Beijing China } 8238a3c961bSfei feng - Sun Microsystems - Beijing China } 8248a3c961bSfei feng - Sun Microsystems - Beijing China 8258a3c961bSfei feng - Sun Microsystems - Beijing China static int 8268a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_alloc_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) 8278a3c961bSfei feng - Sun Microsystems - Beijing China { 8288a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rx_data *data; 8298a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rxd *rxd; 8308a3c961bSfei feng - Sun Microsystems - Beijing China int i, err, size, datalen; 8318a3c961bSfei feng - Sun Microsystems - Beijing China 8328a3c961bSfei feng - Sun Microsystems - Beijing China size = RT2860_RX_RING_COUNT * sizeof (struct rt2860_rxd); 8338a3c961bSfei feng - Sun Microsystems - Beijing China 8348a3c961bSfei feng - Sun Microsystems - Beijing China err = rt2860_alloc_dma_mem(sc->sc_dev, &rt2860_dma_attr, size, 8358a3c961bSfei feng - Sun Microsystems - Beijing China &rt2860_desc_accattr, DDI_DMA_CONSISTENT, 8368a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 8378a3c961bSfei feng - Sun Microsystems - Beijing China &ring->rxdesc_dma); 8388a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 8398a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rt2860_alloc_rx_ring(): " 8408a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc dma mem\n"); 8418a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 8428a3c961bSfei feng - Sun Microsystems - Beijing China } 8438a3c961bSfei feng - Sun Microsystems - Beijing China 8448a3c961bSfei feng - Sun Microsystems - Beijing China ring->rxd = (struct rt2860_rxd *)ring->rxdesc_dma.mem_va; 8458a3c961bSfei feng - Sun Microsystems - Beijing China ring->paddr = ring->rxdesc_dma.cookie.dmac_address; 8468a3c961bSfei feng - Sun Microsystems - Beijing China bzero(ring->rxd, size); 8478a3c961bSfei feng - Sun Microsystems - Beijing China 8488a3c961bSfei feng - Sun Microsystems - Beijing China /* 8498a3c961bSfei feng - Sun Microsystems - Beijing China * Pre-allocate Rx buffers and populate Rx ring. 8508a3c961bSfei feng - Sun Microsystems - Beijing China */ 8518a3c961bSfei feng - Sun Microsystems - Beijing China datalen = RT2860_RX_RING_COUNT * sizeof (struct rt2860_rx_data); 8528a3c961bSfei feng - Sun Microsystems - Beijing China bzero(ring->data, datalen); 8538a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RT2860_RX_RING_COUNT; i++) { 8548a3c961bSfei feng - Sun Microsystems - Beijing China rxd = &ring->rxd[i]; 8558a3c961bSfei feng - Sun Microsystems - Beijing China data = &ring->data[i]; 8568a3c961bSfei feng - Sun Microsystems - Beijing China /* alloc DMA memory */ 8578a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_alloc_dma_mem(sc->sc_dev, &rt2860_dma_attr, 8588a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_dmabuf_size, 8598a3c961bSfei feng - Sun Microsystems - Beijing China &rt2860_buf_accattr, 8608a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_STREAMING, 8618a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_READ | DDI_DMA_STREAMING, 8628a3c961bSfei feng - Sun Microsystems - Beijing China &data->rxbuf_dma); 8638a3c961bSfei feng - Sun Microsystems - Beijing China rxd->sdp0 = LE_32(data->rxbuf_dma.cookie.dmac_address); 8648a3c961bSfei feng - Sun Microsystems - Beijing China rxd->sdl0 = LE_16(sc->sc_dmabuf_size); 8658a3c961bSfei feng - Sun Microsystems - Beijing China } 8668a3c961bSfei feng - Sun Microsystems - Beijing China 8678a3c961bSfei feng - Sun Microsystems - Beijing China ring->cur = 0; 8688a3c961bSfei feng - Sun Microsystems - Beijing China 8698a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(ring->rxdesc_dma, DDI_DMA_SYNC_FORDEV); 8708a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 8718a3c961bSfei feng - Sun Microsystems - Beijing China fail2: 8728a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&ring->rxdesc_dma); 8738a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 8748a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 8758a3c961bSfei feng - Sun Microsystems - Beijing China } 8768a3c961bSfei feng - Sun Microsystems - Beijing China 8778a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 8788a3c961bSfei feng - Sun Microsystems - Beijing China void 8798a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_reset_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) 8808a3c961bSfei feng - Sun Microsystems - Beijing China { 8818a3c961bSfei feng - Sun Microsystems - Beijing China int i; 8828a3c961bSfei feng - Sun Microsystems - Beijing China 8838a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RT2860_RX_RING_COUNT; i++) 8848a3c961bSfei feng - Sun Microsystems - Beijing China ring->rxd[i].sdl0 &= ~LE_16(RT2860_RX_DDONE); 8858a3c961bSfei feng - Sun Microsystems - Beijing China 8868a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(ring->rxdesc_dma, DDI_DMA_SYNC_FORDEV); 8878a3c961bSfei feng - Sun Microsystems - Beijing China 8888a3c961bSfei feng - Sun Microsystems - Beijing China ring->cur = 0; 8898a3c961bSfei feng - Sun Microsystems - Beijing China } 8908a3c961bSfei feng - Sun Microsystems - Beijing China 8918a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 8928a3c961bSfei feng - Sun Microsystems - Beijing China static void 8938a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) 8948a3c961bSfei feng - Sun Microsystems - Beijing China { 8958a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rx_data *data; 8968a3c961bSfei feng - Sun Microsystems - Beijing China int i, count; 8978a3c961bSfei feng - Sun Microsystems - Beijing China 8988a3c961bSfei feng - Sun Microsystems - Beijing China if (ring->rxd != NULL) 8998a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&ring->rxdesc_dma); 9008a3c961bSfei feng - Sun Microsystems - Beijing China 9018a3c961bSfei feng - Sun Microsystems - Beijing China count = RT2860_RX_RING_COUNT; 9028a3c961bSfei feng - Sun Microsystems - Beijing China if (ring->data != NULL) { 9038a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < count; i++) { 9048a3c961bSfei feng - Sun Microsystems - Beijing China data = &ring->data[i]; 9058a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&data->rxbuf_dma); 9068a3c961bSfei feng - Sun Microsystems - Beijing China } 9078a3c961bSfei feng - Sun Microsystems - Beijing China } 9088a3c961bSfei feng - Sun Microsystems - Beijing China } 9098a3c961bSfei feng - Sun Microsystems - Beijing China 9108a3c961bSfei feng - Sun Microsystems - Beijing China static int 9118a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_alloc_tx_pool(struct rt2860_softc *sc) 9128a3c961bSfei feng - Sun Microsystems - Beijing China { 9138a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_data *data; 9148a3c961bSfei feng - Sun Microsystems - Beijing China int i, err, size; 9158a3c961bSfei feng - Sun Microsystems - Beijing China 9168a3c961bSfei feng - Sun Microsystems - Beijing China size = RT2860_TX_POOL_COUNT * sizeof (struct rt2860_txwi); 9178a3c961bSfei feng - Sun Microsystems - Beijing China 9188a3c961bSfei feng - Sun Microsystems - Beijing China /* init data_pool early in case of failure.. */ 9198a3c961bSfei feng - Sun Microsystems - Beijing China SLIST_INIT(&sc->data_pool); 9208a3c961bSfei feng - Sun Microsystems - Beijing China 9218a3c961bSfei feng - Sun Microsystems - Beijing China err = rt2860_alloc_dma_mem(sc->sc_dev, &rt2860_dma_attr, size, 9228a3c961bSfei feng - Sun Microsystems - Beijing China &rt2860_desc_accattr, DDI_DMA_CONSISTENT, 9238a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 9248a3c961bSfei feng - Sun Microsystems - Beijing China &sc->txpool_dma); 9258a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 9268a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rt2860_alloc_tx_pool(): " 9278a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc dma mem\n"); 9288a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 9298a3c961bSfei feng - Sun Microsystems - Beijing China } 9308a3c961bSfei feng - Sun Microsystems - Beijing China 9318a3c961bSfei feng - Sun Microsystems - Beijing China sc->txwi = (struct rt2860_txwi *)sc->txpool_dma.mem_va; 9328a3c961bSfei feng - Sun Microsystems - Beijing China (void) bzero(sc->txwi, size); 9338a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(sc->txpool_dma, DDI_DMA_SYNC_FORDEV); 9348a3c961bSfei feng - Sun Microsystems - Beijing China 9358a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RT2860_TX_POOL_COUNT; i++) { 9368a3c961bSfei feng - Sun Microsystems - Beijing China data = &sc->data[i]; 9378a3c961bSfei feng - Sun Microsystems - Beijing China 9388a3c961bSfei feng - Sun Microsystems - Beijing China err = rt2860_alloc_dma_mem(sc->sc_dev, &rt2860_dma_attr, 9398a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_dmabuf_size, 9408a3c961bSfei feng - Sun Microsystems - Beijing China &rt2860_buf_accattr, DDI_DMA_CONSISTENT, 9418a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 9428a3c961bSfei feng - Sun Microsystems - Beijing China &data->txbuf_dma); 9438a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 9448a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, 9458a3c961bSfei feng - Sun Microsystems - Beijing China "rwn: rt2860_alloc_tx_pool(): " 9468a3c961bSfei feng - Sun Microsystems - Beijing China "failed to alloc dma mem\n"); 9478a3c961bSfei feng - Sun Microsystems - Beijing China goto fail2; 9488a3c961bSfei feng - Sun Microsystems - Beijing China } 9498a3c961bSfei feng - Sun Microsystems - Beijing China data->txwi = &sc->txwi[i]; 9508a3c961bSfei feng - Sun Microsystems - Beijing China data->paddr = sc->txpool_dma.cookie.dmac_address + 9518a3c961bSfei feng - Sun Microsystems - Beijing China i * sizeof (struct rt2860_txwi); 9528a3c961bSfei feng - Sun Microsystems - Beijing China 9538a3c961bSfei feng - Sun Microsystems - Beijing China SLIST_INSERT_HEAD(&sc->data_pool, data, next); 9548a3c961bSfei feng - Sun Microsystems - Beijing China } 9558a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 9568a3c961bSfei feng - Sun Microsystems - Beijing China fail2: 9578a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&sc->txpool_dma); 9588a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 9598a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 9608a3c961bSfei feng - Sun Microsystems - Beijing China } 9618a3c961bSfei feng - Sun Microsystems - Beijing China 9628a3c961bSfei feng - Sun Microsystems - Beijing China static void 9638a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_tx_pool(struct rt2860_softc *sc) 9648a3c961bSfei feng - Sun Microsystems - Beijing China { 9658a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_data *data; 9668a3c961bSfei feng - Sun Microsystems - Beijing China int i; 9678a3c961bSfei feng - Sun Microsystems - Beijing China 9688a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->txwi != NULL) { 9698a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&sc->txpool_dma); 9708a3c961bSfei feng - Sun Microsystems - Beijing China } 9718a3c961bSfei feng - Sun Microsystems - Beijing China 9728a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < RT2860_TX_POOL_COUNT; i++) { 9738a3c961bSfei feng - Sun Microsystems - Beijing China data = &sc->data[i]; 9748a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_dma_mem(&data->txbuf_dma); 9758a3c961bSfei feng - Sun Microsystems - Beijing China } 9768a3c961bSfei feng - Sun Microsystems - Beijing China } 9778a3c961bSfei feng - Sun Microsystems - Beijing China 9788a3c961bSfei feng - Sun Microsystems - Beijing China /* quickly determine if a given rate is CCK or OFDM */ 9798a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) 9808a3c961bSfei feng - Sun Microsystems - Beijing China 9818a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_ACK_SIZE 14 /* 10 + 4(FCS) */ 9828a3c961bSfei feng - Sun Microsystems - Beijing China #define RT2860_SIFS_TIME 10 9838a3c961bSfei feng - Sun Microsystems - Beijing China 9848a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t 9858a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rate2mcs(uint8_t rate) 9868a3c961bSfei feng - Sun Microsystems - Beijing China { 9878a3c961bSfei feng - Sun Microsystems - Beijing China switch (rate) { 9888a3c961bSfei feng - Sun Microsystems - Beijing China /* CCK rates */ 9898a3c961bSfei feng - Sun Microsystems - Beijing China case 2: 9908a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 9918a3c961bSfei feng - Sun Microsystems - Beijing China case 4: 9928a3c961bSfei feng - Sun Microsystems - Beijing China return (1); 9938a3c961bSfei feng - Sun Microsystems - Beijing China case 11: 9948a3c961bSfei feng - Sun Microsystems - Beijing China return (2); 9958a3c961bSfei feng - Sun Microsystems - Beijing China case 22: 9968a3c961bSfei feng - Sun Microsystems - Beijing China return (3); 9978a3c961bSfei feng - Sun Microsystems - Beijing China /* OFDM rates */ 9988a3c961bSfei feng - Sun Microsystems - Beijing China case 12: 9998a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 10008a3c961bSfei feng - Sun Microsystems - Beijing China case 18: 10018a3c961bSfei feng - Sun Microsystems - Beijing China return (1); 10028a3c961bSfei feng - Sun Microsystems - Beijing China case 24: 10038a3c961bSfei feng - Sun Microsystems - Beijing China return (2); 10048a3c961bSfei feng - Sun Microsystems - Beijing China case 36: 10058a3c961bSfei feng - Sun Microsystems - Beijing China return (3); 10068a3c961bSfei feng - Sun Microsystems - Beijing China case 48: 10078a3c961bSfei feng - Sun Microsystems - Beijing China return (4); 10088a3c961bSfei feng - Sun Microsystems - Beijing China case 72: 10098a3c961bSfei feng - Sun Microsystems - Beijing China return (5); 10108a3c961bSfei feng - Sun Microsystems - Beijing China case 96: 10118a3c961bSfei feng - Sun Microsystems - Beijing China return (6); 10128a3c961bSfei feng - Sun Microsystems - Beijing China case 108: 10138a3c961bSfei feng - Sun Microsystems - Beijing China return (7); 10148a3c961bSfei feng - Sun Microsystems - Beijing China } 10158a3c961bSfei feng - Sun Microsystems - Beijing China 10168a3c961bSfei feng - Sun Microsystems - Beijing China return (0); /* shouldn't get there */ 10178a3c961bSfei feng - Sun Microsystems - Beijing China } 10188a3c961bSfei feng - Sun Microsystems - Beijing China 10198a3c961bSfei feng - Sun Microsystems - Beijing China /* 10208a3c961bSfei feng - Sun Microsystems - Beijing China * Return the expected ack rate for a frame transmitted at rate `rate'. 10218a3c961bSfei feng - Sun Microsystems - Beijing China */ 10228a3c961bSfei feng - Sun Microsystems - Beijing China static int 10238a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_ack_rate(struct ieee80211com *ic, int rate) 10248a3c961bSfei feng - Sun Microsystems - Beijing China { 10258a3c961bSfei feng - Sun Microsystems - Beijing China switch (rate) { 10268a3c961bSfei feng - Sun Microsystems - Beijing China /* CCK rates */ 10278a3c961bSfei feng - Sun Microsystems - Beijing China case 2: 10288a3c961bSfei feng - Sun Microsystems - Beijing China return (2); 10298a3c961bSfei feng - Sun Microsystems - Beijing China case 4: 10308a3c961bSfei feng - Sun Microsystems - Beijing China case 11: 10318a3c961bSfei feng - Sun Microsystems - Beijing China case 22: 10328a3c961bSfei feng - Sun Microsystems - Beijing China return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate); 10338a3c961bSfei feng - Sun Microsystems - Beijing China 10348a3c961bSfei feng - Sun Microsystems - Beijing China /* OFDM rates */ 10358a3c961bSfei feng - Sun Microsystems - Beijing China case 12: 10368a3c961bSfei feng - Sun Microsystems - Beijing China case 18: 10378a3c961bSfei feng - Sun Microsystems - Beijing China return (12); 10388a3c961bSfei feng - Sun Microsystems - Beijing China case 24: 10398a3c961bSfei feng - Sun Microsystems - Beijing China case 36: 10408a3c961bSfei feng - Sun Microsystems - Beijing China return (24); 10418a3c961bSfei feng - Sun Microsystems - Beijing China case 48: 10428a3c961bSfei feng - Sun Microsystems - Beijing China case 72: 10438a3c961bSfei feng - Sun Microsystems - Beijing China case 96: 10448a3c961bSfei feng - Sun Microsystems - Beijing China case 108: 10458a3c961bSfei feng - Sun Microsystems - Beijing China return (48); 10468a3c961bSfei feng - Sun Microsystems - Beijing China } 10478a3c961bSfei feng - Sun Microsystems - Beijing China 10488a3c961bSfei feng - Sun Microsystems - Beijing China /* default to 1Mbps */ 10498a3c961bSfei feng - Sun Microsystems - Beijing China return (2); 10508a3c961bSfei feng - Sun Microsystems - Beijing China } 10518a3c961bSfei feng - Sun Microsystems - Beijing China 10528a3c961bSfei feng - Sun Microsystems - Beijing China 10538a3c961bSfei feng - Sun Microsystems - Beijing China /* 10548a3c961bSfei feng - Sun Microsystems - Beijing China * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'. 10558a3c961bSfei feng - Sun Microsystems - Beijing China * The function automatically determines the operating mode depending on the 10568a3c961bSfei feng - Sun Microsystems - Beijing China * given rate. `flags' indicates whether short preamble is in use or not. 10578a3c961bSfei feng - Sun Microsystems - Beijing China */ 10588a3c961bSfei feng - Sun Microsystems - Beijing China static uint16_t 10598a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_txtime(int len, int rate, uint32_t flags) 10608a3c961bSfei feng - Sun Microsystems - Beijing China { 10618a3c961bSfei feng - Sun Microsystems - Beijing China uint16_t txtime; 10628a3c961bSfei feng - Sun Microsystems - Beijing China 10638a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_RATE_IS_OFDM(rate)) { 10648a3c961bSfei feng - Sun Microsystems - Beijing China /* IEEE Std 802.11g-2003, pp. 44 */ 10658a3c961bSfei feng - Sun Microsystems - Beijing China txtime = (8 + 4 * len + 3 + rate - 1) / rate; 10668a3c961bSfei feng - Sun Microsystems - Beijing China txtime = 16 + 4 + 4 * txtime + 6; 10678a3c961bSfei feng - Sun Microsystems - Beijing China } else { 10688a3c961bSfei feng - Sun Microsystems - Beijing China /* IEEE Std 802.11b-1999, pp. 28 */ 10698a3c961bSfei feng - Sun Microsystems - Beijing China txtime = (16 * len + rate - 1) / rate; 10708a3c961bSfei feng - Sun Microsystems - Beijing China if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) 10718a3c961bSfei feng - Sun Microsystems - Beijing China txtime += 72 + 24; 10728a3c961bSfei feng - Sun Microsystems - Beijing China else 10738a3c961bSfei feng - Sun Microsystems - Beijing China txtime += 144 + 48; 10748a3c961bSfei feng - Sun Microsystems - Beijing China } 10758a3c961bSfei feng - Sun Microsystems - Beijing China return (txtime); 10768a3c961bSfei feng - Sun Microsystems - Beijing China } 10778a3c961bSfei feng - Sun Microsystems - Beijing China 10788a3c961bSfei feng - Sun Microsystems - Beijing China static int 10798a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 10808a3c961bSfei feng - Sun Microsystems - Beijing China { 10818a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)ic; 10828a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_ring *ring; 10838a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_data *data; 10848a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_txd *txd; 10858a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_txwi *txwi; 10868a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_frame *wh; 10878a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *ni; 10888a3c961bSfei feng - Sun Microsystems - Beijing China int qid, off, rate, err; 10898a3c961bSfei feng - Sun Microsystems - Beijing China int mblen, pktlen; 10908a3c961bSfei feng - Sun Microsystems - Beijing China uint_t hdrlen; 10918a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t mcs, pid, qsel; 10928a3c961bSfei feng - Sun Microsystems - Beijing China uint16_t dur; 10938a3c961bSfei feng - Sun Microsystems - Beijing China mblk_t *m, *m0; 10948a3c961bSfei feng - Sun Microsystems - Beijing China 10958a3c961bSfei feng - Sun Microsystems - Beijing China err = DDI_SUCCESS; 10968a3c961bSfei feng - Sun Microsystems - Beijing China 10978a3c961bSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 10988a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_IS_SUSPEND(sc)) { 10998a3c961bSfei feng - Sun Microsystems - Beijing China err = ENXIO; 11008a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 11018a3c961bSfei feng - Sun Microsystems - Beijing China } 11028a3c961bSfei feng - Sun Microsystems - Beijing China 11038a3c961bSfei feng - Sun Microsystems - Beijing China if ((type & IEEE80211_FC0_TYPE_MASK) != 11048a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_FC0_TYPE_DATA) 11058a3c961bSfei feng - Sun Microsystems - Beijing China qid = sc->mgtqid; 11068a3c961bSfei feng - Sun Microsystems - Beijing China else 11078a3c961bSfei feng - Sun Microsystems - Beijing China qid = EDCA_AC_BE; 11088a3c961bSfei feng - Sun Microsystems - Beijing China ring = &sc->txq[qid]; 11098a3c961bSfei feng - Sun Microsystems - Beijing China 11108a3c961bSfei feng - Sun Microsystems - Beijing China if (SLIST_EMPTY(&sc->data_pool) || (ring->queued > 15)) { 11118a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_need_sched = 1; 11128a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_tx_nobuf++; 11138a3c961bSfei feng - Sun Microsystems - Beijing China err = ENOMEM; 11148a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 11158a3c961bSfei feng - Sun Microsystems - Beijing China } 11168a3c961bSfei feng - Sun Microsystems - Beijing China 11178a3c961bSfei feng - Sun Microsystems - Beijing China /* the data pool contains at least one element, pick the first */ 11188a3c961bSfei feng - Sun Microsystems - Beijing China data = SLIST_FIRST(&sc->data_pool); 11198a3c961bSfei feng - Sun Microsystems - Beijing China 11208a3c961bSfei feng - Sun Microsystems - Beijing China m = allocb(msgdsize(mp) + 32, BPRI_MED); 11218a3c961bSfei feng - Sun Microsystems - Beijing China if (m == NULL) { 11228a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_TX, "rwn: rt2860_send():" 1123860387ebSfei feng - Sun Microsystems - Beijing China "rt2860_mgmt_send: can't alloc mblk.\n"); 11248a3c961bSfei feng - Sun Microsystems - Beijing China err = DDI_FAILURE; 11258a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 11268a3c961bSfei feng - Sun Microsystems - Beijing China } 11278a3c961bSfei feng - Sun Microsystems - Beijing China 11288a3c961bSfei feng - Sun Microsystems - Beijing China for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 11298a3c961bSfei feng - Sun Microsystems - Beijing China mblen = MBLKL(m0); 11308a3c961bSfei feng - Sun Microsystems - Beijing China (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen); 11318a3c961bSfei feng - Sun Microsystems - Beijing China off += mblen; 11328a3c961bSfei feng - Sun Microsystems - Beijing China } 11338a3c961bSfei feng - Sun Microsystems - Beijing China m->b_wptr += off; 11348a3c961bSfei feng - Sun Microsystems - Beijing China 11358a3c961bSfei feng - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)m->b_rptr; 11368a3c961bSfei feng - Sun Microsystems - Beijing China ni = ieee80211_find_txnode(ic, wh->i_addr1); 11378a3c961bSfei feng - Sun Microsystems - Beijing China if (ni == NULL) { 11388a3c961bSfei feng - Sun Microsystems - Beijing China err = DDI_FAILURE; 11398a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_tx_err++; 11408a3c961bSfei feng - Sun Microsystems - Beijing China goto fail2; 11418a3c961bSfei feng - Sun Microsystems - Beijing China } 11428a3c961bSfei feng - Sun Microsystems - Beijing China 11438a3c961bSfei feng - Sun Microsystems - Beijing China if ((type & IEEE80211_FC0_TYPE_MASK) == 11448a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_FC0_TYPE_DATA) 11458a3c961bSfei feng - Sun Microsystems - Beijing China (void) ieee80211_encap(ic, m, ni); 11468a3c961bSfei feng - Sun Microsystems - Beijing China 11478a3c961bSfei feng - Sun Microsystems - Beijing China if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 11488a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_key *k; 11498a3c961bSfei feng - Sun Microsystems - Beijing China k = ieee80211_crypto_encap(ic, m); 11508a3c961bSfei feng - Sun Microsystems - Beijing China if (k == NULL) { 11518a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_tx_err++; 11528a3c961bSfei feng - Sun Microsystems - Beijing China err = DDI_FAILURE; 11538a3c961bSfei feng - Sun Microsystems - Beijing China goto fail3; 11548a3c961bSfei feng - Sun Microsystems - Beijing China } 11558a3c961bSfei feng - Sun Microsystems - Beijing China /* packet header may have moved, reset our local pointer */ 11568a3c961bSfei feng - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)m->b_rptr; 11578a3c961bSfei feng - Sun Microsystems - Beijing China } 11588a3c961bSfei feng - Sun Microsystems - Beijing China pktlen = msgdsize(m); 11598a3c961bSfei feng - Sun Microsystems - Beijing China hdrlen = sizeof (*wh); 11608a3c961bSfei feng - Sun Microsystems - Beijing China 11618a3c961bSfei feng - Sun Microsystems - Beijing China /* pickup a rate */ 11628a3c961bSfei feng - Sun Microsystems - Beijing China if (IEEE80211_IS_MULTICAST(wh->i_addr1) || 11638a3c961bSfei feng - Sun Microsystems - Beijing China ((type & IEEE80211_FC0_TYPE_MASK) != 11648a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_FC0_TYPE_DATA)) 11658a3c961bSfei feng - Sun Microsystems - Beijing China rate = ni->in_rates.ir_rates[0]; 11668a3c961bSfei feng - Sun Microsystems - Beijing China else { 11678a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) 11688a3c961bSfei feng - Sun Microsystems - Beijing China rate = ic->ic_fixed_rate; 11698a3c961bSfei feng - Sun Microsystems - Beijing China else 11708a3c961bSfei feng - Sun Microsystems - Beijing China rate = ni->in_rates.ir_rates[ni->in_txrate]; 11718a3c961bSfei feng - Sun Microsystems - Beijing China } 11728a3c961bSfei feng - Sun Microsystems - Beijing China rate &= IEEE80211_RATE_VAL; 11738a3c961bSfei feng - Sun Microsystems - Beijing China 11748a3c961bSfei feng - Sun Microsystems - Beijing China /* get MCS code from rate */ 11758a3c961bSfei feng - Sun Microsystems - Beijing China mcs = rt2860_rate2mcs(rate); 11768a3c961bSfei feng - Sun Microsystems - Beijing China 11778a3c961bSfei feng - Sun Microsystems - Beijing China /* setup TX Wireless Information */ 11788a3c961bSfei feng - Sun Microsystems - Beijing China txwi = data->txwi; 11798a3c961bSfei feng - Sun Microsystems - Beijing China (void) bzero(txwi, sizeof (struct rt2860_txwi)); 11808a3c961bSfei feng - Sun Microsystems - Beijing China txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA) ? 11818a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_AID2WCID(ni->in_associd) : 0xff; 11828a3c961bSfei feng - Sun Microsystems - Beijing China txwi->len = LE_16(pktlen); 11838a3c961bSfei feng - Sun Microsystems - Beijing China if (!RT2860_RATE_IS_OFDM(rate)) { 11848a3c961bSfei feng - Sun Microsystems - Beijing China txwi->phy = LE_16(RT2860_PHY_CCK); 11858a3c961bSfei feng - Sun Microsystems - Beijing China if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 11868a3c961bSfei feng - Sun Microsystems - Beijing China mcs |= RT2860_PHY_SHPRE; 11878a3c961bSfei feng - Sun Microsystems - Beijing China } else 11888a3c961bSfei feng - Sun Microsystems - Beijing China txwi->phy = LE_16(RT2860_PHY_OFDM); 11898a3c961bSfei feng - Sun Microsystems - Beijing China txwi->phy |= LE_16(mcs); 11908a3c961bSfei feng - Sun Microsystems - Beijing China 11918a3c961bSfei feng - Sun Microsystems - Beijing China /* 11928a3c961bSfei feng - Sun Microsystems - Beijing China * We store the MCS code into the driver-private PacketID field. 11938a3c961bSfei feng - Sun Microsystems - Beijing China * The PacketID is latched into TX_STAT_FIFO when Tx completes so 11948a3c961bSfei feng - Sun Microsystems - Beijing China * that we know at which initial rate the frame was transmitted. 11958a3c961bSfei feng - Sun Microsystems - Beijing China * We add 1 to the MCS code because setting the PacketID field to 11968a3c961bSfei feng - Sun Microsystems - Beijing China * 0 means that we don't want feedback in TX_STAT_FIFO. 11978a3c961bSfei feng - Sun Microsystems - Beijing China */ 11988a3c961bSfei feng - Sun Microsystems - Beijing China pid = (mcs + 1) & 0xf; 11998a3c961bSfei feng - Sun Microsystems - Beijing China txwi->len |= LE_16(pid << RT2860_TX_PID_SHIFT); 12008a3c961bSfei feng - Sun Microsystems - Beijing China 12018a3c961bSfei feng - Sun Microsystems - Beijing China /* check if RTS/CTS or CTS-to-self protection is required */ 12028a3c961bSfei feng - Sun Microsystems - Beijing China if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && 12038a3c961bSfei feng - Sun Microsystems - Beijing China (pktlen + IEEE80211_CRC_LEN > ic->ic_rtsthreshold || 12048a3c961bSfei feng - Sun Microsystems - Beijing China ((ic->ic_flags & 12058a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_F_USEPROT) && RT2860_RATE_IS_OFDM(rate)))) 12068a3c961bSfei feng - Sun Microsystems - Beijing China txwi->txop = RT2860_TX_TXOP_HT; 12078a3c961bSfei feng - Sun Microsystems - Beijing China else 12088a3c961bSfei feng - Sun Microsystems - Beijing China txwi->txop = RT2860_TX_TXOP_BACKOFF; 12098a3c961bSfei feng - Sun Microsystems - Beijing China 12108a3c961bSfei feng - Sun Microsystems - Beijing China if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 12118a3c961bSfei feng - Sun Microsystems - Beijing China txwi->xflags |= RT2860_TX_ACK; 12128a3c961bSfei feng - Sun Microsystems - Beijing China 12138a3c961bSfei feng - Sun Microsystems - Beijing China dur = rt2860_txtime(RT2860_ACK_SIZE, rt2860_ack_rate(ic, rate), 12148a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_flags) + sc->sifs; 12158a3c961bSfei feng - Sun Microsystems - Beijing China *(uint16_t *)wh->i_dur = LE_16(dur); 12168a3c961bSfei feng - Sun Microsystems - Beijing China } 12178a3c961bSfei feng - Sun Microsystems - Beijing China 12188a3c961bSfei feng - Sun Microsystems - Beijing China /* copy and trim 802.11 header */ 12198a3c961bSfei feng - Sun Microsystems - Beijing China bcopy(wh, &txwi->wh, hdrlen); 12208a3c961bSfei feng - Sun Microsystems - Beijing China m->b_rptr += hdrlen; 12218a3c961bSfei feng - Sun Microsystems - Beijing China bcopy(m->b_rptr, data->txbuf_dma.mem_va, pktlen - hdrlen); 12228a3c961bSfei feng - Sun Microsystems - Beijing China 12238a3c961bSfei feng - Sun Microsystems - Beijing China qsel = (qid < EDCA_NUM_AC) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_MGMT; 12248a3c961bSfei feng - Sun Microsystems - Beijing China 12258a3c961bSfei feng - Sun Microsystems - Beijing China /* first segment is TXWI + 802.11 header */ 12268a3c961bSfei feng - Sun Microsystems - Beijing China txd = &ring->txd[ring->cur]; 12278a3c961bSfei feng - Sun Microsystems - Beijing China txd->sdp0 = LE_32(data->paddr); 12288a3c961bSfei feng - Sun Microsystems - Beijing China txd->sdl0 = LE_16(16 + hdrlen); 12298a3c961bSfei feng - Sun Microsystems - Beijing China txd->flags = qsel; 12308a3c961bSfei feng - Sun Microsystems - Beijing China 12318a3c961bSfei feng - Sun Microsystems - Beijing China /* finalize last segment */ 12328a3c961bSfei feng - Sun Microsystems - Beijing China txd->sdp1 = LE_32(data->txbuf_dma.cookie.dmac_address); 12338a3c961bSfei feng - Sun Microsystems - Beijing China txd->sdl1 = LE_16(pktlen - hdrlen | RT2860_TX_LS1); 12348a3c961bSfei feng - Sun Microsystems - Beijing China 12358a3c961bSfei feng - Sun Microsystems - Beijing China /* remove from the free pool and link it into the SW Tx slot */ 12368a3c961bSfei feng - Sun Microsystems - Beijing China SLIST_REMOVE_HEAD(&sc->data_pool, next); 12378a3c961bSfei feng - Sun Microsystems - Beijing China data->ni = ieee80211_ref_node(ni); 12388a3c961bSfei feng - Sun Microsystems - Beijing China ring->data[ring->cur] = data; 12398a3c961bSfei feng - Sun Microsystems - Beijing China 12408a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_sync(sc->txpool_dma.dma_hdl, 12418a3c961bSfei feng - Sun Microsystems - Beijing China _PTRDIFF(txwi, sc->txwi), 12428a3c961bSfei feng - Sun Microsystems - Beijing China (hdrlen + 16 + 2), 12438a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SYNC_FORDEV); 12448a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(data->txbuf_dma, DDI_DMA_SYNC_FORDEV); 12458a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(ring->txdesc_dma, DDI_DMA_SYNC_FORDEV); 12468a3c961bSfei feng - Sun Microsystems - Beijing China 12478a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_TX, "rwn: rt2860_send():" 12488a3c961bSfei feng - Sun Microsystems - Beijing China "sending frame qid=%d wcid=%d rate=%d cur = %x\n", 12498a3c961bSfei feng - Sun Microsystems - Beijing China qid, txwi->wcid, rate, ring->cur); 12508a3c961bSfei feng - Sun Microsystems - Beijing China 12518a3c961bSfei feng - Sun Microsystems - Beijing China ring->queued++; 12528a3c961bSfei feng - Sun Microsystems - Beijing China ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; 12538a3c961bSfei feng - Sun Microsystems - Beijing China 12548a3c961bSfei feng - Sun Microsystems - Beijing China /* kick Tx */ 12558a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_CTX_IDX(qid), ring->cur); 12568a3c961bSfei feng - Sun Microsystems - Beijing China 12578a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_tx_timer = 5; 12588a3c961bSfei feng - Sun Microsystems - Beijing China 12598a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_stats.is_tx_frags++; 12608a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_stats.is_tx_bytes += pktlen; 12618a3c961bSfei feng - Sun Microsystems - Beijing China 12628a3c961bSfei feng - Sun Microsystems - Beijing China fail3: 12638a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_free_node(ni); 12648a3c961bSfei feng - Sun Microsystems - Beijing China fail2: 12658a3c961bSfei feng - Sun Microsystems - Beijing China freemsg(m); 12668a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 12678a3c961bSfei feng - Sun Microsystems - Beijing China if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA || 12688a3c961bSfei feng - Sun Microsystems - Beijing China err == DDI_SUCCESS) 12698a3c961bSfei feng - Sun Microsystems - Beijing China freemsg(mp); 12708a3c961bSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 12718a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 12728a3c961bSfei feng - Sun Microsystems - Beijing China } 12738a3c961bSfei feng - Sun Microsystems - Beijing China 12748a3c961bSfei feng - Sun Microsystems - Beijing China /* 12758a3c961bSfei feng - Sun Microsystems - Beijing China * This function is called periodically (every 200ms) during scanning to 12768a3c961bSfei feng - Sun Microsystems - Beijing China * switch from one channel to another. 12778a3c961bSfei feng - Sun Microsystems - Beijing China */ 12788a3c961bSfei feng - Sun Microsystems - Beijing China static void 12798a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_next_scan(void *arg) 12808a3c961bSfei feng - Sun Microsystems - Beijing China { 12818a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 12828a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 12838a3c961bSfei feng - Sun Microsystems - Beijing China 12848a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_state == IEEE80211_S_SCAN) 12858a3c961bSfei feng - Sun Microsystems - Beijing China (void) ieee80211_next_scan(ic); 12868a3c961bSfei feng - Sun Microsystems - Beijing China } 12878a3c961bSfei feng - Sun Microsystems - Beijing China 12888a3c961bSfei feng - Sun Microsystems - Beijing China static void 12898a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_updateslot(struct rt2860_softc *sc) 12908a3c961bSfei feng - Sun Microsystems - Beijing China { 12918a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 12928a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 12938a3c961bSfei feng - Sun Microsystems - Beijing China 12948a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_BKOFF_SLOT_CFG); 12958a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= ~0xff; 12968a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; 12978a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_BKOFF_SLOT_CFG, tmp); 12988a3c961bSfei feng - Sun Microsystems - Beijing China } 12998a3c961bSfei feng - Sun Microsystems - Beijing China 13008a3c961bSfei feng - Sun Microsystems - Beijing China static void 13018a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_iter_func(void *arg, struct ieee80211_node *ni) 13028a3c961bSfei feng - Sun Microsystems - Beijing China { 13038a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 13048a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t wcid; 13058a3c961bSfei feng - Sun Microsystems - Beijing China 13068a3c961bSfei feng - Sun Microsystems - Beijing China wcid = RT2860_AID2WCID(ni->in_associd); 13078a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_amrr_choose(&sc->amrr, ni, &sc->amn[wcid]); 13088a3c961bSfei feng - Sun Microsystems - Beijing China } 13098a3c961bSfei feng - Sun Microsystems - Beijing China 13108a3c961bSfei feng - Sun Microsystems - Beijing China static void 13118a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_updatestats(void *arg) 13128a3c961bSfei feng - Sun Microsystems - Beijing China { 13138a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 13148a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 13158a3c961bSfei feng - Sun Microsystems - Beijing China 13168a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_STA) 13178a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_iter_func(sc, ic->ic_bss); 13188a3c961bSfei feng - Sun Microsystems - Beijing China else 13198a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_iterate_nodes(&ic->ic_sta, rt2860_iter_func, arg); 13208a3c961bSfei feng - Sun Microsystems - Beijing China 13218a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rssadapt_id = timeout(rt2860_updatestats, (void *)sc, 13228a3c961bSfei feng - Sun Microsystems - Beijing China drv_usectohz(500 * 1000)); 13238a3c961bSfei feng - Sun Microsystems - Beijing China } 13248a3c961bSfei feng - Sun Microsystems - Beijing China 13258a3c961bSfei feng - Sun Microsystems - Beijing China static void 13268a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_enable_mrr(struct rt2860_softc *sc) 13278a3c961bSfei feng - Sun Microsystems - Beijing China { 13288a3c961bSfei feng - Sun Microsystems - Beijing China #define CCK(mcs) (mcs) 13298a3c961bSfei feng - Sun Microsystems - Beijing China #define OFDM(mcs) ((uint32_t)1 << 3 | (mcs)) 13308a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_LG_FBK_CFG0, 13318a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(6) << 28 | /* 54->48 */ 13328a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(5) << 24 | /* 48->36 */ 13338a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(4) << 20 | /* 36->24 */ 13348a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(3) << 16 | /* 24->18 */ 13358a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(2) << 12 | /* 18->12 */ 13368a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(1) << 8 | /* 12-> 9 */ 13378a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(0) << 4 | /* 9-> 6 */ 13388a3c961bSfei feng - Sun Microsystems - Beijing China OFDM(0)); /* 6-> 6 */ 13398a3c961bSfei feng - Sun Microsystems - Beijing China 13408a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_LG_FBK_CFG1, 13418a3c961bSfei feng - Sun Microsystems - Beijing China CCK(2) << 12 | /* 11->5.5 */ 13428a3c961bSfei feng - Sun Microsystems - Beijing China CCK(1) << 8 | /* 5.5-> 2 */ 13438a3c961bSfei feng - Sun Microsystems - Beijing China CCK(0) << 4 | /* 2-> 1 */ 13448a3c961bSfei feng - Sun Microsystems - Beijing China CCK(0)); /* 1-> 1 */ 13458a3c961bSfei feng - Sun Microsystems - Beijing China #undef OFDM 13468a3c961bSfei feng - Sun Microsystems - Beijing China #undef CCK 13478a3c961bSfei feng - Sun Microsystems - Beijing China } 13488a3c961bSfei feng - Sun Microsystems - Beijing China 13498a3c961bSfei feng - Sun Microsystems - Beijing China static void 13508a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_txpreamble(struct rt2860_softc *sc) 13518a3c961bSfei feng - Sun Microsystems - Beijing China { 13528a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 13538a3c961bSfei feng - Sun Microsystems - Beijing China 13548a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_AUTO_RSP_CFG); 13558a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= ~RT2860_CCK_SHORT_EN; 13568a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE) 13578a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_CCK_SHORT_EN; 13588a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_AUTO_RSP_CFG, tmp); 13598a3c961bSfei feng - Sun Microsystems - Beijing China } 13608a3c961bSfei feng - Sun Microsystems - Beijing China 13618a3c961bSfei feng - Sun Microsystems - Beijing China static void 13628a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_bssid(struct rt2860_softc *sc, const uint8_t *bssid) 13638a3c961bSfei feng - Sun Microsystems - Beijing China { 13648a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_BSSID_DW0, 13658a3c961bSfei feng - Sun Microsystems - Beijing China bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24); 13668a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_BSSID_DW1, 13678a3c961bSfei feng - Sun Microsystems - Beijing China bssid[4] | bssid[5] << 8); 13688a3c961bSfei feng - Sun Microsystems - Beijing China } 13698a3c961bSfei feng - Sun Microsystems - Beijing China 13708a3c961bSfei feng - Sun Microsystems - Beijing China static void 13718a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_basicrates(struct rt2860_softc *sc) 13728a3c961bSfei feng - Sun Microsystems - Beijing China { 13738a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 13748a3c961bSfei feng - Sun Microsystems - Beijing China 13758a3c961bSfei feng - Sun Microsystems - Beijing China /* set basic rates mask */ 13768a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_curmode == IEEE80211_MODE_11B) 13778a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_LEGACY_BASIC_RATE, 0x003); 13788a3c961bSfei feng - Sun Microsystems - Beijing China else if (ic->ic_curmode == IEEE80211_MODE_11A) 13798a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_LEGACY_BASIC_RATE, 0x150); 13808a3c961bSfei feng - Sun Microsystems - Beijing China else /* 11g */ 13818a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_LEGACY_BASIC_RATE, 0x15f); 13828a3c961bSfei feng - Sun Microsystems - Beijing China } 13838a3c961bSfei feng - Sun Microsystems - Beijing China 13848a3c961bSfei feng - Sun Microsystems - Beijing China static void 13858a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_amrr_node_init(const struct rt2860_amrr *amrr, 13868a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_amrr_node *amn) 13878a3c961bSfei feng - Sun Microsystems - Beijing China { 13888a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success = 0; 13898a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_recovery = 0; 13908a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_txcnt = amn->amn_retrycnt = 0; 13918a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success_threshold = amrr->amrr_min_success_threshold; 13928a3c961bSfei feng - Sun Microsystems - Beijing China } 13938a3c961bSfei feng - Sun Microsystems - Beijing China 13948a3c961bSfei feng - Sun Microsystems - Beijing China static void 13958a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_amrr_choose(struct rt2860_amrr *amrr, struct ieee80211_node *ni, 13968a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_amrr_node *amn) 13978a3c961bSfei feng - Sun Microsystems - Beijing China { 13988a3c961bSfei feng - Sun Microsystems - Beijing China #define RV(rate) ((rate) & IEEE80211_RATE_VAL) 13998a3c961bSfei feng - Sun Microsystems - Beijing China #define is_success(amn) \ 14008a3c961bSfei feng - Sun Microsystems - Beijing China ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10) 14018a3c961bSfei feng - Sun Microsystems - Beijing China #define is_failure(amn) \ 14028a3c961bSfei feng - Sun Microsystems - Beijing China ((amn)->amn_retrycnt > (amn)->amn_txcnt / 3) 14038a3c961bSfei feng - Sun Microsystems - Beijing China #define is_enough(amn) \ 14048a3c961bSfei feng - Sun Microsystems - Beijing China ((amn)->amn_txcnt > 10) 14058a3c961bSfei feng - Sun Microsystems - Beijing China #define is_min_rate(ni) \ 14068a3c961bSfei feng - Sun Microsystems - Beijing China ((ni)->in_txrate == 0) 14078a3c961bSfei feng - Sun Microsystems - Beijing China #define is_max_rate(ni) \ 14088a3c961bSfei feng - Sun Microsystems - Beijing China ((ni)->in_txrate == (ni)->in_rates.ir_nrates - 1) 14098a3c961bSfei feng - Sun Microsystems - Beijing China #define increase_rate(ni) \ 14108a3c961bSfei feng - Sun Microsystems - Beijing China ((ni)->in_txrate++) 14118a3c961bSfei feng - Sun Microsystems - Beijing China #define decrease_rate(ni) \ 14128a3c961bSfei feng - Sun Microsystems - Beijing China ((ni)->in_txrate--) 14138a3c961bSfei feng - Sun Microsystems - Beijing China #define reset_cnt(amn) \ 14148a3c961bSfei feng - Sun Microsystems - Beijing China { (amn)->amn_txcnt = (amn)->amn_retrycnt = 0; } 14158a3c961bSfei feng - Sun Microsystems - Beijing China 14168a3c961bSfei feng - Sun Microsystems - Beijing China int need_change = 0; 14178a3c961bSfei feng - Sun Microsystems - Beijing China 14188a3c961bSfei feng - Sun Microsystems - Beijing China if (is_success(amn) && is_enough(amn)) { 14198a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success++; 14208a3c961bSfei feng - Sun Microsystems - Beijing China if (amn->amn_success >= amn->amn_success_threshold && 14218a3c961bSfei feng - Sun Microsystems - Beijing China !is_max_rate(ni)) { 14228a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_recovery = 1; 14238a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success = 0; 14248a3c961bSfei feng - Sun Microsystems - Beijing China increase_rate(ni); 14258a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_amrr_choose(): " 14268a3c961bSfei feng - Sun Microsystems - Beijing China "increase rate = %d, #tx = %d, #retries = %d\n", 14278a3c961bSfei feng - Sun Microsystems - Beijing China RV(ni->in_rates.ir_rates[ni->in_txrate]), 14288a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_txcnt, amn->amn_retrycnt); 14298a3c961bSfei feng - Sun Microsystems - Beijing China need_change = 1; 14308a3c961bSfei feng - Sun Microsystems - Beijing China } else { 14318a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_recovery = 0; 14328a3c961bSfei feng - Sun Microsystems - Beijing China } 14338a3c961bSfei feng - Sun Microsystems - Beijing China } else if (is_failure(amn)) { 14348a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success = 0; 14358a3c961bSfei feng - Sun Microsystems - Beijing China if (!is_min_rate(ni)) { 14368a3c961bSfei feng - Sun Microsystems - Beijing China if (amn->amn_recovery) { 14378a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success_threshold *= 2; 14388a3c961bSfei feng - Sun Microsystems - Beijing China if (amn->amn_success_threshold > 14398a3c961bSfei feng - Sun Microsystems - Beijing China amrr->amrr_max_success_threshold) 14408a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success_threshold = 14418a3c961bSfei feng - Sun Microsystems - Beijing China amrr->amrr_max_success_threshold; 14428a3c961bSfei feng - Sun Microsystems - Beijing China } else { 14438a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_success_threshold = 14448a3c961bSfei feng - Sun Microsystems - Beijing China amrr->amrr_min_success_threshold; 14458a3c961bSfei feng - Sun Microsystems - Beijing China } 14468a3c961bSfei feng - Sun Microsystems - Beijing China decrease_rate(ni); 14478a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_amrr_choose(): " 14488a3c961bSfei feng - Sun Microsystems - Beijing China "decrease rate = %d, #tx = %d, #retries = %d\n", 14498a3c961bSfei feng - Sun Microsystems - Beijing China RV(ni->in_rates.ir_rates[ni->in_txrate]), 14508a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_txcnt, amn->amn_retrycnt); 14518a3c961bSfei feng - Sun Microsystems - Beijing China need_change = 1; 14528a3c961bSfei feng - Sun Microsystems - Beijing China } 14538a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_recovery = 0; 14548a3c961bSfei feng - Sun Microsystems - Beijing China } 14558a3c961bSfei feng - Sun Microsystems - Beijing China 14568a3c961bSfei feng - Sun Microsystems - Beijing China if (is_enough(amn) || need_change) 14578a3c961bSfei feng - Sun Microsystems - Beijing China reset_cnt(amn); 14588a3c961bSfei feng - Sun Microsystems - Beijing China #undef RV 14598a3c961bSfei feng - Sun Microsystems - Beijing China } 14608a3c961bSfei feng - Sun Microsystems - Beijing China 14618a3c961bSfei feng - Sun Microsystems - Beijing China static void 14628a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_newassoc(struct ieee80211com *ic, struct ieee80211_node *in, int isnew) 14638a3c961bSfei feng - Sun Microsystems - Beijing China { 14648a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)ic; 14658a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t off; 14668a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t *fptr, wcid = 0; 14678a3c961bSfei feng - Sun Microsystems - Beijing China int i; 14688a3c961bSfei feng - Sun Microsystems - Beijing China 14698a3c961bSfei feng - Sun Microsystems - Beijing China if (isnew && in->in_associd != 0) { 14708a3c961bSfei feng - Sun Microsystems - Beijing China /* only interested in true associations */ 14718a3c961bSfei feng - Sun Microsystems - Beijing China wcid = RT2860_AID2WCID(in->in_associd); 14728a3c961bSfei feng - Sun Microsystems - Beijing China 14738a3c961bSfei feng - Sun Microsystems - Beijing China /* init WCID table entry */ 14748a3c961bSfei feng - Sun Microsystems - Beijing China off = RT2860_WCID_ENTRY(wcid); 14758a3c961bSfei feng - Sun Microsystems - Beijing China fptr = in->in_macaddr; 14768a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < IEEE80211_ADDR_LEN; i++) 14778a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mem_write1(sc, off++, *fptr++); 14788a3c961bSfei feng - Sun Microsystems - Beijing China } 14798a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_amrr_node_init(&sc->amrr, &sc->amn[wcid]); 14808a3c961bSfei feng - Sun Microsystems - Beijing China 14818a3c961bSfei feng - Sun Microsystems - Beijing China /* set rate to some reasonable initial value */ 14828a3c961bSfei feng - Sun Microsystems - Beijing China i = in->in_rates.ir_nrates - 1; 14838a3c961bSfei feng - Sun Microsystems - Beijing China for (; i > 0 && (in->in_rates.ir_rates[i] & IEEE80211_RATE_VAL) > 72; ) 14848a3c961bSfei feng - Sun Microsystems - Beijing China i--; 14858a3c961bSfei feng - Sun Microsystems - Beijing China in->in_txrate = i; 14868a3c961bSfei feng - Sun Microsystems - Beijing China 14878a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_80211, "rwn: rt2860_newassoc(): " 14888a3c961bSfei feng - Sun Microsystems - Beijing China "new assoc isnew=%d WCID=%d, initial rate=%d\n", 14898a3c961bSfei feng - Sun Microsystems - Beijing China isnew, wcid, 14908a3c961bSfei feng - Sun Microsystems - Beijing China in->in_rates.ir_rates[i] & IEEE80211_RATE_VAL); 14918a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_80211, "rwn: rt2860_newassoc(): " 14928a3c961bSfei feng - Sun Microsystems - Beijing China "addr=%x:%x:%x:%x:%x:%x\n", 14938a3c961bSfei feng - Sun Microsystems - Beijing China in->in_macaddr[0], in->in_macaddr[1], in->in_macaddr[2], 14948a3c961bSfei feng - Sun Microsystems - Beijing China in->in_macaddr[3], in->in_macaddr[4], in->in_macaddr[5]); 14958a3c961bSfei feng - Sun Microsystems - Beijing China } 14968a3c961bSfei feng - Sun Microsystems - Beijing China 14978a3c961bSfei feng - Sun Microsystems - Beijing China void 14988a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_enable_tsf_sync(struct rt2860_softc *sc) 14998a3c961bSfei feng - Sun Microsystems - Beijing China { 15008a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 15018a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 15028a3c961bSfei feng - Sun Microsystems - Beijing China 15038a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_BCN_TIME_CFG); 15048a3c961bSfei feng - Sun Microsystems - Beijing China 15058a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= ~0x1fffff; 15068a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= ic->ic_bss->in_intval * 16; 15078a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; 15088a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_STA) { 15098a3c961bSfei feng - Sun Microsystems - Beijing China /* 15108a3c961bSfei feng - Sun Microsystems - Beijing China * Local TSF is always updated with remote TSF on beacon 15118a3c961bSfei feng - Sun Microsystems - Beijing China * reception. 15128a3c961bSfei feng - Sun Microsystems - Beijing China */ 15138a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT; 15148a3c961bSfei feng - Sun Microsystems - Beijing China } 15158a3c961bSfei feng - Sun Microsystems - Beijing China 15168a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_BCN_TIME_CFG, tmp); 15178a3c961bSfei feng - Sun Microsystems - Beijing China } 15188a3c961bSfei feng - Sun Microsystems - Beijing China 15198a3c961bSfei feng - Sun Microsystems - Beijing China static int 15208a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 15218a3c961bSfei feng - Sun Microsystems - Beijing China { 15228a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)ic; 15238a3c961bSfei feng - Sun Microsystems - Beijing China enum ieee80211_state ostate; 15248a3c961bSfei feng - Sun Microsystems - Beijing China int err; 15258a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 15268a3c961bSfei feng - Sun Microsystems - Beijing China 15278a3c961bSfei feng - Sun Microsystems - Beijing China ostate = ic->ic_state; 15288a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_80211, "rwn: rt2860_newstate(): " 15298a3c961bSfei feng - Sun Microsystems - Beijing China "%x -> %x!\n", ostate, nstate); 15308a3c961bSfei feng - Sun Microsystems - Beijing China 15318a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 15328a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_scan_id != 0) { 15338a3c961bSfei feng - Sun Microsystems - Beijing China (void) untimeout(sc->sc_scan_id); 15348a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_scan_id = 0; 15358a3c961bSfei feng - Sun Microsystems - Beijing China } 15368a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_rssadapt_id != 0) { 15378a3c961bSfei feng - Sun Microsystems - Beijing China (void) untimeout(sc->sc_rssadapt_id); 15388a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rssadapt_id = 0; 15398a3c961bSfei feng - Sun Microsystems - Beijing China } 15408a3c961bSfei feng - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_RUN) { 15418a3c961bSfei feng - Sun Microsystems - Beijing China /* turn link LED off */ 15428a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_leds(sc, RT2860_LED_RADIO); 15438a3c961bSfei feng - Sun Microsystems - Beijing China } 15448a3c961bSfei feng - Sun Microsystems - Beijing China 15458a3c961bSfei feng - Sun Microsystems - Beijing China switch (nstate) { 15468a3c961bSfei feng - Sun Microsystems - Beijing China case IEEE80211_S_INIT: 15478a3c961bSfei feng - Sun Microsystems - Beijing China if (ostate == IEEE80211_S_RUN) { 15488a3c961bSfei feng - Sun Microsystems - Beijing China /* abort TSF synchronization */ 15498a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_BCN_TIME_CFG); 15508a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_BCN_TIME_CFG, 15518a3c961bSfei feng - Sun Microsystems - Beijing China tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | 15528a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_TBTT_TIMER_EN)); 15538a3c961bSfei feng - Sun Microsystems - Beijing China } 15548a3c961bSfei feng - Sun Microsystems - Beijing China break; 15558a3c961bSfei feng - Sun Microsystems - Beijing China 15568a3c961bSfei feng - Sun Microsystems - Beijing China case IEEE80211_S_SCAN: 15578a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_chan(sc, ic->ic_curchan); 15588a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_scan_id = timeout(rt2860_next_scan, (void *)sc, 15598a3c961bSfei feng - Sun Microsystems - Beijing China drv_usectohz(200000)); 15608a3c961bSfei feng - Sun Microsystems - Beijing China break; 15618a3c961bSfei feng - Sun Microsystems - Beijing China 15628a3c961bSfei feng - Sun Microsystems - Beijing China case IEEE80211_S_AUTH: 15638a3c961bSfei feng - Sun Microsystems - Beijing China case IEEE80211_S_ASSOC: 15648a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_chan(sc, ic->ic_curchan); 15658a3c961bSfei feng - Sun Microsystems - Beijing China break; 15668a3c961bSfei feng - Sun Microsystems - Beijing China 15678a3c961bSfei feng - Sun Microsystems - Beijing China case IEEE80211_S_RUN: 15688a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_chan(sc, ic->ic_curchan); 15698a3c961bSfei feng - Sun Microsystems - Beijing China 15708a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_MONITOR) { 15718a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_updateslot(sc); 15728a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_enable_mrr(sc); 15738a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_txpreamble(sc); 15748a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_basicrates(sc); 15758a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_bssid(sc, ic->ic_bss->in_bssid); 15768a3c961bSfei feng - Sun Microsystems - Beijing China } 15778a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_STA) { 15788a3c961bSfei feng - Sun Microsystems - Beijing China /* fake a join to init the tx rate */ 15798a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_newassoc(ic, ic->ic_bss, 1); 15808a3c961bSfei feng - Sun Microsystems - Beijing China } 15818a3c961bSfei feng - Sun Microsystems - Beijing China 15828a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_MONITOR) { 15838a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_enable_tsf_sync(sc); 15848a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rssadapt_id = timeout(rt2860_updatestats, 15858a3c961bSfei feng - Sun Microsystems - Beijing China (void *)sc, drv_usectohz(500 * 1000)); 15868a3c961bSfei feng - Sun Microsystems - Beijing China } 15878a3c961bSfei feng - Sun Microsystems - Beijing China 15888a3c961bSfei feng - Sun Microsystems - Beijing China /* turn link LED on */ 15898a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_leds(sc, RT2860_LED_RADIO | 15908a3c961bSfei feng - Sun Microsystems - Beijing China (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 15918a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); 15928a3c961bSfei feng - Sun Microsystems - Beijing China break; 15938a3c961bSfei feng - Sun Microsystems - Beijing China } 15948a3c961bSfei feng - Sun Microsystems - Beijing China 15958a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 15968a3c961bSfei feng - Sun Microsystems - Beijing China 15978a3c961bSfei feng - Sun Microsystems - Beijing China err = sc->sc_newstate(ic, nstate, arg); 15988a3c961bSfei feng - Sun Microsystems - Beijing China 15998a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 16008a3c961bSfei feng - Sun Microsystems - Beijing China } 16018a3c961bSfei feng - Sun Microsystems - Beijing China 16028a3c961bSfei feng - Sun Microsystems - Beijing China /* 16038a3c961bSfei feng - Sun Microsystems - Beijing China * Return the Rx chain with the highest RSSI for a given frame. 16048a3c961bSfei feng - Sun Microsystems - Beijing China */ 16058a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t 16068a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_maxrssi_chain(struct rt2860_softc *sc, const struct rt2860_rxwi *rxwi) 16078a3c961bSfei feng - Sun Microsystems - Beijing China { 16088a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t rxchain = 0; 16098a3c961bSfei feng - Sun Microsystems - Beijing China 16108a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->nrxchains > 1) 16118a3c961bSfei feng - Sun Microsystems - Beijing China if (rxwi->rssi[1] > rxwi->rssi[rxchain]) 16128a3c961bSfei feng - Sun Microsystems - Beijing China rxchain = 1; 16138a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->nrxchains > 2) 16148a3c961bSfei feng - Sun Microsystems - Beijing China if (rxwi->rssi[2] > rxwi->rssi[rxchain]) 16158a3c961bSfei feng - Sun Microsystems - Beijing China rxchain = 2; 16168a3c961bSfei feng - Sun Microsystems - Beijing China 16178a3c961bSfei feng - Sun Microsystems - Beijing China return (rxchain); 16188a3c961bSfei feng - Sun Microsystems - Beijing China } 16198a3c961bSfei feng - Sun Microsystems - Beijing China 16208a3c961bSfei feng - Sun Microsystems - Beijing China static void 16218a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_drain_stats_fifo(struct rt2860_softc *sc) 16228a3c961bSfei feng - Sun Microsystems - Beijing China { 16238a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_amrr_node *amn; 16248a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t stat; 16258a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t wcid, mcs, pid; 16268a3c961bSfei feng - Sun Microsystems - Beijing China 16278a3c961bSfei feng - Sun Microsystems - Beijing China /* drain Tx status FIFO (maxsize = 16) */ 16288a3c961bSfei feng - Sun Microsystems - Beijing China while ((stat = RT2860_READ(sc, RT2860_TX_STAT_FIFO)) & RT2860_TXQ_VLD) { 16298a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_TX, "rwn: rt2860_drain_stats_fifo(): " 16308a3c961bSfei feng - Sun Microsystems - Beijing China "tx stat 0x%08\n", stat); 16318a3c961bSfei feng - Sun Microsystems - Beijing China 16328a3c961bSfei feng - Sun Microsystems - Beijing China wcid = (stat >> 8) & 0xff; 16338a3c961bSfei feng - Sun Microsystems - Beijing China 16348a3c961bSfei feng - Sun Microsystems - Beijing China /* if no ACK was requested, no feedback is available */ 16358a3c961bSfei feng - Sun Microsystems - Beijing China if (!(stat & RT2860_TXQ_ACKREQ) || wcid == 0xff) 16368a3c961bSfei feng - Sun Microsystems - Beijing China continue; 16378a3c961bSfei feng - Sun Microsystems - Beijing China /* update per-STA AMRR stats */ 16388a3c961bSfei feng - Sun Microsystems - Beijing China amn = &sc->amn[wcid]; 16398a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_txcnt++; 16408a3c961bSfei feng - Sun Microsystems - Beijing China if (stat & RT2860_TXQ_OK) { 16418a3c961bSfei feng - Sun Microsystems - Beijing China /* 16428a3c961bSfei feng - Sun Microsystems - Beijing China * Check if there were retries, ie if the Tx success 16438a3c961bSfei feng - Sun Microsystems - Beijing China * rate is different from the requested rate. Note 16448a3c961bSfei feng - Sun Microsystems - Beijing China * that it works only because we do not allow rate 16458a3c961bSfei feng - Sun Microsystems - Beijing China * fallback from OFDM to CCK. 16468a3c961bSfei feng - Sun Microsystems - Beijing China */ 16478a3c961bSfei feng - Sun Microsystems - Beijing China mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; 16488a3c961bSfei feng - Sun Microsystems - Beijing China pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; 16498a3c961bSfei feng - Sun Microsystems - Beijing China if (mcs + 1 != pid) 16508a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_retrycnt++; 16518a3c961bSfei feng - Sun Microsystems - Beijing China } else 16528a3c961bSfei feng - Sun Microsystems - Beijing China amn->amn_retrycnt++; 16538a3c961bSfei feng - Sun Microsystems - Beijing China } 16548a3c961bSfei feng - Sun Microsystems - Beijing China } 16558a3c961bSfei feng - Sun Microsystems - Beijing China 16568a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 16578a3c961bSfei feng - Sun Microsystems - Beijing China static void 16588a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(struct rt2860_softc *sc, int qid) 16598a3c961bSfei feng - Sun Microsystems - Beijing China { 16608a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_ring *ring = &sc->txq[qid]; 16618a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 16628a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t hw; 16638a3c961bSfei feng - Sun Microsystems - Beijing China 16648a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_drain_stats_fifo(sc); 16658a3c961bSfei feng - Sun Microsystems - Beijing China 16668a3c961bSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_txlock); 16678a3c961bSfei feng - Sun Microsystems - Beijing China hw = RT2860_READ(sc, RT2860_TX_DTX_IDX(qid)); 16688a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_TX, "rwn: rwn_tx_intr():" 16698a3c961bSfei feng - Sun Microsystems - Beijing China "hw = %x, ring->next = %x, queued = %d\n", 16708a3c961bSfei feng - Sun Microsystems - Beijing China hw, ring->next, ring->queued); 16718a3c961bSfei feng - Sun Microsystems - Beijing China while (ring->next != hw) { 16728a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_txd *txd = &ring->txd[ring->next]; 16738a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_tx_data *data = ring->data[ring->next]; 16748a3c961bSfei feng - Sun Microsystems - Beijing China 16758a3c961bSfei feng - Sun Microsystems - Beijing China if (data != NULL) { 16768a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DMA_SYNC(data->txbuf_dma, DDI_DMA_SYNC_FORDEV); 16778a3c961bSfei feng - Sun Microsystems - Beijing China if (data->ni != NULL) { 16788a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_free_node(data->ni); 16798a3c961bSfei feng - Sun Microsystems - Beijing China data->ni = NULL; 16808a3c961bSfei feng - Sun Microsystems - Beijing China } 16818a3c961bSfei feng - Sun Microsystems - Beijing China SLIST_INSERT_HEAD(&sc->data_pool, data, next); 16828a3c961bSfei feng - Sun Microsystems - Beijing China ring->data[ring->next] = NULL; 16838a3c961bSfei feng - Sun Microsystems - Beijing China } 16848a3c961bSfei feng - Sun Microsystems - Beijing China 16858a3c961bSfei feng - Sun Microsystems - Beijing China txd->sdl0 &= ~LE_16(RT2860_TX_DDONE); 16868a3c961bSfei feng - Sun Microsystems - Beijing China 16878a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_sync(ring->txdesc_dma.dma_hdl, 16888a3c961bSfei feng - Sun Microsystems - Beijing China ring->next * sizeof (struct rt2860_txd), 16898a3c961bSfei feng - Sun Microsystems - Beijing China sizeof (struct rt2860_txd), 16908a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SYNC_FORDEV); 16918a3c961bSfei feng - Sun Microsystems - Beijing China 16928a3c961bSfei feng - Sun Microsystems - Beijing China ring->queued--; 16938a3c961bSfei feng - Sun Microsystems - Beijing China ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; 16948a3c961bSfei feng - Sun Microsystems - Beijing China 16958a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_need_sched && 16968a3c961bSfei feng - Sun Microsystems - Beijing China (ring->queued < RT2860_TX_RING_COUNT)) { 16978a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_need_sched = 0; 16988a3c961bSfei feng - Sun Microsystems - Beijing China mac_tx_update(ic->ic_mach); 16998a3c961bSfei feng - Sun Microsystems - Beijing China } 17008a3c961bSfei feng - Sun Microsystems - Beijing China } 17018a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_tx_timer = 0; 17028a3c961bSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_txlock); 17038a3c961bSfei feng - Sun Microsystems - Beijing China } 1704860387ebSfei feng - Sun Microsystems - Beijing China 17058a3c961bSfei feng - Sun Microsystems - Beijing China static void 17068a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rx_intr(struct rt2860_softc *sc) 17078a3c961bSfei feng - Sun Microsystems - Beijing China { 17088a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 17098a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_node *ni; 17108a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_frame *wh; 17118a3c961bSfei feng - Sun Microsystems - Beijing China int pktlen; 17128a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t ant, rssi, *rxbuf; 17138a3c961bSfei feng - Sun Microsystems - Beijing China mblk_t *mp0; 17148a3c961bSfei feng - Sun Microsystems - Beijing China 17158a3c961bSfei feng - Sun Microsystems - Beijing China mutex_enter(&sc->sc_rxlock); 17168a3c961bSfei feng - Sun Microsystems - Beijing China for (;;) { 17178a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rx_data *data = &sc->rxq.data[sc->rxq.cur]; 17188a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rxd *rxd = &sc->rxq.rxd[sc->rxq.cur]; 17198a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_rxwi *rxwi; 17208a3c961bSfei feng - Sun Microsystems - Beijing China 17218a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_sync(sc->rxq.rxdesc_dma.dma_hdl, 17228a3c961bSfei feng - Sun Microsystems - Beijing China sc->rxq.cur * sizeof (struct rt2860_rxd), 17238a3c961bSfei feng - Sun Microsystems - Beijing China sizeof (struct rt2860_rxd), 17248a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SYNC_FORKERNEL); 17258a3c961bSfei feng - Sun Microsystems - Beijing China 17268a3c961bSfei feng - Sun Microsystems - Beijing China if (!(rxd->sdl0 & LE_16(RT2860_RX_DDONE))) { 17278a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RX, "rwn: rt2860_rx_intr(): " 17288a3c961bSfei feng - Sun Microsystems - Beijing China "rx done!\n"); 17298a3c961bSfei feng - Sun Microsystems - Beijing China break; 17308a3c961bSfei feng - Sun Microsystems - Beijing China } 17318a3c961bSfei feng - Sun Microsystems - Beijing China 17328a3c961bSfei feng - Sun Microsystems - Beijing China if (rxd->flags & 17338a3c961bSfei feng - Sun Microsystems - Beijing China LE_32(RT2860_RX_CRCERR | RT2860_RX_ICVERR)) { 17348a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RX, "rwn: rt2860_rx_intr(): " 17358a3c961bSfei feng - Sun Microsystems - Beijing China "rx crc error & rx icv error!\n"); 17368a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rx_err++; 17378a3c961bSfei feng - Sun Microsystems - Beijing China goto skip; 17388a3c961bSfei feng - Sun Microsystems - Beijing China } 17398a3c961bSfei feng - Sun Microsystems - Beijing China 17408a3c961bSfei feng - Sun Microsystems - Beijing China if (rxd->flags & LE_32(RT2860_RX_MICERR)) { 17418a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RX, "rwn: rt2860_rx_intr(): " 17428a3c961bSfei feng - Sun Microsystems - Beijing China "rx mic error!\n"); 17438a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rx_err++; 17448a3c961bSfei feng - Sun Microsystems - Beijing China goto skip; 17458a3c961bSfei feng - Sun Microsystems - Beijing China } 17468a3c961bSfei feng - Sun Microsystems - Beijing China 17478a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_sync(data->rxbuf_dma.dma_hdl, 17488a3c961bSfei feng - Sun Microsystems - Beijing China data->rxbuf_dma.offset, 17498a3c961bSfei feng - Sun Microsystems - Beijing China data->rxbuf_dma.alength, 17508a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SYNC_FORCPU); 17518a3c961bSfei feng - Sun Microsystems - Beijing China 17528a3c961bSfei feng - Sun Microsystems - Beijing China rxbuf = (uint8_t *)data->rxbuf_dma.mem_va; 17538a3c961bSfei feng - Sun Microsystems - Beijing China rxd->sdp0 = LE_32(data->rxbuf_dma.cookie.dmac_address); 17548a3c961bSfei feng - Sun Microsystems - Beijing China rxwi = (struct rt2860_rxwi *)rxbuf; 17558a3c961bSfei feng - Sun Microsystems - Beijing China rxbuf = (uint8_t *)(rxwi + 1); 17568a3c961bSfei feng - Sun Microsystems - Beijing China pktlen = LE_16(rxwi->len) & 0xfff; 17578a3c961bSfei feng - Sun Microsystems - Beijing China 17588a3c961bSfei feng - Sun Microsystems - Beijing China mp0 = allocb(sc->sc_dmabuf_size, BPRI_MED); 17598a3c961bSfei feng - Sun Microsystems - Beijing China if (mp0 == NULL) { 17608a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RX, "rwn: rt2860_rx_intr():" 17618a3c961bSfei feng - Sun Microsystems - Beijing China "alloc mblk error\n"); 17628a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rx_nobuf++; 17638a3c961bSfei feng - Sun Microsystems - Beijing China goto skip; 17648a3c961bSfei feng - Sun Microsystems - Beijing China } 17658a3c961bSfei feng - Sun Microsystems - Beijing China bcopy(rxbuf, mp0->b_rptr, pktlen); 17668a3c961bSfei feng - Sun Microsystems - Beijing China mp0->b_wptr += pktlen; 17678a3c961bSfei feng - Sun Microsystems - Beijing China 17688a3c961bSfei feng - Sun Microsystems - Beijing China wh = (struct ieee80211_frame *)mp0->b_rptr; 17698a3c961bSfei feng - Sun Microsystems - Beijing China 17708a3c961bSfei feng - Sun Microsystems - Beijing China /* HW may insert 2 padding bytes after 802.11 header */ 17718a3c961bSfei feng - Sun Microsystems - Beijing China if (rxd->flags & LE_32(RT2860_RX_L2PAD)) { 17728a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RX, "rwn: rt2860_rx_intr():" 17738a3c961bSfei feng - Sun Microsystems - Beijing China "2 padding bytes after 80211 header!\n"); 17748a3c961bSfei feng - Sun Microsystems - Beijing China } 17758a3c961bSfei feng - Sun Microsystems - Beijing China 17768a3c961bSfei feng - Sun Microsystems - Beijing China ant = rt2860_maxrssi_chain(sc, rxwi); 1777860387ebSfei feng - Sun Microsystems - Beijing China rssi = RT2860_RSSI_OFFSET - rxwi->rssi[ant]; 17788a3c961bSfei feng - Sun Microsystems - Beijing China /* grab a reference to the source node */ 17798a3c961bSfei feng - Sun Microsystems - Beijing China ni = ieee80211_find_rxnode(ic, wh); 17808a3c961bSfei feng - Sun Microsystems - Beijing China 1781c1374a13SSurya Prakki (void) ieee80211_input(ic, mp0, ni, rssi, 0); 17828a3c961bSfei feng - Sun Microsystems - Beijing China 17838a3c961bSfei feng - Sun Microsystems - Beijing China /* node is no longer needed */ 17848a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_free_node(ni); 17858a3c961bSfei feng - Sun Microsystems - Beijing China skip: 17868a3c961bSfei feng - Sun Microsystems - Beijing China rxd->sdl0 &= ~LE_16(RT2860_RX_DDONE); 17878a3c961bSfei feng - Sun Microsystems - Beijing China 17888a3c961bSfei feng - Sun Microsystems - Beijing China (void) ddi_dma_sync(sc->rxq.rxdesc_dma.dma_hdl, 17898a3c961bSfei feng - Sun Microsystems - Beijing China sc->rxq.cur * sizeof (struct rt2860_rxd), 17908a3c961bSfei feng - Sun Microsystems - Beijing China sizeof (struct rt2860_rxd), 17918a3c961bSfei feng - Sun Microsystems - Beijing China DDI_DMA_SYNC_FORDEV); 17928a3c961bSfei feng - Sun Microsystems - Beijing China 17938a3c961bSfei feng - Sun Microsystems - Beijing China sc->rxq.cur = (sc->rxq.cur + 1) % RT2860_RX_RING_COUNT; 17948a3c961bSfei feng - Sun Microsystems - Beijing China } 17958a3c961bSfei feng - Sun Microsystems - Beijing China mutex_exit(&sc->sc_rxlock); 17968a3c961bSfei feng - Sun Microsystems - Beijing China 17978a3c961bSfei feng - Sun Microsystems - Beijing China /* tell HW what we have processed */ 17988a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_RX_CALC_IDX, 17998a3c961bSfei feng - Sun Microsystems - Beijing China (sc->rxq.cur - 1) % RT2860_RX_RING_COUNT); 18008a3c961bSfei feng - Sun Microsystems - Beijing China } 18018a3c961bSfei feng - Sun Microsystems - Beijing China 18028a3c961bSfei feng - Sun Microsystems - Beijing China static uint_t 18038a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_softintr(caddr_t data) 18048a3c961bSfei feng - Sun Microsystems - Beijing China { 18058a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)data; 18068a3c961bSfei feng - Sun Microsystems - Beijing China 18078a3c961bSfei feng - Sun Microsystems - Beijing China /* 18088a3c961bSfei feng - Sun Microsystems - Beijing China * Check if the soft interrupt is triggered by another 18098a3c961bSfei feng - Sun Microsystems - Beijing China * driver at the same level. 18108a3c961bSfei feng - Sun Microsystems - Beijing China */ 18118a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 18128a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_rx_pend) { 18138a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rx_pend = 0; 18148a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 18158a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rx_intr(sc); 18168a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 18178a3c961bSfei feng - Sun Microsystems - Beijing China } 18188a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 18198a3c961bSfei feng - Sun Microsystems - Beijing China 18208a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 18218a3c961bSfei feng - Sun Microsystems - Beijing China } 18228a3c961bSfei feng - Sun Microsystems - Beijing China 18238a3c961bSfei feng - Sun Microsystems - Beijing China static uint_t 18248a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_intr(caddr_t arg) 18258a3c961bSfei feng - Sun Microsystems - Beijing China { 18268a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 18278a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t r; 18288a3c961bSfei feng - Sun Microsystems - Beijing China 18298a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 18308a3c961bSfei feng - Sun Microsystems - Beijing China 18318a3c961bSfei feng - Sun Microsystems - Beijing China if ((!RT2860_IS_RUNNING(sc)) || RT2860_IS_SUSPEND(sc)) { 18328a3c961bSfei feng - Sun Microsystems - Beijing China /* 18338a3c961bSfei feng - Sun Microsystems - Beijing China * The hardware is not ready/present, don't touch anything. 18348a3c961bSfei feng - Sun Microsystems - Beijing China * Note this can happen early on if the IRQ is shared. 18358a3c961bSfei feng - Sun Microsystems - Beijing China */ 18368a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 18378a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 18388a3c961bSfei feng - Sun Microsystems - Beijing China } 18398a3c961bSfei feng - Sun Microsystems - Beijing China 18408a3c961bSfei feng - Sun Microsystems - Beijing China r = RT2860_READ(sc, RT2860_INT_STATUS); 18418a3c961bSfei feng - Sun Microsystems - Beijing China if (r == 0xffffffff) { 18428a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 18438a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 18448a3c961bSfei feng - Sun Microsystems - Beijing China } 18458a3c961bSfei feng - Sun Microsystems - Beijing China if (r == 0) { 18468a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 18478a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_INTR_UNCLAIMED); 18488a3c961bSfei feng - Sun Microsystems - Beijing China } 18498a3c961bSfei feng - Sun Microsystems - Beijing China 18508a3c961bSfei feng - Sun Microsystems - Beijing China /* acknowledge interrupts */ 18518a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_INT_STATUS, r); 18528a3c961bSfei feng - Sun Microsystems - Beijing China 18538a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_COHERENT) 18548a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr()" 18558a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_COHERENT\n"); 18568a3c961bSfei feng - Sun Microsystems - Beijing China 18578a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_RX_COHERENT) 18588a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr()" 18598a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_RX_COHERENT\n"); 18608a3c961bSfei feng - Sun Microsystems - Beijing China 18618a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_MAC_INT_2) { 18628a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 18638a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_MAC_INT_2\n"); 18648a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_drain_stats_fifo(sc); 18658a3c961bSfei feng - Sun Microsystems - Beijing China } 18668a3c961bSfei feng - Sun Microsystems - Beijing China 18678a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_DONE_INT5) { 18688a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 18698a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_DONE_INT5\n"); 18708a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(sc, 5); 18718a3c961bSfei feng - Sun Microsystems - Beijing China } 18728a3c961bSfei feng - Sun Microsystems - Beijing China 18738a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_RX_DONE_INT) { 18748a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr()" 18758a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_RX_INT\n"); 18768a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_rx_pend = 1; 18778a3c961bSfei feng - Sun Microsystems - Beijing China ddi_trigger_softintr(sc->sc_softintr_hdl); 18788a3c961bSfei feng - Sun Microsystems - Beijing China } 18798a3c961bSfei feng - Sun Microsystems - Beijing China 18808a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_DONE_INT4) { 18818a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 18828a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_DONE_INT4\n"); 18838a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(sc, 4); 18848a3c961bSfei feng - Sun Microsystems - Beijing China } 18858a3c961bSfei feng - Sun Microsystems - Beijing China 18868a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_DONE_INT3) { 18878a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 18888a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_DONE_INT3\n"); 18898a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(sc, 3); 18908a3c961bSfei feng - Sun Microsystems - Beijing China } 18918a3c961bSfei feng - Sun Microsystems - Beijing China 18928a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_DONE_INT2) { 18938a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 18948a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_DONE_INT2\n"); 18958a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(sc, 2); 18968a3c961bSfei feng - Sun Microsystems - Beijing China } 18978a3c961bSfei feng - Sun Microsystems - Beijing China 18988a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_DONE_INT1) { 18998a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 19008a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_DONE_INT1\n"); 19018a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(sc, 1); 19028a3c961bSfei feng - Sun Microsystems - Beijing China } 19038a3c961bSfei feng - Sun Microsystems - Beijing China 19048a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_TX_DONE_INT0) { 19058a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 19068a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_TX_DONE_INT0\n"); 19078a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_tx_intr(sc, 0); 19088a3c961bSfei feng - Sun Microsystems - Beijing China } 19098a3c961bSfei feng - Sun Microsystems - Beijing China 19108a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_MAC_INT_0) { 19118a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 19128a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_MAC_INT_0\n"); 19138a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 19148a3c961bSfei feng - Sun Microsystems - Beijing China /* check if protection mode has changed */ 19158a3c961bSfei feng - Sun Microsystems - Beijing China if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { 19168a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_updateprot(ic); 19178a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_ic_flags = ic->ic_flags; 19188a3c961bSfei feng - Sun Microsystems - Beijing China } 19198a3c961bSfei feng - Sun Microsystems - Beijing China } 19208a3c961bSfei feng - Sun Microsystems - Beijing China 19218a3c961bSfei feng - Sun Microsystems - Beijing China if (r & RT2860_MAC_INT_3) 19228a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_INTR, "rwn: rt2860_intr(): " 19238a3c961bSfei feng - Sun Microsystems - Beijing China "RT2860_MAC_INT_3\n"); 19248a3c961bSfei feng - Sun Microsystems - Beijing China 19258a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 19268a3c961bSfei feng - Sun Microsystems - Beijing China 19278a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_INTR_CLAIMED); 19288a3c961bSfei feng - Sun Microsystems - Beijing China } 19298a3c961bSfei feng - Sun Microsystems - Beijing China 19308a3c961bSfei feng - Sun Microsystems - Beijing China static void 19318a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(struct rt2860_softc *sc, 19328a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t addr, uint32_t data, int size) 19338a3c961bSfei feng - Sun Microsystems - Beijing China { 19348a3c961bSfei feng - Sun Microsystems - Beijing China for (; size > 0; size--, data++, addr += 4) 19358a3c961bSfei feng - Sun Microsystems - Beijing China ddi_put32((sc)->sc_io_handle, 19368a3c961bSfei feng - Sun Microsystems - Beijing China (uint32_t *)((uintptr_t)(sc)->sc_io_base + addr), data); 19378a3c961bSfei feng - Sun Microsystems - Beijing China } 19388a3c961bSfei feng - Sun Microsystems - Beijing China 19398a3c961bSfei feng - Sun Microsystems - Beijing China static int 19408a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_load_microcode(struct rt2860_softc *sc) 19418a3c961bSfei feng - Sun Microsystems - Beijing China { 19428a3c961bSfei feng - Sun Microsystems - Beijing China int ntries; 19438a3c961bSfei feng - Sun Microsystems - Beijing China size_t size; 19448a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t *ucode, *fptr; 19458a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t off, i; 19468a3c961bSfei feng - Sun Microsystems - Beijing China 19478a3c961bSfei feng - Sun Microsystems - Beijing China ucode = rt2860_fw_bin; 19488a3c961bSfei feng - Sun Microsystems - Beijing China size = sizeof (rt2860_fw_bin); 19498a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_load_microcode(): " 19508a3c961bSfei feng - Sun Microsystems - Beijing China "The size of ucode is: %x\n", size); 19518a3c961bSfei feng - Sun Microsystems - Beijing China 19528a3c961bSfei feng - Sun Microsystems - Beijing China /* set "host program ram write selection" bit */ 19538a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, RT2860_HST_PM_SEL); 19548a3c961bSfei feng - Sun Microsystems - Beijing China /* write microcode image */ 19558a3c961bSfei feng - Sun Microsystems - Beijing China fptr = ucode; 19568a3c961bSfei feng - Sun Microsystems - Beijing China off = RT2860_FW_BASE; 19578a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < size; i++) { 19588a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mem_write1(sc, off++, *fptr++); 19598a3c961bSfei feng - Sun Microsystems - Beijing China } 19608a3c961bSfei feng - Sun Microsystems - Beijing China /* kick microcontroller unit */ 19618a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, 0); 19628a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, RT2860_MCU_RESET); 19638a3c961bSfei feng - Sun Microsystems - Beijing China 19648a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_BBPAGENT, 0); 19658a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_MAILBOX, 0); 19668a3c961bSfei feng - Sun Microsystems - Beijing China 19678a3c961bSfei feng - Sun Microsystems - Beijing China /* wait until microcontroller is ready */ 19688a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 1000; ntries++) { 19698a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_READ(sc, RT2860_SYS_CTRL) & RT2860_MCU_READY) 19708a3c961bSfei feng - Sun Microsystems - Beijing China break; 19718a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 19728a3c961bSfei feng - Sun Microsystems - Beijing China } 19738a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 1000) { 19748a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_load_microcode(): " 19758a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for MCU to initialie\n"); 19768a3c961bSfei feng - Sun Microsystems - Beijing China return (ETIMEDOUT); 19778a3c961bSfei feng - Sun Microsystems - Beijing China } 19788a3c961bSfei feng - Sun Microsystems - Beijing China 19798a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 19808a3c961bSfei feng - Sun Microsystems - Beijing China } 19818a3c961bSfei feng - Sun Microsystems - Beijing China 19828a3c961bSfei feng - Sun Microsystems - Beijing China static void 19838a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_macaddr(struct rt2860_softc *sc, const uint8_t *addr) 19848a3c961bSfei feng - Sun Microsystems - Beijing China { 19858a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_ADDR_DW0, 19868a3c961bSfei feng - Sun Microsystems - Beijing China addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); 19878a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_ADDR_DW1, 19888a3c961bSfei feng - Sun Microsystems - Beijing China addr[4] | addr[5] << 8); 19898a3c961bSfei feng - Sun Microsystems - Beijing China } 19908a3c961bSfei feng - Sun Microsystems - Beijing China 19918a3c961bSfei feng - Sun Microsystems - Beijing China /* 19928a3c961bSfei feng - Sun Microsystems - Beijing China * Send a command to the 8051 microcontroller unit. 19938a3c961bSfei feng - Sun Microsystems - Beijing China */ 19948a3c961bSfei feng - Sun Microsystems - Beijing China static int 19958a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd, uint16_t arg) 19968a3c961bSfei feng - Sun Microsystems - Beijing China { 19978a3c961bSfei feng - Sun Microsystems - Beijing China int ntries; 19988a3c961bSfei feng - Sun Microsystems - Beijing China 19998a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 20008a3c961bSfei feng - Sun Microsystems - Beijing China if (!(RT2860_READ(sc, RT2860_H2M_MAILBOX) & RT2860_H2M_BUSY)) 20018a3c961bSfei feng - Sun Microsystems - Beijing China break; 20028a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(2); 20038a3c961bSfei feng - Sun Microsystems - Beijing China } 20048a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) 20058a3c961bSfei feng - Sun Microsystems - Beijing China return (EIO); 20068a3c961bSfei feng - Sun Microsystems - Beijing China 20078a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_MAILBOX, 20088a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_H2M_BUSY | RT2860_TOKEN_NO_INTR << 16 | arg); 20098a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_HOST_CMD, cmd); 20108a3c961bSfei feng - Sun Microsystems - Beijing China 20118a3c961bSfei feng - Sun Microsystems - Beijing China return (RT2860_SUCCESS); 20128a3c961bSfei feng - Sun Microsystems - Beijing China } 20138a3c961bSfei feng - Sun Microsystems - Beijing China 20148a3c961bSfei feng - Sun Microsystems - Beijing China /* 20158a3c961bSfei feng - Sun Microsystems - Beijing China * Reading and writing from/to the BBP is different from RT2560 and RT2661. 20168a3c961bSfei feng - Sun Microsystems - Beijing China * We access the BBP through the 8051 microcontroller unit which means that 20178a3c961bSfei feng - Sun Microsystems - Beijing China * the microcode must be loaded first. 20188a3c961bSfei feng - Sun Microsystems - Beijing China */ 20198a3c961bSfei feng - Sun Microsystems - Beijing China static uint8_t 20208a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_read(struct rt2860_softc *sc, uint8_t reg) 20218a3c961bSfei feng - Sun Microsystems - Beijing China { 20228a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t val; 20238a3c961bSfei feng - Sun Microsystems - Beijing China int ntries; 20248a3c961bSfei feng - Sun Microsystems - Beijing China 20258a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 20268a3c961bSfei feng - Sun Microsystems - Beijing China if (!(RT2860_READ(sc, 20278a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) 20288a3c961bSfei feng - Sun Microsystems - Beijing China break; 20298a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1); 20308a3c961bSfei feng - Sun Microsystems - Beijing China } 20318a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 20328a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_mcu_bbp_read():" 20338a3c961bSfei feng - Sun Microsystems - Beijing China "could not read from BBP through MCU\n"); 20348a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 20358a3c961bSfei feng - Sun Microsystems - Beijing China } 20368a3c961bSfei feng - Sun Microsystems - Beijing China 20378a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | 20388a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_BBP_CSR_KICK | RT2860_BBP_CSR_READ | reg << 8); 20398a3c961bSfei feng - Sun Microsystems - Beijing China 20408a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0); 20418a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 20428a3c961bSfei feng - Sun Microsystems - Beijing China 20438a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 20448a3c961bSfei feng - Sun Microsystems - Beijing China val = RT2860_READ(sc, RT2860_H2M_BBPAGENT); 20458a3c961bSfei feng - Sun Microsystems - Beijing China if (!(val & RT2860_BBP_CSR_KICK)) 20468a3c961bSfei feng - Sun Microsystems - Beijing China return (val & 0xff); 20478a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1); 20488a3c961bSfei feng - Sun Microsystems - Beijing China } 20498a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_mcu_bbp_read():" 20508a3c961bSfei feng - Sun Microsystems - Beijing China "could not read from BBP through MCU\n"); 20518a3c961bSfei feng - Sun Microsystems - Beijing China 20528a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 20538a3c961bSfei feng - Sun Microsystems - Beijing China } 20548a3c961bSfei feng - Sun Microsystems - Beijing China 20558a3c961bSfei feng - Sun Microsystems - Beijing China static void 20568a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) 20578a3c961bSfei feng - Sun Microsystems - Beijing China { 20588a3c961bSfei feng - Sun Microsystems - Beijing China int ntries; 20598a3c961bSfei feng - Sun Microsystems - Beijing China 20608a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 20618a3c961bSfei feng - Sun Microsystems - Beijing China if (!(RT2860_READ(sc, 20628a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) 20638a3c961bSfei feng - Sun Microsystems - Beijing China break; 20648a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1); 20658a3c961bSfei feng - Sun Microsystems - Beijing China } 20668a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 20678a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_mcu_bbp_write():" 20688a3c961bSfei feng - Sun Microsystems - Beijing China "could not write to BBP through MCU\n"); 20698a3c961bSfei feng - Sun Microsystems - Beijing China return; 20708a3c961bSfei feng - Sun Microsystems - Beijing China } 20718a3c961bSfei feng - Sun Microsystems - Beijing China 20728a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | 20738a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_BBP_CSR_KICK | reg << 8 | val); 20748a3c961bSfei feng - Sun Microsystems - Beijing China 20758a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0); 20768a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 20778a3c961bSfei feng - Sun Microsystems - Beijing China } 20788a3c961bSfei feng - Sun Microsystems - Beijing China 20798a3c961bSfei feng - Sun Microsystems - Beijing China static int 20808a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_bbp_init(struct rt2860_softc *sc) 20818a3c961bSfei feng - Sun Microsystems - Beijing China { 20828a3c961bSfei feng - Sun Microsystems - Beijing China int i, ntries; 20838a3c961bSfei feng - Sun Microsystems - Beijing China 20848a3c961bSfei feng - Sun Microsystems - Beijing China /* wait for BBP to wake up */ 20858a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 20; ntries++) { 20868a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t bbp0 = rt2860_mcu_bbp_read(sc, 0); 20878a3c961bSfei feng - Sun Microsystems - Beijing China if (bbp0 != 0 && bbp0 != 0xff) 20888a3c961bSfei feng - Sun Microsystems - Beijing China break; 20898a3c961bSfei feng - Sun Microsystems - Beijing China } 20908a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 20) { 20918a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_bbp_init():" 20928a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for BBP to wake up\n"); 20938a3c961bSfei feng - Sun Microsystems - Beijing China return (ETIMEDOUT); 20948a3c961bSfei feng - Sun Microsystems - Beijing China } 20958a3c961bSfei feng - Sun Microsystems - Beijing China 20968a3c961bSfei feng - Sun Microsystems - Beijing China /* initialize BBP registers to default values */ 20978a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 12; i++) { 20988a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, rt2860_def_bbp[i].reg, 20998a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_def_bbp[i].val); 21008a3c961bSfei feng - Sun Microsystems - Beijing China } 21018a3c961bSfei feng - Sun Microsystems - Beijing China 21028a3c961bSfei feng - Sun Microsystems - Beijing China /* fix BBP69 and BBP73 for RT2860C */ 21038a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->mac_rev == 0x28600100) { 21048a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 69, 0x16); 21058a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 73, 0x12); 21068a3c961bSfei feng - Sun Microsystems - Beijing China } 21078a3c961bSfei feng - Sun Microsystems - Beijing China 21088a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 21098a3c961bSfei feng - Sun Microsystems - Beijing China } 21108a3c961bSfei feng - Sun Microsystems - Beijing China 21118a3c961bSfei feng - Sun Microsystems - Beijing China static void 21128a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val) 21138a3c961bSfei feng - Sun Microsystems - Beijing China { 21148a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 21158a3c961bSfei feng - Sun Microsystems - Beijing China int ntries; 21168a3c961bSfei feng - Sun Microsystems - Beijing China 21178a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 21188a3c961bSfei feng - Sun Microsystems - Beijing China if (!(RT2860_READ(sc, RT2860_RF_CSR_CFG0) & RT2860_RF_REG_CTRL)) 21198a3c961bSfei feng - Sun Microsystems - Beijing China break; 21208a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1); 21218a3c961bSfei feng - Sun Microsystems - Beijing China } 21228a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 21238a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rwn_init()" 21248a3c961bSfei feng - Sun Microsystems - Beijing China "could not write to RF\n"); 21258a3c961bSfei feng - Sun Microsystems - Beijing China return; 21268a3c961bSfei feng - Sun Microsystems - Beijing China } 21278a3c961bSfei feng - Sun Microsystems - Beijing China 21288a3c961bSfei feng - Sun Microsystems - Beijing China /* RF registers are 24-bit on the RT2860 */ 21298a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT | 21308a3c961bSfei feng - Sun Microsystems - Beijing China (val & 0x3fffff) << 2 | (reg & 3); 21318a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_RF_CSR_CFG0, tmp); 21328a3c961bSfei feng - Sun Microsystems - Beijing China } 21338a3c961bSfei feng - Sun Microsystems - Beijing China 21348a3c961bSfei feng - Sun Microsystems - Beijing China static void 21358a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_select_chan_group(struct rt2860_softc *sc, int group) 21368a3c961bSfei feng - Sun Microsystems - Beijing China { 21378a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 21388a3c961bSfei feng - Sun Microsystems - Beijing China 21398a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 62, 0x37 - sc->lna[group]); 21408a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 63, 0x37 - sc->lna[group]); 21418a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 64, 0x37 - sc->lna[group]); 21428a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 82, (group == 0) ? 0x62 : 0xf2); 21438a3c961bSfei feng - Sun Microsystems - Beijing China 21448a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_TX_BAND_CFG); 21458a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= ~(RT2860_5G_BAND_SEL_N | RT2860_5G_BAND_SEL_P); 21468a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= (group == 0) ? RT2860_5G_BAND_SEL_N : RT2860_5G_BAND_SEL_P; 21478a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_BAND_CFG, tmp); 21488a3c961bSfei feng - Sun Microsystems - Beijing China 21498a3c961bSfei feng - Sun Microsystems - Beijing China /* enable appropriate Power Amplifiers and Low Noise Amplifiers */ 21508a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_RFTR_EN | RT2860_TRSW_EN; 21518a3c961bSfei feng - Sun Microsystems - Beijing China if (group == 0) { /* 2GHz */ 21528a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_PA_PE_G0_EN | RT2860_LNA_PE_G0_EN; 21538a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->ntxchains > 1) 21548a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_PA_PE_G1_EN; 21558a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->nrxchains > 1) 21568a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_LNA_PE_G1_EN; 21578a3c961bSfei feng - Sun Microsystems - Beijing China } else { /* 5GHz */ 21588a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_PA_PE_A0_EN | RT2860_LNA_PE_A0_EN; 21598a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->ntxchains > 1) 21608a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_PA_PE_A1_EN; 21618a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->nrxchains > 1) 21628a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_LNA_PE_A1_EN; 21638a3c961bSfei feng - Sun Microsystems - Beijing China } 21648a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_PIN_CFG, tmp); 21658a3c961bSfei feng - Sun Microsystems - Beijing China 21668a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 66, 0x2e + sc->lna[group]); 21678a3c961bSfei feng - Sun Microsystems - Beijing China } 21688a3c961bSfei feng - Sun Microsystems - Beijing China static void 21698a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) 21708a3c961bSfei feng - Sun Microsystems - Beijing China { 21718a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 21728a3c961bSfei feng - Sun Microsystems - Beijing China const struct rfprog *rfprog = rt2860_rf2850; 21738a3c961bSfei feng - Sun Microsystems - Beijing China uint_t i, chan, group; 21748a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t txpow1, txpow2; 21758a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t r2, r3, r4; 21768a3c961bSfei feng - Sun Microsystems - Beijing China 21778a3c961bSfei feng - Sun Microsystems - Beijing China chan = ieee80211_chan2ieee(ic, c); 21788a3c961bSfei feng - Sun Microsystems - Beijing China if (chan == 0 || chan == IEEE80211_CHAN_ANY) { 21798a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "Unkonwn channel!\n"); 21808a3c961bSfei feng - Sun Microsystems - Beijing China return; 21818a3c961bSfei feng - Sun Microsystems - Beijing China } 21828a3c961bSfei feng - Sun Microsystems - Beijing China 21838a3c961bSfei feng - Sun Microsystems - Beijing China /* find the settings for this channel (we know it exists) */ 21848a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; rfprog[i].chan != chan; ) 21858a3c961bSfei feng - Sun Microsystems - Beijing China i++; 21868a3c961bSfei feng - Sun Microsystems - Beijing China 21878a3c961bSfei feng - Sun Microsystems - Beijing China r2 = rfprog[i].r2; 21888a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->ntxchains == 1) 21898a3c961bSfei feng - Sun Microsystems - Beijing China r2 |= 1 << 12; /* 1T: disable Tx chain 2 */ 21908a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->nrxchains == 1) 21918a3c961bSfei feng - Sun Microsystems - Beijing China r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ 21928a3c961bSfei feng - Sun Microsystems - Beijing China else if (sc->nrxchains == 2) 21938a3c961bSfei feng - Sun Microsystems - Beijing China r2 |= 1 << 4; /* 2R: disable Rx chain 3 */ 21948a3c961bSfei feng - Sun Microsystems - Beijing China 21958a3c961bSfei feng - Sun Microsystems - Beijing China /* use Tx power values from EEPROM */ 21968a3c961bSfei feng - Sun Microsystems - Beijing China txpow1 = sc->txpow1[i]; 21978a3c961bSfei feng - Sun Microsystems - Beijing China txpow2 = sc->txpow2[i]; 21988a3c961bSfei feng - Sun Microsystems - Beijing China if (IEEE80211_IS_CHAN_5GHZ(c)) { 21998a3c961bSfei feng - Sun Microsystems - Beijing China txpow1 = txpow1 << 1 | 1; 22008a3c961bSfei feng - Sun Microsystems - Beijing China txpow2 = txpow2 << 1 | 1; 22018a3c961bSfei feng - Sun Microsystems - Beijing China } 22028a3c961bSfei feng - Sun Microsystems - Beijing China r3 = rfprog[i].r3 | txpow1 << 7; 22038a3c961bSfei feng - Sun Microsystems - Beijing China r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4; 22048a3c961bSfei feng - Sun Microsystems - Beijing China 22058a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF1, rfprog[i].r1); 22068a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF2, r2); 22078a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF3, r3); 22088a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF4, r4); 22098a3c961bSfei feng - Sun Microsystems - Beijing China 22108a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(200); 22118a3c961bSfei feng - Sun Microsystems - Beijing China 22128a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF1, rfprog[i].r1); 22138a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF2, r2); 22148a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF3, r3 | 1); 22158a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF4, r4); 22168a3c961bSfei feng - Sun Microsystems - Beijing China 22178a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(200); 22188a3c961bSfei feng - Sun Microsystems - Beijing China 22198a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF1, rfprog[i].r1); 22208a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF2, r2); 22218a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF3, r3); 22228a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_rf_write(sc, RAL_RF4, r4); 22238a3c961bSfei feng - Sun Microsystems - Beijing China 22248a3c961bSfei feng - Sun Microsystems - Beijing China /* 802.11a uses a 16 microseconds short interframe space */ 22258a3c961bSfei feng - Sun Microsystems - Beijing China sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10; 22268a3c961bSfei feng - Sun Microsystems - Beijing China 22278a3c961bSfei feng - Sun Microsystems - Beijing China /* determine channel group */ 22288a3c961bSfei feng - Sun Microsystems - Beijing China if (chan <= 14) 22298a3c961bSfei feng - Sun Microsystems - Beijing China group = 0; 22308a3c961bSfei feng - Sun Microsystems - Beijing China else if (chan <= 64) 22318a3c961bSfei feng - Sun Microsystems - Beijing China group = 1; 22328a3c961bSfei feng - Sun Microsystems - Beijing China else if (chan <= 128) 22338a3c961bSfei feng - Sun Microsystems - Beijing China group = 2; 22348a3c961bSfei feng - Sun Microsystems - Beijing China else 22358a3c961bSfei feng - Sun Microsystems - Beijing China group = 3; 22368a3c961bSfei feng - Sun Microsystems - Beijing China 22378a3c961bSfei feng - Sun Microsystems - Beijing China /* XXX necessary only when group has changed! */ 22388a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_select_chan_group(sc, group); 22398a3c961bSfei feng - Sun Microsystems - Beijing China 22408a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 22418a3c961bSfei feng - Sun Microsystems - Beijing China } 22428a3c961bSfei feng - Sun Microsystems - Beijing China 22438a3c961bSfei feng - Sun Microsystems - Beijing China static void 22448a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_updateprot(struct ieee80211com *ic) 22458a3c961bSfei feng - Sun Microsystems - Beijing China { 22468a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)ic; 22478a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 22488a3c961bSfei feng - Sun Microsystems - Beijing China 22498a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; 22508a3c961bSfei feng - Sun Microsystems - Beijing China /* setup protection frame rate (MCS code) */ 22518a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= (ic->ic_curmode == IEEE80211_MODE_11A) ? 0 : 3; 22528a3c961bSfei feng - Sun Microsystems - Beijing China 22538a3c961bSfei feng - Sun Microsystems - Beijing China /* CCK frames don't require protection */ 22548a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_CCK_PROT_CFG, tmp); 22558a3c961bSfei feng - Sun Microsystems - Beijing China 22568a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_flags & IEEE80211_F_USEPROT) { 22578a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 22588a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_PROT_CTRL_RTS_CTS; 22598a3c961bSfei feng - Sun Microsystems - Beijing China else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 22608a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_PROT_CTRL_CTS; 22618a3c961bSfei feng - Sun Microsystems - Beijing China } 22628a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_OFDM_PROT_CFG, tmp); 22638a3c961bSfei feng - Sun Microsystems - Beijing China } 22648a3c961bSfei feng - Sun Microsystems - Beijing China 22658a3c961bSfei feng - Sun Microsystems - Beijing China static void 22668a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_leds(struct rt2860_softc *sc, uint16_t which) 22678a3c961bSfei feng - Sun Microsystems - Beijing China { 22688a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LEDS, 22698a3c961bSfei feng - Sun Microsystems - Beijing China which | (sc->leds & 0x7f)); 22708a3c961bSfei feng - Sun Microsystems - Beijing China } 22718a3c961bSfei feng - Sun Microsystems - Beijing China 22728a3c961bSfei feng - Sun Microsystems - Beijing China static int 22738a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_init(struct rt2860_softc *sc) 22748a3c961bSfei feng - Sun Microsystems - Beijing China { 22758a3c961bSfei feng - Sun Microsystems - Beijing China #define N(a) (sizeof (a) / sizeof ((a)[0])) 22768a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic; 22778a3c961bSfei feng - Sun Microsystems - Beijing China int i, err, qid, ridx, ntries; 22788a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t bbp1, bbp3; 22798a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 22808a3c961bSfei feng - Sun Microsystems - Beijing China 22818a3c961bSfei feng - Sun Microsystems - Beijing China ic = &sc->sc_ic; 22828a3c961bSfei feng - Sun Microsystems - Beijing China 22838a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 22848a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_WPDMA_GLO_CFG); 22858a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= 0xff0; 22868a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp | RT2860_TX_WB_DDONE); 22878a3c961bSfei feng - Sun Microsystems - Beijing China 22888a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_WPDMA_RST_IDX, 0xffffffff); 22898a3c961bSfei feng - Sun Microsystems - Beijing China 22908a3c961bSfei feng - Sun Microsystems - Beijing China /* PBF hardware reset */ 22918a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); 22928a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, 0xe00); 22938a3c961bSfei feng - Sun Microsystems - Beijing China 22948a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_FWLOADED)) { 22958a3c961bSfei feng - Sun Microsystems - Beijing China if ((err = rt2860_load_microcode(sc)) != 0) { 22968a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_init(): " 22978a3c961bSfei feng - Sun Microsystems - Beijing China "could not load 8051 microcode\n"); 22988a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 22998a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 23008a3c961bSfei feng - Sun Microsystems - Beijing China } 23018a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 23028a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags |= RT2860_FWLOADED; 23038a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 23048a3c961bSfei feng - Sun Microsystems - Beijing China } 23058a3c961bSfei feng - Sun Microsystems - Beijing China 23068a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_macaddr(sc, ic->ic_macaddr); 23078a3c961bSfei feng - Sun Microsystems - Beijing China 23088a3c961bSfei feng - Sun Microsystems - Beijing China /* init Tx power for all Tx rates (from EEPROM) */ 23098a3c961bSfei feng - Sun Microsystems - Beijing China for (ridx = 0; ridx < 5; ridx++) { 23108a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->txpow20mhz[ridx] == 0xffffffff) 23118a3c961bSfei feng - Sun Microsystems - Beijing China continue; 23128a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]); 23138a3c961bSfei feng - Sun Microsystems - Beijing China } 23148a3c961bSfei feng - Sun Microsystems - Beijing China 23158a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 23168a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_WPDMA_GLO_CFG); 23178a3c961bSfei feng - Sun Microsystems - Beijing China if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 23188a3c961bSfei feng - Sun Microsystems - Beijing China break; 23198a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 23208a3c961bSfei feng - Sun Microsystems - Beijing China } 23218a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 23228a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rt2860_init():" 23238a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for DMA engine\n"); 23248a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 23258a3c961bSfei feng - Sun Microsystems - Beijing China return (ETIMEDOUT); 23268a3c961bSfei feng - Sun Microsystems - Beijing China } 23278a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= 0xff0; 23288a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp | RT2860_TX_WB_DDONE); 23298a3c961bSfei feng - Sun Microsystems - Beijing China 23308a3c961bSfei feng - Sun Microsystems - Beijing China /* reset Rx ring and all 6 Tx rings */ 23318a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_WPDMA_RST_IDX, 0x1003f); 23328a3c961bSfei feng - Sun Microsystems - Beijing China 23338a3c961bSfei feng - Sun Microsystems - Beijing China /* PBF hardware reset */ 23348a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); 23358a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_SYS_CTRL, 0xe00); 23368a3c961bSfei feng - Sun Microsystems - Beijing China 23378a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, 23388a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_BBP_HRST | RT2860_MAC_SRST); 23398a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); 23408a3c961bSfei feng - Sun Microsystems - Beijing China 23418a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < N(rt2860_def_mac); i++) 23428a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, rt2860_def_mac[i].reg, rt2860_def_mac[i].val); 23438a3c961bSfei feng - Sun Microsystems - Beijing China 23448a3c961bSfei feng - Sun Microsystems - Beijing China /* wait while MAC is busy */ 23458a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 23468a3c961bSfei feng - Sun Microsystems - Beijing China if (!(RT2860_READ(sc, RT2860_MAC_STATUS_REG) & 23478a3c961bSfei feng - Sun Microsystems - Beijing China (RT2860_RX_STATUS_BUSY | RT2860_TX_STATUS_BUSY))) 23488a3c961bSfei feng - Sun Microsystems - Beijing China break; 23498a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 23508a3c961bSfei feng - Sun Microsystems - Beijing China } 23518a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 23528a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_FW, "rwn: rt2860_init():" 23538a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for MAC\n"); 23548a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 23558a3c961bSfei feng - Sun Microsystems - Beijing China return (ETIMEDOUT); 23568a3c961bSfei feng - Sun Microsystems - Beijing China } 23578a3c961bSfei feng - Sun Microsystems - Beijing China 23588a3c961bSfei feng - Sun Microsystems - Beijing China /* clear Host to MCU mailbox */ 23598a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_BBPAGENT, 0); 23608a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_H2M_MAILBOX, 0); 23618a3c961bSfei feng - Sun Microsystems - Beijing China 23628a3c961bSfei feng - Sun Microsystems - Beijing China if ((err = rt2860_bbp_init(sc)) != 0) { 23638a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 23648a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 23658a3c961bSfei feng - Sun Microsystems - Beijing China } 23668a3c961bSfei feng - Sun Microsystems - Beijing China 23678a3c961bSfei feng - Sun Microsystems - Beijing China /* init Tx rings (4 EDCAs + HCCA + Mgt) */ 23688a3c961bSfei feng - Sun Microsystems - Beijing China for (qid = 0; qid < 6; qid++) { 23698a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_BASE_PTR(qid), sc->txq[qid].paddr); 23708a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_MAX_CNT(qid), RT2860_TX_RING_COUNT); 23718a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_TX_CTX_IDX(qid), 0); 23728a3c961bSfei feng - Sun Microsystems - Beijing China } 23738a3c961bSfei feng - Sun Microsystems - Beijing China 23748a3c961bSfei feng - Sun Microsystems - Beijing China /* init Rx ring */ 23758a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_RX_BASE_PTR, sc->rxq.paddr); 23768a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_RX_MAX_CNT, RT2860_RX_RING_COUNT); 23778a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_RX_CALC_IDX, RT2860_RX_RING_COUNT - 1); 23788a3c961bSfei feng - Sun Microsystems - Beijing China 23798a3c961bSfei feng - Sun Microsystems - Beijing China /* setup maximum buffer sizes */ 23808a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAX_LEN_CFG, 1 << 12 | 23818a3c961bSfei feng - Sun Microsystems - Beijing China (sc->sc_dmabuf_size - sizeof (struct rt2860_rxwi) - 2)); 23828a3c961bSfei feng - Sun Microsystems - Beijing China 23838a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 23848a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_WPDMA_GLO_CFG); 23858a3c961bSfei feng - Sun Microsystems - Beijing China if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 23868a3c961bSfei feng - Sun Microsystems - Beijing China break; 23878a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 23888a3c961bSfei feng - Sun Microsystems - Beijing China } 23898a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 23908a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rt2860_init():" 23918a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for DMA engine\n"); 23928a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 23938a3c961bSfei feng - Sun Microsystems - Beijing China return (ETIMEDOUT); 23948a3c961bSfei feng - Sun Microsystems - Beijing China } 23958a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= 0xff0; 23968a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp | RT2860_TX_WB_DDONE); 23978a3c961bSfei feng - Sun Microsystems - Beijing China 23988a3c961bSfei feng - Sun Microsystems - Beijing China /* disable interrupts mitigation */ 23998a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_DELAY_INT_CFG, 0); 24008a3c961bSfei feng - Sun Microsystems - Beijing China 24018a3c961bSfei feng - Sun Microsystems - Beijing China /* write vendor-specific BBP values (from EEPROM) */ 24028a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 0; i < 8; i++) { 24038a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff) 24048a3c961bSfei feng - Sun Microsystems - Beijing China continue; 24058a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val); 24068a3c961bSfei feng - Sun Microsystems - Beijing China } 24078a3c961bSfei feng - Sun Microsystems - Beijing China 24088a3c961bSfei feng - Sun Microsystems - Beijing China /* send LEDs operating mode to microcontroller */ 24098a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED1, sc->led[0]); 24108a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1]); 24118a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2]); 24128a3c961bSfei feng - Sun Microsystems - Beijing China 24138a3c961bSfei feng - Sun Microsystems - Beijing China /* disable non-existing Rx chains */ 24148a3c961bSfei feng - Sun Microsystems - Beijing China bbp3 = rt2860_mcu_bbp_read(sc, 3); 24158a3c961bSfei feng - Sun Microsystems - Beijing China bbp3 &= ~(1 << 3 | 1 << 4); 24168a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->nrxchains == 2) 24178a3c961bSfei feng - Sun Microsystems - Beijing China bbp3 |= 1 << 3; 24188a3c961bSfei feng - Sun Microsystems - Beijing China else if (sc->nrxchains == 3) 24198a3c961bSfei feng - Sun Microsystems - Beijing China bbp3 |= 1 << 4; 24208a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 3, bbp3); 24218a3c961bSfei feng - Sun Microsystems - Beijing China 24228a3c961bSfei feng - Sun Microsystems - Beijing China /* disable non-existing Tx chains */ 24238a3c961bSfei feng - Sun Microsystems - Beijing China bbp1 = rt2860_mcu_bbp_read(sc, 1); 24248a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->ntxchains == 1) 24258a3c961bSfei feng - Sun Microsystems - Beijing China bbp1 &= ~(1 << 3 | 1 << 4); 24268a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_mcu_bbp_write(sc, 1, bbp1); 24278a3c961bSfei feng - Sun Microsystems - Beijing China 24288a3c961bSfei feng - Sun Microsystems - Beijing China /* select default channel */ 24298a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_chan(sc, ic->ic_curchan); 24308a3c961bSfei feng - Sun Microsystems - Beijing China 24318a3c961bSfei feng - Sun Microsystems - Beijing China /* XXX not clear what the following 8051 command does.. */ 24328a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BOOT, 0); 24338a3c961bSfei feng - Sun Microsystems - Beijing China 24348a3c961bSfei feng - Sun Microsystems - Beijing China /* set RTS threshold */ 24358a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_TX_RTS_CFG); 24368a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= ~0xffff00; 24378a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= ic->ic_rtsthreshold << 8; 24388a3c961bSfei feng - Sun Microsystems - Beijing China 24398a3c961bSfei feng - Sun Microsystems - Beijing China /* setup initial protection mode */ 24408a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_ic_flags = ic->ic_flags; 24418a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_updateprot(ic); 24428a3c961bSfei feng - Sun Microsystems - Beijing China 24438a3c961bSfei feng - Sun Microsystems - Beijing China /* enable Tx/Rx DMA engine */ 24448a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); 24458a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 200; ntries++) { 24468a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_WPDMA_GLO_CFG); 24478a3c961bSfei feng - Sun Microsystems - Beijing China if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 24488a3c961bSfei feng - Sun Microsystems - Beijing China break; 24498a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(1000); 24508a3c961bSfei feng - Sun Microsystems - Beijing China } 24518a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 200) { 24528a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_DMA, "rwn: rt2860_int():" 24538a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for DMA engine\n"); 24548a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 24558a3c961bSfei feng - Sun Microsystems - Beijing China return (ETIMEDOUT); 24568a3c961bSfei feng - Sun Microsystems - Beijing China } 24578a3c961bSfei feng - Sun Microsystems - Beijing China 24588a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(50); 24598a3c961bSfei feng - Sun Microsystems - Beijing China 24608a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_TX_WB_DDONE | RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | 24618a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WPDMA_BT_SIZE64 << RT2860_WPDMA_BT_SIZE_SHIFT; 24628a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); 24638a3c961bSfei feng - Sun Microsystems - Beijing China 24648a3c961bSfei feng - Sun Microsystems - Beijing China /* turn radio LED on */ 24658a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_leds(sc, RT2860_LED_RADIO); 24668a3c961bSfei feng - Sun Microsystems - Beijing China 24678a3c961bSfei feng - Sun Microsystems - Beijing China /* set Rx filter */ 24688a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR; 24698a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode != IEEE80211_M_MONITOR) { 24708a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL | 24718a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK | 24728a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV | 24738a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_DROP_CFACK | RT2860_DROP_CFEND; 24748a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_opmode == IEEE80211_M_STA) 24758a3c961bSfei feng - Sun Microsystems - Beijing China tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; 24768a3c961bSfei feng - Sun Microsystems - Beijing China } 24778a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); 24788a3c961bSfei feng - Sun Microsystems - Beijing China 24798a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, 24808a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 24818a3c961bSfei feng - Sun Microsystems - Beijing China 24828a3c961bSfei feng - Sun Microsystems - Beijing China /* clear pending interrupts */ 24838a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_INT_STATUS, 0xffffffff); 24848a3c961bSfei feng - Sun Microsystems - Beijing China /* enable interrupts */ 24858a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_INT_MASK, 0x3fffc); 24868a3c961bSfei feng - Sun Microsystems - Beijing China 24878a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_flags & RT2860_ADVANCED_PS) 24888a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel); 24898a3c961bSfei feng - Sun Microsystems - Beijing China 24908a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 24918a3c961bSfei feng - Sun Microsystems - Beijing China } 24928a3c961bSfei feng - Sun Microsystems - Beijing China 24938a3c961bSfei feng - Sun Microsystems - Beijing China static int 24948a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_quiesce(dev_info_t *dip) 24958a3c961bSfei feng - Sun Microsystems - Beijing China { 24968a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc; 24978a3c961bSfei feng - Sun Microsystems - Beijing China 24988a3c961bSfei feng - Sun Microsystems - Beijing China sc = ddi_get_soft_state(rt2860_soft_state_p, ddi_get_instance(dip)); 24998a3c961bSfei feng - Sun Microsystems - Beijing China if (sc == NULL) 25008a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_FAILURE); 25018a3c961bSfei feng - Sun Microsystems - Beijing China 25028a3c961bSfei feng - Sun Microsystems - Beijing China #ifdef DEBUG 25038a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_dbg_flags = 0; 25048a3c961bSfei feng - Sun Microsystems - Beijing China #endif 25058a3c961bSfei feng - Sun Microsystems - Beijing China 25068a3c961bSfei feng - Sun Microsystems - Beijing China /* 25078a3c961bSfei feng - Sun Microsystems - Beijing China * No more blocking is allowed while we are in quiesce(9E) entry point 25088a3c961bSfei feng - Sun Microsystems - Beijing China */ 25098a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags |= RT2860_F_QUIESCE; 25108a3c961bSfei feng - Sun Microsystems - Beijing China 25118a3c961bSfei feng - Sun Microsystems - Beijing China /* 25128a3c961bSfei feng - Sun Microsystems - Beijing China * Disable and mask all interrupts 25138a3c961bSfei feng - Sun Microsystems - Beijing China */ 25148a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 25158a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 25168a3c961bSfei feng - Sun Microsystems - Beijing China } 25178a3c961bSfei feng - Sun Microsystems - Beijing China 25188a3c961bSfei feng - Sun Microsystems - Beijing China static void 25198a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(struct rt2860_softc *sc) 25208a3c961bSfei feng - Sun Microsystems - Beijing China { 25218a3c961bSfei feng - Sun Microsystems - Beijing China int qid; 25228a3c961bSfei feng - Sun Microsystems - Beijing China uint32_t tmp; 25238a3c961bSfei feng - Sun Microsystems - Beijing China 25248a3c961bSfei feng - Sun Microsystems - Beijing China /* by pass if it's quiesced */ 25258a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_F_QUIESCE)) 25268a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 25278a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->sc_flags == RT2860_F_RUNNING) 25288a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_leds(sc, 0); /* turn all LEDs off */ 25298a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_tx_timer = 0; 25308a3c961bSfei feng - Sun Microsystems - Beijing China /* by pass if it's quiesced */ 25318a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_F_QUIESCE)) 25328a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 25338a3c961bSfei feng - Sun Microsystems - Beijing China 25348a3c961bSfei feng - Sun Microsystems - Beijing China /* clear RX WCID search table */ 25358a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512); 25368a3c961bSfei feng - Sun Microsystems - Beijing China /* clear pairwise key table */ 25378a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(sc, RT2860_PKEY(0), 0, 2048); 25388a3c961bSfei feng - Sun Microsystems - Beijing China /* clear IV/EIV table */ 25398a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(sc, RT2860_IVEIV(0), 0, 512); 25408a3c961bSfei feng - Sun Microsystems - Beijing China /* clear WCID attribute table */ 25418a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 256); 25428a3c961bSfei feng - Sun Microsystems - Beijing China /* clear shared key table */ 25438a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); 25448a3c961bSfei feng - Sun Microsystems - Beijing China /* clear shared key mode */ 25458a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); 25468a3c961bSfei feng - Sun Microsystems - Beijing China 25478a3c961bSfei feng - Sun Microsystems - Beijing China /* disable interrupts */ 25488a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_INT_MASK, 0); 25498a3c961bSfei feng - Sun Microsystems - Beijing China 25508a3c961bSfei feng - Sun Microsystems - Beijing China /* disable Rx */ 25518a3c961bSfei feng - Sun Microsystems - Beijing China tmp = RT2860_READ(sc, RT2860_MAC_SYS_CTRL); 25528a3c961bSfei feng - Sun Microsystems - Beijing China tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 25538a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, tmp); 25548a3c961bSfei feng - Sun Microsystems - Beijing China 25558a3c961bSfei feng - Sun Microsystems - Beijing China /* reset adapter */ 25568a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, 25578a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_BBP_HRST | RT2860_MAC_SRST); 25588a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); 25598a3c961bSfei feng - Sun Microsystems - Beijing China 25608a3c961bSfei feng - Sun Microsystems - Beijing China /* reset Tx and Rx rings (and reclaim TXWIs) */ 25618a3c961bSfei feng - Sun Microsystems - Beijing China for (qid = 0; qid < 6; qid++) 25628a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_reset_tx_ring(sc, &sc->txq[qid]); 25638a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_reset_rx_ring(sc, &sc->rxq); 25648a3c961bSfei feng - Sun Microsystems - Beijing China 25658a3c961bSfei feng - Sun Microsystems - Beijing China /* by pass if it's quiesced */ 25668a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_F_QUIESCE)) 25678a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 25688a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags &= ~RT2860_UPD_BEACON; 25698a3c961bSfei feng - Sun Microsystems - Beijing China /* by pass if it's quiesced */ 25708a3c961bSfei feng - Sun Microsystems - Beijing China if (!(sc->sc_flags & RT2860_F_QUIESCE)) 25718a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 25728a3c961bSfei feng - Sun Microsystems - Beijing China } 25738a3c961bSfei feng - Sun Microsystems - Beijing China 25748a3c961bSfei feng - Sun Microsystems - Beijing China static int 25758a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_start(void *arg) 25768a3c961bSfei feng - Sun Microsystems - Beijing China { 25778a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 25788a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 25798a3c961bSfei feng - Sun Microsystems - Beijing China int err; 25808a3c961bSfei feng - Sun Microsystems - Beijing China 25818a3c961bSfei feng - Sun Microsystems - Beijing China err = rt2860_init(sc); 25828a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 25838a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_m_start():" 25848a3c961bSfei feng - Sun Microsystems - Beijing China "Hardware initialization failed\n"); 25858a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 25868a3c961bSfei feng - Sun Microsystems - Beijing China } 25878a3c961bSfei feng - Sun Microsystems - Beijing China 25888a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 25898a3c961bSfei feng - Sun Microsystems - Beijing China 25908a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 25918a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags |= RT2860_F_RUNNING; 25928a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 25938a3c961bSfei feng - Sun Microsystems - Beijing China 25948a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 25958a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 25968a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 25978a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 25988a3c961bSfei feng - Sun Microsystems - Beijing China } 25998a3c961bSfei feng - Sun Microsystems - Beijing China 26008a3c961bSfei feng - Sun Microsystems - Beijing China static void 26018a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_stop(void *arg) 26028a3c961bSfei feng - Sun Microsystems - Beijing China { 26038a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 26048a3c961bSfei feng - Sun Microsystems - Beijing China 26058a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_stop(sc); 26068a3c961bSfei feng - Sun Microsystems - Beijing China 26078a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1); 26088a3c961bSfei feng - Sun Microsystems - Beijing China 26098a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 26108a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags &= ~RT2860_F_RUNNING; 26118a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 26128a3c961bSfei feng - Sun Microsystems - Beijing China } 26138a3c961bSfei feng - Sun Microsystems - Beijing China 26148a3c961bSfei feng - Sun Microsystems - Beijing China static void 26158a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 26168a3c961bSfei feng - Sun Microsystems - Beijing China { 26178a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 26188a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 26198a3c961bSfei feng - Sun Microsystems - Beijing China int err; 26208a3c961bSfei feng - Sun Microsystems - Beijing China 26218a3c961bSfei feng - Sun Microsystems - Beijing China err = ieee80211_ioctl(ic, wq, mp); 26228a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 26238a3c961bSfei feng - Sun Microsystems - Beijing China if (err == ENETRESET) { 26248a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_des_esslen) { 26258a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_IS_RUNNING(sc)) { 26268a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 26278a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_init(sc); 26288a3c961bSfei feng - Sun Microsystems - Beijing China (void) ieee80211_new_state(ic, 26298a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_S_SCAN, -1); 26308a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 26318a3c961bSfei feng - Sun Microsystems - Beijing China } 26328a3c961bSfei feng - Sun Microsystems - Beijing China } 26338a3c961bSfei feng - Sun Microsystems - Beijing China } 26348a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 26358a3c961bSfei feng - Sun Microsystems - Beijing China } 26368a3c961bSfei feng - Sun Microsystems - Beijing China 26378a3c961bSfei feng - Sun Microsystems - Beijing China /* 26388a3c961bSfei feng - Sun Microsystems - Beijing China * Call back function for get/set proporty 26398a3c961bSfei feng - Sun Microsystems - Beijing China */ 26408a3c961bSfei feng - Sun Microsystems - Beijing China static int 26418a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2642*0dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf) 26438a3c961bSfei feng - Sun Microsystems - Beijing China { 26448a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 26458a3c961bSfei feng - Sun Microsystems - Beijing China int err = 0; 26468a3c961bSfei feng - Sun Microsystems - Beijing China 26478a3c961bSfei feng - Sun Microsystems - Beijing China err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, 2648*0dc2366fSVenugopal Iyer wldp_length, wldp_buf); 26498a3c961bSfei feng - Sun Microsystems - Beijing China 26508a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 26518a3c961bSfei feng - Sun Microsystems - Beijing China } 26528a3c961bSfei feng - Sun Microsystems - Beijing China 2653*0dc2366fSVenugopal Iyer static void 2654*0dc2366fSVenugopal Iyer rt2860_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2655*0dc2366fSVenugopal Iyer mac_prop_info_handle_t prh) 2656*0dc2366fSVenugopal Iyer { 2657*0dc2366fSVenugopal Iyer struct rt2860_softc *sc = (struct rt2860_softc *)arg; 2658*0dc2366fSVenugopal Iyer 2659*0dc2366fSVenugopal Iyer ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, prh); 2660*0dc2366fSVenugopal Iyer } 2661*0dc2366fSVenugopal Iyer 26628a3c961bSfei feng - Sun Microsystems - Beijing China static int 26638a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 26648a3c961bSfei feng - Sun Microsystems - Beijing China uint_t wldp_length, const void *wldp_buf) 26658a3c961bSfei feng - Sun Microsystems - Beijing China { 26668a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 26678a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_ic; 26688a3c961bSfei feng - Sun Microsystems - Beijing China int err; 26698a3c961bSfei feng - Sun Microsystems - Beijing China 26708a3c961bSfei feng - Sun Microsystems - Beijing China err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length, 26718a3c961bSfei feng - Sun Microsystems - Beijing China wldp_buf); 26728a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 26738a3c961bSfei feng - Sun Microsystems - Beijing China if (err == ENETRESET) { 26748a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_des_esslen) { 26758a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_IS_RUNNING(sc)) { 26768a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 26778a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_init(sc); 26788a3c961bSfei feng - Sun Microsystems - Beijing China (void) ieee80211_new_state(ic, 26798a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_S_SCAN, -1); 26808a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 26818a3c961bSfei feng - Sun Microsystems - Beijing China } 26828a3c961bSfei feng - Sun Microsystems - Beijing China } 26838a3c961bSfei feng - Sun Microsystems - Beijing China err = 0; 26848a3c961bSfei feng - Sun Microsystems - Beijing China } 26858a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 26868a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 26878a3c961bSfei feng - Sun Microsystems - Beijing China } 26888a3c961bSfei feng - Sun Microsystems - Beijing China 26898a3c961bSfei feng - Sun Microsystems - Beijing China static mblk_t * 26908a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_tx(void *arg, mblk_t *mp) 26918a3c961bSfei feng - Sun Microsystems - Beijing China { 26928a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 26938a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic; 26948a3c961bSfei feng - Sun Microsystems - Beijing China mblk_t *next; 26958a3c961bSfei feng - Sun Microsystems - Beijing China 26968a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_IS_SUSPEND(sc)) { 26978a3c961bSfei feng - Sun Microsystems - Beijing China freemsgchain(mp); 26988a3c961bSfei feng - Sun Microsystems - Beijing China return (NULL); 26998a3c961bSfei feng - Sun Microsystems - Beijing China } 27008a3c961bSfei feng - Sun Microsystems - Beijing China 27018a3c961bSfei feng - Sun Microsystems - Beijing China /* 27028a3c961bSfei feng - Sun Microsystems - Beijing China * No data frames go out unless we're associated; this 27038a3c961bSfei feng - Sun Microsystems - Beijing China * should not happen as the 802.11 layer does not enable 27048a3c961bSfei feng - Sun Microsystems - Beijing China * the xmit queue until we enter the RUN state. 27058a3c961bSfei feng - Sun Microsystems - Beijing China */ 27068a3c961bSfei feng - Sun Microsystems - Beijing China if (ic->ic_state != IEEE80211_S_RUN) { 27078a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_TX, "rwn: rt2860_tx_data(): " 27088a3c961bSfei feng - Sun Microsystems - Beijing China "discard, state %u\n", ic->ic_state); 27098a3c961bSfei feng - Sun Microsystems - Beijing China freemsgchain(mp); 27108a3c961bSfei feng - Sun Microsystems - Beijing China return (NULL); 27118a3c961bSfei feng - Sun Microsystems - Beijing China } 27128a3c961bSfei feng - Sun Microsystems - Beijing China 27138a3c961bSfei feng - Sun Microsystems - Beijing China while (mp != NULL) { 27148a3c961bSfei feng - Sun Microsystems - Beijing China next = mp->b_next; 27158a3c961bSfei feng - Sun Microsystems - Beijing China mp->b_next = NULL; 27168a3c961bSfei feng - Sun Microsystems - Beijing China if (rt2860_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != 27178a3c961bSfei feng - Sun Microsystems - Beijing China DDI_SUCCESS) { 27188a3c961bSfei feng - Sun Microsystems - Beijing China mp->b_next = next; 27198a3c961bSfei feng - Sun Microsystems - Beijing China break; 27208a3c961bSfei feng - Sun Microsystems - Beijing China } 27218a3c961bSfei feng - Sun Microsystems - Beijing China mp = next; 27228a3c961bSfei feng - Sun Microsystems - Beijing China } 27238a3c961bSfei feng - Sun Microsystems - Beijing China return (mp); 27248a3c961bSfei feng - Sun Microsystems - Beijing China } 27258a3c961bSfei feng - Sun Microsystems - Beijing China 27268a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 27278a3c961bSfei feng - Sun Microsystems - Beijing China static int 27288a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_unicst(void *arg, const uint8_t *macaddr) 27298a3c961bSfei feng - Sun Microsystems - Beijing China { 27308a3c961bSfei feng - Sun Microsystems - Beijing China return (ENOTSUP); 27318a3c961bSfei feng - Sun Microsystems - Beijing China } 27328a3c961bSfei feng - Sun Microsystems - Beijing China 27338a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 27348a3c961bSfei feng - Sun Microsystems - Beijing China static int 27358a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 27368a3c961bSfei feng - Sun Microsystems - Beijing China { 27378a3c961bSfei feng - Sun Microsystems - Beijing China return (ENOTSUP); 27388a3c961bSfei feng - Sun Microsystems - Beijing China } 27398a3c961bSfei feng - Sun Microsystems - Beijing China 27408a3c961bSfei feng - Sun Microsystems - Beijing China /*ARGSUSED*/ 27418a3c961bSfei feng - Sun Microsystems - Beijing China static int 27428a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_promisc(void *arg, boolean_t on) 27438a3c961bSfei feng - Sun Microsystems - Beijing China { 27448a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 27458a3c961bSfei feng - Sun Microsystems - Beijing China } 27468a3c961bSfei feng - Sun Microsystems - Beijing China 27478a3c961bSfei feng - Sun Microsystems - Beijing China static int 27488a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_m_stat(void *arg, uint_t stat, uint64_t *val) 27498a3c961bSfei feng - Sun Microsystems - Beijing China { 27508a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc = (struct rt2860_softc *)arg; 27518a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211com_t *ic = &sc->sc_ic; 27528a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_node_t *ni = ic->ic_bss; 27538a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211_rateset *rs = &ni->in_rates; 27548a3c961bSfei feng - Sun Microsystems - Beijing China 27558a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 27568a3c961bSfei feng - Sun Microsystems - Beijing China switch (stat) { 27578a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_IFSPEED: 27588a3c961bSfei feng - Sun Microsystems - Beijing China *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 27598a3c961bSfei feng - Sun Microsystems - Beijing China (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 27608a3c961bSfei feng - Sun Microsystems - Beijing China : ic->ic_fixed_rate) / 2 * 1000000; 27618a3c961bSfei feng - Sun Microsystems - Beijing China break; 27628a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_NOXMTBUF: 27638a3c961bSfei feng - Sun Microsystems - Beijing China *val = sc->sc_tx_nobuf; 27648a3c961bSfei feng - Sun Microsystems - Beijing China break; 27658a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_NORCVBUF: 27668a3c961bSfei feng - Sun Microsystems - Beijing China *val = sc->sc_rx_nobuf; 27678a3c961bSfei feng - Sun Microsystems - Beijing China break; 27688a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_IERRORS: 27698a3c961bSfei feng - Sun Microsystems - Beijing China *val = sc->sc_rx_err; 27708a3c961bSfei feng - Sun Microsystems - Beijing China break; 27718a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_RBYTES: 27728a3c961bSfei feng - Sun Microsystems - Beijing China *val = ic->ic_stats.is_rx_bytes; 27738a3c961bSfei feng - Sun Microsystems - Beijing China break; 27748a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_IPACKETS: 27758a3c961bSfei feng - Sun Microsystems - Beijing China *val = ic->ic_stats.is_rx_frags; 27768a3c961bSfei feng - Sun Microsystems - Beijing China break; 27778a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_OBYTES: 27788a3c961bSfei feng - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_bytes; 27798a3c961bSfei feng - Sun Microsystems - Beijing China break; 27808a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_OPACKETS: 27818a3c961bSfei feng - Sun Microsystems - Beijing China *val = ic->ic_stats.is_tx_frags; 27828a3c961bSfei feng - Sun Microsystems - Beijing China break; 27838a3c961bSfei feng - Sun Microsystems - Beijing China case MAC_STAT_OERRORS: 27848a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_TX_FAILED: 27858a3c961bSfei feng - Sun Microsystems - Beijing China *val = sc->sc_tx_err; 27868a3c961bSfei feng - Sun Microsystems - Beijing China break; 27878a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_TX_RETRANS: 27888a3c961bSfei feng - Sun Microsystems - Beijing China *val = sc->sc_tx_retries; 27898a3c961bSfei feng - Sun Microsystems - Beijing China break; 27908a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_FCS_ERRORS: 27918a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_WEP_ERRORS: 27928a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_TX_FRAGS: 27938a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_MCAST_TX: 27948a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_RTS_SUCCESS: 27958a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_RTS_FAILURE: 27968a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_ACK_FAILURE: 27978a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_RX_FRAGS: 27988a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_MCAST_RX: 27998a3c961bSfei feng - Sun Microsystems - Beijing China case WIFI_STAT_RX_DUPS: 28008a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 28018a3c961bSfei feng - Sun Microsystems - Beijing China return (ieee80211_stat(ic, stat, val)); 28028a3c961bSfei feng - Sun Microsystems - Beijing China default: 28038a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 28048a3c961bSfei feng - Sun Microsystems - Beijing China return (ENOTSUP); 28058a3c961bSfei feng - Sun Microsystems - Beijing China } 28068a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 28078a3c961bSfei feng - Sun Microsystems - Beijing China 28088a3c961bSfei feng - Sun Microsystems - Beijing China return (0); 28098a3c961bSfei feng - Sun Microsystems - Beijing China } 28108a3c961bSfei feng - Sun Microsystems - Beijing China 28118a3c961bSfei feng - Sun Microsystems - Beijing China static int 28128a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 28138a3c961bSfei feng - Sun Microsystems - Beijing China { 28148a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc; 28158a3c961bSfei feng - Sun Microsystems - Beijing China struct ieee80211com *ic; 28168a3c961bSfei feng - Sun Microsystems - Beijing China int i, err, qid, ntries, instance; 28178a3c961bSfei feng - Sun Microsystems - Beijing China uint8_t cachelsz; 28188a3c961bSfei feng - Sun Microsystems - Beijing China uint16_t command, vendor_id, device_id; 28198a3c961bSfei feng - Sun Microsystems - Beijing China char strbuf[32]; 28208a3c961bSfei feng - Sun Microsystems - Beijing China wifi_data_t wd = { 0 }; 28218a3c961bSfei feng - Sun Microsystems - Beijing China mac_register_t *macp; 28228a3c961bSfei feng - Sun Microsystems - Beijing China 28238a3c961bSfei feng - Sun Microsystems - Beijing China switch (cmd) { 28248a3c961bSfei feng - Sun Microsystems - Beijing China case DDI_ATTACH: 28258a3c961bSfei feng - Sun Microsystems - Beijing China break; 28268a3c961bSfei feng - Sun Microsystems - Beijing China case DDI_RESUME: 28278a3c961bSfei feng - Sun Microsystems - Beijing China sc = ddi_get_soft_state(rt2860_soft_state_p, 28288a3c961bSfei feng - Sun Microsystems - Beijing China ddi_get_instance(devinfo)); 28298a3c961bSfei feng - Sun Microsystems - Beijing China ASSERT(sc != NULL); 28308a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 28318a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags &= ~RT2860_F_SUSPEND; 28328a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 28338a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_IS_RUNNING(sc)) 28348a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_init(sc); 28358a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RESUME, "rwn: rt2860_attach(): " 28368a3c961bSfei feng - Sun Microsystems - Beijing China "resume now\n"); 28378a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 28388a3c961bSfei feng - Sun Microsystems - Beijing China default: 28398a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_FAILURE); 28408a3c961bSfei feng - Sun Microsystems - Beijing China } 28418a3c961bSfei feng - Sun Microsystems - Beijing China 28428a3c961bSfei feng - Sun Microsystems - Beijing China instance = ddi_get_instance(devinfo); 28438a3c961bSfei feng - Sun Microsystems - Beijing China 28448a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_soft_state_zalloc(rt2860_soft_state_p, instance); 28458a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 28468a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 28478a3c961bSfei feng - Sun Microsystems - Beijing China "unable to alloc soft_state_p\n"); 28488a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 28498a3c961bSfei feng - Sun Microsystems - Beijing China } 28508a3c961bSfei feng - Sun Microsystems - Beijing China 28518a3c961bSfei feng - Sun Microsystems - Beijing China sc = ddi_get_soft_state(rt2860_soft_state_p, instance); 28528a3c961bSfei feng - Sun Microsystems - Beijing China ic = (ieee80211com_t *)&sc->sc_ic; 28538a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_dev = devinfo; 28548a3c961bSfei feng - Sun Microsystems - Beijing China 28558a3c961bSfei feng - Sun Microsystems - Beijing China /* pci configuration */ 28568a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_regs_map_setup(devinfo, 0, &sc->sc_cfg_base, 0, 0, 28578a3c961bSfei feng - Sun Microsystems - Beijing China &rwn_csr_accattr, &sc->sc_cfg_handle); 28588a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 28598a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 28608a3c961bSfei feng - Sun Microsystems - Beijing China "ddi_regs_map_setup() failed"); 28618a3c961bSfei feng - Sun Microsystems - Beijing China goto fail1; 28628a3c961bSfei feng - Sun Microsystems - Beijing China } 28638a3c961bSfei feng - Sun Microsystems - Beijing China 28648a3c961bSfei feng - Sun Microsystems - Beijing China cachelsz = ddi_get8(sc->sc_cfg_handle, 28658a3c961bSfei feng - Sun Microsystems - Beijing China (uint8_t *)(sc->sc_cfg_base + PCI_CONF_CACHE_LINESZ)); 28668a3c961bSfei feng - Sun Microsystems - Beijing China if (cachelsz == 0) 28678a3c961bSfei feng - Sun Microsystems - Beijing China cachelsz = 0x10; 28688a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_cachelsz = cachelsz << 2; 28698a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_dmabuf_size = roundup(IEEE80211_MAX_LEN, sc->sc_cachelsz); 28708a3c961bSfei feng - Sun Microsystems - Beijing China 28718a3c961bSfei feng - Sun Microsystems - Beijing China vendor_id = ddi_get16(sc->sc_cfg_handle, 28728a3c961bSfei feng - Sun Microsystems - Beijing China (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_VENID)); 28738a3c961bSfei feng - Sun Microsystems - Beijing China device_id = ddi_get16(sc->sc_cfg_handle, 28748a3c961bSfei feng - Sun Microsystems - Beijing China (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_DEVID)); 28758a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 28768a3c961bSfei feng - Sun Microsystems - Beijing China "vendor 0x%x, device id 0x%x, cache size %d\n", 28778a3c961bSfei feng - Sun Microsystems - Beijing China vendor_id, device_id, cachelsz); 28788a3c961bSfei feng - Sun Microsystems - Beijing China 28798a3c961bSfei feng - Sun Microsystems - Beijing China /* 28808a3c961bSfei feng - Sun Microsystems - Beijing China * Enable response to memory space accesses, 28818a3c961bSfei feng - Sun Microsystems - Beijing China * and enabe bus master. 28828a3c961bSfei feng - Sun Microsystems - Beijing China */ 28838a3c961bSfei feng - Sun Microsystems - Beijing China command = PCI_COMM_MAE | PCI_COMM_ME; 28848a3c961bSfei feng - Sun Microsystems - Beijing China ddi_put16(sc->sc_cfg_handle, 28858a3c961bSfei feng - Sun Microsystems - Beijing China (uint16_t *)((uintptr_t)(sc->sc_cfg_base) + PCI_CONF_COMM), 28868a3c961bSfei feng - Sun Microsystems - Beijing China command); 28878a3c961bSfei feng - Sun Microsystems - Beijing China ddi_put8(sc->sc_cfg_handle, 28888a3c961bSfei feng - Sun Microsystems - Beijing China (uint8_t *)(sc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8); 28898a3c961bSfei feng - Sun Microsystems - Beijing China ddi_put8(sc->sc_cfg_handle, 28908a3c961bSfei feng - Sun Microsystems - Beijing China (uint8_t *)(sc->sc_cfg_base + PCI_CONF_ILINE), 0x10); 28918a3c961bSfei feng - Sun Microsystems - Beijing China 28928a3c961bSfei feng - Sun Microsystems - Beijing China /* pci i/o space */ 28938a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_regs_map_setup(devinfo, 1, 28948a3c961bSfei feng - Sun Microsystems - Beijing China &sc->sc_io_base, 0, 0, &rwn_csr_accattr, &sc->sc_io_handle); 28958a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 28968a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 28978a3c961bSfei feng - Sun Microsystems - Beijing China "ddi_regs_map_setup() failed"); 28988a3c961bSfei feng - Sun Microsystems - Beijing China goto fail2; 28998a3c961bSfei feng - Sun Microsystems - Beijing China } 29008a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 29018a3c961bSfei feng - Sun Microsystems - Beijing China "PCI configuration is done successfully\n"); 29028a3c961bSfei feng - Sun Microsystems - Beijing China 2903860387ebSfei feng - Sun Microsystems - Beijing China sc->amrr.amrr_min_success_threshold = 1; 2904860387ebSfei feng - Sun Microsystems - Beijing China sc->amrr.amrr_max_success_threshold = 15; 2905860387ebSfei feng - Sun Microsystems - Beijing China 29068a3c961bSfei feng - Sun Microsystems - Beijing China /* wait for NIC to initialize */ 29078a3c961bSfei feng - Sun Microsystems - Beijing China for (ntries = 0; ntries < 100; ntries++) { 29088a3c961bSfei feng - Sun Microsystems - Beijing China sc->mac_rev = RT2860_READ(sc, RT2860_ASIC_VER_ID); 29098a3c961bSfei feng - Sun Microsystems - Beijing China if (sc->mac_rev != 0 && sc->mac_rev != 0xffffffff) 29108a3c961bSfei feng - Sun Microsystems - Beijing China break; 29118a3c961bSfei feng - Sun Microsystems - Beijing China DELAY(10); 29128a3c961bSfei feng - Sun Microsystems - Beijing China } 29138a3c961bSfei feng - Sun Microsystems - Beijing China if (ntries == 100) { 29148a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 29158a3c961bSfei feng - Sun Microsystems - Beijing China "timeout waiting for NIC initialize\n"); 29168a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_FAILURE); 29178a3c961bSfei feng - Sun Microsystems - Beijing China } 29188a3c961bSfei feng - Sun Microsystems - Beijing China 29198a3c961bSfei feng - Sun Microsystems - Beijing China if ((sc->mac_rev >> 16) != 0x2860 && 29208a3c961bSfei feng - Sun Microsystems - Beijing China (device_id == PRODUCT_RALINK_RT2890 || 29218a3c961bSfei feng - Sun Microsystems - Beijing China device_id == PRODUCT_RALINK_RT2790 || 29228a3c961bSfei feng - Sun Microsystems - Beijing China device_id == PRODUCT_AWT_RT2890)) 29238a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags |= RT2860_ADVANCED_PS; 29248a3c961bSfei feng - Sun Microsystems - Beijing China 29258a3c961bSfei feng - Sun Microsystems - Beijing China /* retrieve RF rev. no and various other things from EEPROM */ 29268a3c961bSfei feng - Sun Microsystems - Beijing China (void) rt2860_read_eeprom(sc); 29278a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 29288a3c961bSfei feng - Sun Microsystems - Beijing China "MAC/BBP RT%X (rev 0x%04X), RF %s (%dT%dR)\n", 29298a3c961bSfei feng - Sun Microsystems - Beijing China sc->mac_rev >> 16, sc->mac_rev & 0xffff, 29308a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_get_rf(sc->rf_rev), sc->ntxchains, sc->nrxchains); 29318a3c961bSfei feng - Sun Microsystems - Beijing China 29328a3c961bSfei feng - Sun Microsystems - Beijing China /* 29338a3c961bSfei feng - Sun Microsystems - Beijing China * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. 29348a3c961bSfei feng - Sun Microsystems - Beijing China */ 29358a3c961bSfei feng - Sun Microsystems - Beijing China for (qid = 0; qid < 6; qid++) { 29368a3c961bSfei feng - Sun Microsystems - Beijing China if ((err = rt2860_alloc_tx_ring(sc, &sc->txq[qid])) != 0) { 29378a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 29388a3c961bSfei feng - Sun Microsystems - Beijing China "could not allocate Tx ring %d\n", qid); 29398a3c961bSfei feng - Sun Microsystems - Beijing China goto fail3; 29408a3c961bSfei feng - Sun Microsystems - Beijing China } 29418a3c961bSfei feng - Sun Microsystems - Beijing China } 29428a3c961bSfei feng - Sun Microsystems - Beijing China 29438a3c961bSfei feng - Sun Microsystems - Beijing China if ((err = rt2860_alloc_rx_ring(sc, &sc->rxq)) != 0) { 29448a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 29458a3c961bSfei feng - Sun Microsystems - Beijing China "could not allocte Rx ring\n"); 29468a3c961bSfei feng - Sun Microsystems - Beijing China goto fail4; 29478a3c961bSfei feng - Sun Microsystems - Beijing China } 29488a3c961bSfei feng - Sun Microsystems - Beijing China 29498a3c961bSfei feng - Sun Microsystems - Beijing China if ((err = rt2860_alloc_tx_pool(sc)) != 0) { 29508a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 29518a3c961bSfei feng - Sun Microsystems - Beijing China "could not allocte Tx pool\n"); 29528a3c961bSfei feng - Sun Microsystems - Beijing China goto fail5; 29538a3c961bSfei feng - Sun Microsystems - Beijing China } 29548a3c961bSfei feng - Sun Microsystems - Beijing China 29558a3c961bSfei feng - Sun Microsystems - Beijing China mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 29568a3c961bSfei feng - Sun Microsystems - Beijing China mutex_init(&sc->sc_txlock, NULL, MUTEX_DRIVER, NULL); 29578a3c961bSfei feng - Sun Microsystems - Beijing China mutex_init(&sc->sc_rxlock, NULL, MUTEX_DRIVER, NULL); 29588a3c961bSfei feng - Sun Microsystems - Beijing China 29598a3c961bSfei feng - Sun Microsystems - Beijing China /* mgmt ring is broken on RT2860C, use EDCA AC VO ring instead */ 29608a3c961bSfei feng - Sun Microsystems - Beijing China sc->mgtqid = (sc->mac_rev == 0x28600100) ? EDCA_AC_VO : 5; 29618a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach():" 29628a3c961bSfei feng - Sun Microsystems - Beijing China "mgtqid = %x\n", sc->mgtqid); 29638a3c961bSfei feng - Sun Microsystems - Beijing China 29648a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 29658a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 29668a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_state = IEEE80211_S_INIT; 29678a3c961bSfei feng - Sun Microsystems - Beijing China 29688a3c961bSfei feng - Sun Microsystems - Beijing China /* set device capabilities */ 29698a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_caps = 29708a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_C_TXPMGT | /* tx power management */ 29718a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 29728a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_C_SHSLOT; /* short slot time supported */ 29738a3c961bSfei feng - Sun Microsystems - Beijing China 29748a3c961bSfei feng - Sun Microsystems - Beijing China /* WPA/WPA2 support */ 29758a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */ 29768a3c961bSfei feng - Sun Microsystems - Beijing China 29778a3c961bSfei feng - Sun Microsystems - Beijing China /* set supported .11b and .11g rates */ 2978860387ebSfei feng - Sun Microsystems - Beijing China ic->ic_sup_rates[IEEE80211_MODE_11B] = rt2860_rateset_11b; 2979860387ebSfei feng - Sun Microsystems - Beijing China ic->ic_sup_rates[IEEE80211_MODE_11G] = rt2860_rateset_11g; 29808a3c961bSfei feng - Sun Microsystems - Beijing China 29818a3c961bSfei feng - Sun Microsystems - Beijing China /* set supported .11b and .11g channels (1 through 14) */ 29828a3c961bSfei feng - Sun Microsystems - Beijing China for (i = 1; i <= 14; i++) { 29838a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_sup_channels[i].ich_freq = 29848a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 29858a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_sup_channels[i].ich_flags = 29868a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 29878a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 29888a3c961bSfei feng - Sun Microsystems - Beijing China } 29898a3c961bSfei feng - Sun Microsystems - Beijing China 2990860387ebSfei feng - Sun Microsystems - Beijing China ic->ic_maxrssi = 63; 29918a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_xmit = rt2860_send; 29928a3c961bSfei feng - Sun Microsystems - Beijing China 29938a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_attach(ic); 29948a3c961bSfei feng - Sun Microsystems - Beijing China 29958a3c961bSfei feng - Sun Microsystems - Beijing China /* register WPA door */ 29968a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_register_door(ic, ddi_driver_name(devinfo), 29978a3c961bSfei feng - Sun Microsystems - Beijing China ddi_get_instance(devinfo)); 29988a3c961bSfei feng - Sun Microsystems - Beijing China 29998a3c961bSfei feng - Sun Microsystems - Beijing China /* override state transition machine */ 30008a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_newstate = ic->ic_newstate; 30018a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_newstate = rt2860_newstate; 30028a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_media_init(ic); 30038a3c961bSfei feng - Sun Microsystems - Beijing China ic->ic_def_txkey = 0; 30048a3c961bSfei feng - Sun Microsystems - Beijing China 30058a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_add_softintr(devinfo, DDI_SOFTINT_LOW, 30068a3c961bSfei feng - Sun Microsystems - Beijing China &sc->sc_softintr_hdl, NULL, 0, rt2860_softintr, (caddr_t)sc); 30078a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 30088a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 30098a3c961bSfei feng - Sun Microsystems - Beijing China "ddi_add_softintr() failed"); 30108a3c961bSfei feng - Sun Microsystems - Beijing China goto fail8; 30118a3c961bSfei feng - Sun Microsystems - Beijing China } 30128a3c961bSfei feng - Sun Microsystems - Beijing China 30138a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_get_iblock_cookie(devinfo, 0, &sc->sc_iblock); 30148a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 30158a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 30168a3c961bSfei feng - Sun Microsystems - Beijing China "Can not get iblock cookie for INT\n"); 30178a3c961bSfei feng - Sun Microsystems - Beijing China goto fail7; 30188a3c961bSfei feng - Sun Microsystems - Beijing China } 30198a3c961bSfei feng - Sun Microsystems - Beijing China 30208a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_add_intr(devinfo, 0, NULL, NULL, rt2860_intr, (caddr_t)sc); 30218a3c961bSfei feng - Sun Microsystems - Beijing China if (err != DDI_SUCCESS) { 30228a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 30238a3c961bSfei feng - Sun Microsystems - Beijing China "unable to add device interrupt handler\n"); 30248a3c961bSfei feng - Sun Microsystems - Beijing China goto fail7; 30258a3c961bSfei feng - Sun Microsystems - Beijing China } 30268a3c961bSfei feng - Sun Microsystems - Beijing China 30278a3c961bSfei feng - Sun Microsystems - Beijing China /* 30288a3c961bSfei feng - Sun Microsystems - Beijing China * Provide initial settings for the WiFi plugin; whenever this 30298a3c961bSfei feng - Sun Microsystems - Beijing China * information changes, we need to call mac_plugindata_update() 30308a3c961bSfei feng - Sun Microsystems - Beijing China */ 30318a3c961bSfei feng - Sun Microsystems - Beijing China wd.wd_opmode = ic->ic_opmode; 30328a3c961bSfei feng - Sun Microsystems - Beijing China wd.wd_secalloc = WIFI_SEC_NONE; 30338a3c961bSfei feng - Sun Microsystems - Beijing China IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 30348a3c961bSfei feng - Sun Microsystems - Beijing China 30358a3c961bSfei feng - Sun Microsystems - Beijing China if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 30368a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 30378a3c961bSfei feng - Sun Microsystems - Beijing China "MAC version mismatch\n"); 30388a3c961bSfei feng - Sun Microsystems - Beijing China goto fail9; 30398a3c961bSfei feng - Sun Microsystems - Beijing China } 30408a3c961bSfei feng - Sun Microsystems - Beijing China 30418a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 30428a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_driver = sc; 30438a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_dip = devinfo; 30448a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_src_addr = ic->ic_macaddr; 30458a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_callbacks = &rt2860_m_callbacks; 30468a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_min_sdu = 0; 30478a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_max_sdu = IEEE80211_MTU; 30488a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_pdata = &wd; 30498a3c961bSfei feng - Sun Microsystems - Beijing China macp->m_pdata_size = sizeof (wd); 30508a3c961bSfei feng - Sun Microsystems - Beijing China 30518a3c961bSfei feng - Sun Microsystems - Beijing China err = mac_register(macp, &ic->ic_mach); 30528a3c961bSfei feng - Sun Microsystems - Beijing China mac_free(macp); 30538a3c961bSfei feng - Sun Microsystems - Beijing China if (err != 0) { 30548a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach(): " 30558a3c961bSfei feng - Sun Microsystems - Beijing China "mac_register err %x\n", err); 30568a3c961bSfei feng - Sun Microsystems - Beijing China goto fail9; 30578a3c961bSfei feng - Sun Microsystems - Beijing China } 30588a3c961bSfei feng - Sun Microsystems - Beijing China 30598a3c961bSfei feng - Sun Microsystems - Beijing China /* 30608a3c961bSfei feng - Sun Microsystems - Beijing China * Create minor node of type DDI_NT_NET_WIFI 30618a3c961bSfei feng - Sun Microsystems - Beijing China */ 30628a3c961bSfei feng - Sun Microsystems - Beijing China (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 30638a3c961bSfei feng - Sun Microsystems - Beijing China "rwn", instance); 30648a3c961bSfei feng - Sun Microsystems - Beijing China err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 30658a3c961bSfei feng - Sun Microsystems - Beijing China instance + 1, DDI_NT_NET_WIFI, 0); 30668a3c961bSfei feng - Sun Microsystems - Beijing China 30678a3c961bSfei feng - Sun Microsystems - Beijing China /* 30688a3c961bSfei feng - Sun Microsystems - Beijing China * Notify link is down now 30698a3c961bSfei feng - Sun Microsystems - Beijing China */ 30708a3c961bSfei feng - Sun Microsystems - Beijing China mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 30718a3c961bSfei feng - Sun Microsystems - Beijing China 30728a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags &= ~RT2860_F_RUNNING; 30738a3c961bSfei feng - Sun Microsystems - Beijing China 30748a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_MSG, "rwn: rt2860_attach() successfully.\n"); 30758a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 30768a3c961bSfei feng - Sun Microsystems - Beijing China fail9: 30778a3c961bSfei feng - Sun Microsystems - Beijing China ddi_remove_softintr(sc->sc_softintr_hdl); 30788a3c961bSfei feng - Sun Microsystems - Beijing China fail8: 30798a3c961bSfei feng - Sun Microsystems - Beijing China ddi_remove_intr(devinfo, 0, sc->sc_iblock); 30808a3c961bSfei feng - Sun Microsystems - Beijing China fail7: 30818a3c961bSfei feng - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_genlock); 30828a3c961bSfei feng - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_txlock); 30838a3c961bSfei feng - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_rxlock); 30848a3c961bSfei feng - Sun Microsystems - Beijing China fail6: 30858a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_tx_pool(sc); 30868a3c961bSfei feng - Sun Microsystems - Beijing China fail5: 30878a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_rx_ring(sc, &sc->rxq); 30888a3c961bSfei feng - Sun Microsystems - Beijing China fail4: 30898a3c961bSfei feng - Sun Microsystems - Beijing China while (--qid >= 0) 30908a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_tx_ring(sc, &sc->txq[qid]); 30918a3c961bSfei feng - Sun Microsystems - Beijing China fail3: 30928a3c961bSfei feng - Sun Microsystems - Beijing China ddi_regs_map_free(&sc->sc_io_handle); 30938a3c961bSfei feng - Sun Microsystems - Beijing China fail2: 30948a3c961bSfei feng - Sun Microsystems - Beijing China ddi_regs_map_free(&sc->sc_cfg_handle); 30958a3c961bSfei feng - Sun Microsystems - Beijing China fail1: 30968a3c961bSfei feng - Sun Microsystems - Beijing China return (err); 30978a3c961bSfei feng - Sun Microsystems - Beijing China } 30988a3c961bSfei feng - Sun Microsystems - Beijing China 30998a3c961bSfei feng - Sun Microsystems - Beijing China static int 31008a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 31018a3c961bSfei feng - Sun Microsystems - Beijing China { 31028a3c961bSfei feng - Sun Microsystems - Beijing China struct rt2860_softc *sc; 31038a3c961bSfei feng - Sun Microsystems - Beijing China int qid; 31048a3c961bSfei feng - Sun Microsystems - Beijing China 31058a3c961bSfei feng - Sun Microsystems - Beijing China sc = ddi_get_soft_state(rt2860_soft_state_p, ddi_get_instance(devinfo)); 31068a3c961bSfei feng - Sun Microsystems - Beijing China 31078a3c961bSfei feng - Sun Microsystems - Beijing China switch (cmd) { 31088a3c961bSfei feng - Sun Microsystems - Beijing China case DDI_DETACH: 31098a3c961bSfei feng - Sun Microsystems - Beijing China break; 31108a3c961bSfei feng - Sun Microsystems - Beijing China case DDI_SUSPEND: 31118a3c961bSfei feng - Sun Microsystems - Beijing China if (RT2860_IS_RUNNING(sc)) 31128a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 31138a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GLOCK(sc); 31148a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags &= ~RT2860_FWLOADED; 31158a3c961bSfei feng - Sun Microsystems - Beijing China sc->sc_flags |= RT2860_F_SUSPEND; 31168a3c961bSfei feng - Sun Microsystems - Beijing China RT2860_GUNLOCK(sc); 31178a3c961bSfei feng - Sun Microsystems - Beijing China RWN_DEBUG(RT2860_DBG_RESUME, "rwn: rt2860_detach(): " 31188a3c961bSfei feng - Sun Microsystems - Beijing China "suspend now\n"); 31198a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 31208a3c961bSfei feng - Sun Microsystems - Beijing China default: 31218a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_FAILURE); 31228a3c961bSfei feng - Sun Microsystems - Beijing China } 31238a3c961bSfei feng - Sun Microsystems - Beijing China 31248a3c961bSfei feng - Sun Microsystems - Beijing China if (mac_disable(sc->sc_ic.ic_mach) != 0) 31258a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_FAILURE); 31268a3c961bSfei feng - Sun Microsystems - Beijing China 31278a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_stop(sc); 31288a3c961bSfei feng - Sun Microsystems - Beijing China 31298a3c961bSfei feng - Sun Microsystems - Beijing China /* 31308a3c961bSfei feng - Sun Microsystems - Beijing China * Unregister from the MAC layer subsystem 31318a3c961bSfei feng - Sun Microsystems - Beijing China */ 31328a3c961bSfei feng - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_ic.ic_mach); 31338a3c961bSfei feng - Sun Microsystems - Beijing China 31348a3c961bSfei feng - Sun Microsystems - Beijing China ddi_remove_intr(devinfo, 0, sc->sc_iblock); 31358a3c961bSfei feng - Sun Microsystems - Beijing China ddi_remove_softintr(sc->sc_softintr_hdl); 31368a3c961bSfei feng - Sun Microsystems - Beijing China 31378a3c961bSfei feng - Sun Microsystems - Beijing China /* 31388a3c961bSfei feng - Sun Microsystems - Beijing China * detach ieee80211 layer 31398a3c961bSfei feng - Sun Microsystems - Beijing China */ 31408a3c961bSfei feng - Sun Microsystems - Beijing China ieee80211_detach(&sc->sc_ic); 31418a3c961bSfei feng - Sun Microsystems - Beijing China 31428a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_tx_pool(sc); 31438a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_rx_ring(sc, &sc->rxq); 31448a3c961bSfei feng - Sun Microsystems - Beijing China for (qid = 0; qid < 6; qid++) 31458a3c961bSfei feng - Sun Microsystems - Beijing China rt2860_free_tx_ring(sc, &sc->txq[qid]); 31468a3c961bSfei feng - Sun Microsystems - Beijing China 31478a3c961bSfei feng - Sun Microsystems - Beijing China ddi_regs_map_free(&sc->sc_io_handle); 31488a3c961bSfei feng - Sun Microsystems - Beijing China 31498a3c961bSfei feng - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_genlock); 31508a3c961bSfei feng - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_txlock); 31518a3c961bSfei feng - Sun Microsystems - Beijing China mutex_destroy(&sc->sc_rxlock); 31528a3c961bSfei feng - Sun Microsystems - Beijing China 31538a3c961bSfei feng - Sun Microsystems - Beijing China ddi_remove_minor_node(devinfo, NULL); 31548a3c961bSfei feng - Sun Microsystems - Beijing China ddi_soft_state_free(rt2860_soft_state_p, ddi_get_instance(devinfo)); 31558a3c961bSfei feng - Sun Microsystems - Beijing China 31568a3c961bSfei feng - Sun Microsystems - Beijing China return (DDI_SUCCESS); 31578a3c961bSfei feng - Sun Microsystems - Beijing China } 31588a3c961bSfei feng - Sun Microsystems - Beijing China 31598a3c961bSfei feng - Sun Microsystems - Beijing China int 31608a3c961bSfei feng - Sun Microsystems - Beijing China _info(struct modinfo *modinfop) 31618a3c961bSfei feng - Sun Microsystems - Beijing China { 31628a3c961bSfei feng - Sun Microsystems - Beijing China return (mod_info(&modlinkage, modinfop)); 31638a3c961bSfei feng - Sun Microsystems - Beijing China } 31648a3c961bSfei feng - Sun Microsystems - Beijing China 31658a3c961bSfei feng - Sun Microsystems - Beijing China int 31668a3c961bSfei feng - Sun Microsystems - Beijing China _init(void) 31678a3c961bSfei feng - Sun Microsystems - Beijing China { 31688a3c961bSfei feng - Sun Microsystems - Beijing China int status; 31698a3c961bSfei feng - Sun Microsystems - Beijing China 31708a3c961bSfei feng - Sun Microsystems - Beijing China status = ddi_soft_state_init(&rt2860_soft_state_p, 31718a3c961bSfei feng - Sun Microsystems - Beijing China sizeof (struct rt2860_softc), 1); 31728a3c961bSfei feng - Sun Microsystems - Beijing China if (status != 0) 31738a3c961bSfei feng - Sun Microsystems - Beijing China return (status); 31748a3c961bSfei feng - Sun Microsystems - Beijing China 31758a3c961bSfei feng - Sun Microsystems - Beijing China mac_init_ops(&rwn_dev_ops, "rwn"); 31768a3c961bSfei feng - Sun Microsystems - Beijing China status = mod_install(&modlinkage); 31778a3c961bSfei feng - Sun Microsystems - Beijing China if (status != 0) { 31788a3c961bSfei feng - Sun Microsystems - Beijing China mac_fini_ops(&rwn_dev_ops); 31798a3c961bSfei feng - Sun Microsystems - Beijing China ddi_soft_state_fini(&rt2860_soft_state_p); 31808a3c961bSfei feng - Sun Microsystems - Beijing China } 31818a3c961bSfei feng - Sun Microsystems - Beijing China return (status); 31828a3c961bSfei feng - Sun Microsystems - Beijing China } 31838a3c961bSfei feng - Sun Microsystems - Beijing China 31848a3c961bSfei feng - Sun Microsystems - Beijing China int 31858a3c961bSfei feng - Sun Microsystems - Beijing China _fini(void) 31868a3c961bSfei feng - Sun Microsystems - Beijing China { 31878a3c961bSfei feng - Sun Microsystems - Beijing China int status; 31888a3c961bSfei feng - Sun Microsystems - Beijing China 31898a3c961bSfei feng - Sun Microsystems - Beijing China status = mod_remove(&modlinkage); 31908a3c961bSfei feng - Sun Microsystems - Beijing China if (status == 0) { 31918a3c961bSfei feng - Sun Microsystems - Beijing China mac_fini_ops(&rwn_dev_ops); 31928a3c961bSfei feng - Sun Microsystems - Beijing China ddi_soft_state_fini(&rt2860_soft_state_p); 31938a3c961bSfei feng - Sun Microsystems - Beijing China } 31948a3c961bSfei feng - Sun Microsystems - Beijing China return (status); 31958a3c961bSfei feng - Sun Microsystems - Beijing China } 3196