140db2e2bSzf162725 /* 2*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 340db2e2bSzf162725 * Use is subject to license terms. 440db2e2bSzf162725 */ 540db2e2bSzf162725 640db2e2bSzf162725 /* 740db2e2bSzf162725 * Copyright (c) 2005, 2006 840db2e2bSzf162725 * Damien Bergamini <damien.bergamini@free.fr> 940db2e2bSzf162725 * 1040db2e2bSzf162725 * Permission to use, copy, modify, and distribute this software for any 1140db2e2bSzf162725 * purpose with or without fee is hereby granted, provided that the above 1240db2e2bSzf162725 * copyright notice and this permission notice appear in all copies. 1340db2e2bSzf162725 * 1440db2e2bSzf162725 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1540db2e2bSzf162725 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1640db2e2bSzf162725 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1740db2e2bSzf162725 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1840db2e2bSzf162725 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1940db2e2bSzf162725 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 2040db2e2bSzf162725 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2140db2e2bSzf162725 */ 2240db2e2bSzf162725 2340db2e2bSzf162725 /* 2440db2e2bSzf162725 * Ralink Technology RT2500USB chipset driver 2540db2e2bSzf162725 * http://www.ralinktech.com/ 2640db2e2bSzf162725 */ 2740db2e2bSzf162725 #include <sys/types.h> 2840db2e2bSzf162725 #include <sys/cmn_err.h> 2940db2e2bSzf162725 #include <sys/strsubr.h> 3040db2e2bSzf162725 #include <sys/modctl.h> 3140db2e2bSzf162725 #include <sys/devops.h> 32*0dc2366fSVenugopal Iyer #include <sys/byteorder.h> 33da14cebeSEric Cheng #include <sys/mac_provider.h> 3440db2e2bSzf162725 #include <sys/mac_wifi.h> 3540db2e2bSzf162725 #include <sys/net80211.h> 3640db2e2bSzf162725 3740db2e2bSzf162725 #define USBDRV_MAJOR_VER 2 3840db2e2bSzf162725 #define USBDRV_MINOR_VER 0 3940db2e2bSzf162725 #include <sys/usb/usba.h> 401a932f2eSQuaker Fang #include <sys/usb/usba/usba_types.h> 4140db2e2bSzf162725 4240db2e2bSzf162725 #include "ural_reg.h" 4340db2e2bSzf162725 #include "ural_var.h" 4440db2e2bSzf162725 4540db2e2bSzf162725 static void *ural_soft_state_p = NULL; 4640db2e2bSzf162725 4740db2e2bSzf162725 #define RAL_TXBUF_SIZE (IEEE80211_MAX_LEN) 4840db2e2bSzf162725 #define RAL_RXBUF_SIZE (IEEE80211_MAX_LEN) 4940db2e2bSzf162725 5040db2e2bSzf162725 /* quickly determine if a given rate is CCK or OFDM */ 5140db2e2bSzf162725 #define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) 5240db2e2bSzf162725 #define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */ 5340db2e2bSzf162725 #define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */ 5440db2e2bSzf162725 #define RAL_SIFS 10 /* us */ 5540db2e2bSzf162725 #define RAL_RXTX_TURNAROUND 5 /* us */ 5640db2e2bSzf162725 5740db2e2bSzf162725 #define URAL_N(a) (sizeof (a) / sizeof ((a)[0])) 5840db2e2bSzf162725 5940db2e2bSzf162725 /* 6040db2e2bSzf162725 * Supported rates for 802.11a/b/g modes (in 500Kbps unit). 6140db2e2bSzf162725 */ 6240db2e2bSzf162725 static const struct ieee80211_rateset ural_rateset_11a = 6340db2e2bSzf162725 { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } }; 6440db2e2bSzf162725 6540db2e2bSzf162725 static const struct ieee80211_rateset ural_rateset_11b = 6640db2e2bSzf162725 { 4, { 2, 4, 11, 22 } }; 6740db2e2bSzf162725 6840db2e2bSzf162725 static const struct ieee80211_rateset ural_rateset_11g = 6940db2e2bSzf162725 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 7040db2e2bSzf162725 7140db2e2bSzf162725 /* 7240db2e2bSzf162725 * Default values for MAC registers; values taken from the reference driver. 7340db2e2bSzf162725 */ 7440db2e2bSzf162725 static const struct { 7540db2e2bSzf162725 uint16_t reg; 7640db2e2bSzf162725 uint16_t val; 7740db2e2bSzf162725 } ural_def_mac[] = { 7840db2e2bSzf162725 { RAL_TXRX_CSR5, 0x8c8d }, 7940db2e2bSzf162725 { RAL_TXRX_CSR6, 0x8b8a }, 8040db2e2bSzf162725 { RAL_TXRX_CSR7, 0x8687 }, 8140db2e2bSzf162725 { RAL_TXRX_CSR8, 0x0085 }, 8240db2e2bSzf162725 { RAL_MAC_CSR13, 0x1111 }, 8340db2e2bSzf162725 { RAL_MAC_CSR14, 0x1e11 }, 8440db2e2bSzf162725 { RAL_TXRX_CSR21, 0xe78f }, 8540db2e2bSzf162725 { RAL_MAC_CSR9, 0xff1d }, 8640db2e2bSzf162725 { RAL_MAC_CSR11, 0x0002 }, 8740db2e2bSzf162725 { RAL_MAC_CSR22, 0x0053 }, 8840db2e2bSzf162725 { RAL_MAC_CSR15, 0x0000 }, 8940db2e2bSzf162725 { RAL_MAC_CSR8, 0x0780 }, 9040db2e2bSzf162725 { RAL_TXRX_CSR19, 0x0000 }, 9140db2e2bSzf162725 { RAL_TXRX_CSR18, 0x005a }, 9240db2e2bSzf162725 { RAL_PHY_CSR2, 0x0000 }, 9340db2e2bSzf162725 { RAL_TXRX_CSR0, 0x1ec0 }, 9440db2e2bSzf162725 { RAL_PHY_CSR4, 0x000f } 9540db2e2bSzf162725 }; 9640db2e2bSzf162725 9740db2e2bSzf162725 /* 9840db2e2bSzf162725 * Default values for BBP registers; values taken from the reference driver. 9940db2e2bSzf162725 */ 10040db2e2bSzf162725 static const struct { 10140db2e2bSzf162725 uint8_t reg; 10240db2e2bSzf162725 uint8_t val; 10340db2e2bSzf162725 } ural_def_bbp[] = { 10440db2e2bSzf162725 { 3, 0x02 }, 10540db2e2bSzf162725 { 4, 0x19 }, 10640db2e2bSzf162725 { 14, 0x1c }, 10740db2e2bSzf162725 { 15, 0x30 }, 10840db2e2bSzf162725 { 16, 0xac }, 10940db2e2bSzf162725 { 17, 0x48 }, 11040db2e2bSzf162725 { 18, 0x18 }, 11140db2e2bSzf162725 { 19, 0xff }, 11240db2e2bSzf162725 { 20, 0x1e }, 11340db2e2bSzf162725 { 21, 0x08 }, 11440db2e2bSzf162725 { 22, 0x08 }, 11540db2e2bSzf162725 { 23, 0x08 }, 11640db2e2bSzf162725 { 24, 0x80 }, 11740db2e2bSzf162725 { 25, 0x50 }, 11840db2e2bSzf162725 { 26, 0x08 }, 11940db2e2bSzf162725 { 27, 0x23 }, 12040db2e2bSzf162725 { 30, 0x10 }, 12140db2e2bSzf162725 { 31, 0x2b }, 12240db2e2bSzf162725 { 32, 0xb9 }, 12340db2e2bSzf162725 { 34, 0x12 }, 12440db2e2bSzf162725 { 35, 0x50 }, 12540db2e2bSzf162725 { 39, 0xc4 }, 12640db2e2bSzf162725 { 40, 0x02 }, 12740db2e2bSzf162725 { 41, 0x60 }, 12840db2e2bSzf162725 { 53, 0x10 }, 12940db2e2bSzf162725 { 54, 0x18 }, 13040db2e2bSzf162725 { 56, 0x08 }, 13140db2e2bSzf162725 { 57, 0x10 }, 13240db2e2bSzf162725 { 58, 0x08 }, 13340db2e2bSzf162725 { 61, 0x60 }, 13440db2e2bSzf162725 { 62, 0x10 }, 13540db2e2bSzf162725 { 75, 0xff } 13640db2e2bSzf162725 }; 13740db2e2bSzf162725 13840db2e2bSzf162725 /* 13940db2e2bSzf162725 * Default values for RF register R2 indexed by channel numbers. 14040db2e2bSzf162725 */ 14140db2e2bSzf162725 static const uint32_t ural_rf2522_r2[] = { 14240db2e2bSzf162725 0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814, 14340db2e2bSzf162725 0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e 14440db2e2bSzf162725 }; 14540db2e2bSzf162725 14640db2e2bSzf162725 static const uint32_t ural_rf2523_r2[] = { 14740db2e2bSzf162725 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, 14840db2e2bSzf162725 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 14940db2e2bSzf162725 }; 15040db2e2bSzf162725 15140db2e2bSzf162725 static const uint32_t ural_rf2524_r2[] = { 15240db2e2bSzf162725 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, 15340db2e2bSzf162725 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 15440db2e2bSzf162725 }; 15540db2e2bSzf162725 15640db2e2bSzf162725 static const uint32_t ural_rf2525_r2[] = { 15740db2e2bSzf162725 0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d, 15840db2e2bSzf162725 0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346 15940db2e2bSzf162725 }; 16040db2e2bSzf162725 16140db2e2bSzf162725 static const uint32_t ural_rf2525_hi_r2[] = { 16240db2e2bSzf162725 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345, 16340db2e2bSzf162725 0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e 16440db2e2bSzf162725 }; 16540db2e2bSzf162725 16640db2e2bSzf162725 static const uint32_t ural_rf2525e_r2[] = { 16740db2e2bSzf162725 0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463, 16840db2e2bSzf162725 0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b 16940db2e2bSzf162725 }; 17040db2e2bSzf162725 17140db2e2bSzf162725 static const uint32_t ural_rf2526_hi_r2[] = { 17240db2e2bSzf162725 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d, 17340db2e2bSzf162725 0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241 17440db2e2bSzf162725 }; 17540db2e2bSzf162725 17640db2e2bSzf162725 static const uint32_t ural_rf2526_r2[] = { 17740db2e2bSzf162725 0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229, 17840db2e2bSzf162725 0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d 17940db2e2bSzf162725 }; 18040db2e2bSzf162725 18140db2e2bSzf162725 /* 18240db2e2bSzf162725 * For dual-band RF, RF registers R1 and R4 also depend on channel number; 18340db2e2bSzf162725 * values taken from the reference driver. 18440db2e2bSzf162725 */ 18540db2e2bSzf162725 static const struct { 18640db2e2bSzf162725 uint8_t chan; 18740db2e2bSzf162725 uint32_t r1; 18840db2e2bSzf162725 uint32_t r2; 18940db2e2bSzf162725 uint32_t r4; 19040db2e2bSzf162725 } ural_rf5222[] = { 19140db2e2bSzf162725 { 1, 0x08808, 0x0044d, 0x00282 }, 19240db2e2bSzf162725 { 2, 0x08808, 0x0044e, 0x00282 }, 19340db2e2bSzf162725 { 3, 0x08808, 0x0044f, 0x00282 }, 19440db2e2bSzf162725 { 4, 0x08808, 0x00460, 0x00282 }, 19540db2e2bSzf162725 { 5, 0x08808, 0x00461, 0x00282 }, 19640db2e2bSzf162725 { 6, 0x08808, 0x00462, 0x00282 }, 19740db2e2bSzf162725 { 7, 0x08808, 0x00463, 0x00282 }, 19840db2e2bSzf162725 { 8, 0x08808, 0x00464, 0x00282 }, 19940db2e2bSzf162725 { 9, 0x08808, 0x00465, 0x00282 }, 20040db2e2bSzf162725 { 10, 0x08808, 0x00466, 0x00282 }, 20140db2e2bSzf162725 { 11, 0x08808, 0x00467, 0x00282 }, 20240db2e2bSzf162725 { 12, 0x08808, 0x00468, 0x00282 }, 20340db2e2bSzf162725 { 13, 0x08808, 0x00469, 0x00282 }, 20440db2e2bSzf162725 { 14, 0x08808, 0x0046b, 0x00286 }, 20540db2e2bSzf162725 20640db2e2bSzf162725 { 36, 0x08804, 0x06225, 0x00287 }, 20740db2e2bSzf162725 { 40, 0x08804, 0x06226, 0x00287 }, 20840db2e2bSzf162725 { 44, 0x08804, 0x06227, 0x00287 }, 20940db2e2bSzf162725 { 48, 0x08804, 0x06228, 0x00287 }, 21040db2e2bSzf162725 { 52, 0x08804, 0x06229, 0x00287 }, 21140db2e2bSzf162725 { 56, 0x08804, 0x0622a, 0x00287 }, 21240db2e2bSzf162725 { 60, 0x08804, 0x0622b, 0x00287 }, 21340db2e2bSzf162725 { 64, 0x08804, 0x0622c, 0x00287 }, 21440db2e2bSzf162725 21540db2e2bSzf162725 { 100, 0x08804, 0x02200, 0x00283 }, 21640db2e2bSzf162725 { 104, 0x08804, 0x02201, 0x00283 }, 21740db2e2bSzf162725 { 108, 0x08804, 0x02202, 0x00283 }, 21840db2e2bSzf162725 { 112, 0x08804, 0x02203, 0x00283 }, 21940db2e2bSzf162725 { 116, 0x08804, 0x02204, 0x00283 }, 22040db2e2bSzf162725 { 120, 0x08804, 0x02205, 0x00283 }, 22140db2e2bSzf162725 { 124, 0x08804, 0x02206, 0x00283 }, 22240db2e2bSzf162725 { 128, 0x08804, 0x02207, 0x00283 }, 22340db2e2bSzf162725 { 132, 0x08804, 0x02208, 0x00283 }, 22440db2e2bSzf162725 { 136, 0x08804, 0x02209, 0x00283 }, 22540db2e2bSzf162725 { 140, 0x08804, 0x0220a, 0x00283 }, 22640db2e2bSzf162725 22740db2e2bSzf162725 { 149, 0x08808, 0x02429, 0x00281 }, 22840db2e2bSzf162725 { 153, 0x08808, 0x0242b, 0x00281 }, 22940db2e2bSzf162725 { 157, 0x08808, 0x0242d, 0x00281 }, 23040db2e2bSzf162725 { 161, 0x08808, 0x0242f, 0x00281 } 23140db2e2bSzf162725 }; 23240db2e2bSzf162725 23340db2e2bSzf162725 /* 23440db2e2bSzf162725 * device operations 23540db2e2bSzf162725 */ 23640db2e2bSzf162725 static int ural_attach(dev_info_t *, ddi_attach_cmd_t); 23740db2e2bSzf162725 static int ural_detach(dev_info_t *, ddi_detach_cmd_t); 23840db2e2bSzf162725 23940db2e2bSzf162725 /* 24040db2e2bSzf162725 * Module Loading Data & Entry Points 24140db2e2bSzf162725 */ 24240db2e2bSzf162725 DDI_DEFINE_STREAM_OPS(ural_dev_ops, nulldev, nulldev, ural_attach, 2435644143aSQuaker Fang ural_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed); 24440db2e2bSzf162725 24540db2e2bSzf162725 static struct modldrv ural_modldrv = { 24640db2e2bSzf162725 &mod_driverops, /* Type of module. This one is a driver */ 2471a932f2eSQuaker Fang "ural driver v1.4", /* short description */ 24840db2e2bSzf162725 &ural_dev_ops /* driver specific ops */ 24940db2e2bSzf162725 }; 25040db2e2bSzf162725 25140db2e2bSzf162725 static struct modlinkage modlinkage = { 25240db2e2bSzf162725 MODREV_1, 25340db2e2bSzf162725 (void *)&ural_modldrv, 25440db2e2bSzf162725 NULL 25540db2e2bSzf162725 }; 25640db2e2bSzf162725 25740db2e2bSzf162725 static int ural_m_stat(void *, uint_t, uint64_t *); 25840db2e2bSzf162725 static int ural_m_start(void *); 25940db2e2bSzf162725 static void ural_m_stop(void *); 26040db2e2bSzf162725 static int ural_m_promisc(void *, boolean_t); 26140db2e2bSzf162725 static int ural_m_multicst(void *, boolean_t, const uint8_t *); 26240db2e2bSzf162725 static int ural_m_unicst(void *, const uint8_t *); 26340db2e2bSzf162725 static mblk_t *ural_m_tx(void *, mblk_t *); 26440db2e2bSzf162725 static void ural_m_ioctl(void *, queue_t *, mblk_t *); 2655644143aSQuaker Fang static int ural_m_setprop(void *, const char *, mac_prop_id_t, 2665644143aSQuaker Fang uint_t, const void *); 2675644143aSQuaker Fang static int ural_m_getprop(void *, const char *, mac_prop_id_t, 268*0dc2366fSVenugopal Iyer uint_t, void *); 269*0dc2366fSVenugopal Iyer static void ural_m_propinfo(void *, const char *, mac_prop_id_t, 270*0dc2366fSVenugopal Iyer mac_prop_info_handle_t); 27140db2e2bSzf162725 27240db2e2bSzf162725 static mac_callbacks_t ural_m_callbacks = { 273*0dc2366fSVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 27440db2e2bSzf162725 ural_m_stat, 27540db2e2bSzf162725 ural_m_start, 27640db2e2bSzf162725 ural_m_stop, 27740db2e2bSzf162725 ural_m_promisc, 27840db2e2bSzf162725 ural_m_multicst, 27940db2e2bSzf162725 ural_m_unicst, 28040db2e2bSzf162725 ural_m_tx, 281*0dc2366fSVenugopal Iyer NULL, 28240db2e2bSzf162725 ural_m_ioctl, 2835644143aSQuaker Fang NULL, /* mc_getcapab */ 2845644143aSQuaker Fang NULL, 2855644143aSQuaker Fang NULL, 2865644143aSQuaker Fang ural_m_setprop, 287*0dc2366fSVenugopal Iyer ural_m_getprop, 288*0dc2366fSVenugopal Iyer ural_m_propinfo 28940db2e2bSzf162725 }; 29040db2e2bSzf162725 29140db2e2bSzf162725 static void ural_amrr_start(struct ural_softc *, struct ieee80211_node *); 29240db2e2bSzf162725 static int ural_tx_trigger(struct ural_softc *, mblk_t *); 29340db2e2bSzf162725 static int ural_rx_trigger(struct ural_softc *); 29440db2e2bSzf162725 29540db2e2bSzf162725 uint32_t ural_dbg_flags = 0; 29640db2e2bSzf162725 29740db2e2bSzf162725 void 29840db2e2bSzf162725 ral_debug(uint32_t dbg_flags, const int8_t *fmt, ...) 29940db2e2bSzf162725 { 30040db2e2bSzf162725 va_list args; 30140db2e2bSzf162725 30240db2e2bSzf162725 if (dbg_flags & ural_dbg_flags) { 30340db2e2bSzf162725 va_start(args, fmt); 30440db2e2bSzf162725 vcmn_err(CE_CONT, fmt, args); 30540db2e2bSzf162725 va_end(args); 30640db2e2bSzf162725 } 30740db2e2bSzf162725 } 30840db2e2bSzf162725 30940db2e2bSzf162725 static uint16_t 31040db2e2bSzf162725 ural_read(struct ural_softc *sc, uint16_t reg) 31140db2e2bSzf162725 { 31240db2e2bSzf162725 usb_ctrl_setup_t req; 31340db2e2bSzf162725 usb_cr_t cr; 31440db2e2bSzf162725 usb_cb_flags_t cf; 31540db2e2bSzf162725 mblk_t *mp; 31640db2e2bSzf162725 int err; 31740db2e2bSzf162725 uint16_t val; 31840db2e2bSzf162725 31940db2e2bSzf162725 bzero(&req, sizeof (req)); 32040db2e2bSzf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST; 32140db2e2bSzf162725 req.bRequest = RAL_READ_MAC; 32240db2e2bSzf162725 req.wValue = 0; 32340db2e2bSzf162725 req.wIndex = reg; 32440db2e2bSzf162725 req.wLength = sizeof (uint16_t); 32540db2e2bSzf162725 32640db2e2bSzf162725 mp = NULL; 32740db2e2bSzf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 32840db2e2bSzf162725 &cr, &cf, 0); 32940db2e2bSzf162725 33040db2e2bSzf162725 if (err != USB_SUCCESS) { 3311a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 33240db2e2bSzf162725 "ural_read(): could not read MAC register:" 33340db2e2bSzf162725 " cr:%s(%d), cf:(%x)\n", 33440db2e2bSzf162725 usb_str_cr(cr), cr, cf); 33540db2e2bSzf162725 return (0); 33640db2e2bSzf162725 } 33740db2e2bSzf162725 33840db2e2bSzf162725 bcopy(mp->b_rptr, &val, sizeof (uint16_t)); 33940db2e2bSzf162725 34040db2e2bSzf162725 if (mp) 34140db2e2bSzf162725 freemsg(mp); 34240db2e2bSzf162725 34340db2e2bSzf162725 return (LE_16(val)); 34440db2e2bSzf162725 } 34540db2e2bSzf162725 34640db2e2bSzf162725 static void 34740db2e2bSzf162725 ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) 34840db2e2bSzf162725 { 34940db2e2bSzf162725 usb_ctrl_setup_t req; 35040db2e2bSzf162725 usb_cr_t cr; 35140db2e2bSzf162725 usb_cb_flags_t cf; 35240db2e2bSzf162725 mblk_t *mp; 35340db2e2bSzf162725 int err; 35440db2e2bSzf162725 35540db2e2bSzf162725 bzero(&req, sizeof (req)); 35640db2e2bSzf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST; 35740db2e2bSzf162725 req.bRequest = RAL_READ_MULTI_MAC; 35840db2e2bSzf162725 req.wValue = 0; 35940db2e2bSzf162725 req.wIndex = reg; 36040db2e2bSzf162725 req.wLength = (uint16_t)len; 36140db2e2bSzf162725 req.attrs = USB_ATTRS_AUTOCLEARING; 36240db2e2bSzf162725 36340db2e2bSzf162725 mp = NULL; 36440db2e2bSzf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 36540db2e2bSzf162725 &cr, &cf, 0); 36640db2e2bSzf162725 36740db2e2bSzf162725 if (err != USB_SUCCESS) { 3681a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 36940db2e2bSzf162725 "ural_read_multi(): could not read MAC register:" 37040db2e2bSzf162725 "cr:%s(%d), cf:(%x)\n", 37140db2e2bSzf162725 usb_str_cr(cr), cr, cf); 37240db2e2bSzf162725 return; 37340db2e2bSzf162725 } 37440db2e2bSzf162725 37540db2e2bSzf162725 bcopy(mp->b_rptr, buf, len); 37640db2e2bSzf162725 37740db2e2bSzf162725 if (mp) 37840db2e2bSzf162725 freemsg(mp); 37940db2e2bSzf162725 } 38040db2e2bSzf162725 38140db2e2bSzf162725 static void 38240db2e2bSzf162725 ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val) 38340db2e2bSzf162725 { 38440db2e2bSzf162725 usb_ctrl_setup_t req; 38540db2e2bSzf162725 usb_cr_t cr; 38640db2e2bSzf162725 usb_cb_flags_t cf; 38740db2e2bSzf162725 int err; 38840db2e2bSzf162725 38940db2e2bSzf162725 bzero(&req, sizeof (req)); 39040db2e2bSzf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV; 39140db2e2bSzf162725 req.bRequest = RAL_WRITE_MAC; 39240db2e2bSzf162725 req.wValue = val; 39340db2e2bSzf162725 req.wIndex = reg; 39440db2e2bSzf162725 req.wLength = 0; 39540db2e2bSzf162725 req.attrs = USB_ATTRS_NONE; 39640db2e2bSzf162725 39740db2e2bSzf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, NULL, 39840db2e2bSzf162725 &cr, &cf, 0); 39940db2e2bSzf162725 40040db2e2bSzf162725 if (err != USB_SUCCESS) { 4011a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 40240db2e2bSzf162725 "ural_write(): could not write MAC register:" 40340db2e2bSzf162725 "cr:%s(%d), cf:(%x)\n", 40440db2e2bSzf162725 usb_str_cr(cr), cr, cf); 40540db2e2bSzf162725 } 40640db2e2bSzf162725 } 40740db2e2bSzf162725 40840db2e2bSzf162725 /* ARGSUSED */ 40940db2e2bSzf162725 static void 41040db2e2bSzf162725 ural_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 41140db2e2bSzf162725 { 41240db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)req->bulk_client_private; 41340db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 41440db2e2bSzf162725 4151a932f2eSQuaker Fang ral_debug(RAL_DBG_TX, 41640db2e2bSzf162725 "ural_txeof(): cr:%s(%d), flags:0x%x, tx_queued:%d", 41740db2e2bSzf162725 usb_str_cr(req->bulk_completion_reason), 41840db2e2bSzf162725 req->bulk_completion_reason, 41940db2e2bSzf162725 req->bulk_cb_flags, 42040db2e2bSzf162725 sc->tx_queued); 42140db2e2bSzf162725 42240db2e2bSzf162725 if (req->bulk_completion_reason != USB_CR_OK) 42340db2e2bSzf162725 sc->sc_tx_err++; 42440db2e2bSzf162725 42540db2e2bSzf162725 mutex_enter(&sc->tx_lock); 42640db2e2bSzf162725 42740db2e2bSzf162725 sc->tx_queued--; 42840db2e2bSzf162725 sc->sc_tx_timer = 0; 42940db2e2bSzf162725 43040db2e2bSzf162725 if (sc->sc_need_sched) { 43140db2e2bSzf162725 sc->sc_need_sched = 0; 43240db2e2bSzf162725 mac_tx_update(ic->ic_mach); 43340db2e2bSzf162725 } 43440db2e2bSzf162725 43540db2e2bSzf162725 mutex_exit(&sc->tx_lock); 43640db2e2bSzf162725 usb_free_bulk_req(req); 43740db2e2bSzf162725 } 43840db2e2bSzf162725 43940db2e2bSzf162725 /* ARGSUSED */ 44040db2e2bSzf162725 static void 44140db2e2bSzf162725 ural_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 44240db2e2bSzf162725 { 44340db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)req->bulk_client_private; 44440db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 44540db2e2bSzf162725 44640db2e2bSzf162725 struct ural_rx_desc *desc; 44740db2e2bSzf162725 struct ieee80211_frame *wh; 44840db2e2bSzf162725 struct ieee80211_node *ni; 44940db2e2bSzf162725 45040db2e2bSzf162725 mblk_t *m, *mp; 45140db2e2bSzf162725 int len, pktlen; 45240db2e2bSzf162725 char *rxbuf; 45340db2e2bSzf162725 45440db2e2bSzf162725 mp = req->bulk_data; 45540db2e2bSzf162725 req->bulk_data = NULL; 45640db2e2bSzf162725 4571a932f2eSQuaker Fang ral_debug(RAL_DBG_RX, 45840db2e2bSzf162725 "ural_rxeof(): cr:%s(%d), flags:0x%x, rx_queued:%d", 45940db2e2bSzf162725 usb_str_cr(req->bulk_completion_reason), 46040db2e2bSzf162725 req->bulk_completion_reason, 46140db2e2bSzf162725 req->bulk_cb_flags, 46240db2e2bSzf162725 sc->rx_queued); 46340db2e2bSzf162725 46440db2e2bSzf162725 if (req->bulk_completion_reason != USB_CR_OK) { 46540db2e2bSzf162725 sc->sc_rx_err++; 46640db2e2bSzf162725 goto fail; 46740db2e2bSzf162725 } 46840db2e2bSzf162725 46940db2e2bSzf162725 len = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr; 47040db2e2bSzf162725 rxbuf = (char *)mp->b_rptr; 47140db2e2bSzf162725 47240db2e2bSzf162725 if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) { 4731a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 47440db2e2bSzf162725 "ural_rxeof(): xfer too short %d\n", len); 47540db2e2bSzf162725 sc->sc_rx_err++; 47640db2e2bSzf162725 goto fail; 47740db2e2bSzf162725 } 47840db2e2bSzf162725 47940db2e2bSzf162725 /* rx descriptor is located at the end */ 48040db2e2bSzf162725 desc = (struct ural_rx_desc *)(rxbuf + len - RAL_RX_DESC_SIZE); 48140db2e2bSzf162725 48240db2e2bSzf162725 if ((LE_32(desc->flags) & RAL_RX_PHY_ERROR) || 48340db2e2bSzf162725 (LE_32(desc->flags) & RAL_RX_CRC_ERROR)) { 48440db2e2bSzf162725 /* 48540db2e2bSzf162725 * This should not happen since we did not request to receive 48640db2e2bSzf162725 * those frames when we filled RAL_TXRX_CSR2. 48740db2e2bSzf162725 */ 4881a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "PHY or CRC error\n"); 48940db2e2bSzf162725 sc->sc_rx_err++; 49040db2e2bSzf162725 goto fail; 49140db2e2bSzf162725 } 49240db2e2bSzf162725 49340db2e2bSzf162725 pktlen = (LE_32(desc->flags) >> 16) & 0xfff; 49440db2e2bSzf162725 49540db2e2bSzf162725 if (pktlen > (len - RAL_RX_DESC_SIZE)) { 4961a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 49740db2e2bSzf162725 "ural_rxeof(): pktlen mismatch <%d, %d>.\n", pktlen, len); 49840db2e2bSzf162725 goto fail; 49940db2e2bSzf162725 } 50040db2e2bSzf162725 50140db2e2bSzf162725 /* Strip trailing 802.11 MAC FCS. */ 50240db2e2bSzf162725 pktlen -= IEEE80211_CRC_LEN; 50340db2e2bSzf162725 50440db2e2bSzf162725 if ((m = allocb(pktlen, BPRI_MED)) == NULL) { 5051a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 50640db2e2bSzf162725 "ural_rxeof(): allocate mblk failed.\n"); 50740db2e2bSzf162725 sc->sc_rx_nobuf++; 50840db2e2bSzf162725 goto fail; 50940db2e2bSzf162725 } 51040db2e2bSzf162725 51140db2e2bSzf162725 bcopy(rxbuf, m->b_rptr, pktlen); 51240db2e2bSzf162725 m->b_wptr += pktlen; 51340db2e2bSzf162725 51440db2e2bSzf162725 wh = (struct ieee80211_frame *)m->b_rptr; 51540db2e2bSzf162725 ni = ieee80211_find_rxnode(ic, wh); 51640db2e2bSzf162725 51740db2e2bSzf162725 /* send the frame to the 802.11 layer */ 51840db2e2bSzf162725 (void) ieee80211_input(ic, m, ni, desc->rssi, 0); 51940db2e2bSzf162725 52040db2e2bSzf162725 /* node is no longer needed */ 52140db2e2bSzf162725 ieee80211_free_node(ni); 52240db2e2bSzf162725 fail: 52340db2e2bSzf162725 mutex_enter(&sc->rx_lock); 52440db2e2bSzf162725 sc->rx_queued--; 52540db2e2bSzf162725 mutex_exit(&sc->rx_lock); 52640db2e2bSzf162725 52740db2e2bSzf162725 freemsg(mp); 52840db2e2bSzf162725 usb_free_bulk_req(req); 52940db2e2bSzf162725 53040db2e2bSzf162725 if (RAL_IS_RUNNING(sc)) 53140db2e2bSzf162725 (void) ural_rx_trigger(sc); 53240db2e2bSzf162725 } 53340db2e2bSzf162725 53440db2e2bSzf162725 /* 53540db2e2bSzf162725 * Return the expected ack rate for a frame transmitted at rate `rate'. 53640db2e2bSzf162725 * this should depend on the destination node basic rate set. 53740db2e2bSzf162725 */ 53840db2e2bSzf162725 static int 53940db2e2bSzf162725 ural_ack_rate(struct ieee80211com *ic, int rate) 54040db2e2bSzf162725 { 54140db2e2bSzf162725 switch (rate) { 54240db2e2bSzf162725 /* CCK rates */ 54340db2e2bSzf162725 case 2: 54440db2e2bSzf162725 return (2); 54540db2e2bSzf162725 case 4: 54640db2e2bSzf162725 case 11: 54740db2e2bSzf162725 case 22: 54840db2e2bSzf162725 return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate); 54940db2e2bSzf162725 55040db2e2bSzf162725 /* OFDM rates */ 55140db2e2bSzf162725 case 12: 55240db2e2bSzf162725 case 18: 55340db2e2bSzf162725 return (12); 55440db2e2bSzf162725 case 24: 55540db2e2bSzf162725 case 36: 55640db2e2bSzf162725 return (24); 55740db2e2bSzf162725 case 48: 55840db2e2bSzf162725 case 72: 55940db2e2bSzf162725 case 96: 56040db2e2bSzf162725 case 108: 56140db2e2bSzf162725 return (48); 56240db2e2bSzf162725 } 56340db2e2bSzf162725 56440db2e2bSzf162725 /* default to 1Mbps */ 56540db2e2bSzf162725 return (2); 56640db2e2bSzf162725 } 56740db2e2bSzf162725 56840db2e2bSzf162725 /* 56940db2e2bSzf162725 * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'. 57040db2e2bSzf162725 * The function automatically determines the operating mode depending on the 57140db2e2bSzf162725 * given rate. `flags' indicates whether short preamble is in use or not. 57240db2e2bSzf162725 */ 57340db2e2bSzf162725 static uint16_t 57440db2e2bSzf162725 ural_txtime(int len, int rate, uint32_t flags) 57540db2e2bSzf162725 { 57640db2e2bSzf162725 uint16_t txtime; 57740db2e2bSzf162725 57840db2e2bSzf162725 if (RAL_RATE_IS_OFDM(rate)) { 57940db2e2bSzf162725 /* IEEE Std 802.11a-1999, pp. 37 */ 58040db2e2bSzf162725 txtime = (8 + 4 * len + 3 + rate - 1) / rate; 58140db2e2bSzf162725 txtime = 16 + 4 + 4 * txtime + 6; 58240db2e2bSzf162725 } else { 58340db2e2bSzf162725 /* IEEE Std 802.11b-1999, pp. 28 */ 58440db2e2bSzf162725 txtime = (16 * len + rate - 1) / rate; 58540db2e2bSzf162725 if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) 58640db2e2bSzf162725 txtime += 72 + 24; 58740db2e2bSzf162725 else 58840db2e2bSzf162725 txtime += 144 + 48; 58940db2e2bSzf162725 } 59040db2e2bSzf162725 return (txtime); 59140db2e2bSzf162725 } 59240db2e2bSzf162725 59340db2e2bSzf162725 static uint8_t 59440db2e2bSzf162725 ural_plcp_signal(int rate) 59540db2e2bSzf162725 { 59640db2e2bSzf162725 switch (rate) { 59740db2e2bSzf162725 /* CCK rates (returned values are device-dependent) */ 59840db2e2bSzf162725 case 2: return (0x0); 59940db2e2bSzf162725 case 4: return (0x1); 60040db2e2bSzf162725 case 11: return (0x2); 60140db2e2bSzf162725 case 22: return (0x3); 60240db2e2bSzf162725 60340db2e2bSzf162725 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 60440db2e2bSzf162725 case 12: return (0xb); 60540db2e2bSzf162725 case 18: return (0xf); 60640db2e2bSzf162725 case 24: return (0xa); 60740db2e2bSzf162725 case 36: return (0xe); 60840db2e2bSzf162725 case 48: return (0x9); 60940db2e2bSzf162725 case 72: return (0xd); 61040db2e2bSzf162725 case 96: return (0x8); 61140db2e2bSzf162725 case 108: return (0xc); 61240db2e2bSzf162725 61340db2e2bSzf162725 /* unsupported rates (should not get there) */ 61440db2e2bSzf162725 default: return (0xff); 61540db2e2bSzf162725 } 61640db2e2bSzf162725 } 61740db2e2bSzf162725 61840db2e2bSzf162725 static void 61940db2e2bSzf162725 ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, 62040db2e2bSzf162725 uint32_t flags, int len, int rate) 62140db2e2bSzf162725 { 62240db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 62340db2e2bSzf162725 uint16_t plcp_length; 62440db2e2bSzf162725 int remainder; 62540db2e2bSzf162725 62640db2e2bSzf162725 desc->flags = LE_32(flags); 62740db2e2bSzf162725 desc->flags |= LE_32(RAL_TX_NEWSEQ); 62840db2e2bSzf162725 desc->flags |= LE_32(len << 16); 62940db2e2bSzf162725 63040db2e2bSzf162725 desc->wme = LE_16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5)); 63140db2e2bSzf162725 desc->wme |= LE_16(RAL_IVOFFSET(sizeof (struct ieee80211_frame))); 63240db2e2bSzf162725 63340db2e2bSzf162725 /* setup PLCP fields */ 63440db2e2bSzf162725 desc->plcp_signal = ural_plcp_signal(rate); 63540db2e2bSzf162725 desc->plcp_service = 4; 63640db2e2bSzf162725 63740db2e2bSzf162725 len += IEEE80211_CRC_LEN; 63840db2e2bSzf162725 if (RAL_RATE_IS_OFDM(rate)) { 63940db2e2bSzf162725 desc->flags |= LE_32(RAL_TX_OFDM); 64040db2e2bSzf162725 64140db2e2bSzf162725 plcp_length = len & 0xfff; 64240db2e2bSzf162725 desc->plcp_length_hi = plcp_length >> 6; 64340db2e2bSzf162725 desc->plcp_length_lo = plcp_length & 0x3f; 64440db2e2bSzf162725 } else { 64540db2e2bSzf162725 plcp_length = (16 * len + rate - 1) / rate; 64640db2e2bSzf162725 if (rate == 22) { 64740db2e2bSzf162725 remainder = (16 * len) % 22; 64840db2e2bSzf162725 if (remainder != 0 && remainder < 7) 64940db2e2bSzf162725 desc->plcp_service |= RAL_PLCP_LENGEXT; 65040db2e2bSzf162725 } 65140db2e2bSzf162725 desc->plcp_length_hi = plcp_length >> 8; 65240db2e2bSzf162725 desc->plcp_length_lo = plcp_length & 0xff; 65340db2e2bSzf162725 65440db2e2bSzf162725 if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 65540db2e2bSzf162725 desc->plcp_signal |= 0x08; 65640db2e2bSzf162725 } 65740db2e2bSzf162725 65840db2e2bSzf162725 desc->iv = 0; 65940db2e2bSzf162725 desc->eiv = 0; 66040db2e2bSzf162725 } 66140db2e2bSzf162725 66240db2e2bSzf162725 #define RAL_TX_TIMEOUT 5 66340db2e2bSzf162725 66440db2e2bSzf162725 static int 66540db2e2bSzf162725 ural_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type) 66640db2e2bSzf162725 { 66740db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)ic; 66840db2e2bSzf162725 struct ural_tx_desc *desc; 66940db2e2bSzf162725 67040db2e2bSzf162725 struct ieee80211_frame *wh; 67140db2e2bSzf162725 struct ieee80211_key *k; 67240db2e2bSzf162725 67340db2e2bSzf162725 uint16_t dur; 67440db2e2bSzf162725 uint32_t flags = 0; 67540db2e2bSzf162725 int rate, err = DDI_SUCCESS; 67640db2e2bSzf162725 67740db2e2bSzf162725 struct ieee80211_node *ni = NULL; 67840db2e2bSzf162725 mblk_t *m, *m0; 67940db2e2bSzf162725 int off, mblen, pktlen, xferlen; 68040db2e2bSzf162725 6811a932f2eSQuaker Fang /* discard packets while suspending or not inited */ 6821a932f2eSQuaker Fang if (!RAL_IS_RUNNING(sc)) { 6831a932f2eSQuaker Fang freemsg(mp); 6841a932f2eSQuaker Fang return (ENXIO); 6851a932f2eSQuaker Fang } 6861a932f2eSQuaker Fang 68740db2e2bSzf162725 mutex_enter(&sc->tx_lock); 68840db2e2bSzf162725 68940db2e2bSzf162725 if (sc->tx_queued > RAL_TX_LIST_COUNT) { 6901a932f2eSQuaker Fang ral_debug(RAL_DBG_TX, "ural_send(): " 69140db2e2bSzf162725 "no TX buffer available!\n"); 69240db2e2bSzf162725 if ((type & IEEE80211_FC0_TYPE_MASK) == 69340db2e2bSzf162725 IEEE80211_FC0_TYPE_DATA) { 69440db2e2bSzf162725 sc->sc_need_sched = 1; 69540db2e2bSzf162725 } 69640db2e2bSzf162725 sc->sc_tx_nobuf++; 69740db2e2bSzf162725 err = ENOMEM; 69840db2e2bSzf162725 goto fail; 69940db2e2bSzf162725 } 70040db2e2bSzf162725 70140db2e2bSzf162725 m = allocb(RAL_TXBUF_SIZE + RAL_TX_DESC_SIZE, BPRI_MED); 70240db2e2bSzf162725 if (m == NULL) { 7031a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_send(): can't alloc mblk.\n"); 70440db2e2bSzf162725 err = DDI_FAILURE; 70540db2e2bSzf162725 goto fail; 70640db2e2bSzf162725 } 70740db2e2bSzf162725 70840db2e2bSzf162725 m->b_rptr += RAL_TX_DESC_SIZE; /* skip TX descriptor */ 70940db2e2bSzf162725 m->b_wptr += RAL_TX_DESC_SIZE; 71040db2e2bSzf162725 71140db2e2bSzf162725 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) { 71240db2e2bSzf162725 mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr; 71340db2e2bSzf162725 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen); 71440db2e2bSzf162725 off += mblen; 71540db2e2bSzf162725 } 71640db2e2bSzf162725 m->b_wptr += off; 71740db2e2bSzf162725 71840db2e2bSzf162725 wh = (struct ieee80211_frame *)m->b_rptr; 71940db2e2bSzf162725 72040db2e2bSzf162725 ni = ieee80211_find_txnode(ic, wh->i_addr1); 72140db2e2bSzf162725 if (ni == NULL) { 72240db2e2bSzf162725 err = DDI_FAILURE; 72340db2e2bSzf162725 sc->sc_tx_err++; 72440db2e2bSzf162725 freemsg(m); 72540db2e2bSzf162725 goto fail; 72640db2e2bSzf162725 } 72740db2e2bSzf162725 72840db2e2bSzf162725 if ((type & IEEE80211_FC0_TYPE_MASK) == 72940db2e2bSzf162725 IEEE80211_FC0_TYPE_DATA) { 73040db2e2bSzf162725 (void) ieee80211_encap(ic, m, ni); 73140db2e2bSzf162725 } 73240db2e2bSzf162725 73340db2e2bSzf162725 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 73440db2e2bSzf162725 k = ieee80211_crypto_encap(ic, m); 73540db2e2bSzf162725 if (k == NULL) { 73640db2e2bSzf162725 sc->sc_tx_err++; 73740db2e2bSzf162725 freemsg(m); 73840db2e2bSzf162725 err = DDI_FAILURE; 73940db2e2bSzf162725 goto fail; 74040db2e2bSzf162725 } 74140db2e2bSzf162725 /* packet header may have moved, reset our local pointer */ 74240db2e2bSzf162725 wh = (struct ieee80211_frame *)m->b_rptr; 74340db2e2bSzf162725 } 74440db2e2bSzf162725 74540db2e2bSzf162725 m->b_rptr -= RAL_TX_DESC_SIZE; /* restore */ 74640db2e2bSzf162725 desc = (struct ural_tx_desc *)m->b_rptr; 74740db2e2bSzf162725 74840db2e2bSzf162725 if ((type & IEEE80211_FC0_TYPE_MASK) == 74940db2e2bSzf162725 IEEE80211_FC0_TYPE_DATA) { /* DATA */ 75040db2e2bSzf162725 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) 75140db2e2bSzf162725 rate = ic->ic_bss->in_rates.ir_rates[ic->ic_fixed_rate]; 75240db2e2bSzf162725 else 75340db2e2bSzf162725 rate = ni->in_rates.ir_rates[ni->in_txrate]; 75440db2e2bSzf162725 75540db2e2bSzf162725 rate &= IEEE80211_RATE_VAL; 75640db2e2bSzf162725 if (rate <= 0) { 75740db2e2bSzf162725 rate = 2; /* basic rate */ 75840db2e2bSzf162725 } 75940db2e2bSzf162725 76040db2e2bSzf162725 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 76140db2e2bSzf162725 flags |= RAL_TX_ACK; 76240db2e2bSzf162725 flags |= RAL_TX_RETRY(7); 76340db2e2bSzf162725 76440db2e2bSzf162725 dur = ural_txtime(RAL_ACK_SIZE, ural_ack_rate(ic, rate), 76540db2e2bSzf162725 ic->ic_flags) + RAL_SIFS; 76640db2e2bSzf162725 *(uint16_t *)(uintptr_t)wh->i_dur = LE_16(dur); 76740db2e2bSzf162725 } 76840db2e2bSzf162725 } else { /* MGMT */ 76940db2e2bSzf162725 rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; 77040db2e2bSzf162725 77140db2e2bSzf162725 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 77240db2e2bSzf162725 flags |= RAL_TX_ACK; 77340db2e2bSzf162725 77440db2e2bSzf162725 dur = ural_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) 77540db2e2bSzf162725 + RAL_SIFS; 77640db2e2bSzf162725 *(uint16_t *)(uintptr_t)wh->i_dur = LE_16(dur); 77740db2e2bSzf162725 77840db2e2bSzf162725 /* tell hardware to add timestamp for probe responses */ 77940db2e2bSzf162725 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 78040db2e2bSzf162725 IEEE80211_FC0_TYPE_MGT && 78140db2e2bSzf162725 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 78240db2e2bSzf162725 IEEE80211_FC0_SUBTYPE_PROBE_RESP) 78340db2e2bSzf162725 flags |= RAL_TX_TIMESTAMP; 78440db2e2bSzf162725 } 78540db2e2bSzf162725 } 78640db2e2bSzf162725 78740db2e2bSzf162725 pktlen = (uintptr_t)m->b_wptr - (uintptr_t)m->b_rptr - RAL_TX_DESC_SIZE; 78840db2e2bSzf162725 ural_setup_tx_desc(sc, desc, flags, pktlen, rate); 78940db2e2bSzf162725 79040db2e2bSzf162725 /* align end on a 2-bytes boundary */ 79140db2e2bSzf162725 xferlen = (RAL_TX_DESC_SIZE + pktlen + 1) & ~1; 79240db2e2bSzf162725 79340db2e2bSzf162725 /* 79440db2e2bSzf162725 * No space left in the last URB to store the extra 2 bytes, force 79540db2e2bSzf162725 * sending of another URB. 79640db2e2bSzf162725 */ 79740db2e2bSzf162725 if ((xferlen % 64) == 0) 79840db2e2bSzf162725 xferlen += 2; 79940db2e2bSzf162725 80040db2e2bSzf162725 m->b_wptr = m->b_rptr + xferlen; 80140db2e2bSzf162725 8021a932f2eSQuaker Fang ral_debug(RAL_DBG_TX, "sending data frame len=%u rate=%u xfer len=%u\n", 80340db2e2bSzf162725 pktlen, rate, xferlen); 80440db2e2bSzf162725 80540db2e2bSzf162725 (void) ural_tx_trigger(sc, m); 80640db2e2bSzf162725 80740db2e2bSzf162725 ic->ic_stats.is_tx_frags++; 80840db2e2bSzf162725 ic->ic_stats.is_tx_bytes += pktlen; 80940db2e2bSzf162725 81040db2e2bSzf162725 fail: 81140db2e2bSzf162725 if (ni != NULL) 81240db2e2bSzf162725 ieee80211_free_node(ni); 81340db2e2bSzf162725 81440db2e2bSzf162725 if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA || 81540db2e2bSzf162725 err == 0) { 81640db2e2bSzf162725 freemsg(mp); 81740db2e2bSzf162725 } 81840db2e2bSzf162725 81940db2e2bSzf162725 mutex_exit(&sc->tx_lock); 82040db2e2bSzf162725 82140db2e2bSzf162725 return (err); 82240db2e2bSzf162725 } 82340db2e2bSzf162725 82440db2e2bSzf162725 static mblk_t * 82540db2e2bSzf162725 ural_m_tx(void *arg, mblk_t *mp) 82640db2e2bSzf162725 { 82740db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 82840db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 82940db2e2bSzf162725 mblk_t *next; 83040db2e2bSzf162725 83140db2e2bSzf162725 /* 83240db2e2bSzf162725 * No data frames go out unless we're associated; this 83340db2e2bSzf162725 * should not happen as the 802.11 layer does not enable 83440db2e2bSzf162725 * the xmit queue until we enter the RUN state. 83540db2e2bSzf162725 */ 83640db2e2bSzf162725 if (ic->ic_state != IEEE80211_S_RUN) { 8371a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_m_tx(): " 83840db2e2bSzf162725 "discard, state %u\n", ic->ic_state); 83940db2e2bSzf162725 freemsgchain(mp); 84040db2e2bSzf162725 return (NULL); 84140db2e2bSzf162725 } 84240db2e2bSzf162725 84340db2e2bSzf162725 while (mp != NULL) { 84440db2e2bSzf162725 next = mp->b_next; 84540db2e2bSzf162725 mp->b_next = NULL; 84640db2e2bSzf162725 if (ural_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) { 84740db2e2bSzf162725 mp->b_next = next; 84840db2e2bSzf162725 freemsgchain(mp); 84940db2e2bSzf162725 return (NULL); 85040db2e2bSzf162725 } 85140db2e2bSzf162725 mp = next; 85240db2e2bSzf162725 } 85340db2e2bSzf162725 return (mp); 85440db2e2bSzf162725 } 85540db2e2bSzf162725 85640db2e2bSzf162725 static void 85740db2e2bSzf162725 ural_set_testmode(struct ural_softc *sc) 85840db2e2bSzf162725 { 85940db2e2bSzf162725 usb_ctrl_setup_t req; 86040db2e2bSzf162725 usb_cr_t cr; 86140db2e2bSzf162725 usb_cb_flags_t cf; 86240db2e2bSzf162725 int err; 86340db2e2bSzf162725 86440db2e2bSzf162725 bzero(&req, sizeof (req)); 86540db2e2bSzf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV; 86640db2e2bSzf162725 req.bRequest = RAL_VENDOR_REQUEST; 86740db2e2bSzf162725 req.wValue = 4; 86840db2e2bSzf162725 req.wIndex = 1; 86940db2e2bSzf162725 req.wLength = 0; 87040db2e2bSzf162725 req.attrs = USB_ATTRS_NONE; 87140db2e2bSzf162725 87240db2e2bSzf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, NULL, 87340db2e2bSzf162725 &cr, &cf, 0); 87440db2e2bSzf162725 87540db2e2bSzf162725 if (err != USB_SUCCESS) { 8761a932f2eSQuaker Fang ral_debug(RAL_DBG_USB, 87740db2e2bSzf162725 "ural_set_testmode(): could not set test mode:" 87840db2e2bSzf162725 "cr:%s(%d), cf:%(x)\n", 87940db2e2bSzf162725 usb_str_cr(cr), cr, cf); 88040db2e2bSzf162725 } 88140db2e2bSzf162725 } 88240db2e2bSzf162725 88340db2e2bSzf162725 static void 88440db2e2bSzf162725 ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len) 88540db2e2bSzf162725 { 88640db2e2bSzf162725 usb_ctrl_setup_t req; 88740db2e2bSzf162725 usb_cr_t cr; 88840db2e2bSzf162725 usb_cb_flags_t cf; 88940db2e2bSzf162725 mblk_t *mp; 89040db2e2bSzf162725 int err; 89140db2e2bSzf162725 89240db2e2bSzf162725 bzero(&req, sizeof (req)); 89340db2e2bSzf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST; 89440db2e2bSzf162725 req.bRequest = RAL_READ_EEPROM; 89540db2e2bSzf162725 req.wValue = 0; 89640db2e2bSzf162725 req.wIndex = addr; 89740db2e2bSzf162725 req.wLength = (uint16_t)len; 89840db2e2bSzf162725 89940db2e2bSzf162725 mp = NULL; 90040db2e2bSzf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp, 90140db2e2bSzf162725 &cr, &cf, 0); 90240db2e2bSzf162725 90340db2e2bSzf162725 if (err != USB_SUCCESS) { 9041a932f2eSQuaker Fang ral_debug(RAL_DBG_USB, 90540db2e2bSzf162725 "ural_eeprom_read(): could not read EEPROM:" 90640db2e2bSzf162725 "cr:%s(%d), cf:(%x)\n", 90740db2e2bSzf162725 usb_str_cr(cr), cr, cf); 90840db2e2bSzf162725 return; 90940db2e2bSzf162725 } 91040db2e2bSzf162725 91140db2e2bSzf162725 bcopy(mp->b_rptr, buf, len); 91240db2e2bSzf162725 91340db2e2bSzf162725 if (mp) 91440db2e2bSzf162725 freemsg(mp); 91540db2e2bSzf162725 } 91640db2e2bSzf162725 91740db2e2bSzf162725 static void 91840db2e2bSzf162725 ural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val) 91940db2e2bSzf162725 { 92040db2e2bSzf162725 uint16_t tmp; 92140db2e2bSzf162725 int ntries; 92240db2e2bSzf162725 92340db2e2bSzf162725 for (ntries = 0; ntries < 5; ntries++) { 92440db2e2bSzf162725 if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) 92540db2e2bSzf162725 break; 92640db2e2bSzf162725 } 92740db2e2bSzf162725 if (ntries == 5) { 9281a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 92940db2e2bSzf162725 "ural_bbp_write(): could not write to BBP\n"); 93040db2e2bSzf162725 return; 93140db2e2bSzf162725 } 93240db2e2bSzf162725 93340db2e2bSzf162725 tmp = reg << 8 | val; 93440db2e2bSzf162725 ural_write(sc, RAL_PHY_CSR7, tmp); 93540db2e2bSzf162725 } 93640db2e2bSzf162725 93740db2e2bSzf162725 static uint8_t 93840db2e2bSzf162725 ural_bbp_read(struct ural_softc *sc, uint8_t reg) 93940db2e2bSzf162725 { 94040db2e2bSzf162725 uint16_t val; 94140db2e2bSzf162725 int ntries; 94240db2e2bSzf162725 94340db2e2bSzf162725 val = RAL_BBP_WRITE | reg << 8; 94440db2e2bSzf162725 ural_write(sc, RAL_PHY_CSR7, val); 94540db2e2bSzf162725 94640db2e2bSzf162725 for (ntries = 0; ntries < 5; ntries++) { 94740db2e2bSzf162725 if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) 94840db2e2bSzf162725 break; 94940db2e2bSzf162725 } 95040db2e2bSzf162725 if (ntries == 5) { 9511a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_bbp_read(): could not read BBP\n"); 95240db2e2bSzf162725 return (0); 95340db2e2bSzf162725 } 95440db2e2bSzf162725 95540db2e2bSzf162725 return (ural_read(sc, RAL_PHY_CSR7) & 0xff); 95640db2e2bSzf162725 } 95740db2e2bSzf162725 95840db2e2bSzf162725 static void 95940db2e2bSzf162725 ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val) 96040db2e2bSzf162725 { 96140db2e2bSzf162725 uint32_t tmp; 96240db2e2bSzf162725 int ntries; 96340db2e2bSzf162725 96440db2e2bSzf162725 for (ntries = 0; ntries < 5; ntries++) { 96540db2e2bSzf162725 if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY)) 96640db2e2bSzf162725 break; 96740db2e2bSzf162725 } 96840db2e2bSzf162725 if (ntries == 5) { 9691a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 97040db2e2bSzf162725 "ural_rf_write(): could not write to RF\n"); 97140db2e2bSzf162725 return; 97240db2e2bSzf162725 } 97340db2e2bSzf162725 97440db2e2bSzf162725 tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xffff) << 2 | (reg & 0x3); 97540db2e2bSzf162725 ural_write(sc, RAL_PHY_CSR9, tmp & 0xffff); 97640db2e2bSzf162725 ural_write(sc, RAL_PHY_CSR10, tmp >> 16); 97740db2e2bSzf162725 97840db2e2bSzf162725 /* remember last written value in sc */ 97940db2e2bSzf162725 sc->rf_regs[reg] = val; 98040db2e2bSzf162725 9811a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff); 98240db2e2bSzf162725 } 98340db2e2bSzf162725 98440db2e2bSzf162725 /* 98540db2e2bSzf162725 * Disable RF auto-tuning. 98640db2e2bSzf162725 */ 98740db2e2bSzf162725 static void 98840db2e2bSzf162725 ural_disable_rf_tune(struct ural_softc *sc) 98940db2e2bSzf162725 { 99040db2e2bSzf162725 uint32_t tmp; 99140db2e2bSzf162725 99240db2e2bSzf162725 if (sc->rf_rev != RAL_RF_2523) { 99340db2e2bSzf162725 tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE; 99440db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, tmp); 99540db2e2bSzf162725 } 99640db2e2bSzf162725 99740db2e2bSzf162725 tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE; 99840db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, tmp); 99940db2e2bSzf162725 10001a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, "disabling RF autotune\n"); 100140db2e2bSzf162725 } 100240db2e2bSzf162725 100340db2e2bSzf162725 100440db2e2bSzf162725 static void 100540db2e2bSzf162725 ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) 100640db2e2bSzf162725 { 100740db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 100840db2e2bSzf162725 uint8_t power, tmp; 100940db2e2bSzf162725 uint_t i, chan; 101040db2e2bSzf162725 101140db2e2bSzf162725 chan = ieee80211_chan2ieee(ic, c); 101240db2e2bSzf162725 if (chan == 0 || chan == IEEE80211_CHAN_ANY) 101340db2e2bSzf162725 return; 101440db2e2bSzf162725 101540db2e2bSzf162725 if (IEEE80211_IS_CHAN_2GHZ(c)) 101640db2e2bSzf162725 power = min(sc->txpow[chan - 1], 31); 101740db2e2bSzf162725 else 101840db2e2bSzf162725 power = 31; 101940db2e2bSzf162725 102040db2e2bSzf162725 /* adjust txpower using ifconfig settings */ 102140db2e2bSzf162725 power -= (100 - ic->ic_txpowlimit) / 8; 102240db2e2bSzf162725 10231a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, "setting channel to %u, txpower to %u\n", 102440db2e2bSzf162725 chan, power); 102540db2e2bSzf162725 102640db2e2bSzf162725 switch (sc->rf_rev) { 102740db2e2bSzf162725 case RAL_RF_2522: 102840db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x00814); 102940db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]); 103040db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 103140db2e2bSzf162725 break; 103240db2e2bSzf162725 103340db2e2bSzf162725 case RAL_RF_2523: 103440db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x08804); 103540db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]); 103640db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044); 103740db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 103840db2e2bSzf162725 break; 103940db2e2bSzf162725 104040db2e2bSzf162725 case RAL_RF_2524: 104140db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x0c808); 104240db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]); 104340db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 104440db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 104540db2e2bSzf162725 break; 104640db2e2bSzf162725 104740db2e2bSzf162725 case RAL_RF_2525: 104840db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x08808); 104940db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]); 105040db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 105140db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 105240db2e2bSzf162725 105340db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x08808); 105440db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]); 105540db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 105640db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 105740db2e2bSzf162725 break; 105840db2e2bSzf162725 105940db2e2bSzf162725 case RAL_RF_2525E: 106040db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x08808); 106140db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]); 106240db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 106340db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282); 106440db2e2bSzf162725 break; 106540db2e2bSzf162725 106640db2e2bSzf162725 case RAL_RF_2526: 106740db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]); 106840db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 106940db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, 0x08804); 107040db2e2bSzf162725 107140db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]); 107240db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 107340db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 107440db2e2bSzf162725 break; 107540db2e2bSzf162725 107640db2e2bSzf162725 /* dual-band RF */ 107740db2e2bSzf162725 case RAL_RF_5222: 107840db2e2bSzf162725 for (i = 0; ural_rf5222[i].chan != chan; i++) { 107940db2e2bSzf162725 if (i > URAL_N(ural_rf5222)) break; 108040db2e2bSzf162725 } 108140db2e2bSzf162725 108240db2e2bSzf162725 ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1); 108340db2e2bSzf162725 ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2); 108440db2e2bSzf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 108540db2e2bSzf162725 ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4); 108640db2e2bSzf162725 break; 108740db2e2bSzf162725 } 108840db2e2bSzf162725 108940db2e2bSzf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR && 109040db2e2bSzf162725 ic->ic_state != IEEE80211_S_SCAN) { 109140db2e2bSzf162725 /* set Japan filter bit for channel 14 */ 109240db2e2bSzf162725 tmp = ural_bbp_read(sc, 70); 109340db2e2bSzf162725 109440db2e2bSzf162725 tmp &= ~RAL_JAPAN_FILTER; 109540db2e2bSzf162725 if (chan == 14) 109640db2e2bSzf162725 tmp |= RAL_JAPAN_FILTER; 109740db2e2bSzf162725 109840db2e2bSzf162725 ural_bbp_write(sc, 70, tmp); 109940db2e2bSzf162725 110040db2e2bSzf162725 /* clear CRC errs */ 110140db2e2bSzf162725 (void) ural_read(sc, RAL_STA_CSR0); 110240db2e2bSzf162725 110340db2e2bSzf162725 drv_usecwait(10000); 110440db2e2bSzf162725 ural_disable_rf_tune(sc); 110540db2e2bSzf162725 } 110640db2e2bSzf162725 } 110740db2e2bSzf162725 110840db2e2bSzf162725 /* 110940db2e2bSzf162725 * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF 111040db2e2bSzf162725 * synchronization. 111140db2e2bSzf162725 */ 111240db2e2bSzf162725 static void 111340db2e2bSzf162725 ural_enable_tsf_sync(struct ural_softc *sc) 111440db2e2bSzf162725 { 111540db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 111640db2e2bSzf162725 uint16_t logcwmin, preload, tmp; 111740db2e2bSzf162725 111840db2e2bSzf162725 /* first, disable TSF synchronization */ 111940db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR19, 0); 112040db2e2bSzf162725 112140db2e2bSzf162725 tmp = (16 * ic->ic_bss->in_intval) << 4; 112240db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR18, tmp); 112340db2e2bSzf162725 112440db2e2bSzf162725 logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0; 112540db2e2bSzf162725 preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6; 112640db2e2bSzf162725 tmp = logcwmin << 12 | preload; 112740db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR20, tmp); 112840db2e2bSzf162725 112940db2e2bSzf162725 /* finally, enable TSF synchronization */ 113040db2e2bSzf162725 tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN; 113140db2e2bSzf162725 if (ic->ic_opmode == IEEE80211_M_STA) 113240db2e2bSzf162725 tmp |= RAL_ENABLE_TSF_SYNC(1); 113340db2e2bSzf162725 else 113440db2e2bSzf162725 tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR; 113540db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR19, tmp); 113640db2e2bSzf162725 11371a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, "enabling TSF synchronization\n"); 113840db2e2bSzf162725 } 113940db2e2bSzf162725 114040db2e2bSzf162725 /* 114140db2e2bSzf162725 * This function can be called by ieee80211_set_shortslottime(). Refer to 114240db2e2bSzf162725 * IEEE Std 802.11-1999 pp. 85 to know how these values are computed. 114340db2e2bSzf162725 */ 114440db2e2bSzf162725 /* ARGSUSED */ 114540db2e2bSzf162725 static void 114640db2e2bSzf162725 ural_update_slot(struct ieee80211com *ic, int onoff) 114740db2e2bSzf162725 { 114840db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)ic; 114940db2e2bSzf162725 uint16_t slottime, sifs, eifs; 115040db2e2bSzf162725 115140db2e2bSzf162725 slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; 115240db2e2bSzf162725 /* slottime = (onoff ? 9 : 20); */ 115340db2e2bSzf162725 115440db2e2bSzf162725 /* 115540db2e2bSzf162725 * These settings may sound a bit inconsistent but this is what the 115640db2e2bSzf162725 * reference driver does. 115740db2e2bSzf162725 */ 115840db2e2bSzf162725 if (ic->ic_curmode == IEEE80211_MODE_11B) { 115940db2e2bSzf162725 sifs = 16 - RAL_RXTX_TURNAROUND; 116040db2e2bSzf162725 eifs = 364; 116140db2e2bSzf162725 } else { 116240db2e2bSzf162725 sifs = 10 - RAL_RXTX_TURNAROUND; 116340db2e2bSzf162725 eifs = 64; 116440db2e2bSzf162725 } 116540db2e2bSzf162725 116640db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR10, slottime); 116740db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR11, sifs); 116840db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR12, eifs); 116940db2e2bSzf162725 } 117040db2e2bSzf162725 117140db2e2bSzf162725 static void 117240db2e2bSzf162725 ural_set_txpreamble(struct ural_softc *sc) 117340db2e2bSzf162725 { 117440db2e2bSzf162725 uint16_t tmp; 117540db2e2bSzf162725 117640db2e2bSzf162725 tmp = ural_read(sc, RAL_TXRX_CSR10); 117740db2e2bSzf162725 117840db2e2bSzf162725 tmp &= ~RAL_SHORT_PREAMBLE; 117940db2e2bSzf162725 if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE) 118040db2e2bSzf162725 tmp |= RAL_SHORT_PREAMBLE; 118140db2e2bSzf162725 118240db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR10, tmp); 118340db2e2bSzf162725 } 118440db2e2bSzf162725 118540db2e2bSzf162725 static void 118640db2e2bSzf162725 ural_set_basicrates(struct ural_softc *sc) 118740db2e2bSzf162725 { 118840db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 118940db2e2bSzf162725 119040db2e2bSzf162725 /* update basic rate set */ 119140db2e2bSzf162725 if (ic->ic_curmode == IEEE80211_MODE_11B) { 119240db2e2bSzf162725 /* 11b basic rates: 1, 2Mbps */ 119340db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR11, 0x3); 119440db2e2bSzf162725 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->in_chan)) { 119540db2e2bSzf162725 /* 11a basic rates: 6, 12, 24Mbps */ 119640db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR11, 0x150); 119740db2e2bSzf162725 } else { 119840db2e2bSzf162725 /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */ 119940db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR11, 0x15f); 120040db2e2bSzf162725 } 120140db2e2bSzf162725 } 120240db2e2bSzf162725 120340db2e2bSzf162725 static void 120440db2e2bSzf162725 ural_set_bssid(struct ural_softc *sc, uint8_t *bssid) 120540db2e2bSzf162725 { 120640db2e2bSzf162725 uint16_t tmp; 120740db2e2bSzf162725 120840db2e2bSzf162725 tmp = bssid[0] | bssid[1] << 8; 120940db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR5, tmp); 121040db2e2bSzf162725 121140db2e2bSzf162725 tmp = bssid[2] | bssid[3] << 8; 121240db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR6, tmp); 121340db2e2bSzf162725 121440db2e2bSzf162725 tmp = bssid[4] | bssid[5] << 8; 121540db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR7, tmp); 121640db2e2bSzf162725 12171a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, "setting BSSID to " MACSTR "\n", MAC2STR(bssid)); 121840db2e2bSzf162725 } 121940db2e2bSzf162725 122040db2e2bSzf162725 static void 122140db2e2bSzf162725 ural_set_macaddr(struct ural_softc *sc, uint8_t *addr) 122240db2e2bSzf162725 { 122340db2e2bSzf162725 uint16_t tmp; 122440db2e2bSzf162725 122540db2e2bSzf162725 tmp = addr[0] | addr[1] << 8; 122640db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR2, tmp); 122740db2e2bSzf162725 122840db2e2bSzf162725 tmp = addr[2] | addr[3] << 8; 122940db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR3, tmp); 123040db2e2bSzf162725 123140db2e2bSzf162725 tmp = addr[4] | addr[5] << 8; 123240db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR4, tmp); 123340db2e2bSzf162725 12341a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, 123540db2e2bSzf162725 "setting MAC address to " MACSTR "\n", MAC2STR(addr)); 123640db2e2bSzf162725 } 123740db2e2bSzf162725 123840db2e2bSzf162725 static void 123940db2e2bSzf162725 ural_update_promisc(struct ural_softc *sc) 124040db2e2bSzf162725 { 124140db2e2bSzf162725 uint32_t tmp; 124240db2e2bSzf162725 124340db2e2bSzf162725 tmp = ural_read(sc, RAL_TXRX_CSR2); 124440db2e2bSzf162725 124540db2e2bSzf162725 tmp &= ~RAL_DROP_NOT_TO_ME; 124640db2e2bSzf162725 if (!(sc->sc_rcr & RAL_RCR_PROMISC)) 124740db2e2bSzf162725 tmp |= RAL_DROP_NOT_TO_ME; 124840db2e2bSzf162725 124940db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR2, tmp); 125040db2e2bSzf162725 12511a932f2eSQuaker Fang ral_debug(RAL_DBG_HW, "%s promiscuous mode\n", 125240db2e2bSzf162725 (sc->sc_rcr & RAL_RCR_PROMISC) ? "entering" : "leaving"); 125340db2e2bSzf162725 } 125440db2e2bSzf162725 125540db2e2bSzf162725 static const char * 125640db2e2bSzf162725 ural_get_rf(int rev) 125740db2e2bSzf162725 { 125840db2e2bSzf162725 switch (rev) { 125940db2e2bSzf162725 case RAL_RF_2522: return ("RT2522"); 126040db2e2bSzf162725 case RAL_RF_2523: return ("RT2523"); 126140db2e2bSzf162725 case RAL_RF_2524: return ("RT2524"); 126240db2e2bSzf162725 case RAL_RF_2525: return ("RT2525"); 126340db2e2bSzf162725 case RAL_RF_2525E: return ("RT2525e"); 126440db2e2bSzf162725 case RAL_RF_2526: return ("RT2526"); 126540db2e2bSzf162725 case RAL_RF_5222: return ("RT5222"); 126640db2e2bSzf162725 default: return ("unknown"); 126740db2e2bSzf162725 } 126840db2e2bSzf162725 } 126940db2e2bSzf162725 127040db2e2bSzf162725 static void 127140db2e2bSzf162725 ural_read_eeprom(struct ural_softc *sc) 127240db2e2bSzf162725 { 127340db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 127440db2e2bSzf162725 uint16_t val; 127540db2e2bSzf162725 127640db2e2bSzf162725 ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); 127740db2e2bSzf162725 val = LE_16(val); 127840db2e2bSzf162725 sc->rf_rev = (val >> 11) & 0x7; 127940db2e2bSzf162725 sc->hw_radio = (val >> 10) & 0x1; 128040db2e2bSzf162725 sc->led_mode = (val >> 6) & 0x7; 128140db2e2bSzf162725 sc->rx_ant = (val >> 4) & 0x3; 128240db2e2bSzf162725 sc->tx_ant = (val >> 2) & 0x3; 128340db2e2bSzf162725 sc->nb_ant = val & 0x3; 128440db2e2bSzf162725 128540db2e2bSzf162725 /* read MAC address */ 128640db2e2bSzf162725 ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6); 128740db2e2bSzf162725 128840db2e2bSzf162725 /* read default values for BBP registers */ 128940db2e2bSzf162725 ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); 129040db2e2bSzf162725 129140db2e2bSzf162725 /* read Tx power for all b/g channels */ 129240db2e2bSzf162725 ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14); 129340db2e2bSzf162725 } 129440db2e2bSzf162725 129540db2e2bSzf162725 static int 129640db2e2bSzf162725 ural_bbp_init(struct ural_softc *sc) 129740db2e2bSzf162725 { 129840db2e2bSzf162725 int i, ntries; 129940db2e2bSzf162725 130040db2e2bSzf162725 /* wait for BBP to be ready */ 130140db2e2bSzf162725 for (ntries = 0; ntries < 100; ntries++) { 130240db2e2bSzf162725 if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0) 130340db2e2bSzf162725 break; 130440db2e2bSzf162725 drv_usecwait(1000); 130540db2e2bSzf162725 } 130640db2e2bSzf162725 if (ntries == 100) { 13071a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "timeout waiting for BBP\n"); 130840db2e2bSzf162725 return (EIO); 130940db2e2bSzf162725 } 131040db2e2bSzf162725 131140db2e2bSzf162725 /* initialize BBP registers to default values */ 131240db2e2bSzf162725 for (i = 0; i < URAL_N(ural_def_bbp); i++) 131340db2e2bSzf162725 ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val); 131440db2e2bSzf162725 131540db2e2bSzf162725 return (0); 131640db2e2bSzf162725 } 131740db2e2bSzf162725 131840db2e2bSzf162725 static void 131940db2e2bSzf162725 ural_set_txantenna(struct ural_softc *sc, int antenna) 132040db2e2bSzf162725 { 132140db2e2bSzf162725 uint16_t tmp; 132240db2e2bSzf162725 uint8_t tx; 132340db2e2bSzf162725 132440db2e2bSzf162725 tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK; 132540db2e2bSzf162725 if (antenna == 1) 132640db2e2bSzf162725 tx |= RAL_BBP_ANTA; 132740db2e2bSzf162725 else if (antenna == 2) 132840db2e2bSzf162725 tx |= RAL_BBP_ANTB; 132940db2e2bSzf162725 else 133040db2e2bSzf162725 tx |= RAL_BBP_DIVERSITY; 133140db2e2bSzf162725 133240db2e2bSzf162725 /* need to force I/Q flip for RF 2525e, 2526 and 5222 */ 133340db2e2bSzf162725 if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 || 133440db2e2bSzf162725 sc->rf_rev == RAL_RF_5222) 133540db2e2bSzf162725 tx |= RAL_BBP_FLIPIQ; 133640db2e2bSzf162725 133740db2e2bSzf162725 ural_bbp_write(sc, RAL_BBP_TX, tx); 133840db2e2bSzf162725 133940db2e2bSzf162725 /* update values in PHY_CSR5 and PHY_CSR6 */ 134040db2e2bSzf162725 tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7; 134140db2e2bSzf162725 ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7)); 134240db2e2bSzf162725 134340db2e2bSzf162725 tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7; 134440db2e2bSzf162725 ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7)); 134540db2e2bSzf162725 } 134640db2e2bSzf162725 134740db2e2bSzf162725 static void 134840db2e2bSzf162725 ural_set_rxantenna(struct ural_softc *sc, int antenna) 134940db2e2bSzf162725 { 135040db2e2bSzf162725 uint8_t rx; 135140db2e2bSzf162725 135240db2e2bSzf162725 rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK; 135340db2e2bSzf162725 if (antenna == 1) 135440db2e2bSzf162725 rx |= RAL_BBP_ANTA; 135540db2e2bSzf162725 else if (antenna == 2) 135640db2e2bSzf162725 rx |= RAL_BBP_ANTB; 135740db2e2bSzf162725 else 135840db2e2bSzf162725 rx |= RAL_BBP_DIVERSITY; 135940db2e2bSzf162725 136040db2e2bSzf162725 /* need to force no I/Q flip for RF 2525e and 2526 */ 136140db2e2bSzf162725 if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526) 136240db2e2bSzf162725 rx &= ~RAL_BBP_FLIPIQ; 136340db2e2bSzf162725 136440db2e2bSzf162725 ural_bbp_write(sc, RAL_BBP_RX, rx); 136540db2e2bSzf162725 } 136640db2e2bSzf162725 136740db2e2bSzf162725 /* 136840db2e2bSzf162725 * This function is called periodically (every 200ms) during scanning to 136940db2e2bSzf162725 * switch from one channel to another. 137040db2e2bSzf162725 */ 137140db2e2bSzf162725 static void 137240db2e2bSzf162725 ural_next_scan(void *arg) 137340db2e2bSzf162725 { 137440db2e2bSzf162725 struct ural_softc *sc = arg; 137540db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 137640db2e2bSzf162725 137740db2e2bSzf162725 if (ic->ic_state == IEEE80211_S_SCAN) 137840db2e2bSzf162725 ieee80211_next_scan(ic); 137940db2e2bSzf162725 } 138040db2e2bSzf162725 138140db2e2bSzf162725 static int 138240db2e2bSzf162725 ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 138340db2e2bSzf162725 { 138440db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)ic; 138540db2e2bSzf162725 enum ieee80211_state ostate; 138640db2e2bSzf162725 struct ieee80211_node *ni; 138740db2e2bSzf162725 int err; 138840db2e2bSzf162725 138940db2e2bSzf162725 RAL_LOCK(sc); 139040db2e2bSzf162725 139140db2e2bSzf162725 ostate = ic->ic_state; 139240db2e2bSzf162725 139340db2e2bSzf162725 if (sc->sc_scan_id != 0) { 139440db2e2bSzf162725 (void) untimeout(sc->sc_scan_id); 139540db2e2bSzf162725 sc->sc_scan_id = 0; 139640db2e2bSzf162725 } 139740db2e2bSzf162725 139840db2e2bSzf162725 if (sc->sc_amrr_id != 0) { 139940db2e2bSzf162725 (void) untimeout(sc->sc_amrr_id); 140040db2e2bSzf162725 sc->sc_amrr_id = 0; 140140db2e2bSzf162725 } 140240db2e2bSzf162725 140340db2e2bSzf162725 switch (nstate) { 140440db2e2bSzf162725 case IEEE80211_S_INIT: 140540db2e2bSzf162725 if (ostate == IEEE80211_S_RUN) { 140640db2e2bSzf162725 /* abort TSF synchronization */ 140740db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR19, 0); 140840db2e2bSzf162725 /* force tx led to stop blinking */ 140940db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR20, 0); 141040db2e2bSzf162725 } 141140db2e2bSzf162725 break; 141240db2e2bSzf162725 141340db2e2bSzf162725 case IEEE80211_S_SCAN: 141440db2e2bSzf162725 ural_set_chan(sc, ic->ic_curchan); 141540db2e2bSzf162725 sc->sc_scan_id = timeout(ural_next_scan, (void *)sc, 141640db2e2bSzf162725 drv_usectohz(sc->dwelltime * 1000)); 141740db2e2bSzf162725 break; 141840db2e2bSzf162725 141940db2e2bSzf162725 case IEEE80211_S_AUTH: 142040db2e2bSzf162725 ural_set_chan(sc, ic->ic_curchan); 142140db2e2bSzf162725 break; 142240db2e2bSzf162725 142340db2e2bSzf162725 case IEEE80211_S_ASSOC: 142440db2e2bSzf162725 ural_set_chan(sc, ic->ic_curchan); 142540db2e2bSzf162725 break; 142640db2e2bSzf162725 142740db2e2bSzf162725 case IEEE80211_S_RUN: 142840db2e2bSzf162725 ural_set_chan(sc, ic->ic_curchan); 142940db2e2bSzf162725 143040db2e2bSzf162725 ni = ic->ic_bss; 143140db2e2bSzf162725 143240db2e2bSzf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 143340db2e2bSzf162725 ural_update_slot(ic, 1); 143440db2e2bSzf162725 ural_set_txpreamble(sc); 143540db2e2bSzf162725 ural_set_basicrates(sc); 143640db2e2bSzf162725 ural_set_bssid(sc, ni->in_bssid); 143740db2e2bSzf162725 } 143840db2e2bSzf162725 143940db2e2bSzf162725 144040db2e2bSzf162725 /* make tx led blink on tx (controlled by ASIC) */ 144140db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR20, 1); 144240db2e2bSzf162725 144340db2e2bSzf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) 144440db2e2bSzf162725 ural_enable_tsf_sync(sc); 144540db2e2bSzf162725 144640db2e2bSzf162725 /* enable automatic rate adaptation in STA mode */ 144740db2e2bSzf162725 if (ic->ic_opmode == IEEE80211_M_STA && 144840db2e2bSzf162725 ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) 144940db2e2bSzf162725 ural_amrr_start(sc, ni); 145040db2e2bSzf162725 145140db2e2bSzf162725 break; 145240db2e2bSzf162725 } 145340db2e2bSzf162725 145440db2e2bSzf162725 RAL_UNLOCK(sc); 145540db2e2bSzf162725 145640db2e2bSzf162725 err = sc->sc_newstate(ic, nstate, arg); 145740db2e2bSzf162725 /* 145840db2e2bSzf162725 * Finally, start any timers. 145940db2e2bSzf162725 */ 146040db2e2bSzf162725 if (nstate == IEEE80211_S_RUN) 146140db2e2bSzf162725 ieee80211_start_watchdog(ic, 1); 146240db2e2bSzf162725 146340db2e2bSzf162725 return (err); 146440db2e2bSzf162725 } 146540db2e2bSzf162725 146640db2e2bSzf162725 146740db2e2bSzf162725 146840db2e2bSzf162725 static void 146940db2e2bSzf162725 ural_close_pipes(struct ural_softc *sc) 147040db2e2bSzf162725 { 147140db2e2bSzf162725 usb_flags_t flags = USB_FLAGS_SLEEP; 147240db2e2bSzf162725 147340db2e2bSzf162725 if (sc->sc_rx_pipeh != NULL) { 147440db2e2bSzf162725 usb_pipe_reset(sc->sc_dev, sc->sc_rx_pipeh, flags, NULL, 0); 147540db2e2bSzf162725 usb_pipe_close(sc->sc_dev, sc->sc_rx_pipeh, flags, NULL, 0); 147640db2e2bSzf162725 sc->sc_rx_pipeh = NULL; 147740db2e2bSzf162725 } 147840db2e2bSzf162725 147940db2e2bSzf162725 if (sc->sc_tx_pipeh != NULL) { 148040db2e2bSzf162725 usb_pipe_reset(sc->sc_dev, sc->sc_tx_pipeh, flags, NULL, 0); 148140db2e2bSzf162725 usb_pipe_close(sc->sc_dev, sc->sc_tx_pipeh, flags, NULL, 0); 148240db2e2bSzf162725 sc->sc_tx_pipeh = NULL; 148340db2e2bSzf162725 } 148440db2e2bSzf162725 } 148540db2e2bSzf162725 148640db2e2bSzf162725 static int 148740db2e2bSzf162725 ural_open_pipes(struct ural_softc *sc) 148840db2e2bSzf162725 { 148940db2e2bSzf162725 usb_ep_data_t *ep_node; 149040db2e2bSzf162725 usb_pipe_policy_t policy; 149140db2e2bSzf162725 int err; 149240db2e2bSzf162725 149340db2e2bSzf162725 ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0, 149440db2e2bSzf162725 USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 149540db2e2bSzf162725 149640db2e2bSzf162725 bzero(&policy, sizeof (usb_pipe_policy_t)); 149740db2e2bSzf162725 policy.pp_max_async_reqs = RAL_TX_LIST_COUNT; 149840db2e2bSzf162725 149940db2e2bSzf162725 if ((err = usb_pipe_open(sc->sc_dev, 150040db2e2bSzf162725 &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 150140db2e2bSzf162725 &sc->sc_tx_pipeh)) != USB_SUCCESS) { 15021a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 150340db2e2bSzf162725 "ural_open_pipes(): %x failed to open tx pipe\n", err); 150440db2e2bSzf162725 goto fail; 150540db2e2bSzf162725 } 150640db2e2bSzf162725 150740db2e2bSzf162725 ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0, 150840db2e2bSzf162725 USB_EP_ATTR_BULK, USB_EP_DIR_IN); 150940db2e2bSzf162725 151040db2e2bSzf162725 bzero(&policy, sizeof (usb_pipe_policy_t)); 151140db2e2bSzf162725 policy.pp_max_async_reqs = RAL_RX_LIST_COUNT + 32; 151240db2e2bSzf162725 151340db2e2bSzf162725 if ((err = usb_pipe_open(sc->sc_dev, 151440db2e2bSzf162725 &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP, 151540db2e2bSzf162725 &sc->sc_rx_pipeh)) != USB_SUCCESS) { 15161a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 151740db2e2bSzf162725 "ural_open_pipes(): %x failed to open rx pipe\n", err); 151840db2e2bSzf162725 goto fail; 151940db2e2bSzf162725 } 152040db2e2bSzf162725 152140db2e2bSzf162725 return (USB_SUCCESS); 152240db2e2bSzf162725 152340db2e2bSzf162725 fail: 152440db2e2bSzf162725 if (sc->sc_rx_pipeh != NULL) { 152540db2e2bSzf162725 usb_pipe_close(sc->sc_dev, sc->sc_rx_pipeh, 152640db2e2bSzf162725 USB_FLAGS_SLEEP, NULL, 0); 152740db2e2bSzf162725 sc->sc_rx_pipeh = NULL; 152840db2e2bSzf162725 } 152940db2e2bSzf162725 153040db2e2bSzf162725 if (sc->sc_tx_pipeh != NULL) { 153140db2e2bSzf162725 usb_pipe_close(sc->sc_dev, sc->sc_tx_pipeh, 153240db2e2bSzf162725 USB_FLAGS_SLEEP, NULL, 0); 153340db2e2bSzf162725 sc->sc_tx_pipeh = NULL; 153440db2e2bSzf162725 } 153540db2e2bSzf162725 153640db2e2bSzf162725 return (USB_FAILURE); 153740db2e2bSzf162725 } 153840db2e2bSzf162725 153940db2e2bSzf162725 static int 154040db2e2bSzf162725 ural_tx_trigger(struct ural_softc *sc, mblk_t *mp) 154140db2e2bSzf162725 { 154240db2e2bSzf162725 usb_bulk_req_t *req; 154340db2e2bSzf162725 int err; 154440db2e2bSzf162725 154540db2e2bSzf162725 sc->sc_tx_timer = RAL_TX_TIMEOUT; 154640db2e2bSzf162725 154740db2e2bSzf162725 req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP); 154840db2e2bSzf162725 if (req == NULL) { 15491a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 155040db2e2bSzf162725 "ural_tx_trigger(): failed to allocate req"); 155140db2e2bSzf162725 freemsg(mp); 155240db2e2bSzf162725 return (-1); 155340db2e2bSzf162725 } 155440db2e2bSzf162725 155540db2e2bSzf162725 req->bulk_len = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr; 155640db2e2bSzf162725 req->bulk_data = mp; 155740db2e2bSzf162725 req->bulk_client_private = (usb_opaque_t)sc; 155840db2e2bSzf162725 req->bulk_timeout = RAL_TX_TIMEOUT; 155940db2e2bSzf162725 req->bulk_attributes = USB_ATTRS_AUTOCLEARING; 156040db2e2bSzf162725 req->bulk_cb = ural_txeof; 156140db2e2bSzf162725 req->bulk_exc_cb = ural_txeof; 156240db2e2bSzf162725 req->bulk_completion_reason = 0; 156340db2e2bSzf162725 req->bulk_cb_flags = 0; 156440db2e2bSzf162725 156540db2e2bSzf162725 if ((err = usb_pipe_bulk_xfer(sc->sc_tx_pipeh, req, 0)) 156640db2e2bSzf162725 != USB_SUCCESS) { 156740db2e2bSzf162725 15681a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_tx_trigger(): " 156940db2e2bSzf162725 "failed to do tx xfer, %d", err); 157040db2e2bSzf162725 usb_free_bulk_req(req); 157140db2e2bSzf162725 return (-1); 157240db2e2bSzf162725 } 157340db2e2bSzf162725 157440db2e2bSzf162725 sc->tx_queued++; 157540db2e2bSzf162725 157640db2e2bSzf162725 return (0); 157740db2e2bSzf162725 } 157840db2e2bSzf162725 157940db2e2bSzf162725 static int 158040db2e2bSzf162725 ural_rx_trigger(struct ural_softc *sc) 158140db2e2bSzf162725 { 158240db2e2bSzf162725 usb_bulk_req_t *req; 158340db2e2bSzf162725 int err; 158440db2e2bSzf162725 158540db2e2bSzf162725 req = usb_alloc_bulk_req(sc->sc_dev, RAL_RXBUF_SIZE, USB_FLAGS_SLEEP); 158640db2e2bSzf162725 if (req == NULL) { 15871a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 158840db2e2bSzf162725 "ural_rx_trigger(): failed to allocate req"); 158940db2e2bSzf162725 return (-1); 159040db2e2bSzf162725 } 159140db2e2bSzf162725 159240db2e2bSzf162725 req->bulk_len = RAL_RXBUF_SIZE; 159340db2e2bSzf162725 req->bulk_client_private = (usb_opaque_t)sc; 159440db2e2bSzf162725 req->bulk_timeout = 0; 159540db2e2bSzf162725 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK 159640db2e2bSzf162725 | USB_ATTRS_AUTOCLEARING; 159740db2e2bSzf162725 req->bulk_cb = ural_rxeof; 159840db2e2bSzf162725 req->bulk_exc_cb = ural_rxeof; 159940db2e2bSzf162725 req->bulk_completion_reason = 0; 160040db2e2bSzf162725 req->bulk_cb_flags = 0; 160140db2e2bSzf162725 160240db2e2bSzf162725 err = usb_pipe_bulk_xfer(sc->sc_rx_pipeh, req, 0); 160340db2e2bSzf162725 160440db2e2bSzf162725 if (err != USB_SUCCESS) { 16051a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_rx_trigger(): " 160640db2e2bSzf162725 "failed to do rx xfer, %d", err); 160740db2e2bSzf162725 usb_free_bulk_req(req); 160840db2e2bSzf162725 160940db2e2bSzf162725 return (-1); 161040db2e2bSzf162725 } 161140db2e2bSzf162725 161240db2e2bSzf162725 mutex_enter(&sc->rx_lock); 161340db2e2bSzf162725 sc->rx_queued++; 161440db2e2bSzf162725 mutex_exit(&sc->rx_lock); 161540db2e2bSzf162725 161640db2e2bSzf162725 return (0); 161740db2e2bSzf162725 } 161840db2e2bSzf162725 161940db2e2bSzf162725 static void 162040db2e2bSzf162725 ural_init_tx_queue(struct ural_softc *sc) 162140db2e2bSzf162725 { 162240db2e2bSzf162725 sc->tx_queued = 0; 162340db2e2bSzf162725 } 162440db2e2bSzf162725 162540db2e2bSzf162725 static int 162640db2e2bSzf162725 ural_init_rx_queue(struct ural_softc *sc) 162740db2e2bSzf162725 { 162840db2e2bSzf162725 int i; 162940db2e2bSzf162725 163040db2e2bSzf162725 sc->rx_queued = 0; 163140db2e2bSzf162725 163240db2e2bSzf162725 for (i = 0; i < RAL_RX_LIST_COUNT; i++) { 163340db2e2bSzf162725 if (ural_rx_trigger(sc) != 0) { 163440db2e2bSzf162725 return (USB_FAILURE); 163540db2e2bSzf162725 } 163640db2e2bSzf162725 } 163740db2e2bSzf162725 163840db2e2bSzf162725 return (USB_SUCCESS); 163940db2e2bSzf162725 } 164040db2e2bSzf162725 164140db2e2bSzf162725 static void 164240db2e2bSzf162725 ural_stop(struct ural_softc *sc) 164340db2e2bSzf162725 { 164440db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 164540db2e2bSzf162725 164640db2e2bSzf162725 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 164740db2e2bSzf162725 ieee80211_stop_watchdog(ic); /* stop the watchdog */ 164840db2e2bSzf162725 164940db2e2bSzf162725 RAL_LOCK(sc); 165040db2e2bSzf162725 165140db2e2bSzf162725 sc->sc_tx_timer = 0; 165240db2e2bSzf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */ 165340db2e2bSzf162725 165440db2e2bSzf162725 /* disable Rx */ 165540db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); 165640db2e2bSzf162725 165740db2e2bSzf162725 /* reset ASIC and BBP (but won't reset MAC registers!) */ 165840db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP); 165940db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR1, 0); 166040db2e2bSzf162725 166140db2e2bSzf162725 ural_close_pipes(sc); 166240db2e2bSzf162725 166340db2e2bSzf162725 RAL_UNLOCK(sc); 166440db2e2bSzf162725 } 166540db2e2bSzf162725 166640db2e2bSzf162725 static int 166740db2e2bSzf162725 ural_init(struct ural_softc *sc) 166840db2e2bSzf162725 { 166940db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 167040db2e2bSzf162725 uint16_t tmp; 167140db2e2bSzf162725 int i, ntries; 167240db2e2bSzf162725 167340db2e2bSzf162725 ural_set_testmode(sc); 167440db2e2bSzf162725 ural_write(sc, 0x308, 0x00f0); /* magic */ 167540db2e2bSzf162725 167640db2e2bSzf162725 ural_stop(sc); 167740db2e2bSzf162725 167840db2e2bSzf162725 /* initialize MAC registers to default values */ 167940db2e2bSzf162725 for (i = 0; i < URAL_N(ural_def_mac); i++) 168040db2e2bSzf162725 ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val); 168140db2e2bSzf162725 168240db2e2bSzf162725 /* wait for BBP and RF to wake up (this can take a long time!) */ 168340db2e2bSzf162725 for (ntries = 0; ntries < 100; ntries++) { 168440db2e2bSzf162725 tmp = ural_read(sc, RAL_MAC_CSR17); 168540db2e2bSzf162725 if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) == 168640db2e2bSzf162725 (RAL_BBP_AWAKE | RAL_RF_AWAKE)) 168740db2e2bSzf162725 break; 168840db2e2bSzf162725 drv_usecwait(1000); 168940db2e2bSzf162725 } 169040db2e2bSzf162725 if (ntries == 100) { 16911a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 169240db2e2bSzf162725 "ural_init(): timeout waiting for BBP/RF to wakeup\n"); 169340db2e2bSzf162725 goto fail; 169440db2e2bSzf162725 } 169540db2e2bSzf162725 169640db2e2bSzf162725 /* we're ready! */ 169740db2e2bSzf162725 ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY); 169840db2e2bSzf162725 169940db2e2bSzf162725 /* set basic rate set (will be updated later) */ 170040db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR11, 0x15f); 170140db2e2bSzf162725 170240db2e2bSzf162725 if (ural_bbp_init(sc) != 0) 170340db2e2bSzf162725 goto fail; 170440db2e2bSzf162725 170540db2e2bSzf162725 /* set default BSS channel */ 170640db2e2bSzf162725 ural_set_chan(sc, ic->ic_curchan); 170740db2e2bSzf162725 170840db2e2bSzf162725 /* clear statistic registers (STA_CSR0 to STA_CSR10) */ 170940db2e2bSzf162725 ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta)); 171040db2e2bSzf162725 171140db2e2bSzf162725 ural_set_txantenna(sc, sc->tx_ant); 171240db2e2bSzf162725 ural_set_rxantenna(sc, sc->rx_ant); 171340db2e2bSzf162725 171440db2e2bSzf162725 ural_set_macaddr(sc, ic->ic_macaddr); 171540db2e2bSzf162725 171640db2e2bSzf162725 if (ural_open_pipes(sc) != USB_SUCCESS) { 17171a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_init(): " 171840db2e2bSzf162725 "could not open pipes.\n"); 171940db2e2bSzf162725 goto fail; 172040db2e2bSzf162725 } 172140db2e2bSzf162725 172240db2e2bSzf162725 ural_init_tx_queue(sc); 172340db2e2bSzf162725 172440db2e2bSzf162725 if (ural_init_rx_queue(sc) != USB_SUCCESS) 172540db2e2bSzf162725 goto fail; 172640db2e2bSzf162725 172740db2e2bSzf162725 /* kick Rx */ 172840db2e2bSzf162725 tmp = RAL_DROP_PHY | RAL_DROP_CRC; 172940db2e2bSzf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 173040db2e2bSzf162725 tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; 173140db2e2bSzf162725 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 173240db2e2bSzf162725 tmp |= RAL_DROP_TODS; 173340db2e2bSzf162725 if (!(sc->sc_rcr & RAL_RCR_PROMISC)) 173440db2e2bSzf162725 tmp |= RAL_DROP_NOT_TO_ME; 173540db2e2bSzf162725 } 173640db2e2bSzf162725 ural_write(sc, RAL_TXRX_CSR2, tmp); 173740db2e2bSzf162725 sc->sc_flags |= RAL_FLAG_RUNNING; /* RUNNING */ 173840db2e2bSzf162725 173940db2e2bSzf162725 return (DDI_SUCCESS); 174040db2e2bSzf162725 fail: 174140db2e2bSzf162725 ural_stop(sc); 174240db2e2bSzf162725 return (EIO); 174340db2e2bSzf162725 } 174440db2e2bSzf162725 174540db2e2bSzf162725 static int 17461a932f2eSQuaker Fang ural_disconnect(dev_info_t *devinfo) 174740db2e2bSzf162725 { 174840db2e2bSzf162725 struct ural_softc *sc; 174940db2e2bSzf162725 struct ieee80211com *ic; 175040db2e2bSzf162725 175140db2e2bSzf162725 /* 175240db2e2bSzf162725 * We can't call ural_stop() here, since the hardware is removed, 175340db2e2bSzf162725 * we can't access the register anymore. 175440db2e2bSzf162725 */ 175540db2e2bSzf162725 sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo)); 17561a932f2eSQuaker Fang ASSERT(sc != NULL); 175740db2e2bSzf162725 17581a932f2eSQuaker Fang if (!RAL_IS_RUNNING(sc)) /* different device or not inited */ 17591a932f2eSQuaker Fang return (DDI_SUCCESS); 17601a932f2eSQuaker Fang 17611a932f2eSQuaker Fang ic = &sc->sc_ic; 176240db2e2bSzf162725 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 176340db2e2bSzf162725 ieee80211_stop_watchdog(ic); /* stop the watchdog */ 176440db2e2bSzf162725 176540db2e2bSzf162725 RAL_LOCK(sc); 176640db2e2bSzf162725 176740db2e2bSzf162725 sc->sc_tx_timer = 0; 176840db2e2bSzf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */ 176940db2e2bSzf162725 177040db2e2bSzf162725 ural_close_pipes(sc); 177140db2e2bSzf162725 177240db2e2bSzf162725 RAL_UNLOCK(sc); 177340db2e2bSzf162725 177440db2e2bSzf162725 return (DDI_SUCCESS); 177540db2e2bSzf162725 } 177640db2e2bSzf162725 177740db2e2bSzf162725 static int 17781a932f2eSQuaker Fang ural_reconnect(dev_info_t *devinfo) 177940db2e2bSzf162725 { 178040db2e2bSzf162725 struct ural_softc *sc; 178140db2e2bSzf162725 int err; 178240db2e2bSzf162725 178340db2e2bSzf162725 sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo)); 17841a932f2eSQuaker Fang ASSERT(sc != NULL); 17851a932f2eSQuaker Fang 17861a932f2eSQuaker Fang /* check device changes after disconnect */ 17871a932f2eSQuaker Fang if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1, 17881a932f2eSQuaker Fang USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) { 17891a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "different device connected\n"); 17901a932f2eSQuaker Fang return (DDI_FAILURE); 17911a932f2eSQuaker Fang } 17921a932f2eSQuaker Fang 179340db2e2bSzf162725 err = ural_init(sc); 179440db2e2bSzf162725 179540db2e2bSzf162725 return (err); 179640db2e2bSzf162725 } 179740db2e2bSzf162725 17981a932f2eSQuaker Fang static void 17991a932f2eSQuaker Fang ural_resume(struct ural_softc *sc) 18001a932f2eSQuaker Fang { 18011a932f2eSQuaker Fang /* check device changes after suspend */ 18021a932f2eSQuaker Fang if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1, 18031a932f2eSQuaker Fang USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) { 18041a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "no or different device connected\n"); 18051a932f2eSQuaker Fang return; 18061a932f2eSQuaker Fang } 18071a932f2eSQuaker Fang 18081a932f2eSQuaker Fang (void) ural_init(sc); 18091a932f2eSQuaker Fang } 18101a932f2eSQuaker Fang 181140db2e2bSzf162725 #define URAL_AMRR_MIN_SUCCESS_THRESHOLD 1 181240db2e2bSzf162725 #define URAL_AMRR_MAX_SUCCESS_THRESHOLD 10 181340db2e2bSzf162725 181440db2e2bSzf162725 /* 181540db2e2bSzf162725 * Naive implementation of the Adaptive Multi Rate Retry algorithm: 181640db2e2bSzf162725 * "IEEE 802.11 Rate Adaptation: A Practical Approach" 181740db2e2bSzf162725 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti 181840db2e2bSzf162725 * INRIA Sophia - Projet Planete 181940db2e2bSzf162725 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html 182040db2e2bSzf162725 * 182140db2e2bSzf162725 * This algorithm is particularly well suited for ural since it does not 182240db2e2bSzf162725 * require per-frame retry statistics. Note however that since h/w does 182340db2e2bSzf162725 * not provide per-frame stats, we can't do per-node rate adaptation and 182440db2e2bSzf162725 * thus automatic rate adaptation is only enabled in STA operating mode. 182540db2e2bSzf162725 */ 182640db2e2bSzf162725 #define is_success(amrr) \ 182740db2e2bSzf162725 ((amrr)->retrycnt < (amrr)->txcnt / 10) 182840db2e2bSzf162725 #define is_failure(amrr) \ 182940db2e2bSzf162725 ((amrr)->retrycnt > (amrr)->txcnt / 3) 183040db2e2bSzf162725 #define is_enough(amrr) \ 183140db2e2bSzf162725 ((amrr)->txcnt > 10) 183240db2e2bSzf162725 #define is_min_rate(ni) \ 183340db2e2bSzf162725 ((ni)->in_txrate == 0) 183440db2e2bSzf162725 #define is_max_rate(ni) \ 183540db2e2bSzf162725 ((ni)->in_txrate == (ni)->in_rates.ir_nrates - 1) 183640db2e2bSzf162725 #define increase_rate(ni) \ 183740db2e2bSzf162725 ((ni)->in_txrate++) 183840db2e2bSzf162725 #define decrease_rate(ni) \ 183940db2e2bSzf162725 ((ni)->in_txrate--) 184040db2e2bSzf162725 #define reset_cnt(amrr) do { \ 184140db2e2bSzf162725 (amrr)->txcnt = (amrr)->retrycnt = 0; \ 184240db2e2bSzf162725 _NOTE(CONSTCOND) \ 184340db2e2bSzf162725 } while (/* CONSTCOND */0) 184440db2e2bSzf162725 184540db2e2bSzf162725 static void 184640db2e2bSzf162725 ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni) 184740db2e2bSzf162725 { 184840db2e2bSzf162725 int need_change = 0; 184940db2e2bSzf162725 185040db2e2bSzf162725 if (is_success(amrr) && is_enough(amrr)) { 185140db2e2bSzf162725 amrr->success++; 185240db2e2bSzf162725 if (amrr->success >= amrr->success_threshold && 185340db2e2bSzf162725 !is_max_rate(ni)) { 185440db2e2bSzf162725 amrr->recovery = 1; 185540db2e2bSzf162725 amrr->success = 0; 185640db2e2bSzf162725 increase_rate(ni); 185740db2e2bSzf162725 need_change = 1; 185840db2e2bSzf162725 } else { 185940db2e2bSzf162725 amrr->recovery = 0; 186040db2e2bSzf162725 } 186140db2e2bSzf162725 } else if (is_failure(amrr)) { 186240db2e2bSzf162725 amrr->success = 0; 186340db2e2bSzf162725 if (!is_min_rate(ni)) { 186440db2e2bSzf162725 if (amrr->recovery) { 186540db2e2bSzf162725 amrr->success_threshold *= 2; 186640db2e2bSzf162725 if (amrr->success_threshold > 186740db2e2bSzf162725 URAL_AMRR_MAX_SUCCESS_THRESHOLD) 186840db2e2bSzf162725 amrr->success_threshold = 186940db2e2bSzf162725 URAL_AMRR_MAX_SUCCESS_THRESHOLD; 187040db2e2bSzf162725 } else { 187140db2e2bSzf162725 amrr->success_threshold = 187240db2e2bSzf162725 URAL_AMRR_MIN_SUCCESS_THRESHOLD; 187340db2e2bSzf162725 } 187440db2e2bSzf162725 decrease_rate(ni); 187540db2e2bSzf162725 need_change = 1; 187640db2e2bSzf162725 } 187740db2e2bSzf162725 amrr->recovery = 0; /* original paper was incorrect */ 187840db2e2bSzf162725 } 187940db2e2bSzf162725 188040db2e2bSzf162725 if (is_enough(amrr) || need_change) 188140db2e2bSzf162725 reset_cnt(amrr); 188240db2e2bSzf162725 } 188340db2e2bSzf162725 188440db2e2bSzf162725 static void 188540db2e2bSzf162725 ural_amrr_timeout(void *arg) 188640db2e2bSzf162725 { 188740db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 188840db2e2bSzf162725 struct ural_amrr *amrr = &sc->amrr; 188940db2e2bSzf162725 189040db2e2bSzf162725 ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta)); 189140db2e2bSzf162725 189240db2e2bSzf162725 /* count TX retry-fail as Tx errors */ 189340db2e2bSzf162725 sc->sc_tx_err += sc->sta[9]; 189440db2e2bSzf162725 sc->sc_tx_retries += (sc->sta[7] + sc->sta[8]); 189540db2e2bSzf162725 189640db2e2bSzf162725 amrr->retrycnt = 189740db2e2bSzf162725 sc->sta[7] + /* TX one-retry ok count */ 189840db2e2bSzf162725 sc->sta[8] + /* TX more-retry ok count */ 189940db2e2bSzf162725 sc->sta[9]; /* TX retry-fail count */ 190040db2e2bSzf162725 190140db2e2bSzf162725 amrr->txcnt = 190240db2e2bSzf162725 amrr->retrycnt + 190340db2e2bSzf162725 sc->sta[6]; /* TX no-retry ok count */ 190440db2e2bSzf162725 190540db2e2bSzf162725 ural_ratectl(amrr, sc->sc_ic.ic_bss); 190640db2e2bSzf162725 190740db2e2bSzf162725 sc->sc_amrr_id = timeout(ural_amrr_timeout, (void *)sc, 190840db2e2bSzf162725 drv_usectohz(1000 * 1000)); /* 1 second */ 190940db2e2bSzf162725 } 191040db2e2bSzf162725 191140db2e2bSzf162725 191240db2e2bSzf162725 static void 191340db2e2bSzf162725 ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni) 191440db2e2bSzf162725 { 191540db2e2bSzf162725 struct ural_amrr *amrr = &sc->amrr; 191640db2e2bSzf162725 int i; 191740db2e2bSzf162725 191840db2e2bSzf162725 /* clear statistic registers (STA_CSR0 to STA_CSR10) */ 191940db2e2bSzf162725 ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta)); 192040db2e2bSzf162725 192140db2e2bSzf162725 amrr->success = 0; 192240db2e2bSzf162725 amrr->recovery = 0; 192340db2e2bSzf162725 amrr->txcnt = amrr->retrycnt = 0; 192440db2e2bSzf162725 amrr->success_threshold = URAL_AMRR_MIN_SUCCESS_THRESHOLD; 192540db2e2bSzf162725 192640db2e2bSzf162725 /* set rate to some reasonable initial value */ 192740db2e2bSzf162725 for (i = ni->in_rates.ir_nrates - 1; 192840db2e2bSzf162725 i > 0 && (ni->in_rates.ir_rates[i] & IEEE80211_RATE_VAL) > 72; 192940db2e2bSzf162725 i--) { 193040db2e2bSzf162725 } 193140db2e2bSzf162725 193240db2e2bSzf162725 ni->in_txrate = i; 193340db2e2bSzf162725 193440db2e2bSzf162725 sc->sc_amrr_id = timeout(ural_amrr_timeout, (void *)sc, 193540db2e2bSzf162725 drv_usectohz(1000 * 1000)); /* 1 second */ 193640db2e2bSzf162725 } 193740db2e2bSzf162725 193840db2e2bSzf162725 void 193940db2e2bSzf162725 ural_watchdog(void *arg) 194040db2e2bSzf162725 { 194140db2e2bSzf162725 struct ural_softc *sc = arg; 194240db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 194340db2e2bSzf162725 int ntimer = 0; 194440db2e2bSzf162725 194540db2e2bSzf162725 RAL_LOCK(sc); 194640db2e2bSzf162725 ic->ic_watchdog_timer = 0; 194740db2e2bSzf162725 194840db2e2bSzf162725 if (!RAL_IS_RUNNING(sc)) { 194940db2e2bSzf162725 RAL_UNLOCK(sc); 195040db2e2bSzf162725 return; 195140db2e2bSzf162725 } 195240db2e2bSzf162725 195340db2e2bSzf162725 if (sc->sc_tx_timer > 0) { 195440db2e2bSzf162725 if (--sc->sc_tx_timer == 0) { 19551a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "tx timer timeout\n"); 195640db2e2bSzf162725 RAL_UNLOCK(sc); 195740db2e2bSzf162725 (void) ural_init(sc); 195840db2e2bSzf162725 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 195940db2e2bSzf162725 return; 196040db2e2bSzf162725 } 196140db2e2bSzf162725 } 196240db2e2bSzf162725 196340db2e2bSzf162725 if (ic->ic_state == IEEE80211_S_RUN) 196440db2e2bSzf162725 ntimer = 1; 196540db2e2bSzf162725 196640db2e2bSzf162725 RAL_UNLOCK(sc); 196740db2e2bSzf162725 196840db2e2bSzf162725 ieee80211_watchdog(ic); 196940db2e2bSzf162725 197040db2e2bSzf162725 if (ntimer) 197140db2e2bSzf162725 ieee80211_start_watchdog(ic, ntimer); 197240db2e2bSzf162725 } 197340db2e2bSzf162725 197440db2e2bSzf162725 static int 197540db2e2bSzf162725 ural_m_start(void *arg) 197640db2e2bSzf162725 { 197740db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 197840db2e2bSzf162725 int err; 197940db2e2bSzf162725 198040db2e2bSzf162725 /* 198140db2e2bSzf162725 * initialize RT2500USB hardware 198240db2e2bSzf162725 */ 198340db2e2bSzf162725 err = ural_init(sc); 198440db2e2bSzf162725 if (err != DDI_SUCCESS) { 19851a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "device configuration failed\n"); 198640db2e2bSzf162725 goto fail; 198740db2e2bSzf162725 } 198840db2e2bSzf162725 sc->sc_flags |= RAL_FLAG_RUNNING; /* RUNNING */ 198940db2e2bSzf162725 return (err); 199040db2e2bSzf162725 199140db2e2bSzf162725 fail: 199240db2e2bSzf162725 ural_stop(sc); 199340db2e2bSzf162725 return (err); 199440db2e2bSzf162725 } 199540db2e2bSzf162725 199640db2e2bSzf162725 static void 199740db2e2bSzf162725 ural_m_stop(void *arg) 199840db2e2bSzf162725 { 199940db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 200040db2e2bSzf162725 200140db2e2bSzf162725 (void) ural_stop(sc); 200240db2e2bSzf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */ 200340db2e2bSzf162725 } 200440db2e2bSzf162725 200540db2e2bSzf162725 static int 200640db2e2bSzf162725 ural_m_unicst(void *arg, const uint8_t *macaddr) 200740db2e2bSzf162725 { 200840db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 200940db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 201040db2e2bSzf162725 20111a932f2eSQuaker Fang ral_debug(RAL_DBG_MSG, "ural_m_unicst(): " MACSTR "\n", 201240db2e2bSzf162725 MAC2STR(macaddr)); 201340db2e2bSzf162725 201440db2e2bSzf162725 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr); 201540db2e2bSzf162725 (void) ural_set_macaddr(sc, (uint8_t *)macaddr); 201640db2e2bSzf162725 (void) ural_init(sc); 201740db2e2bSzf162725 201840db2e2bSzf162725 return (0); 201940db2e2bSzf162725 } 202040db2e2bSzf162725 202140db2e2bSzf162725 /*ARGSUSED*/ 202240db2e2bSzf162725 static int 202340db2e2bSzf162725 ural_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 202440db2e2bSzf162725 { 202540db2e2bSzf162725 return (0); 202640db2e2bSzf162725 } 202740db2e2bSzf162725 202840db2e2bSzf162725 static int 202940db2e2bSzf162725 ural_m_promisc(void *arg, boolean_t on) 203040db2e2bSzf162725 { 203140db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 203240db2e2bSzf162725 203340db2e2bSzf162725 if (on) { 203440db2e2bSzf162725 sc->sc_rcr |= RAL_RCR_PROMISC; 203540db2e2bSzf162725 sc->sc_rcr |= RAL_RCR_MULTI; 203640db2e2bSzf162725 } else { 203740db2e2bSzf162725 sc->sc_rcr &= ~RAL_RCR_PROMISC; 203840db2e2bSzf162725 sc->sc_rcr &= ~RAL_RCR_PROMISC; 203940db2e2bSzf162725 } 204040db2e2bSzf162725 204140db2e2bSzf162725 ural_update_promisc(sc); 204240db2e2bSzf162725 return (0); 204340db2e2bSzf162725 } 204440db2e2bSzf162725 20455644143aSQuaker Fang /* 20465644143aSQuaker Fang * callback functions for /get/set properties 20475644143aSQuaker Fang */ 20485644143aSQuaker Fang static int 20495644143aSQuaker Fang ural_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 20505644143aSQuaker Fang uint_t wldp_length, const void *wldp_buf) 20515644143aSQuaker Fang { 20525644143aSQuaker Fang struct ural_softc *sc = (struct ural_softc *)arg; 20535644143aSQuaker Fang struct ieee80211com *ic = &sc->sc_ic; 20545644143aSQuaker Fang int err; 20555644143aSQuaker Fang 20565644143aSQuaker Fang err = ieee80211_setprop(ic, pr_name, wldp_pr_num, 20575644143aSQuaker Fang wldp_length, wldp_buf); 20585644143aSQuaker Fang RAL_LOCK(sc); 20595644143aSQuaker Fang if (err == ENETRESET) { 20605644143aSQuaker Fang if (RAL_IS_RUNNING(sc)) { 20615644143aSQuaker Fang RAL_UNLOCK(sc); 20625644143aSQuaker Fang (void) ural_init(sc); 20635644143aSQuaker Fang (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 20645644143aSQuaker Fang RAL_LOCK(sc); 20655644143aSQuaker Fang } 20665644143aSQuaker Fang err = 0; 20675644143aSQuaker Fang } 20685644143aSQuaker Fang RAL_UNLOCK(sc); 20695644143aSQuaker Fang 20705644143aSQuaker Fang return (err); 20715644143aSQuaker Fang } 20725644143aSQuaker Fang 20735644143aSQuaker Fang static int 20745644143aSQuaker Fang ural_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2075*0dc2366fSVenugopal Iyer uint_t wldp_length, void *wldp_buf) 20765644143aSQuaker Fang { 20775644143aSQuaker Fang struct ural_softc *sc = (struct ural_softc *)arg; 20785644143aSQuaker Fang int err; 20795644143aSQuaker Fang 20805644143aSQuaker Fang err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, 2081*0dc2366fSVenugopal Iyer wldp_length, wldp_buf); 20825644143aSQuaker Fang 20835644143aSQuaker Fang return (err); 20845644143aSQuaker Fang } 20855644143aSQuaker Fang 208640db2e2bSzf162725 static void 2087*0dc2366fSVenugopal Iyer ural_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, 2088*0dc2366fSVenugopal Iyer mac_prop_info_handle_t mph) 2089*0dc2366fSVenugopal Iyer { 2090*0dc2366fSVenugopal Iyer struct ural_softc *sc = (struct ural_softc *)arg; 2091*0dc2366fSVenugopal Iyer 2092*0dc2366fSVenugopal Iyer ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph); 2093*0dc2366fSVenugopal Iyer } 2094*0dc2366fSVenugopal Iyer 2095*0dc2366fSVenugopal Iyer static void 209640db2e2bSzf162725 ural_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) 209740db2e2bSzf162725 { 209840db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 209940db2e2bSzf162725 struct ieee80211com *ic = &sc->sc_ic; 210040db2e2bSzf162725 int err; 210140db2e2bSzf162725 210240db2e2bSzf162725 err = ieee80211_ioctl(ic, wq, mp); 210340db2e2bSzf162725 RAL_LOCK(sc); 210440db2e2bSzf162725 if (err == ENETRESET) { 210540db2e2bSzf162725 if (RAL_IS_RUNNING(sc)) { 210640db2e2bSzf162725 RAL_UNLOCK(sc); 210740db2e2bSzf162725 (void) ural_init(sc); 210840db2e2bSzf162725 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 210940db2e2bSzf162725 RAL_LOCK(sc); 211040db2e2bSzf162725 } 211140db2e2bSzf162725 } 211240db2e2bSzf162725 RAL_UNLOCK(sc); 211340db2e2bSzf162725 } 211440db2e2bSzf162725 211540db2e2bSzf162725 static int 211640db2e2bSzf162725 ural_m_stat(void *arg, uint_t stat, uint64_t *val) 211740db2e2bSzf162725 { 211840db2e2bSzf162725 struct ural_softc *sc = (struct ural_softc *)arg; 211940db2e2bSzf162725 ieee80211com_t *ic = &sc->sc_ic; 212040db2e2bSzf162725 ieee80211_node_t *ni = ic->ic_bss; 212140db2e2bSzf162725 struct ieee80211_rateset *rs = &ni->in_rates; 212240db2e2bSzf162725 212340db2e2bSzf162725 RAL_LOCK(sc); 212440db2e2bSzf162725 switch (stat) { 212540db2e2bSzf162725 case MAC_STAT_IFSPEED: 212640db2e2bSzf162725 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? 212740db2e2bSzf162725 (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL) 2128020c4770Sql147931 : ic->ic_fixed_rate) / 2 * 1000000; 212940db2e2bSzf162725 break; 213040db2e2bSzf162725 case MAC_STAT_NOXMTBUF: 213140db2e2bSzf162725 *val = sc->sc_tx_nobuf; 213240db2e2bSzf162725 break; 213340db2e2bSzf162725 case MAC_STAT_NORCVBUF: 213440db2e2bSzf162725 *val = sc->sc_rx_nobuf; 213540db2e2bSzf162725 break; 213640db2e2bSzf162725 case MAC_STAT_IERRORS: 213740db2e2bSzf162725 *val = sc->sc_rx_err; 213840db2e2bSzf162725 break; 213940db2e2bSzf162725 case MAC_STAT_RBYTES: 214040db2e2bSzf162725 *val = ic->ic_stats.is_rx_bytes; 214140db2e2bSzf162725 break; 214240db2e2bSzf162725 case MAC_STAT_IPACKETS: 214340db2e2bSzf162725 *val = ic->ic_stats.is_rx_frags; 214440db2e2bSzf162725 break; 214540db2e2bSzf162725 case MAC_STAT_OBYTES: 214640db2e2bSzf162725 *val = ic->ic_stats.is_tx_bytes; 214740db2e2bSzf162725 break; 214840db2e2bSzf162725 case MAC_STAT_OPACKETS: 214940db2e2bSzf162725 *val = ic->ic_stats.is_tx_frags; 215040db2e2bSzf162725 break; 215140db2e2bSzf162725 case MAC_STAT_OERRORS: 215240db2e2bSzf162725 case WIFI_STAT_TX_FAILED: 215340db2e2bSzf162725 *val = sc->sc_tx_err; 215440db2e2bSzf162725 break; 215540db2e2bSzf162725 case WIFI_STAT_TX_RETRANS: 215640db2e2bSzf162725 *val = sc->sc_tx_retries; 215740db2e2bSzf162725 break; 215840db2e2bSzf162725 case WIFI_STAT_FCS_ERRORS: 215940db2e2bSzf162725 case WIFI_STAT_WEP_ERRORS: 216040db2e2bSzf162725 case WIFI_STAT_TX_FRAGS: 216140db2e2bSzf162725 case WIFI_STAT_MCAST_TX: 216240db2e2bSzf162725 case WIFI_STAT_RTS_SUCCESS: 216340db2e2bSzf162725 case WIFI_STAT_RTS_FAILURE: 216440db2e2bSzf162725 case WIFI_STAT_ACK_FAILURE: 216540db2e2bSzf162725 case WIFI_STAT_RX_FRAGS: 216640db2e2bSzf162725 case WIFI_STAT_MCAST_RX: 216740db2e2bSzf162725 case WIFI_STAT_RX_DUPS: 216840db2e2bSzf162725 RAL_UNLOCK(sc); 216940db2e2bSzf162725 return (ieee80211_stat(ic, stat, val)); 217040db2e2bSzf162725 default: 217140db2e2bSzf162725 RAL_UNLOCK(sc); 217240db2e2bSzf162725 return (ENOTSUP); 217340db2e2bSzf162725 } 217440db2e2bSzf162725 RAL_UNLOCK(sc); 217540db2e2bSzf162725 217640db2e2bSzf162725 return (0); 217740db2e2bSzf162725 } 217840db2e2bSzf162725 217940db2e2bSzf162725 218040db2e2bSzf162725 static int 218140db2e2bSzf162725 ural_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 218240db2e2bSzf162725 { 218340db2e2bSzf162725 struct ural_softc *sc; 218440db2e2bSzf162725 struct ieee80211com *ic; 218540db2e2bSzf162725 int err, i; 218640db2e2bSzf162725 int instance; 218740db2e2bSzf162725 218840db2e2bSzf162725 char strbuf[32]; 218940db2e2bSzf162725 219040db2e2bSzf162725 wifi_data_t wd = { 0 }; 219140db2e2bSzf162725 mac_register_t *macp; 219240db2e2bSzf162725 21931a932f2eSQuaker Fang switch (cmd) { 21941a932f2eSQuaker Fang case DDI_ATTACH: 21951a932f2eSQuaker Fang break; 21961a932f2eSQuaker Fang case DDI_RESUME: 21971a932f2eSQuaker Fang sc = ddi_get_soft_state(ural_soft_state_p, 21981a932f2eSQuaker Fang ddi_get_instance(devinfo)); 21991a932f2eSQuaker Fang ASSERT(sc != NULL); 22001a932f2eSQuaker Fang ural_resume(sc); 22011a932f2eSQuaker Fang return (DDI_SUCCESS); 22021a932f2eSQuaker Fang default: 220340db2e2bSzf162725 return (DDI_FAILURE); 22041a932f2eSQuaker Fang } 220540db2e2bSzf162725 220640db2e2bSzf162725 instance = ddi_get_instance(devinfo); 220740db2e2bSzf162725 220840db2e2bSzf162725 if (ddi_soft_state_zalloc(ural_soft_state_p, instance) != DDI_SUCCESS) { 22091a932f2eSQuaker Fang ral_debug(RAL_DBG_MSG, "ural_attach(): " 221040db2e2bSzf162725 "unable to alloc soft_state_p\n"); 221140db2e2bSzf162725 return (DDI_FAILURE); 221240db2e2bSzf162725 } 221340db2e2bSzf162725 221440db2e2bSzf162725 sc = ddi_get_soft_state(ural_soft_state_p, instance); 221540db2e2bSzf162725 ic = (ieee80211com_t *)&sc->sc_ic; 221640db2e2bSzf162725 sc->sc_dev = devinfo; 221740db2e2bSzf162725 221840db2e2bSzf162725 if (usb_client_attach(devinfo, USBDRV_VERSION, 0) != USB_SUCCESS) { 22191a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 222040db2e2bSzf162725 "ural_attach(): usb_client_attach failed\n"); 222140db2e2bSzf162725 goto fail1; 222240db2e2bSzf162725 } 222340db2e2bSzf162725 222440db2e2bSzf162725 if (usb_get_dev_data(devinfo, &sc->sc_udev, 222540db2e2bSzf162725 USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) { 222640db2e2bSzf162725 sc->sc_udev = NULL; 222740db2e2bSzf162725 goto fail2; 222840db2e2bSzf162725 } 222940db2e2bSzf162725 223040db2e2bSzf162725 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL); 223140db2e2bSzf162725 mutex_init(&sc->tx_lock, NULL, MUTEX_DRIVER, NULL); 223240db2e2bSzf162725 mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL); 223340db2e2bSzf162725 223440db2e2bSzf162725 /* retrieve RT2570 rev. no */ 223540db2e2bSzf162725 sc->asic_rev = ural_read(sc, RAL_MAC_CSR0); 223640db2e2bSzf162725 223740db2e2bSzf162725 /* retrieve MAC address and various other things from EEPROM */ 223840db2e2bSzf162725 ural_read_eeprom(sc); 223940db2e2bSzf162725 22401a932f2eSQuaker Fang ral_debug(RAL_DBG_MSG, "ural: MAC/BBP RT2570 (rev 0x%02x), RF %s\n", 224140db2e2bSzf162725 sc->asic_rev, ural_get_rf(sc->rf_rev)); 224240db2e2bSzf162725 224340db2e2bSzf162725 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 224440db2e2bSzf162725 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 224540db2e2bSzf162725 ic->ic_state = IEEE80211_S_INIT; 224640db2e2bSzf162725 224740db2e2bSzf162725 ic->ic_maxrssi = 63; 224840db2e2bSzf162725 ic->ic_set_shortslot = ural_update_slot; 224940db2e2bSzf162725 ic->ic_xmit = ural_send; 225040db2e2bSzf162725 225140db2e2bSzf162725 /* set device capabilities */ 225240db2e2bSzf162725 ic->ic_caps = 225340db2e2bSzf162725 IEEE80211_C_TXPMGT | /* tx power management */ 225440db2e2bSzf162725 IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 225540db2e2bSzf162725 IEEE80211_C_SHSLOT; /* short slot time supported */ 225640db2e2bSzf162725 225740db2e2bSzf162725 ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */ 225840db2e2bSzf162725 225940db2e2bSzf162725 #define IEEE80211_CHAN_A \ 226040db2e2bSzf162725 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) 226140db2e2bSzf162725 226240db2e2bSzf162725 if (sc->rf_rev == RAL_RF_5222) { 226340db2e2bSzf162725 /* set supported .11a rates */ 226440db2e2bSzf162725 ic->ic_sup_rates[IEEE80211_MODE_11A] = ural_rateset_11a; 226540db2e2bSzf162725 226640db2e2bSzf162725 /* set supported .11a channels */ 226740db2e2bSzf162725 for (i = 36; i <= 64; i += 4) { 226840db2e2bSzf162725 ic->ic_sup_channels[i].ich_freq = 226940db2e2bSzf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 227040db2e2bSzf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A; 227140db2e2bSzf162725 } 227240db2e2bSzf162725 for (i = 100; i <= 140; i += 4) { 227340db2e2bSzf162725 ic->ic_sup_channels[i].ich_freq = 227440db2e2bSzf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 227540db2e2bSzf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A; 227640db2e2bSzf162725 } 227740db2e2bSzf162725 for (i = 149; i <= 161; i += 4) { 227840db2e2bSzf162725 ic->ic_sup_channels[i].ich_freq = 227940db2e2bSzf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 228040db2e2bSzf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A; 228140db2e2bSzf162725 } 228240db2e2bSzf162725 } 228340db2e2bSzf162725 228440db2e2bSzf162725 /* set supported .11b and .11g rates */ 228540db2e2bSzf162725 ic->ic_sup_rates[IEEE80211_MODE_11B] = ural_rateset_11b; 228640db2e2bSzf162725 ic->ic_sup_rates[IEEE80211_MODE_11G] = ural_rateset_11g; 228740db2e2bSzf162725 228840db2e2bSzf162725 /* set supported .11b and .11g channels (1 through 14) */ 228940db2e2bSzf162725 for (i = 1; i <= 14; i++) { 229040db2e2bSzf162725 ic->ic_sup_channels[i].ich_freq = 229140db2e2bSzf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 229240db2e2bSzf162725 ic->ic_sup_channels[i].ich_flags = 229340db2e2bSzf162725 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 229440db2e2bSzf162725 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 229540db2e2bSzf162725 } 229640db2e2bSzf162725 229740db2e2bSzf162725 ieee80211_attach(ic); 229840db2e2bSzf162725 229940db2e2bSzf162725 /* register WPA door */ 230040db2e2bSzf162725 ieee80211_register_door(ic, ddi_driver_name(devinfo), 230140db2e2bSzf162725 ddi_get_instance(devinfo)); 230240db2e2bSzf162725 230340db2e2bSzf162725 /* override state transition machine */ 230440db2e2bSzf162725 sc->sc_newstate = ic->ic_newstate; 230540db2e2bSzf162725 ic->ic_newstate = ural_newstate; 230640db2e2bSzf162725 ic->ic_watchdog = ural_watchdog; 230740db2e2bSzf162725 ieee80211_media_init(ic); 230840db2e2bSzf162725 ic->ic_def_txkey = 0; 230940db2e2bSzf162725 231040db2e2bSzf162725 sc->sc_rcr = 0; 231140db2e2bSzf162725 sc->dwelltime = 300; 23121a932f2eSQuaker Fang sc->sc_flags &= 0; 231340db2e2bSzf162725 231440db2e2bSzf162725 /* 231540db2e2bSzf162725 * Provide initial settings for the WiFi plugin; whenever this 231640db2e2bSzf162725 * information changes, we need to call mac_plugindata_update() 231740db2e2bSzf162725 */ 231840db2e2bSzf162725 wd.wd_opmode = ic->ic_opmode; 231940db2e2bSzf162725 wd.wd_secalloc = WIFI_SEC_NONE; 232040db2e2bSzf162725 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid); 232140db2e2bSzf162725 232240db2e2bSzf162725 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 23231a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_attach(): " 232440db2e2bSzf162725 "MAC version mismatch\n"); 232540db2e2bSzf162725 goto fail3; 232640db2e2bSzf162725 } 232740db2e2bSzf162725 232840db2e2bSzf162725 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI; 232940db2e2bSzf162725 macp->m_driver = sc; 233040db2e2bSzf162725 macp->m_dip = devinfo; 233140db2e2bSzf162725 macp->m_src_addr = ic->ic_macaddr; 233240db2e2bSzf162725 macp->m_callbacks = &ural_m_callbacks; 233340db2e2bSzf162725 macp->m_min_sdu = 0; 233440db2e2bSzf162725 macp->m_max_sdu = IEEE80211_MTU; 233540db2e2bSzf162725 macp->m_pdata = &wd; 233640db2e2bSzf162725 macp->m_pdata_size = sizeof (wd); 233740db2e2bSzf162725 233840db2e2bSzf162725 err = mac_register(macp, &ic->ic_mach); 233940db2e2bSzf162725 mac_free(macp); 234040db2e2bSzf162725 if (err != 0) { 23411a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ural_attach(): " 234240db2e2bSzf162725 "mac_register() err %x\n", err); 234340db2e2bSzf162725 goto fail3; 234440db2e2bSzf162725 } 234540db2e2bSzf162725 23461a932f2eSQuaker Fang if (usb_register_hotplug_cbs(devinfo, ural_disconnect, 23471a932f2eSQuaker Fang ural_reconnect) != USB_SUCCESS) { 23481a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, 234940db2e2bSzf162725 "ural: ural_attach() failed to register events"); 235040db2e2bSzf162725 goto fail4; 235140db2e2bSzf162725 } 235240db2e2bSzf162725 235340db2e2bSzf162725 /* 235440db2e2bSzf162725 * Create minor node of type DDI_NT_NET_WIFI 235540db2e2bSzf162725 */ 235640db2e2bSzf162725 (void) snprintf(strbuf, sizeof (strbuf), "%s%d", 235740db2e2bSzf162725 "ural", instance); 235840db2e2bSzf162725 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR, 235940db2e2bSzf162725 instance + 1, DDI_NT_NET_WIFI, 0); 236040db2e2bSzf162725 236140db2e2bSzf162725 if (err != DDI_SUCCESS) 23621a932f2eSQuaker Fang ral_debug(RAL_DBG_ERR, "ddi_create_minor_node() failed\n"); 236340db2e2bSzf162725 236440db2e2bSzf162725 /* 236540db2e2bSzf162725 * Notify link is down now 236640db2e2bSzf162725 */ 236740db2e2bSzf162725 mac_link_update(ic->ic_mach, LINK_STATE_DOWN); 236840db2e2bSzf162725 236940db2e2bSzf162725 return (DDI_SUCCESS); 237040db2e2bSzf162725 fail4: 237140db2e2bSzf162725 (void) mac_unregister(ic->ic_mach); 237240db2e2bSzf162725 fail3: 237340db2e2bSzf162725 mutex_destroy(&sc->sc_genlock); 237440db2e2bSzf162725 mutex_destroy(&sc->tx_lock); 237540db2e2bSzf162725 mutex_destroy(&sc->rx_lock); 237640db2e2bSzf162725 fail2: 237740db2e2bSzf162725 usb_client_detach(sc->sc_dev, sc->sc_udev); 237840db2e2bSzf162725 fail1: 237940db2e2bSzf162725 ddi_soft_state_free(ural_soft_state_p, ddi_get_instance(devinfo)); 238040db2e2bSzf162725 238140db2e2bSzf162725 return (DDI_FAILURE); 238240db2e2bSzf162725 } 238340db2e2bSzf162725 238440db2e2bSzf162725 static int 238540db2e2bSzf162725 ural_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 238640db2e2bSzf162725 { 238740db2e2bSzf162725 struct ural_softc *sc; 238840db2e2bSzf162725 238940db2e2bSzf162725 sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo)); 23901a932f2eSQuaker Fang ASSERT(sc != NULL); 239140db2e2bSzf162725 23921a932f2eSQuaker Fang switch (cmd) { 23931a932f2eSQuaker Fang case DDI_DETACH: 23941a932f2eSQuaker Fang break; 23951a932f2eSQuaker Fang case DDI_SUSPEND: 23961a932f2eSQuaker Fang if (RAL_IS_RUNNING(sc)) 23971a932f2eSQuaker Fang (void) ural_stop(sc); 23981a932f2eSQuaker Fang return (DDI_SUCCESS); 23991a932f2eSQuaker Fang default: 240040db2e2bSzf162725 return (DDI_FAILURE); 24011a932f2eSQuaker Fang } 240240db2e2bSzf162725 240342516a0cSxinghua wen - Sun Microsystems - Beijing China if (mac_disable(sc->sc_ic.ic_mach) != 0) 240442516a0cSxinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE); 240542516a0cSxinghua wen - Sun Microsystems - Beijing China 240640db2e2bSzf162725 ural_stop(sc); 240740db2e2bSzf162725 usb_unregister_hotplug_cbs(devinfo); 240840db2e2bSzf162725 240940db2e2bSzf162725 /* 241040db2e2bSzf162725 * Unregister from the MAC layer subsystem 241140db2e2bSzf162725 */ 241242516a0cSxinghua wen - Sun Microsystems - Beijing China (void) mac_unregister(sc->sc_ic.ic_mach); 241340db2e2bSzf162725 241440db2e2bSzf162725 /* 241540db2e2bSzf162725 * detach ieee80211 layer 241640db2e2bSzf162725 */ 241740db2e2bSzf162725 ieee80211_detach(&sc->sc_ic); 241840db2e2bSzf162725 241940db2e2bSzf162725 mutex_destroy(&sc->sc_genlock); 242040db2e2bSzf162725 mutex_destroy(&sc->tx_lock); 242140db2e2bSzf162725 mutex_destroy(&sc->rx_lock); 242240db2e2bSzf162725 242340db2e2bSzf162725 /* pipes will be close in ural_stop() */ 242440db2e2bSzf162725 usb_client_detach(devinfo, sc->sc_udev); 242540db2e2bSzf162725 sc->sc_udev = NULL; 242640db2e2bSzf162725 242740db2e2bSzf162725 ddi_remove_minor_node(devinfo, NULL); 242840db2e2bSzf162725 ddi_soft_state_free(ural_soft_state_p, ddi_get_instance(devinfo)); 242940db2e2bSzf162725 243040db2e2bSzf162725 return (DDI_SUCCESS); 243140db2e2bSzf162725 } 243240db2e2bSzf162725 243340db2e2bSzf162725 int 243440db2e2bSzf162725 _info(struct modinfo *modinfop) 243540db2e2bSzf162725 { 243640db2e2bSzf162725 return (mod_info(&modlinkage, modinfop)); 243740db2e2bSzf162725 } 243840db2e2bSzf162725 243940db2e2bSzf162725 int 244040db2e2bSzf162725 _init(void) 244140db2e2bSzf162725 { 244240db2e2bSzf162725 int status; 244340db2e2bSzf162725 244440db2e2bSzf162725 status = ddi_soft_state_init(&ural_soft_state_p, 244540db2e2bSzf162725 sizeof (struct ural_softc), 1); 244640db2e2bSzf162725 if (status != 0) 244740db2e2bSzf162725 return (status); 244840db2e2bSzf162725 244940db2e2bSzf162725 mac_init_ops(&ural_dev_ops, "ural"); 245040db2e2bSzf162725 status = mod_install(&modlinkage); 245140db2e2bSzf162725 if (status != 0) { 245240db2e2bSzf162725 mac_fini_ops(&ural_dev_ops); 245340db2e2bSzf162725 ddi_soft_state_fini(&ural_soft_state_p); 245440db2e2bSzf162725 } 245540db2e2bSzf162725 return (status); 245640db2e2bSzf162725 } 245740db2e2bSzf162725 245840db2e2bSzf162725 int 245940db2e2bSzf162725 _fini(void) 246040db2e2bSzf162725 { 246140db2e2bSzf162725 int status; 246240db2e2bSzf162725 246340db2e2bSzf162725 status = mod_remove(&modlinkage); 246440db2e2bSzf162725 if (status == 0) { 246540db2e2bSzf162725 mac_fini_ops(&ural_dev_ops); 246640db2e2bSzf162725 ddi_soft_state_fini(&ural_soft_state_p); 246740db2e2bSzf162725 } 246840db2e2bSzf162725 return (status); 246940db2e2bSzf162725 } 2470