16629Szf162725 /*
2*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
36629Szf162725 * Use is subject to license terms.
46629Szf162725 */
56629Szf162725
66629Szf162725 /*
76629Szf162725 * Copyright (c) 2005, 2006
86629Szf162725 * Damien Bergamini <damien.bergamini@free.fr>
96629Szf162725 *
106629Szf162725 * Permission to use, copy, modify, and distribute this software for any
116629Szf162725 * purpose with or without fee is hereby granted, provided that the above
126629Szf162725 * copyright notice and this permission notice appear in all copies.
136629Szf162725 *
146629Szf162725 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
156629Szf162725 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
166629Szf162725 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
176629Szf162725 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
186629Szf162725 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
196629Szf162725 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
206629Szf162725 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
216629Szf162725 */
226629Szf162725
236629Szf162725 /*
246629Szf162725 * Ralink Technology RT2500USB chipset driver
256629Szf162725 * http://www.ralinktech.com/
266629Szf162725 */
276629Szf162725 #include <sys/types.h>
286629Szf162725 #include <sys/cmn_err.h>
296629Szf162725 #include <sys/strsubr.h>
306629Szf162725 #include <sys/modctl.h>
316629Szf162725 #include <sys/devops.h>
32*11878SVenu.Iyer@Sun.COM #include <sys/byteorder.h>
338275SEric Cheng #include <sys/mac_provider.h>
346629Szf162725 #include <sys/mac_wifi.h>
356629Szf162725 #include <sys/net80211.h>
366629Szf162725
376629Szf162725 #define USBDRV_MAJOR_VER 2
386629Szf162725 #define USBDRV_MINOR_VER 0
396629Szf162725 #include <sys/usb/usba.h>
409345SQuaker.Fang@Sun.COM #include <sys/usb/usba/usba_types.h>
416629Szf162725
426629Szf162725 #include "ural_reg.h"
436629Szf162725 #include "ural_var.h"
446629Szf162725
456629Szf162725 static void *ural_soft_state_p = NULL;
466629Szf162725
476629Szf162725 #define RAL_TXBUF_SIZE (IEEE80211_MAX_LEN)
486629Szf162725 #define RAL_RXBUF_SIZE (IEEE80211_MAX_LEN)
496629Szf162725
506629Szf162725 /* quickly determine if a given rate is CCK or OFDM */
516629Szf162725 #define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
526629Szf162725 #define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */
536629Szf162725 #define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */
546629Szf162725 #define RAL_SIFS 10 /* us */
556629Szf162725 #define RAL_RXTX_TURNAROUND 5 /* us */
566629Szf162725
576629Szf162725 #define URAL_N(a) (sizeof (a) / sizeof ((a)[0]))
586629Szf162725
596629Szf162725 /*
606629Szf162725 * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
616629Szf162725 */
626629Szf162725 static const struct ieee80211_rateset ural_rateset_11a =
636629Szf162725 { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
646629Szf162725
656629Szf162725 static const struct ieee80211_rateset ural_rateset_11b =
666629Szf162725 { 4, { 2, 4, 11, 22 } };
676629Szf162725
686629Szf162725 static const struct ieee80211_rateset ural_rateset_11g =
696629Szf162725 { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
706629Szf162725
716629Szf162725 /*
726629Szf162725 * Default values for MAC registers; values taken from the reference driver.
736629Szf162725 */
746629Szf162725 static const struct {
756629Szf162725 uint16_t reg;
766629Szf162725 uint16_t val;
776629Szf162725 } ural_def_mac[] = {
786629Szf162725 { RAL_TXRX_CSR5, 0x8c8d },
796629Szf162725 { RAL_TXRX_CSR6, 0x8b8a },
806629Szf162725 { RAL_TXRX_CSR7, 0x8687 },
816629Szf162725 { RAL_TXRX_CSR8, 0x0085 },
826629Szf162725 { RAL_MAC_CSR13, 0x1111 },
836629Szf162725 { RAL_MAC_CSR14, 0x1e11 },
846629Szf162725 { RAL_TXRX_CSR21, 0xe78f },
856629Szf162725 { RAL_MAC_CSR9, 0xff1d },
866629Szf162725 { RAL_MAC_CSR11, 0x0002 },
876629Szf162725 { RAL_MAC_CSR22, 0x0053 },
886629Szf162725 { RAL_MAC_CSR15, 0x0000 },
896629Szf162725 { RAL_MAC_CSR8, 0x0780 },
906629Szf162725 { RAL_TXRX_CSR19, 0x0000 },
916629Szf162725 { RAL_TXRX_CSR18, 0x005a },
926629Szf162725 { RAL_PHY_CSR2, 0x0000 },
936629Szf162725 { RAL_TXRX_CSR0, 0x1ec0 },
946629Szf162725 { RAL_PHY_CSR4, 0x000f }
956629Szf162725 };
966629Szf162725
976629Szf162725 /*
986629Szf162725 * Default values for BBP registers; values taken from the reference driver.
996629Szf162725 */
1006629Szf162725 static const struct {
1016629Szf162725 uint8_t reg;
1026629Szf162725 uint8_t val;
1036629Szf162725 } ural_def_bbp[] = {
1046629Szf162725 { 3, 0x02 },
1056629Szf162725 { 4, 0x19 },
1066629Szf162725 { 14, 0x1c },
1076629Szf162725 { 15, 0x30 },
1086629Szf162725 { 16, 0xac },
1096629Szf162725 { 17, 0x48 },
1106629Szf162725 { 18, 0x18 },
1116629Szf162725 { 19, 0xff },
1126629Szf162725 { 20, 0x1e },
1136629Szf162725 { 21, 0x08 },
1146629Szf162725 { 22, 0x08 },
1156629Szf162725 { 23, 0x08 },
1166629Szf162725 { 24, 0x80 },
1176629Szf162725 { 25, 0x50 },
1186629Szf162725 { 26, 0x08 },
1196629Szf162725 { 27, 0x23 },
1206629Szf162725 { 30, 0x10 },
1216629Szf162725 { 31, 0x2b },
1226629Szf162725 { 32, 0xb9 },
1236629Szf162725 { 34, 0x12 },
1246629Szf162725 { 35, 0x50 },
1256629Szf162725 { 39, 0xc4 },
1266629Szf162725 { 40, 0x02 },
1276629Szf162725 { 41, 0x60 },
1286629Szf162725 { 53, 0x10 },
1296629Szf162725 { 54, 0x18 },
1306629Szf162725 { 56, 0x08 },
1316629Szf162725 { 57, 0x10 },
1326629Szf162725 { 58, 0x08 },
1336629Szf162725 { 61, 0x60 },
1346629Szf162725 { 62, 0x10 },
1356629Szf162725 { 75, 0xff }
1366629Szf162725 };
1376629Szf162725
1386629Szf162725 /*
1396629Szf162725 * Default values for RF register R2 indexed by channel numbers.
1406629Szf162725 */
1416629Szf162725 static const uint32_t ural_rf2522_r2[] = {
1426629Szf162725 0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814,
1436629Szf162725 0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e
1446629Szf162725 };
1456629Szf162725
1466629Szf162725 static const uint32_t ural_rf2523_r2[] = {
1476629Szf162725 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
1486629Szf162725 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
1496629Szf162725 };
1506629Szf162725
1516629Szf162725 static const uint32_t ural_rf2524_r2[] = {
1526629Szf162725 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
1536629Szf162725 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
1546629Szf162725 };
1556629Szf162725
1566629Szf162725 static const uint32_t ural_rf2525_r2[] = {
1576629Szf162725 0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d,
1586629Szf162725 0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346
1596629Szf162725 };
1606629Szf162725
1616629Szf162725 static const uint32_t ural_rf2525_hi_r2[] = {
1626629Szf162725 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345,
1636629Szf162725 0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e
1646629Szf162725 };
1656629Szf162725
1666629Szf162725 static const uint32_t ural_rf2525e_r2[] = {
1676629Szf162725 0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463,
1686629Szf162725 0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b
1696629Szf162725 };
1706629Szf162725
1716629Szf162725 static const uint32_t ural_rf2526_hi_r2[] = {
1726629Szf162725 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d,
1736629Szf162725 0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241
1746629Szf162725 };
1756629Szf162725
1766629Szf162725 static const uint32_t ural_rf2526_r2[] = {
1776629Szf162725 0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229,
1786629Szf162725 0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d
1796629Szf162725 };
1806629Szf162725
1816629Szf162725 /*
1826629Szf162725 * For dual-band RF, RF registers R1 and R4 also depend on channel number;
1836629Szf162725 * values taken from the reference driver.
1846629Szf162725 */
1856629Szf162725 static const struct {
1866629Szf162725 uint8_t chan;
1876629Szf162725 uint32_t r1;
1886629Szf162725 uint32_t r2;
1896629Szf162725 uint32_t r4;
1906629Szf162725 } ural_rf5222[] = {
1916629Szf162725 { 1, 0x08808, 0x0044d, 0x00282 },
1926629Szf162725 { 2, 0x08808, 0x0044e, 0x00282 },
1936629Szf162725 { 3, 0x08808, 0x0044f, 0x00282 },
1946629Szf162725 { 4, 0x08808, 0x00460, 0x00282 },
1956629Szf162725 { 5, 0x08808, 0x00461, 0x00282 },
1966629Szf162725 { 6, 0x08808, 0x00462, 0x00282 },
1976629Szf162725 { 7, 0x08808, 0x00463, 0x00282 },
1986629Szf162725 { 8, 0x08808, 0x00464, 0x00282 },
1996629Szf162725 { 9, 0x08808, 0x00465, 0x00282 },
2006629Szf162725 { 10, 0x08808, 0x00466, 0x00282 },
2016629Szf162725 { 11, 0x08808, 0x00467, 0x00282 },
2026629Szf162725 { 12, 0x08808, 0x00468, 0x00282 },
2036629Szf162725 { 13, 0x08808, 0x00469, 0x00282 },
2046629Szf162725 { 14, 0x08808, 0x0046b, 0x00286 },
2056629Szf162725
2066629Szf162725 { 36, 0x08804, 0x06225, 0x00287 },
2076629Szf162725 { 40, 0x08804, 0x06226, 0x00287 },
2086629Szf162725 { 44, 0x08804, 0x06227, 0x00287 },
2096629Szf162725 { 48, 0x08804, 0x06228, 0x00287 },
2106629Szf162725 { 52, 0x08804, 0x06229, 0x00287 },
2116629Szf162725 { 56, 0x08804, 0x0622a, 0x00287 },
2126629Szf162725 { 60, 0x08804, 0x0622b, 0x00287 },
2136629Szf162725 { 64, 0x08804, 0x0622c, 0x00287 },
2146629Szf162725
2156629Szf162725 { 100, 0x08804, 0x02200, 0x00283 },
2166629Szf162725 { 104, 0x08804, 0x02201, 0x00283 },
2176629Szf162725 { 108, 0x08804, 0x02202, 0x00283 },
2186629Szf162725 { 112, 0x08804, 0x02203, 0x00283 },
2196629Szf162725 { 116, 0x08804, 0x02204, 0x00283 },
2206629Szf162725 { 120, 0x08804, 0x02205, 0x00283 },
2216629Szf162725 { 124, 0x08804, 0x02206, 0x00283 },
2226629Szf162725 { 128, 0x08804, 0x02207, 0x00283 },
2236629Szf162725 { 132, 0x08804, 0x02208, 0x00283 },
2246629Szf162725 { 136, 0x08804, 0x02209, 0x00283 },
2256629Szf162725 { 140, 0x08804, 0x0220a, 0x00283 },
2266629Szf162725
2276629Szf162725 { 149, 0x08808, 0x02429, 0x00281 },
2286629Szf162725 { 153, 0x08808, 0x0242b, 0x00281 },
2296629Szf162725 { 157, 0x08808, 0x0242d, 0x00281 },
2306629Szf162725 { 161, 0x08808, 0x0242f, 0x00281 }
2316629Szf162725 };
2326629Szf162725
2336629Szf162725 /*
2346629Szf162725 * device operations
2356629Szf162725 */
2366629Szf162725 static int ural_attach(dev_info_t *, ddi_attach_cmd_t);
2376629Szf162725 static int ural_detach(dev_info_t *, ddi_detach_cmd_t);
2386629Szf162725
2396629Szf162725 /*
2406629Szf162725 * Module Loading Data & Entry Points
2416629Szf162725 */
2426629Szf162725 DDI_DEFINE_STREAM_OPS(ural_dev_ops, nulldev, nulldev, ural_attach,
2438099SQuaker.Fang@Sun.COM ural_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed);
2446629Szf162725
2456629Szf162725 static struct modldrv ural_modldrv = {
2466629Szf162725 &mod_driverops, /* Type of module. This one is a driver */
2479345SQuaker.Fang@Sun.COM "ural driver v1.4", /* short description */
2486629Szf162725 &ural_dev_ops /* driver specific ops */
2496629Szf162725 };
2506629Szf162725
2516629Szf162725 static struct modlinkage modlinkage = {
2526629Szf162725 MODREV_1,
2536629Szf162725 (void *)&ural_modldrv,
2546629Szf162725 NULL
2556629Szf162725 };
2566629Szf162725
2576629Szf162725 static int ural_m_stat(void *, uint_t, uint64_t *);
2586629Szf162725 static int ural_m_start(void *);
2596629Szf162725 static void ural_m_stop(void *);
2606629Szf162725 static int ural_m_promisc(void *, boolean_t);
2616629Szf162725 static int ural_m_multicst(void *, boolean_t, const uint8_t *);
2626629Szf162725 static int ural_m_unicst(void *, const uint8_t *);
2636629Szf162725 static mblk_t *ural_m_tx(void *, mblk_t *);
2646629Szf162725 static void ural_m_ioctl(void *, queue_t *, mblk_t *);
2658099SQuaker.Fang@Sun.COM static int ural_m_setprop(void *, const char *, mac_prop_id_t,
2668099SQuaker.Fang@Sun.COM uint_t, const void *);
2678099SQuaker.Fang@Sun.COM static int ural_m_getprop(void *, const char *, mac_prop_id_t,
268*11878SVenu.Iyer@Sun.COM uint_t, void *);
269*11878SVenu.Iyer@Sun.COM static void ural_m_propinfo(void *, const char *, mac_prop_id_t,
270*11878SVenu.Iyer@Sun.COM mac_prop_info_handle_t);
2716629Szf162725
2726629Szf162725 static mac_callbacks_t ural_m_callbacks = {
273*11878SVenu.Iyer@Sun.COM MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
2746629Szf162725 ural_m_stat,
2756629Szf162725 ural_m_start,
2766629Szf162725 ural_m_stop,
2776629Szf162725 ural_m_promisc,
2786629Szf162725 ural_m_multicst,
2796629Szf162725 ural_m_unicst,
2806629Szf162725 ural_m_tx,
281*11878SVenu.Iyer@Sun.COM NULL,
2826629Szf162725 ural_m_ioctl,
2838099SQuaker.Fang@Sun.COM NULL, /* mc_getcapab */
2848099SQuaker.Fang@Sun.COM NULL,
2858099SQuaker.Fang@Sun.COM NULL,
2868099SQuaker.Fang@Sun.COM ural_m_setprop,
287*11878SVenu.Iyer@Sun.COM ural_m_getprop,
288*11878SVenu.Iyer@Sun.COM ural_m_propinfo
2896629Szf162725 };
2906629Szf162725
2916629Szf162725 static void ural_amrr_start(struct ural_softc *, struct ieee80211_node *);
2926629Szf162725 static int ural_tx_trigger(struct ural_softc *, mblk_t *);
2936629Szf162725 static int ural_rx_trigger(struct ural_softc *);
2946629Szf162725
2956629Szf162725 uint32_t ural_dbg_flags = 0;
2966629Szf162725
2976629Szf162725 void
ral_debug(uint32_t dbg_flags,const int8_t * fmt,...)2986629Szf162725 ral_debug(uint32_t dbg_flags, const int8_t *fmt, ...)
2996629Szf162725 {
3006629Szf162725 va_list args;
3016629Szf162725
3026629Szf162725 if (dbg_flags & ural_dbg_flags) {
3036629Szf162725 va_start(args, fmt);
3046629Szf162725 vcmn_err(CE_CONT, fmt, args);
3056629Szf162725 va_end(args);
3066629Szf162725 }
3076629Szf162725 }
3086629Szf162725
3096629Szf162725 static uint16_t
ural_read(struct ural_softc * sc,uint16_t reg)3106629Szf162725 ural_read(struct ural_softc *sc, uint16_t reg)
3116629Szf162725 {
3126629Szf162725 usb_ctrl_setup_t req;
3136629Szf162725 usb_cr_t cr;
3146629Szf162725 usb_cb_flags_t cf;
3156629Szf162725 mblk_t *mp;
3166629Szf162725 int err;
3176629Szf162725 uint16_t val;
3186629Szf162725
3196629Szf162725 bzero(&req, sizeof (req));
3206629Szf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
3216629Szf162725 req.bRequest = RAL_READ_MAC;
3226629Szf162725 req.wValue = 0;
3236629Szf162725 req.wIndex = reg;
3246629Szf162725 req.wLength = sizeof (uint16_t);
3256629Szf162725
3266629Szf162725 mp = NULL;
3276629Szf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
3286629Szf162725 &cr, &cf, 0);
3296629Szf162725
3306629Szf162725 if (err != USB_SUCCESS) {
3319345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
3326629Szf162725 "ural_read(): could not read MAC register:"
3336629Szf162725 " cr:%s(%d), cf:(%x)\n",
3346629Szf162725 usb_str_cr(cr), cr, cf);
3356629Szf162725 return (0);
3366629Szf162725 }
3376629Szf162725
3386629Szf162725 bcopy(mp->b_rptr, &val, sizeof (uint16_t));
3396629Szf162725
3406629Szf162725 if (mp)
3416629Szf162725 freemsg(mp);
3426629Szf162725
3436629Szf162725 return (LE_16(val));
3446629Szf162725 }
3456629Szf162725
3466629Szf162725 static void
ural_read_multi(struct ural_softc * sc,uint16_t reg,void * buf,int len)3476629Szf162725 ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
3486629Szf162725 {
3496629Szf162725 usb_ctrl_setup_t req;
3506629Szf162725 usb_cr_t cr;
3516629Szf162725 usb_cb_flags_t cf;
3526629Szf162725 mblk_t *mp;
3536629Szf162725 int err;
3546629Szf162725
3556629Szf162725 bzero(&req, sizeof (req));
3566629Szf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
3576629Szf162725 req.bRequest = RAL_READ_MULTI_MAC;
3586629Szf162725 req.wValue = 0;
3596629Szf162725 req.wIndex = reg;
3606629Szf162725 req.wLength = (uint16_t)len;
3616629Szf162725 req.attrs = USB_ATTRS_AUTOCLEARING;
3626629Szf162725
3636629Szf162725 mp = NULL;
3646629Szf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
3656629Szf162725 &cr, &cf, 0);
3666629Szf162725
3676629Szf162725 if (err != USB_SUCCESS) {
3689345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
3696629Szf162725 "ural_read_multi(): could not read MAC register:"
3706629Szf162725 "cr:%s(%d), cf:(%x)\n",
3716629Szf162725 usb_str_cr(cr), cr, cf);
3726629Szf162725 return;
3736629Szf162725 }
3746629Szf162725
3756629Szf162725 bcopy(mp->b_rptr, buf, len);
3766629Szf162725
3776629Szf162725 if (mp)
3786629Szf162725 freemsg(mp);
3796629Szf162725 }
3806629Szf162725
3816629Szf162725 static void
ural_write(struct ural_softc * sc,uint16_t reg,uint16_t val)3826629Szf162725 ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val)
3836629Szf162725 {
3846629Szf162725 usb_ctrl_setup_t req;
3856629Szf162725 usb_cr_t cr;
3866629Szf162725 usb_cb_flags_t cf;
3876629Szf162725 int err;
3886629Szf162725
3896629Szf162725 bzero(&req, sizeof (req));
3906629Szf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV;
3916629Szf162725 req.bRequest = RAL_WRITE_MAC;
3926629Szf162725 req.wValue = val;
3936629Szf162725 req.wIndex = reg;
3946629Szf162725 req.wLength = 0;
3956629Szf162725 req.attrs = USB_ATTRS_NONE;
3966629Szf162725
3976629Szf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, NULL,
3986629Szf162725 &cr, &cf, 0);
3996629Szf162725
4006629Szf162725 if (err != USB_SUCCESS) {
4019345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
4026629Szf162725 "ural_write(): could not write MAC register:"
4036629Szf162725 "cr:%s(%d), cf:(%x)\n",
4046629Szf162725 usb_str_cr(cr), cr, cf);
4056629Szf162725 }
4066629Szf162725 }
4076629Szf162725
4086629Szf162725 /* ARGSUSED */
4096629Szf162725 static void
ural_txeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)4106629Szf162725 ural_txeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
4116629Szf162725 {
4126629Szf162725 struct ural_softc *sc = (struct ural_softc *)req->bulk_client_private;
4136629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
4146629Szf162725
4159345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_TX,
4166629Szf162725 "ural_txeof(): cr:%s(%d), flags:0x%x, tx_queued:%d",
4176629Szf162725 usb_str_cr(req->bulk_completion_reason),
4186629Szf162725 req->bulk_completion_reason,
4196629Szf162725 req->bulk_cb_flags,
4206629Szf162725 sc->tx_queued);
4216629Szf162725
4226629Szf162725 if (req->bulk_completion_reason != USB_CR_OK)
4236629Szf162725 sc->sc_tx_err++;
4246629Szf162725
4256629Szf162725 mutex_enter(&sc->tx_lock);
4266629Szf162725
4276629Szf162725 sc->tx_queued--;
4286629Szf162725 sc->sc_tx_timer = 0;
4296629Szf162725
4306629Szf162725 if (sc->sc_need_sched) {
4316629Szf162725 sc->sc_need_sched = 0;
4326629Szf162725 mac_tx_update(ic->ic_mach);
4336629Szf162725 }
4346629Szf162725
4356629Szf162725 mutex_exit(&sc->tx_lock);
4366629Szf162725 usb_free_bulk_req(req);
4376629Szf162725 }
4386629Szf162725
4396629Szf162725 /* ARGSUSED */
4406629Szf162725 static void
ural_rxeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)4416629Szf162725 ural_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
4426629Szf162725 {
4436629Szf162725 struct ural_softc *sc = (struct ural_softc *)req->bulk_client_private;
4446629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
4456629Szf162725
4466629Szf162725 struct ural_rx_desc *desc;
4476629Szf162725 struct ieee80211_frame *wh;
4486629Szf162725 struct ieee80211_node *ni;
4496629Szf162725
4506629Szf162725 mblk_t *m, *mp;
4516629Szf162725 int len, pktlen;
4526629Szf162725 char *rxbuf;
4536629Szf162725
4546629Szf162725 mp = req->bulk_data;
4556629Szf162725 req->bulk_data = NULL;
4566629Szf162725
4579345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_RX,
4586629Szf162725 "ural_rxeof(): cr:%s(%d), flags:0x%x, rx_queued:%d",
4596629Szf162725 usb_str_cr(req->bulk_completion_reason),
4606629Szf162725 req->bulk_completion_reason,
4616629Szf162725 req->bulk_cb_flags,
4626629Szf162725 sc->rx_queued);
4636629Szf162725
4646629Szf162725 if (req->bulk_completion_reason != USB_CR_OK) {
4656629Szf162725 sc->sc_rx_err++;
4666629Szf162725 goto fail;
4676629Szf162725 }
4686629Szf162725
4696629Szf162725 len = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
4706629Szf162725 rxbuf = (char *)mp->b_rptr;
4716629Szf162725
4726629Szf162725 if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) {
4739345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
4746629Szf162725 "ural_rxeof(): xfer too short %d\n", len);
4756629Szf162725 sc->sc_rx_err++;
4766629Szf162725 goto fail;
4776629Szf162725 }
4786629Szf162725
4796629Szf162725 /* rx descriptor is located at the end */
4806629Szf162725 desc = (struct ural_rx_desc *)(rxbuf + len - RAL_RX_DESC_SIZE);
4816629Szf162725
4826629Szf162725 if ((LE_32(desc->flags) & RAL_RX_PHY_ERROR) ||
4836629Szf162725 (LE_32(desc->flags) & RAL_RX_CRC_ERROR)) {
4846629Szf162725 /*
4856629Szf162725 * This should not happen since we did not request to receive
4866629Szf162725 * those frames when we filled RAL_TXRX_CSR2.
4876629Szf162725 */
4889345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "PHY or CRC error\n");
4896629Szf162725 sc->sc_rx_err++;
4906629Szf162725 goto fail;
4916629Szf162725 }
4926629Szf162725
4936629Szf162725 pktlen = (LE_32(desc->flags) >> 16) & 0xfff;
4946629Szf162725
4956629Szf162725 if (pktlen > (len - RAL_RX_DESC_SIZE)) {
4969345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
4976629Szf162725 "ural_rxeof(): pktlen mismatch <%d, %d>.\n", pktlen, len);
4986629Szf162725 goto fail;
4996629Szf162725 }
5006629Szf162725
5016629Szf162725 /* Strip trailing 802.11 MAC FCS. */
5026629Szf162725 pktlen -= IEEE80211_CRC_LEN;
5036629Szf162725
5046629Szf162725 if ((m = allocb(pktlen, BPRI_MED)) == NULL) {
5059345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
5066629Szf162725 "ural_rxeof(): allocate mblk failed.\n");
5076629Szf162725 sc->sc_rx_nobuf++;
5086629Szf162725 goto fail;
5096629Szf162725 }
5106629Szf162725
5116629Szf162725 bcopy(rxbuf, m->b_rptr, pktlen);
5126629Szf162725 m->b_wptr += pktlen;
5136629Szf162725
5146629Szf162725 wh = (struct ieee80211_frame *)m->b_rptr;
5156629Szf162725 ni = ieee80211_find_rxnode(ic, wh);
5166629Szf162725
5176629Szf162725 /* send the frame to the 802.11 layer */
5186629Szf162725 (void) ieee80211_input(ic, m, ni, desc->rssi, 0);
5196629Szf162725
5206629Szf162725 /* node is no longer needed */
5216629Szf162725 ieee80211_free_node(ni);
5226629Szf162725 fail:
5236629Szf162725 mutex_enter(&sc->rx_lock);
5246629Szf162725 sc->rx_queued--;
5256629Szf162725 mutex_exit(&sc->rx_lock);
5266629Szf162725
5276629Szf162725 freemsg(mp);
5286629Szf162725 usb_free_bulk_req(req);
5296629Szf162725
5306629Szf162725 if (RAL_IS_RUNNING(sc))
5316629Szf162725 (void) ural_rx_trigger(sc);
5326629Szf162725 }
5336629Szf162725
5346629Szf162725 /*
5356629Szf162725 * Return the expected ack rate for a frame transmitted at rate `rate'.
5366629Szf162725 * this should depend on the destination node basic rate set.
5376629Szf162725 */
5386629Szf162725 static int
ural_ack_rate(struct ieee80211com * ic,int rate)5396629Szf162725 ural_ack_rate(struct ieee80211com *ic, int rate)
5406629Szf162725 {
5416629Szf162725 switch (rate) {
5426629Szf162725 /* CCK rates */
5436629Szf162725 case 2:
5446629Szf162725 return (2);
5456629Szf162725 case 4:
5466629Szf162725 case 11:
5476629Szf162725 case 22:
5486629Szf162725 return ((ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate);
5496629Szf162725
5506629Szf162725 /* OFDM rates */
5516629Szf162725 case 12:
5526629Szf162725 case 18:
5536629Szf162725 return (12);
5546629Szf162725 case 24:
5556629Szf162725 case 36:
5566629Szf162725 return (24);
5576629Szf162725 case 48:
5586629Szf162725 case 72:
5596629Szf162725 case 96:
5606629Szf162725 case 108:
5616629Szf162725 return (48);
5626629Szf162725 }
5636629Szf162725
5646629Szf162725 /* default to 1Mbps */
5656629Szf162725 return (2);
5666629Szf162725 }
5676629Szf162725
5686629Szf162725 /*
5696629Szf162725 * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
5706629Szf162725 * The function automatically determines the operating mode depending on the
5716629Szf162725 * given rate. `flags' indicates whether short preamble is in use or not.
5726629Szf162725 */
5736629Szf162725 static uint16_t
ural_txtime(int len,int rate,uint32_t flags)5746629Szf162725 ural_txtime(int len, int rate, uint32_t flags)
5756629Szf162725 {
5766629Szf162725 uint16_t txtime;
5776629Szf162725
5786629Szf162725 if (RAL_RATE_IS_OFDM(rate)) {
5796629Szf162725 /* IEEE Std 802.11a-1999, pp. 37 */
5806629Szf162725 txtime = (8 + 4 * len + 3 + rate - 1) / rate;
5816629Szf162725 txtime = 16 + 4 + 4 * txtime + 6;
5826629Szf162725 } else {
5836629Szf162725 /* IEEE Std 802.11b-1999, pp. 28 */
5846629Szf162725 txtime = (16 * len + rate - 1) / rate;
5856629Szf162725 if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
5866629Szf162725 txtime += 72 + 24;
5876629Szf162725 else
5886629Szf162725 txtime += 144 + 48;
5896629Szf162725 }
5906629Szf162725 return (txtime);
5916629Szf162725 }
5926629Szf162725
5936629Szf162725 static uint8_t
ural_plcp_signal(int rate)5946629Szf162725 ural_plcp_signal(int rate)
5956629Szf162725 {
5966629Szf162725 switch (rate) {
5976629Szf162725 /* CCK rates (returned values are device-dependent) */
5986629Szf162725 case 2: return (0x0);
5996629Szf162725 case 4: return (0x1);
6006629Szf162725 case 11: return (0x2);
6016629Szf162725 case 22: return (0x3);
6026629Szf162725
6036629Szf162725 /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
6046629Szf162725 case 12: return (0xb);
6056629Szf162725 case 18: return (0xf);
6066629Szf162725 case 24: return (0xa);
6076629Szf162725 case 36: return (0xe);
6086629Szf162725 case 48: return (0x9);
6096629Szf162725 case 72: return (0xd);
6106629Szf162725 case 96: return (0x8);
6116629Szf162725 case 108: return (0xc);
6126629Szf162725
6136629Szf162725 /* unsupported rates (should not get there) */
6146629Szf162725 default: return (0xff);
6156629Szf162725 }
6166629Szf162725 }
6176629Szf162725
6186629Szf162725 static void
ural_setup_tx_desc(struct ural_softc * sc,struct ural_tx_desc * desc,uint32_t flags,int len,int rate)6196629Szf162725 ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
6206629Szf162725 uint32_t flags, int len, int rate)
6216629Szf162725 {
6226629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
6236629Szf162725 uint16_t plcp_length;
6246629Szf162725 int remainder;
6256629Szf162725
6266629Szf162725 desc->flags = LE_32(flags);
6276629Szf162725 desc->flags |= LE_32(RAL_TX_NEWSEQ);
6286629Szf162725 desc->flags |= LE_32(len << 16);
6296629Szf162725
6306629Szf162725 desc->wme = LE_16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5));
6316629Szf162725 desc->wme |= LE_16(RAL_IVOFFSET(sizeof (struct ieee80211_frame)));
6326629Szf162725
6336629Szf162725 /* setup PLCP fields */
6346629Szf162725 desc->plcp_signal = ural_plcp_signal(rate);
6356629Szf162725 desc->plcp_service = 4;
6366629Szf162725
6376629Szf162725 len += IEEE80211_CRC_LEN;
6386629Szf162725 if (RAL_RATE_IS_OFDM(rate)) {
6396629Szf162725 desc->flags |= LE_32(RAL_TX_OFDM);
6406629Szf162725
6416629Szf162725 plcp_length = len & 0xfff;
6426629Szf162725 desc->plcp_length_hi = plcp_length >> 6;
6436629Szf162725 desc->plcp_length_lo = plcp_length & 0x3f;
6446629Szf162725 } else {
6456629Szf162725 plcp_length = (16 * len + rate - 1) / rate;
6466629Szf162725 if (rate == 22) {
6476629Szf162725 remainder = (16 * len) % 22;
6486629Szf162725 if (remainder != 0 && remainder < 7)
6496629Szf162725 desc->plcp_service |= RAL_PLCP_LENGEXT;
6506629Szf162725 }
6516629Szf162725 desc->plcp_length_hi = plcp_length >> 8;
6526629Szf162725 desc->plcp_length_lo = plcp_length & 0xff;
6536629Szf162725
6546629Szf162725 if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
6556629Szf162725 desc->plcp_signal |= 0x08;
6566629Szf162725 }
6576629Szf162725
6586629Szf162725 desc->iv = 0;
6596629Szf162725 desc->eiv = 0;
6606629Szf162725 }
6616629Szf162725
6626629Szf162725 #define RAL_TX_TIMEOUT 5
6636629Szf162725
6646629Szf162725 static int
ural_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)6656629Szf162725 ural_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
6666629Szf162725 {
6676629Szf162725 struct ural_softc *sc = (struct ural_softc *)ic;
6686629Szf162725 struct ural_tx_desc *desc;
6696629Szf162725
6706629Szf162725 struct ieee80211_frame *wh;
6716629Szf162725 struct ieee80211_key *k;
6726629Szf162725
6736629Szf162725 uint16_t dur;
6746629Szf162725 uint32_t flags = 0;
6756629Szf162725 int rate, err = DDI_SUCCESS;
6766629Szf162725
6776629Szf162725 struct ieee80211_node *ni = NULL;
6786629Szf162725 mblk_t *m, *m0;
6796629Szf162725 int off, mblen, pktlen, xferlen;
6806629Szf162725
6819345SQuaker.Fang@Sun.COM /* discard packets while suspending or not inited */
6829345SQuaker.Fang@Sun.COM if (!RAL_IS_RUNNING(sc)) {
6839345SQuaker.Fang@Sun.COM freemsg(mp);
6849345SQuaker.Fang@Sun.COM return (ENXIO);
6859345SQuaker.Fang@Sun.COM }
6869345SQuaker.Fang@Sun.COM
6876629Szf162725 mutex_enter(&sc->tx_lock);
6886629Szf162725
6896629Szf162725 if (sc->tx_queued > RAL_TX_LIST_COUNT) {
6909345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_TX, "ural_send(): "
6916629Szf162725 "no TX buffer available!\n");
6926629Szf162725 if ((type & IEEE80211_FC0_TYPE_MASK) ==
6936629Szf162725 IEEE80211_FC0_TYPE_DATA) {
6946629Szf162725 sc->sc_need_sched = 1;
6956629Szf162725 }
6966629Szf162725 sc->sc_tx_nobuf++;
6976629Szf162725 err = ENOMEM;
6986629Szf162725 goto fail;
6996629Szf162725 }
7006629Szf162725
7016629Szf162725 m = allocb(RAL_TXBUF_SIZE + RAL_TX_DESC_SIZE, BPRI_MED);
7026629Szf162725 if (m == NULL) {
7039345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_send(): can't alloc mblk.\n");
7046629Szf162725 err = DDI_FAILURE;
7056629Szf162725 goto fail;
7066629Szf162725 }
7076629Szf162725
7086629Szf162725 m->b_rptr += RAL_TX_DESC_SIZE; /* skip TX descriptor */
7096629Szf162725 m->b_wptr += RAL_TX_DESC_SIZE;
7106629Szf162725
7116629Szf162725 for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
7126629Szf162725 mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr;
7136629Szf162725 (void) memcpy(m->b_rptr + off, m0->b_rptr, mblen);
7146629Szf162725 off += mblen;
7156629Szf162725 }
7166629Szf162725 m->b_wptr += off;
7176629Szf162725
7186629Szf162725 wh = (struct ieee80211_frame *)m->b_rptr;
7196629Szf162725
7206629Szf162725 ni = ieee80211_find_txnode(ic, wh->i_addr1);
7216629Szf162725 if (ni == NULL) {
7226629Szf162725 err = DDI_FAILURE;
7236629Szf162725 sc->sc_tx_err++;
7246629Szf162725 freemsg(m);
7256629Szf162725 goto fail;
7266629Szf162725 }
7276629Szf162725
7286629Szf162725 if ((type & IEEE80211_FC0_TYPE_MASK) ==
7296629Szf162725 IEEE80211_FC0_TYPE_DATA) {
7306629Szf162725 (void) ieee80211_encap(ic, m, ni);
7316629Szf162725 }
7326629Szf162725
7336629Szf162725 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
7346629Szf162725 k = ieee80211_crypto_encap(ic, m);
7356629Szf162725 if (k == NULL) {
7366629Szf162725 sc->sc_tx_err++;
7376629Szf162725 freemsg(m);
7386629Szf162725 err = DDI_FAILURE;
7396629Szf162725 goto fail;
7406629Szf162725 }
7416629Szf162725 /* packet header may have moved, reset our local pointer */
7426629Szf162725 wh = (struct ieee80211_frame *)m->b_rptr;
7436629Szf162725 }
7446629Szf162725
7456629Szf162725 m->b_rptr -= RAL_TX_DESC_SIZE; /* restore */
7466629Szf162725 desc = (struct ural_tx_desc *)m->b_rptr;
7476629Szf162725
7486629Szf162725 if ((type & IEEE80211_FC0_TYPE_MASK) ==
7496629Szf162725 IEEE80211_FC0_TYPE_DATA) { /* DATA */
7506629Szf162725 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
7516629Szf162725 rate = ic->ic_bss->in_rates.ir_rates[ic->ic_fixed_rate];
7526629Szf162725 else
7536629Szf162725 rate = ni->in_rates.ir_rates[ni->in_txrate];
7546629Szf162725
7556629Szf162725 rate &= IEEE80211_RATE_VAL;
7566629Szf162725 if (rate <= 0) {
7576629Szf162725 rate = 2; /* basic rate */
7586629Szf162725 }
7596629Szf162725
7606629Szf162725 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
7616629Szf162725 flags |= RAL_TX_ACK;
7626629Szf162725 flags |= RAL_TX_RETRY(7);
7636629Szf162725
7646629Szf162725 dur = ural_txtime(RAL_ACK_SIZE, ural_ack_rate(ic, rate),
7656629Szf162725 ic->ic_flags) + RAL_SIFS;
7666629Szf162725 *(uint16_t *)(uintptr_t)wh->i_dur = LE_16(dur);
7676629Szf162725 }
7686629Szf162725 } else { /* MGMT */
7696629Szf162725 rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2;
7706629Szf162725
7716629Szf162725 if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
7726629Szf162725 flags |= RAL_TX_ACK;
7736629Szf162725
7746629Szf162725 dur = ural_txtime(RAL_ACK_SIZE, rate, ic->ic_flags)
7756629Szf162725 + RAL_SIFS;
7766629Szf162725 *(uint16_t *)(uintptr_t)wh->i_dur = LE_16(dur);
7776629Szf162725
7786629Szf162725 /* tell hardware to add timestamp for probe responses */
7796629Szf162725 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
7806629Szf162725 IEEE80211_FC0_TYPE_MGT &&
7816629Szf162725 (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
7826629Szf162725 IEEE80211_FC0_SUBTYPE_PROBE_RESP)
7836629Szf162725 flags |= RAL_TX_TIMESTAMP;
7846629Szf162725 }
7856629Szf162725 }
7866629Szf162725
7876629Szf162725 pktlen = (uintptr_t)m->b_wptr - (uintptr_t)m->b_rptr - RAL_TX_DESC_SIZE;
7886629Szf162725 ural_setup_tx_desc(sc, desc, flags, pktlen, rate);
7896629Szf162725
7906629Szf162725 /* align end on a 2-bytes boundary */
7916629Szf162725 xferlen = (RAL_TX_DESC_SIZE + pktlen + 1) & ~1;
7926629Szf162725
7936629Szf162725 /*
7946629Szf162725 * No space left in the last URB to store the extra 2 bytes, force
7956629Szf162725 * sending of another URB.
7966629Szf162725 */
7976629Szf162725 if ((xferlen % 64) == 0)
7986629Szf162725 xferlen += 2;
7996629Szf162725
8006629Szf162725 m->b_wptr = m->b_rptr + xferlen;
8016629Szf162725
8029345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_TX, "sending data frame len=%u rate=%u xfer len=%u\n",
8036629Szf162725 pktlen, rate, xferlen);
8046629Szf162725
8056629Szf162725 (void) ural_tx_trigger(sc, m);
8066629Szf162725
8076629Szf162725 ic->ic_stats.is_tx_frags++;
8086629Szf162725 ic->ic_stats.is_tx_bytes += pktlen;
8096629Szf162725
8106629Szf162725 fail:
8116629Szf162725 if (ni != NULL)
8126629Szf162725 ieee80211_free_node(ni);
8136629Szf162725
8146629Szf162725 if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
8156629Szf162725 err == 0) {
8166629Szf162725 freemsg(mp);
8176629Szf162725 }
8186629Szf162725
8196629Szf162725 mutex_exit(&sc->tx_lock);
8206629Szf162725
8216629Szf162725 return (err);
8226629Szf162725 }
8236629Szf162725
8246629Szf162725 static mblk_t *
ural_m_tx(void * arg,mblk_t * mp)8256629Szf162725 ural_m_tx(void *arg, mblk_t *mp)
8266629Szf162725 {
8276629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
8286629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
8296629Szf162725 mblk_t *next;
8306629Szf162725
8316629Szf162725 /*
8326629Szf162725 * No data frames go out unless we're associated; this
8336629Szf162725 * should not happen as the 802.11 layer does not enable
8346629Szf162725 * the xmit queue until we enter the RUN state.
8356629Szf162725 */
8366629Szf162725 if (ic->ic_state != IEEE80211_S_RUN) {
8379345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_m_tx(): "
8386629Szf162725 "discard, state %u\n", ic->ic_state);
8396629Szf162725 freemsgchain(mp);
8406629Szf162725 return (NULL);
8416629Szf162725 }
8426629Szf162725
8436629Szf162725 while (mp != NULL) {
8446629Szf162725 next = mp->b_next;
8456629Szf162725 mp->b_next = NULL;
8466629Szf162725 if (ural_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) {
8476629Szf162725 mp->b_next = next;
8486629Szf162725 freemsgchain(mp);
8496629Szf162725 return (NULL);
8506629Szf162725 }
8516629Szf162725 mp = next;
8526629Szf162725 }
8536629Szf162725 return (mp);
8546629Szf162725 }
8556629Szf162725
8566629Szf162725 static void
ural_set_testmode(struct ural_softc * sc)8576629Szf162725 ural_set_testmode(struct ural_softc *sc)
8586629Szf162725 {
8596629Szf162725 usb_ctrl_setup_t req;
8606629Szf162725 usb_cr_t cr;
8616629Szf162725 usb_cb_flags_t cf;
8626629Szf162725 int err;
8636629Szf162725
8646629Szf162725 bzero(&req, sizeof (req));
8656629Szf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_HOST_TO_DEV;
8666629Szf162725 req.bRequest = RAL_VENDOR_REQUEST;
8676629Szf162725 req.wValue = 4;
8686629Szf162725 req.wIndex = 1;
8696629Szf162725 req.wLength = 0;
8706629Szf162725 req.attrs = USB_ATTRS_NONE;
8716629Szf162725
8726629Szf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, NULL,
8736629Szf162725 &cr, &cf, 0);
8746629Szf162725
8756629Szf162725 if (err != USB_SUCCESS) {
8769345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_USB,
8776629Szf162725 "ural_set_testmode(): could not set test mode:"
8786629Szf162725 "cr:%s(%d), cf:%(x)\n",
8796629Szf162725 usb_str_cr(cr), cr, cf);
8806629Szf162725 }
8816629Szf162725 }
8826629Szf162725
8836629Szf162725 static void
ural_eeprom_read(struct ural_softc * sc,uint16_t addr,void * buf,int len)8846629Szf162725 ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len)
8856629Szf162725 {
8866629Szf162725 usb_ctrl_setup_t req;
8876629Szf162725 usb_cr_t cr;
8886629Szf162725 usb_cb_flags_t cf;
8896629Szf162725 mblk_t *mp;
8906629Szf162725 int err;
8916629Szf162725
8926629Szf162725 bzero(&req, sizeof (req));
8936629Szf162725 req.bmRequestType = USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_DEV_TO_HOST;
8946629Szf162725 req.bRequest = RAL_READ_EEPROM;
8956629Szf162725 req.wValue = 0;
8966629Szf162725 req.wIndex = addr;
8976629Szf162725 req.wLength = (uint16_t)len;
8986629Szf162725
8996629Szf162725 mp = NULL;
9006629Szf162725 err = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
9016629Szf162725 &cr, &cf, 0);
9026629Szf162725
9036629Szf162725 if (err != USB_SUCCESS) {
9049345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_USB,
9056629Szf162725 "ural_eeprom_read(): could not read EEPROM:"
9066629Szf162725 "cr:%s(%d), cf:(%x)\n",
9076629Szf162725 usb_str_cr(cr), cr, cf);
9086629Szf162725 return;
9096629Szf162725 }
9106629Szf162725
9116629Szf162725 bcopy(mp->b_rptr, buf, len);
9126629Szf162725
9136629Szf162725 if (mp)
9146629Szf162725 freemsg(mp);
9156629Szf162725 }
9166629Szf162725
9176629Szf162725 static void
ural_bbp_write(struct ural_softc * sc,uint8_t reg,uint8_t val)9186629Szf162725 ural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val)
9196629Szf162725 {
9206629Szf162725 uint16_t tmp;
9216629Szf162725 int ntries;
9226629Szf162725
9236629Szf162725 for (ntries = 0; ntries < 5; ntries++) {
9246629Szf162725 if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY))
9256629Szf162725 break;
9266629Szf162725 }
9276629Szf162725 if (ntries == 5) {
9289345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
9296629Szf162725 "ural_bbp_write(): could not write to BBP\n");
9306629Szf162725 return;
9316629Szf162725 }
9326629Szf162725
9336629Szf162725 tmp = reg << 8 | val;
9346629Szf162725 ural_write(sc, RAL_PHY_CSR7, tmp);
9356629Szf162725 }
9366629Szf162725
9376629Szf162725 static uint8_t
ural_bbp_read(struct ural_softc * sc,uint8_t reg)9386629Szf162725 ural_bbp_read(struct ural_softc *sc, uint8_t reg)
9396629Szf162725 {
9406629Szf162725 uint16_t val;
9416629Szf162725 int ntries;
9426629Szf162725
9436629Szf162725 val = RAL_BBP_WRITE | reg << 8;
9446629Szf162725 ural_write(sc, RAL_PHY_CSR7, val);
9456629Szf162725
9466629Szf162725 for (ntries = 0; ntries < 5; ntries++) {
9476629Szf162725 if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY))
9486629Szf162725 break;
9496629Szf162725 }
9506629Szf162725 if (ntries == 5) {
9519345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_bbp_read(): could not read BBP\n");
9526629Szf162725 return (0);
9536629Szf162725 }
9546629Szf162725
9556629Szf162725 return (ural_read(sc, RAL_PHY_CSR7) & 0xff);
9566629Szf162725 }
9576629Szf162725
9586629Szf162725 static void
ural_rf_write(struct ural_softc * sc,uint8_t reg,uint32_t val)9596629Szf162725 ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
9606629Szf162725 {
9616629Szf162725 uint32_t tmp;
9626629Szf162725 int ntries;
9636629Szf162725
9646629Szf162725 for (ntries = 0; ntries < 5; ntries++) {
9656629Szf162725 if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY))
9666629Szf162725 break;
9676629Szf162725 }
9686629Szf162725 if (ntries == 5) {
9699345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
9706629Szf162725 "ural_rf_write(): could not write to RF\n");
9716629Szf162725 return;
9726629Szf162725 }
9736629Szf162725
9746629Szf162725 tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xffff) << 2 | (reg & 0x3);
9756629Szf162725 ural_write(sc, RAL_PHY_CSR9, tmp & 0xffff);
9766629Szf162725 ural_write(sc, RAL_PHY_CSR10, tmp >> 16);
9776629Szf162725
9786629Szf162725 /* remember last written value in sc */
9796629Szf162725 sc->rf_regs[reg] = val;
9806629Szf162725
9819345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff);
9826629Szf162725 }
9836629Szf162725
9846629Szf162725 /*
9856629Szf162725 * Disable RF auto-tuning.
9866629Szf162725 */
9876629Szf162725 static void
ural_disable_rf_tune(struct ural_softc * sc)9886629Szf162725 ural_disable_rf_tune(struct ural_softc *sc)
9896629Szf162725 {
9906629Szf162725 uint32_t tmp;
9916629Szf162725
9926629Szf162725 if (sc->rf_rev != RAL_RF_2523) {
9936629Szf162725 tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE;
9946629Szf162725 ural_rf_write(sc, RAL_RF1, tmp);
9956629Szf162725 }
9966629Szf162725
9976629Szf162725 tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE;
9986629Szf162725 ural_rf_write(sc, RAL_RF3, tmp);
9996629Szf162725
10009345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW, "disabling RF autotune\n");
10016629Szf162725 }
10026629Szf162725
10036629Szf162725
10046629Szf162725 static void
ural_set_chan(struct ural_softc * sc,struct ieee80211_channel * c)10056629Szf162725 ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
10066629Szf162725 {
10076629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
10086629Szf162725 uint8_t power, tmp;
10096629Szf162725 uint_t i, chan;
10106629Szf162725
10116629Szf162725 chan = ieee80211_chan2ieee(ic, c);
10126629Szf162725 if (chan == 0 || chan == IEEE80211_CHAN_ANY)
10136629Szf162725 return;
10146629Szf162725
10156629Szf162725 if (IEEE80211_IS_CHAN_2GHZ(c))
10166629Szf162725 power = min(sc->txpow[chan - 1], 31);
10176629Szf162725 else
10186629Szf162725 power = 31;
10196629Szf162725
10206629Szf162725 /* adjust txpower using ifconfig settings */
10216629Szf162725 power -= (100 - ic->ic_txpowlimit) / 8;
10226629Szf162725
10239345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW, "setting channel to %u, txpower to %u\n",
10246629Szf162725 chan, power);
10256629Szf162725
10266629Szf162725 switch (sc->rf_rev) {
10276629Szf162725 case RAL_RF_2522:
10286629Szf162725 ural_rf_write(sc, RAL_RF1, 0x00814);
10296629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]);
10306629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
10316629Szf162725 break;
10326629Szf162725
10336629Szf162725 case RAL_RF_2523:
10346629Szf162725 ural_rf_write(sc, RAL_RF1, 0x08804);
10356629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]);
10366629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044);
10376629Szf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10386629Szf162725 break;
10396629Szf162725
10406629Szf162725 case RAL_RF_2524:
10416629Szf162725 ural_rf_write(sc, RAL_RF1, 0x0c808);
10426629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]);
10436629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
10446629Szf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10456629Szf162725 break;
10466629Szf162725
10476629Szf162725 case RAL_RF_2525:
10486629Szf162725 ural_rf_write(sc, RAL_RF1, 0x08808);
10496629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]);
10506629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10516629Szf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10526629Szf162725
10536629Szf162725 ural_rf_write(sc, RAL_RF1, 0x08808);
10546629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]);
10556629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10566629Szf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286);
10576629Szf162725 break;
10586629Szf162725
10596629Szf162725 case RAL_RF_2525E:
10606629Szf162725 ural_rf_write(sc, RAL_RF1, 0x08808);
10616629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]);
10626629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10636629Szf162725 ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282);
10646629Szf162725 break;
10656629Szf162725
10666629Szf162725 case RAL_RF_2526:
10676629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]);
10686629Szf162725 ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
10696629Szf162725 ural_rf_write(sc, RAL_RF1, 0x08804);
10706629Szf162725
10716629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]);
10726629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044);
10736629Szf162725 ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381);
10746629Szf162725 break;
10756629Szf162725
10766629Szf162725 /* dual-band RF */
10776629Szf162725 case RAL_RF_5222:
10786629Szf162725 for (i = 0; ural_rf5222[i].chan != chan; i++) {
10796629Szf162725 if (i > URAL_N(ural_rf5222)) break;
10806629Szf162725 }
10816629Szf162725
10826629Szf162725 ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1);
10836629Szf162725 ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2);
10846629Szf162725 ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040);
10856629Szf162725 ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4);
10866629Szf162725 break;
10876629Szf162725 }
10886629Szf162725
10896629Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR &&
10906629Szf162725 ic->ic_state != IEEE80211_S_SCAN) {
10916629Szf162725 /* set Japan filter bit for channel 14 */
10926629Szf162725 tmp = ural_bbp_read(sc, 70);
10936629Szf162725
10946629Szf162725 tmp &= ~RAL_JAPAN_FILTER;
10956629Szf162725 if (chan == 14)
10966629Szf162725 tmp |= RAL_JAPAN_FILTER;
10976629Szf162725
10986629Szf162725 ural_bbp_write(sc, 70, tmp);
10996629Szf162725
11006629Szf162725 /* clear CRC errs */
11016629Szf162725 (void) ural_read(sc, RAL_STA_CSR0);
11026629Szf162725
11036629Szf162725 drv_usecwait(10000);
11046629Szf162725 ural_disable_rf_tune(sc);
11056629Szf162725 }
11066629Szf162725 }
11076629Szf162725
11086629Szf162725 /*
11096629Szf162725 * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
11106629Szf162725 * synchronization.
11116629Szf162725 */
11126629Szf162725 static void
ural_enable_tsf_sync(struct ural_softc * sc)11136629Szf162725 ural_enable_tsf_sync(struct ural_softc *sc)
11146629Szf162725 {
11156629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
11166629Szf162725 uint16_t logcwmin, preload, tmp;
11176629Szf162725
11186629Szf162725 /* first, disable TSF synchronization */
11196629Szf162725 ural_write(sc, RAL_TXRX_CSR19, 0);
11206629Szf162725
11216629Szf162725 tmp = (16 * ic->ic_bss->in_intval) << 4;
11226629Szf162725 ural_write(sc, RAL_TXRX_CSR18, tmp);
11236629Szf162725
11246629Szf162725 logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0;
11256629Szf162725 preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6;
11266629Szf162725 tmp = logcwmin << 12 | preload;
11276629Szf162725 ural_write(sc, RAL_TXRX_CSR20, tmp);
11286629Szf162725
11296629Szf162725 /* finally, enable TSF synchronization */
11306629Szf162725 tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN;
11316629Szf162725 if (ic->ic_opmode == IEEE80211_M_STA)
11326629Szf162725 tmp |= RAL_ENABLE_TSF_SYNC(1);
11336629Szf162725 else
11346629Szf162725 tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR;
11356629Szf162725 ural_write(sc, RAL_TXRX_CSR19, tmp);
11366629Szf162725
11379345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW, "enabling TSF synchronization\n");
11386629Szf162725 }
11396629Szf162725
11406629Szf162725 /*
11416629Szf162725 * This function can be called by ieee80211_set_shortslottime(). Refer to
11426629Szf162725 * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
11436629Szf162725 */
11446629Szf162725 /* ARGSUSED */
11456629Szf162725 static void
ural_update_slot(struct ieee80211com * ic,int onoff)11466629Szf162725 ural_update_slot(struct ieee80211com *ic, int onoff)
11476629Szf162725 {
11486629Szf162725 struct ural_softc *sc = (struct ural_softc *)ic;
11496629Szf162725 uint16_t slottime, sifs, eifs;
11506629Szf162725
11516629Szf162725 slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
11526629Szf162725 /* slottime = (onoff ? 9 : 20); */
11536629Szf162725
11546629Szf162725 /*
11556629Szf162725 * These settings may sound a bit inconsistent but this is what the
11566629Szf162725 * reference driver does.
11576629Szf162725 */
11586629Szf162725 if (ic->ic_curmode == IEEE80211_MODE_11B) {
11596629Szf162725 sifs = 16 - RAL_RXTX_TURNAROUND;
11606629Szf162725 eifs = 364;
11616629Szf162725 } else {
11626629Szf162725 sifs = 10 - RAL_RXTX_TURNAROUND;
11636629Szf162725 eifs = 64;
11646629Szf162725 }
11656629Szf162725
11666629Szf162725 ural_write(sc, RAL_MAC_CSR10, slottime);
11676629Szf162725 ural_write(sc, RAL_MAC_CSR11, sifs);
11686629Szf162725 ural_write(sc, RAL_MAC_CSR12, eifs);
11696629Szf162725 }
11706629Szf162725
11716629Szf162725 static void
ural_set_txpreamble(struct ural_softc * sc)11726629Szf162725 ural_set_txpreamble(struct ural_softc *sc)
11736629Szf162725 {
11746629Szf162725 uint16_t tmp;
11756629Szf162725
11766629Szf162725 tmp = ural_read(sc, RAL_TXRX_CSR10);
11776629Szf162725
11786629Szf162725 tmp &= ~RAL_SHORT_PREAMBLE;
11796629Szf162725 if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
11806629Szf162725 tmp |= RAL_SHORT_PREAMBLE;
11816629Szf162725
11826629Szf162725 ural_write(sc, RAL_TXRX_CSR10, tmp);
11836629Szf162725 }
11846629Szf162725
11856629Szf162725 static void
ural_set_basicrates(struct ural_softc * sc)11866629Szf162725 ural_set_basicrates(struct ural_softc *sc)
11876629Szf162725 {
11886629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
11896629Szf162725
11906629Szf162725 /* update basic rate set */
11916629Szf162725 if (ic->ic_curmode == IEEE80211_MODE_11B) {
11926629Szf162725 /* 11b basic rates: 1, 2Mbps */
11936629Szf162725 ural_write(sc, RAL_TXRX_CSR11, 0x3);
11946629Szf162725 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->in_chan)) {
11956629Szf162725 /* 11a basic rates: 6, 12, 24Mbps */
11966629Szf162725 ural_write(sc, RAL_TXRX_CSR11, 0x150);
11976629Szf162725 } else {
11986629Szf162725 /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
11996629Szf162725 ural_write(sc, RAL_TXRX_CSR11, 0x15f);
12006629Szf162725 }
12016629Szf162725 }
12026629Szf162725
12036629Szf162725 static void
ural_set_bssid(struct ural_softc * sc,uint8_t * bssid)12046629Szf162725 ural_set_bssid(struct ural_softc *sc, uint8_t *bssid)
12056629Szf162725 {
12066629Szf162725 uint16_t tmp;
12076629Szf162725
12086629Szf162725 tmp = bssid[0] | bssid[1] << 8;
12096629Szf162725 ural_write(sc, RAL_MAC_CSR5, tmp);
12106629Szf162725
12116629Szf162725 tmp = bssid[2] | bssid[3] << 8;
12126629Szf162725 ural_write(sc, RAL_MAC_CSR6, tmp);
12136629Szf162725
12146629Szf162725 tmp = bssid[4] | bssid[5] << 8;
12156629Szf162725 ural_write(sc, RAL_MAC_CSR7, tmp);
12166629Szf162725
12179345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW, "setting BSSID to " MACSTR "\n", MAC2STR(bssid));
12186629Szf162725 }
12196629Szf162725
12206629Szf162725 static void
ural_set_macaddr(struct ural_softc * sc,uint8_t * addr)12216629Szf162725 ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
12226629Szf162725 {
12236629Szf162725 uint16_t tmp;
12246629Szf162725
12256629Szf162725 tmp = addr[0] | addr[1] << 8;
12266629Szf162725 ural_write(sc, RAL_MAC_CSR2, tmp);
12276629Szf162725
12286629Szf162725 tmp = addr[2] | addr[3] << 8;
12296629Szf162725 ural_write(sc, RAL_MAC_CSR3, tmp);
12306629Szf162725
12316629Szf162725 tmp = addr[4] | addr[5] << 8;
12326629Szf162725 ural_write(sc, RAL_MAC_CSR4, tmp);
12336629Szf162725
12349345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW,
12356629Szf162725 "setting MAC address to " MACSTR "\n", MAC2STR(addr));
12366629Szf162725 }
12376629Szf162725
12386629Szf162725 static void
ural_update_promisc(struct ural_softc * sc)12396629Szf162725 ural_update_promisc(struct ural_softc *sc)
12406629Szf162725 {
12416629Szf162725 uint32_t tmp;
12426629Szf162725
12436629Szf162725 tmp = ural_read(sc, RAL_TXRX_CSR2);
12446629Szf162725
12456629Szf162725 tmp &= ~RAL_DROP_NOT_TO_ME;
12466629Szf162725 if (!(sc->sc_rcr & RAL_RCR_PROMISC))
12476629Szf162725 tmp |= RAL_DROP_NOT_TO_ME;
12486629Szf162725
12496629Szf162725 ural_write(sc, RAL_TXRX_CSR2, tmp);
12506629Szf162725
12519345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_HW, "%s promiscuous mode\n",
12526629Szf162725 (sc->sc_rcr & RAL_RCR_PROMISC) ? "entering" : "leaving");
12536629Szf162725 }
12546629Szf162725
12556629Szf162725 static const char *
ural_get_rf(int rev)12566629Szf162725 ural_get_rf(int rev)
12576629Szf162725 {
12586629Szf162725 switch (rev) {
12596629Szf162725 case RAL_RF_2522: return ("RT2522");
12606629Szf162725 case RAL_RF_2523: return ("RT2523");
12616629Szf162725 case RAL_RF_2524: return ("RT2524");
12626629Szf162725 case RAL_RF_2525: return ("RT2525");
12636629Szf162725 case RAL_RF_2525E: return ("RT2525e");
12646629Szf162725 case RAL_RF_2526: return ("RT2526");
12656629Szf162725 case RAL_RF_5222: return ("RT5222");
12666629Szf162725 default: return ("unknown");
12676629Szf162725 }
12686629Szf162725 }
12696629Szf162725
12706629Szf162725 static void
ural_read_eeprom(struct ural_softc * sc)12716629Szf162725 ural_read_eeprom(struct ural_softc *sc)
12726629Szf162725 {
12736629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
12746629Szf162725 uint16_t val;
12756629Szf162725
12766629Szf162725 ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
12776629Szf162725 val = LE_16(val);
12786629Szf162725 sc->rf_rev = (val >> 11) & 0x7;
12796629Szf162725 sc->hw_radio = (val >> 10) & 0x1;
12806629Szf162725 sc->led_mode = (val >> 6) & 0x7;
12816629Szf162725 sc->rx_ant = (val >> 4) & 0x3;
12826629Szf162725 sc->tx_ant = (val >> 2) & 0x3;
12836629Szf162725 sc->nb_ant = val & 0x3;
12846629Szf162725
12856629Szf162725 /* read MAC address */
12866629Szf162725 ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6);
12876629Szf162725
12886629Szf162725 /* read default values for BBP registers */
12896629Szf162725 ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
12906629Szf162725
12916629Szf162725 /* read Tx power for all b/g channels */
12926629Szf162725 ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14);
12936629Szf162725 }
12946629Szf162725
12956629Szf162725 static int
ural_bbp_init(struct ural_softc * sc)12966629Szf162725 ural_bbp_init(struct ural_softc *sc)
12976629Szf162725 {
12986629Szf162725 int i, ntries;
12996629Szf162725
13006629Szf162725 /* wait for BBP to be ready */
13016629Szf162725 for (ntries = 0; ntries < 100; ntries++) {
13026629Szf162725 if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0)
13036629Szf162725 break;
13046629Szf162725 drv_usecwait(1000);
13056629Szf162725 }
13066629Szf162725 if (ntries == 100) {
13079345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "timeout waiting for BBP\n");
13086629Szf162725 return (EIO);
13096629Szf162725 }
13106629Szf162725
13116629Szf162725 /* initialize BBP registers to default values */
13126629Szf162725 for (i = 0; i < URAL_N(ural_def_bbp); i++)
13136629Szf162725 ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val);
13146629Szf162725
13156629Szf162725 return (0);
13166629Szf162725 }
13176629Szf162725
13186629Szf162725 static void
ural_set_txantenna(struct ural_softc * sc,int antenna)13196629Szf162725 ural_set_txantenna(struct ural_softc *sc, int antenna)
13206629Szf162725 {
13216629Szf162725 uint16_t tmp;
13226629Szf162725 uint8_t tx;
13236629Szf162725
13246629Szf162725 tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK;
13256629Szf162725 if (antenna == 1)
13266629Szf162725 tx |= RAL_BBP_ANTA;
13276629Szf162725 else if (antenna == 2)
13286629Szf162725 tx |= RAL_BBP_ANTB;
13296629Szf162725 else
13306629Szf162725 tx |= RAL_BBP_DIVERSITY;
13316629Szf162725
13326629Szf162725 /* need to force I/Q flip for RF 2525e, 2526 and 5222 */
13336629Szf162725 if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 ||
13346629Szf162725 sc->rf_rev == RAL_RF_5222)
13356629Szf162725 tx |= RAL_BBP_FLIPIQ;
13366629Szf162725
13376629Szf162725 ural_bbp_write(sc, RAL_BBP_TX, tx);
13386629Szf162725
13396629Szf162725 /* update values in PHY_CSR5 and PHY_CSR6 */
13406629Szf162725 tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7;
13416629Szf162725 ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7));
13426629Szf162725
13436629Szf162725 tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7;
13446629Szf162725 ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7));
13456629Szf162725 }
13466629Szf162725
13476629Szf162725 static void
ural_set_rxantenna(struct ural_softc * sc,int antenna)13486629Szf162725 ural_set_rxantenna(struct ural_softc *sc, int antenna)
13496629Szf162725 {
13506629Szf162725 uint8_t rx;
13516629Szf162725
13526629Szf162725 rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK;
13536629Szf162725 if (antenna == 1)
13546629Szf162725 rx |= RAL_BBP_ANTA;
13556629Szf162725 else if (antenna == 2)
13566629Szf162725 rx |= RAL_BBP_ANTB;
13576629Szf162725 else
13586629Szf162725 rx |= RAL_BBP_DIVERSITY;
13596629Szf162725
13606629Szf162725 /* need to force no I/Q flip for RF 2525e and 2526 */
13616629Szf162725 if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526)
13626629Szf162725 rx &= ~RAL_BBP_FLIPIQ;
13636629Szf162725
13646629Szf162725 ural_bbp_write(sc, RAL_BBP_RX, rx);
13656629Szf162725 }
13666629Szf162725
13676629Szf162725 /*
13686629Szf162725 * This function is called periodically (every 200ms) during scanning to
13696629Szf162725 * switch from one channel to another.
13706629Szf162725 */
13716629Szf162725 static void
ural_next_scan(void * arg)13726629Szf162725 ural_next_scan(void *arg)
13736629Szf162725 {
13746629Szf162725 struct ural_softc *sc = arg;
13756629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
13766629Szf162725
13776629Szf162725 if (ic->ic_state == IEEE80211_S_SCAN)
13786629Szf162725 ieee80211_next_scan(ic);
13796629Szf162725 }
13806629Szf162725
13816629Szf162725 static int
ural_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)13826629Szf162725 ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
13836629Szf162725 {
13846629Szf162725 struct ural_softc *sc = (struct ural_softc *)ic;
13856629Szf162725 enum ieee80211_state ostate;
13866629Szf162725 struct ieee80211_node *ni;
13876629Szf162725 int err;
13886629Szf162725
13896629Szf162725 RAL_LOCK(sc);
13906629Szf162725
13916629Szf162725 ostate = ic->ic_state;
13926629Szf162725
13936629Szf162725 if (sc->sc_scan_id != 0) {
13946629Szf162725 (void) untimeout(sc->sc_scan_id);
13956629Szf162725 sc->sc_scan_id = 0;
13966629Szf162725 }
13976629Szf162725
13986629Szf162725 if (sc->sc_amrr_id != 0) {
13996629Szf162725 (void) untimeout(sc->sc_amrr_id);
14006629Szf162725 sc->sc_amrr_id = 0;
14016629Szf162725 }
14026629Szf162725
14036629Szf162725 switch (nstate) {
14046629Szf162725 case IEEE80211_S_INIT:
14056629Szf162725 if (ostate == IEEE80211_S_RUN) {
14066629Szf162725 /* abort TSF synchronization */
14076629Szf162725 ural_write(sc, RAL_TXRX_CSR19, 0);
14086629Szf162725 /* force tx led to stop blinking */
14096629Szf162725 ural_write(sc, RAL_MAC_CSR20, 0);
14106629Szf162725 }
14116629Szf162725 break;
14126629Szf162725
14136629Szf162725 case IEEE80211_S_SCAN:
14146629Szf162725 ural_set_chan(sc, ic->ic_curchan);
14156629Szf162725 sc->sc_scan_id = timeout(ural_next_scan, (void *)sc,
14166629Szf162725 drv_usectohz(sc->dwelltime * 1000));
14176629Szf162725 break;
14186629Szf162725
14196629Szf162725 case IEEE80211_S_AUTH:
14206629Szf162725 ural_set_chan(sc, ic->ic_curchan);
14216629Szf162725 break;
14226629Szf162725
14236629Szf162725 case IEEE80211_S_ASSOC:
14246629Szf162725 ural_set_chan(sc, ic->ic_curchan);
14256629Szf162725 break;
14266629Szf162725
14276629Szf162725 case IEEE80211_S_RUN:
14286629Szf162725 ural_set_chan(sc, ic->ic_curchan);
14296629Szf162725
14306629Szf162725 ni = ic->ic_bss;
14316629Szf162725
14326629Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
14336629Szf162725 ural_update_slot(ic, 1);
14346629Szf162725 ural_set_txpreamble(sc);
14356629Szf162725 ural_set_basicrates(sc);
14366629Szf162725 ural_set_bssid(sc, ni->in_bssid);
14376629Szf162725 }
14386629Szf162725
14396629Szf162725
14406629Szf162725 /* make tx led blink on tx (controlled by ASIC) */
14416629Szf162725 ural_write(sc, RAL_MAC_CSR20, 1);
14426629Szf162725
14436629Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR)
14446629Szf162725 ural_enable_tsf_sync(sc);
14456629Szf162725
14466629Szf162725 /* enable automatic rate adaptation in STA mode */
14476629Szf162725 if (ic->ic_opmode == IEEE80211_M_STA &&
14486629Szf162725 ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
14496629Szf162725 ural_amrr_start(sc, ni);
14506629Szf162725
14516629Szf162725 break;
14526629Szf162725 }
14536629Szf162725
14546629Szf162725 RAL_UNLOCK(sc);
14556629Szf162725
14566629Szf162725 err = sc->sc_newstate(ic, nstate, arg);
14576629Szf162725 /*
14586629Szf162725 * Finally, start any timers.
14596629Szf162725 */
14606629Szf162725 if (nstate == IEEE80211_S_RUN)
14616629Szf162725 ieee80211_start_watchdog(ic, 1);
14626629Szf162725
14636629Szf162725 return (err);
14646629Szf162725 }
14656629Szf162725
14666629Szf162725
14676629Szf162725
14686629Szf162725 static void
ural_close_pipes(struct ural_softc * sc)14696629Szf162725 ural_close_pipes(struct ural_softc *sc)
14706629Szf162725 {
14716629Szf162725 usb_flags_t flags = USB_FLAGS_SLEEP;
14726629Szf162725
14736629Szf162725 if (sc->sc_rx_pipeh != NULL) {
14746629Szf162725 usb_pipe_reset(sc->sc_dev, sc->sc_rx_pipeh, flags, NULL, 0);
14756629Szf162725 usb_pipe_close(sc->sc_dev, sc->sc_rx_pipeh, flags, NULL, 0);
14766629Szf162725 sc->sc_rx_pipeh = NULL;
14776629Szf162725 }
14786629Szf162725
14796629Szf162725 if (sc->sc_tx_pipeh != NULL) {
14806629Szf162725 usb_pipe_reset(sc->sc_dev, sc->sc_tx_pipeh, flags, NULL, 0);
14816629Szf162725 usb_pipe_close(sc->sc_dev, sc->sc_tx_pipeh, flags, NULL, 0);
14826629Szf162725 sc->sc_tx_pipeh = NULL;
14836629Szf162725 }
14846629Szf162725 }
14856629Szf162725
14866629Szf162725 static int
ural_open_pipes(struct ural_softc * sc)14876629Szf162725 ural_open_pipes(struct ural_softc *sc)
14886629Szf162725 {
14896629Szf162725 usb_ep_data_t *ep_node;
14906629Szf162725 usb_pipe_policy_t policy;
14916629Szf162725 int err;
14926629Szf162725
14936629Szf162725 ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0,
14946629Szf162725 USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
14956629Szf162725
14966629Szf162725 bzero(&policy, sizeof (usb_pipe_policy_t));
14976629Szf162725 policy.pp_max_async_reqs = RAL_TX_LIST_COUNT;
14986629Szf162725
14996629Szf162725 if ((err = usb_pipe_open(sc->sc_dev,
15006629Szf162725 &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
15016629Szf162725 &sc->sc_tx_pipeh)) != USB_SUCCESS) {
15029345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
15036629Szf162725 "ural_open_pipes(): %x failed to open tx pipe\n", err);
15046629Szf162725 goto fail;
15056629Szf162725 }
15066629Szf162725
15076629Szf162725 ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0,
15086629Szf162725 USB_EP_ATTR_BULK, USB_EP_DIR_IN);
15096629Szf162725
15106629Szf162725 bzero(&policy, sizeof (usb_pipe_policy_t));
15116629Szf162725 policy.pp_max_async_reqs = RAL_RX_LIST_COUNT + 32;
15126629Szf162725
15136629Szf162725 if ((err = usb_pipe_open(sc->sc_dev,
15146629Szf162725 &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
15156629Szf162725 &sc->sc_rx_pipeh)) != USB_SUCCESS) {
15169345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
15176629Szf162725 "ural_open_pipes(): %x failed to open rx pipe\n", err);
15186629Szf162725 goto fail;
15196629Szf162725 }
15206629Szf162725
15216629Szf162725 return (USB_SUCCESS);
15226629Szf162725
15236629Szf162725 fail:
15246629Szf162725 if (sc->sc_rx_pipeh != NULL) {
15256629Szf162725 usb_pipe_close(sc->sc_dev, sc->sc_rx_pipeh,
15266629Szf162725 USB_FLAGS_SLEEP, NULL, 0);
15276629Szf162725 sc->sc_rx_pipeh = NULL;
15286629Szf162725 }
15296629Szf162725
15306629Szf162725 if (sc->sc_tx_pipeh != NULL) {
15316629Szf162725 usb_pipe_close(sc->sc_dev, sc->sc_tx_pipeh,
15326629Szf162725 USB_FLAGS_SLEEP, NULL, 0);
15336629Szf162725 sc->sc_tx_pipeh = NULL;
15346629Szf162725 }
15356629Szf162725
15366629Szf162725 return (USB_FAILURE);
15376629Szf162725 }
15386629Szf162725
15396629Szf162725 static int
ural_tx_trigger(struct ural_softc * sc,mblk_t * mp)15406629Szf162725 ural_tx_trigger(struct ural_softc *sc, mblk_t *mp)
15416629Szf162725 {
15426629Szf162725 usb_bulk_req_t *req;
15436629Szf162725 int err;
15446629Szf162725
15456629Szf162725 sc->sc_tx_timer = RAL_TX_TIMEOUT;
15466629Szf162725
15476629Szf162725 req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP);
15486629Szf162725 if (req == NULL) {
15499345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
15506629Szf162725 "ural_tx_trigger(): failed to allocate req");
15516629Szf162725 freemsg(mp);
15526629Szf162725 return (-1);
15536629Szf162725 }
15546629Szf162725
15556629Szf162725 req->bulk_len = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
15566629Szf162725 req->bulk_data = mp;
15576629Szf162725 req->bulk_client_private = (usb_opaque_t)sc;
15586629Szf162725 req->bulk_timeout = RAL_TX_TIMEOUT;
15596629Szf162725 req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
15606629Szf162725 req->bulk_cb = ural_txeof;
15616629Szf162725 req->bulk_exc_cb = ural_txeof;
15626629Szf162725 req->bulk_completion_reason = 0;
15636629Szf162725 req->bulk_cb_flags = 0;
15646629Szf162725
15656629Szf162725 if ((err = usb_pipe_bulk_xfer(sc->sc_tx_pipeh, req, 0))
15666629Szf162725 != USB_SUCCESS) {
15676629Szf162725
15689345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_tx_trigger(): "
15696629Szf162725 "failed to do tx xfer, %d", err);
15706629Szf162725 usb_free_bulk_req(req);
15716629Szf162725 return (-1);
15726629Szf162725 }
15736629Szf162725
15746629Szf162725 sc->tx_queued++;
15756629Szf162725
15766629Szf162725 return (0);
15776629Szf162725 }
15786629Szf162725
15796629Szf162725 static int
ural_rx_trigger(struct ural_softc * sc)15806629Szf162725 ural_rx_trigger(struct ural_softc *sc)
15816629Szf162725 {
15826629Szf162725 usb_bulk_req_t *req;
15836629Szf162725 int err;
15846629Szf162725
15856629Szf162725 req = usb_alloc_bulk_req(sc->sc_dev, RAL_RXBUF_SIZE, USB_FLAGS_SLEEP);
15866629Szf162725 if (req == NULL) {
15879345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
15886629Szf162725 "ural_rx_trigger(): failed to allocate req");
15896629Szf162725 return (-1);
15906629Szf162725 }
15916629Szf162725
15926629Szf162725 req->bulk_len = RAL_RXBUF_SIZE;
15936629Szf162725 req->bulk_client_private = (usb_opaque_t)sc;
15946629Szf162725 req->bulk_timeout = 0;
15956629Szf162725 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK
15966629Szf162725 | USB_ATTRS_AUTOCLEARING;
15976629Szf162725 req->bulk_cb = ural_rxeof;
15986629Szf162725 req->bulk_exc_cb = ural_rxeof;
15996629Szf162725 req->bulk_completion_reason = 0;
16006629Szf162725 req->bulk_cb_flags = 0;
16016629Szf162725
16026629Szf162725 err = usb_pipe_bulk_xfer(sc->sc_rx_pipeh, req, 0);
16036629Szf162725
16046629Szf162725 if (err != USB_SUCCESS) {
16059345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_rx_trigger(): "
16066629Szf162725 "failed to do rx xfer, %d", err);
16076629Szf162725 usb_free_bulk_req(req);
16086629Szf162725
16096629Szf162725 return (-1);
16106629Szf162725 }
16116629Szf162725
16126629Szf162725 mutex_enter(&sc->rx_lock);
16136629Szf162725 sc->rx_queued++;
16146629Szf162725 mutex_exit(&sc->rx_lock);
16156629Szf162725
16166629Szf162725 return (0);
16176629Szf162725 }
16186629Szf162725
16196629Szf162725 static void
ural_init_tx_queue(struct ural_softc * sc)16206629Szf162725 ural_init_tx_queue(struct ural_softc *sc)
16216629Szf162725 {
16226629Szf162725 sc->tx_queued = 0;
16236629Szf162725 }
16246629Szf162725
16256629Szf162725 static int
ural_init_rx_queue(struct ural_softc * sc)16266629Szf162725 ural_init_rx_queue(struct ural_softc *sc)
16276629Szf162725 {
16286629Szf162725 int i;
16296629Szf162725
16306629Szf162725 sc->rx_queued = 0;
16316629Szf162725
16326629Szf162725 for (i = 0; i < RAL_RX_LIST_COUNT; i++) {
16336629Szf162725 if (ural_rx_trigger(sc) != 0) {
16346629Szf162725 return (USB_FAILURE);
16356629Szf162725 }
16366629Szf162725 }
16376629Szf162725
16386629Szf162725 return (USB_SUCCESS);
16396629Szf162725 }
16406629Szf162725
16416629Szf162725 static void
ural_stop(struct ural_softc * sc)16426629Szf162725 ural_stop(struct ural_softc *sc)
16436629Szf162725 {
16446629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
16456629Szf162725
16466629Szf162725 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
16476629Szf162725 ieee80211_stop_watchdog(ic); /* stop the watchdog */
16486629Szf162725
16496629Szf162725 RAL_LOCK(sc);
16506629Szf162725
16516629Szf162725 sc->sc_tx_timer = 0;
16526629Szf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */
16536629Szf162725
16546629Szf162725 /* disable Rx */
16556629Szf162725 ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
16566629Szf162725
16576629Szf162725 /* reset ASIC and BBP (but won't reset MAC registers!) */
16586629Szf162725 ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP);
16596629Szf162725 ural_write(sc, RAL_MAC_CSR1, 0);
16606629Szf162725
16616629Szf162725 ural_close_pipes(sc);
16626629Szf162725
16636629Szf162725 RAL_UNLOCK(sc);
16646629Szf162725 }
16656629Szf162725
16666629Szf162725 static int
ural_init(struct ural_softc * sc)16676629Szf162725 ural_init(struct ural_softc *sc)
16686629Szf162725 {
16696629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
16706629Szf162725 uint16_t tmp;
16716629Szf162725 int i, ntries;
16726629Szf162725
16736629Szf162725 ural_set_testmode(sc);
16746629Szf162725 ural_write(sc, 0x308, 0x00f0); /* magic */
16756629Szf162725
16766629Szf162725 ural_stop(sc);
16776629Szf162725
16786629Szf162725 /* initialize MAC registers to default values */
16796629Szf162725 for (i = 0; i < URAL_N(ural_def_mac); i++)
16806629Szf162725 ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val);
16816629Szf162725
16826629Szf162725 /* wait for BBP and RF to wake up (this can take a long time!) */
16836629Szf162725 for (ntries = 0; ntries < 100; ntries++) {
16846629Szf162725 tmp = ural_read(sc, RAL_MAC_CSR17);
16856629Szf162725 if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) ==
16866629Szf162725 (RAL_BBP_AWAKE | RAL_RF_AWAKE))
16876629Szf162725 break;
16886629Szf162725 drv_usecwait(1000);
16896629Szf162725 }
16906629Szf162725 if (ntries == 100) {
16919345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
16926629Szf162725 "ural_init(): timeout waiting for BBP/RF to wakeup\n");
16936629Szf162725 goto fail;
16946629Szf162725 }
16956629Szf162725
16966629Szf162725 /* we're ready! */
16976629Szf162725 ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY);
16986629Szf162725
16996629Szf162725 /* set basic rate set (will be updated later) */
17006629Szf162725 ural_write(sc, RAL_TXRX_CSR11, 0x15f);
17016629Szf162725
17026629Szf162725 if (ural_bbp_init(sc) != 0)
17036629Szf162725 goto fail;
17046629Szf162725
17056629Szf162725 /* set default BSS channel */
17066629Szf162725 ural_set_chan(sc, ic->ic_curchan);
17076629Szf162725
17086629Szf162725 /* clear statistic registers (STA_CSR0 to STA_CSR10) */
17096629Szf162725 ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta));
17106629Szf162725
17116629Szf162725 ural_set_txantenna(sc, sc->tx_ant);
17126629Szf162725 ural_set_rxantenna(sc, sc->rx_ant);
17136629Szf162725
17146629Szf162725 ural_set_macaddr(sc, ic->ic_macaddr);
17156629Szf162725
17166629Szf162725 if (ural_open_pipes(sc) != USB_SUCCESS) {
17179345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_init(): "
17186629Szf162725 "could not open pipes.\n");
17196629Szf162725 goto fail;
17206629Szf162725 }
17216629Szf162725
17226629Szf162725 ural_init_tx_queue(sc);
17236629Szf162725
17246629Szf162725 if (ural_init_rx_queue(sc) != USB_SUCCESS)
17256629Szf162725 goto fail;
17266629Szf162725
17276629Szf162725 /* kick Rx */
17286629Szf162725 tmp = RAL_DROP_PHY | RAL_DROP_CRC;
17296629Szf162725 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
17306629Szf162725 tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
17316629Szf162725 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
17326629Szf162725 tmp |= RAL_DROP_TODS;
17336629Szf162725 if (!(sc->sc_rcr & RAL_RCR_PROMISC))
17346629Szf162725 tmp |= RAL_DROP_NOT_TO_ME;
17356629Szf162725 }
17366629Szf162725 ural_write(sc, RAL_TXRX_CSR2, tmp);
17376629Szf162725 sc->sc_flags |= RAL_FLAG_RUNNING; /* RUNNING */
17386629Szf162725
17396629Szf162725 return (DDI_SUCCESS);
17406629Szf162725 fail:
17416629Szf162725 ural_stop(sc);
17426629Szf162725 return (EIO);
17436629Szf162725 }
17446629Szf162725
17456629Szf162725 static int
ural_disconnect(dev_info_t * devinfo)17469345SQuaker.Fang@Sun.COM ural_disconnect(dev_info_t *devinfo)
17476629Szf162725 {
17486629Szf162725 struct ural_softc *sc;
17496629Szf162725 struct ieee80211com *ic;
17506629Szf162725
17516629Szf162725 /*
17526629Szf162725 * We can't call ural_stop() here, since the hardware is removed,
17536629Szf162725 * we can't access the register anymore.
17546629Szf162725 */
17556629Szf162725 sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo));
17569345SQuaker.Fang@Sun.COM ASSERT(sc != NULL);
17579345SQuaker.Fang@Sun.COM
17589345SQuaker.Fang@Sun.COM if (!RAL_IS_RUNNING(sc)) /* different device or not inited */
17599345SQuaker.Fang@Sun.COM return (DDI_SUCCESS);
17609345SQuaker.Fang@Sun.COM
17616629Szf162725 ic = &sc->sc_ic;
17626629Szf162725 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
17636629Szf162725 ieee80211_stop_watchdog(ic); /* stop the watchdog */
17646629Szf162725
17656629Szf162725 RAL_LOCK(sc);
17666629Szf162725
17676629Szf162725 sc->sc_tx_timer = 0;
17686629Szf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */
17696629Szf162725
17706629Szf162725 ural_close_pipes(sc);
17716629Szf162725
17726629Szf162725 RAL_UNLOCK(sc);
17736629Szf162725
17746629Szf162725 return (DDI_SUCCESS);
17756629Szf162725 }
17766629Szf162725
17776629Szf162725 static int
ural_reconnect(dev_info_t * devinfo)17789345SQuaker.Fang@Sun.COM ural_reconnect(dev_info_t *devinfo)
17796629Szf162725 {
17806629Szf162725 struct ural_softc *sc;
17816629Szf162725 int err;
17826629Szf162725
17836629Szf162725 sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo));
17849345SQuaker.Fang@Sun.COM ASSERT(sc != NULL);
17859345SQuaker.Fang@Sun.COM
17869345SQuaker.Fang@Sun.COM /* check device changes after disconnect */
17879345SQuaker.Fang@Sun.COM if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1,
17889345SQuaker.Fang@Sun.COM USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
17899345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "different device connected\n");
17909345SQuaker.Fang@Sun.COM return (DDI_FAILURE);
17919345SQuaker.Fang@Sun.COM }
17929345SQuaker.Fang@Sun.COM
17936629Szf162725 err = ural_init(sc);
17946629Szf162725
17956629Szf162725 return (err);
17966629Szf162725 }
17976629Szf162725
17989345SQuaker.Fang@Sun.COM static void
ural_resume(struct ural_softc * sc)17999345SQuaker.Fang@Sun.COM ural_resume(struct ural_softc *sc)
18009345SQuaker.Fang@Sun.COM {
18019345SQuaker.Fang@Sun.COM /* check device changes after suspend */
18029345SQuaker.Fang@Sun.COM if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1,
18039345SQuaker.Fang@Sun.COM USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) {
18049345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "no or different device connected\n");
18059345SQuaker.Fang@Sun.COM return;
18069345SQuaker.Fang@Sun.COM }
18079345SQuaker.Fang@Sun.COM
18089345SQuaker.Fang@Sun.COM (void) ural_init(sc);
18099345SQuaker.Fang@Sun.COM }
18109345SQuaker.Fang@Sun.COM
18116629Szf162725 #define URAL_AMRR_MIN_SUCCESS_THRESHOLD 1
18126629Szf162725 #define URAL_AMRR_MAX_SUCCESS_THRESHOLD 10
18136629Szf162725
18146629Szf162725 /*
18156629Szf162725 * Naive implementation of the Adaptive Multi Rate Retry algorithm:
18166629Szf162725 * "IEEE 802.11 Rate Adaptation: A Practical Approach"
18176629Szf162725 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
18186629Szf162725 * INRIA Sophia - Projet Planete
18196629Szf162725 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html
18206629Szf162725 *
18216629Szf162725 * This algorithm is particularly well suited for ural since it does not
18226629Szf162725 * require per-frame retry statistics. Note however that since h/w does
18236629Szf162725 * not provide per-frame stats, we can't do per-node rate adaptation and
18246629Szf162725 * thus automatic rate adaptation is only enabled in STA operating mode.
18256629Szf162725 */
18266629Szf162725 #define is_success(amrr) \
18276629Szf162725 ((amrr)->retrycnt < (amrr)->txcnt / 10)
18286629Szf162725 #define is_failure(amrr) \
18296629Szf162725 ((amrr)->retrycnt > (amrr)->txcnt / 3)
18306629Szf162725 #define is_enough(amrr) \
18316629Szf162725 ((amrr)->txcnt > 10)
18326629Szf162725 #define is_min_rate(ni) \
18336629Szf162725 ((ni)->in_txrate == 0)
18346629Szf162725 #define is_max_rate(ni) \
18356629Szf162725 ((ni)->in_txrate == (ni)->in_rates.ir_nrates - 1)
18366629Szf162725 #define increase_rate(ni) \
18376629Szf162725 ((ni)->in_txrate++)
18386629Szf162725 #define decrease_rate(ni) \
18396629Szf162725 ((ni)->in_txrate--)
18406629Szf162725 #define reset_cnt(amrr) do { \
18416629Szf162725 (amrr)->txcnt = (amrr)->retrycnt = 0; \
18426629Szf162725 _NOTE(CONSTCOND) \
18436629Szf162725 } while (/* CONSTCOND */0)
18446629Szf162725
18456629Szf162725 static void
ural_ratectl(struct ural_amrr * amrr,struct ieee80211_node * ni)18466629Szf162725 ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni)
18476629Szf162725 {
18486629Szf162725 int need_change = 0;
18496629Szf162725
18506629Szf162725 if (is_success(amrr) && is_enough(amrr)) {
18516629Szf162725 amrr->success++;
18526629Szf162725 if (amrr->success >= amrr->success_threshold &&
18536629Szf162725 !is_max_rate(ni)) {
18546629Szf162725 amrr->recovery = 1;
18556629Szf162725 amrr->success = 0;
18566629Szf162725 increase_rate(ni);
18576629Szf162725 need_change = 1;
18586629Szf162725 } else {
18596629Szf162725 amrr->recovery = 0;
18606629Szf162725 }
18616629Szf162725 } else if (is_failure(amrr)) {
18626629Szf162725 amrr->success = 0;
18636629Szf162725 if (!is_min_rate(ni)) {
18646629Szf162725 if (amrr->recovery) {
18656629Szf162725 amrr->success_threshold *= 2;
18666629Szf162725 if (amrr->success_threshold >
18676629Szf162725 URAL_AMRR_MAX_SUCCESS_THRESHOLD)
18686629Szf162725 amrr->success_threshold =
18696629Szf162725 URAL_AMRR_MAX_SUCCESS_THRESHOLD;
18706629Szf162725 } else {
18716629Szf162725 amrr->success_threshold =
18726629Szf162725 URAL_AMRR_MIN_SUCCESS_THRESHOLD;
18736629Szf162725 }
18746629Szf162725 decrease_rate(ni);
18756629Szf162725 need_change = 1;
18766629Szf162725 }
18776629Szf162725 amrr->recovery = 0; /* original paper was incorrect */
18786629Szf162725 }
18796629Szf162725
18806629Szf162725 if (is_enough(amrr) || need_change)
18816629Szf162725 reset_cnt(amrr);
18826629Szf162725 }
18836629Szf162725
18846629Szf162725 static void
ural_amrr_timeout(void * arg)18856629Szf162725 ural_amrr_timeout(void *arg)
18866629Szf162725 {
18876629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
18886629Szf162725 struct ural_amrr *amrr = &sc->amrr;
18896629Szf162725
18906629Szf162725 ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta));
18916629Szf162725
18926629Szf162725 /* count TX retry-fail as Tx errors */
18936629Szf162725 sc->sc_tx_err += sc->sta[9];
18946629Szf162725 sc->sc_tx_retries += (sc->sta[7] + sc->sta[8]);
18956629Szf162725
18966629Szf162725 amrr->retrycnt =
18976629Szf162725 sc->sta[7] + /* TX one-retry ok count */
18986629Szf162725 sc->sta[8] + /* TX more-retry ok count */
18996629Szf162725 sc->sta[9]; /* TX retry-fail count */
19006629Szf162725
19016629Szf162725 amrr->txcnt =
19026629Szf162725 amrr->retrycnt +
19036629Szf162725 sc->sta[6]; /* TX no-retry ok count */
19046629Szf162725
19056629Szf162725 ural_ratectl(amrr, sc->sc_ic.ic_bss);
19066629Szf162725
19076629Szf162725 sc->sc_amrr_id = timeout(ural_amrr_timeout, (void *)sc,
19086629Szf162725 drv_usectohz(1000 * 1000)); /* 1 second */
19096629Szf162725 }
19106629Szf162725
19116629Szf162725
19126629Szf162725 static void
ural_amrr_start(struct ural_softc * sc,struct ieee80211_node * ni)19136629Szf162725 ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni)
19146629Szf162725 {
19156629Szf162725 struct ural_amrr *amrr = &sc->amrr;
19166629Szf162725 int i;
19176629Szf162725
19186629Szf162725 /* clear statistic registers (STA_CSR0 to STA_CSR10) */
19196629Szf162725 ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof (sc->sta));
19206629Szf162725
19216629Szf162725 amrr->success = 0;
19226629Szf162725 amrr->recovery = 0;
19236629Szf162725 amrr->txcnt = amrr->retrycnt = 0;
19246629Szf162725 amrr->success_threshold = URAL_AMRR_MIN_SUCCESS_THRESHOLD;
19256629Szf162725
19266629Szf162725 /* set rate to some reasonable initial value */
19276629Szf162725 for (i = ni->in_rates.ir_nrates - 1;
19286629Szf162725 i > 0 && (ni->in_rates.ir_rates[i] & IEEE80211_RATE_VAL) > 72;
19296629Szf162725 i--) {
19306629Szf162725 }
19316629Szf162725
19326629Szf162725 ni->in_txrate = i;
19336629Szf162725
19346629Szf162725 sc->sc_amrr_id = timeout(ural_amrr_timeout, (void *)sc,
19356629Szf162725 drv_usectohz(1000 * 1000)); /* 1 second */
19366629Szf162725 }
19376629Szf162725
19386629Szf162725 void
ural_watchdog(void * arg)19396629Szf162725 ural_watchdog(void *arg)
19406629Szf162725 {
19416629Szf162725 struct ural_softc *sc = arg;
19426629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
19436629Szf162725 int ntimer = 0;
19446629Szf162725
19456629Szf162725 RAL_LOCK(sc);
19466629Szf162725 ic->ic_watchdog_timer = 0;
19476629Szf162725
19486629Szf162725 if (!RAL_IS_RUNNING(sc)) {
19496629Szf162725 RAL_UNLOCK(sc);
19506629Szf162725 return;
19516629Szf162725 }
19526629Szf162725
19536629Szf162725 if (sc->sc_tx_timer > 0) {
19546629Szf162725 if (--sc->sc_tx_timer == 0) {
19559345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "tx timer timeout\n");
19566629Szf162725 RAL_UNLOCK(sc);
19576629Szf162725 (void) ural_init(sc);
19586629Szf162725 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
19596629Szf162725 return;
19606629Szf162725 }
19616629Szf162725 }
19626629Szf162725
19636629Szf162725 if (ic->ic_state == IEEE80211_S_RUN)
19646629Szf162725 ntimer = 1;
19656629Szf162725
19666629Szf162725 RAL_UNLOCK(sc);
19676629Szf162725
19686629Szf162725 ieee80211_watchdog(ic);
19696629Szf162725
19706629Szf162725 if (ntimer)
19716629Szf162725 ieee80211_start_watchdog(ic, ntimer);
19726629Szf162725 }
19736629Szf162725
19746629Szf162725 static int
ural_m_start(void * arg)19756629Szf162725 ural_m_start(void *arg)
19766629Szf162725 {
19776629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
19786629Szf162725 int err;
19796629Szf162725
19806629Szf162725 /*
19816629Szf162725 * initialize RT2500USB hardware
19826629Szf162725 */
19836629Szf162725 err = ural_init(sc);
19846629Szf162725 if (err != DDI_SUCCESS) {
19859345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "device configuration failed\n");
19866629Szf162725 goto fail;
19876629Szf162725 }
19886629Szf162725 sc->sc_flags |= RAL_FLAG_RUNNING; /* RUNNING */
19896629Szf162725 return (err);
19906629Szf162725
19916629Szf162725 fail:
19926629Szf162725 ural_stop(sc);
19936629Szf162725 return (err);
19946629Szf162725 }
19956629Szf162725
19966629Szf162725 static void
ural_m_stop(void * arg)19976629Szf162725 ural_m_stop(void *arg)
19986629Szf162725 {
19996629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
20006629Szf162725
20016629Szf162725 (void) ural_stop(sc);
20026629Szf162725 sc->sc_flags &= ~RAL_FLAG_RUNNING; /* STOP */
20036629Szf162725 }
20046629Szf162725
20056629Szf162725 static int
ural_m_unicst(void * arg,const uint8_t * macaddr)20066629Szf162725 ural_m_unicst(void *arg, const uint8_t *macaddr)
20076629Szf162725 {
20086629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
20096629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
20106629Szf162725
20119345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_MSG, "ural_m_unicst(): " MACSTR "\n",
20126629Szf162725 MAC2STR(macaddr));
20136629Szf162725
20146629Szf162725 IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
20156629Szf162725 (void) ural_set_macaddr(sc, (uint8_t *)macaddr);
20166629Szf162725 (void) ural_init(sc);
20176629Szf162725
20186629Szf162725 return (0);
20196629Szf162725 }
20206629Szf162725
20216629Szf162725 /*ARGSUSED*/
20226629Szf162725 static int
ural_m_multicst(void * arg,boolean_t add,const uint8_t * mca)20236629Szf162725 ural_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
20246629Szf162725 {
20256629Szf162725 return (0);
20266629Szf162725 }
20276629Szf162725
20286629Szf162725 static int
ural_m_promisc(void * arg,boolean_t on)20296629Szf162725 ural_m_promisc(void *arg, boolean_t on)
20306629Szf162725 {
20316629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
20326629Szf162725
20336629Szf162725 if (on) {
20346629Szf162725 sc->sc_rcr |= RAL_RCR_PROMISC;
20356629Szf162725 sc->sc_rcr |= RAL_RCR_MULTI;
20366629Szf162725 } else {
20376629Szf162725 sc->sc_rcr &= ~RAL_RCR_PROMISC;
20386629Szf162725 sc->sc_rcr &= ~RAL_RCR_PROMISC;
20396629Szf162725 }
20406629Szf162725
20416629Szf162725 ural_update_promisc(sc);
20426629Szf162725 return (0);
20436629Szf162725 }
20446629Szf162725
20458099SQuaker.Fang@Sun.COM /*
20468099SQuaker.Fang@Sun.COM * callback functions for /get/set properties
20478099SQuaker.Fang@Sun.COM */
20488099SQuaker.Fang@Sun.COM static int
ural_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)20498099SQuaker.Fang@Sun.COM ural_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
20508099SQuaker.Fang@Sun.COM uint_t wldp_length, const void *wldp_buf)
20518099SQuaker.Fang@Sun.COM {
20528099SQuaker.Fang@Sun.COM struct ural_softc *sc = (struct ural_softc *)arg;
20538099SQuaker.Fang@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
20548099SQuaker.Fang@Sun.COM int err;
20558099SQuaker.Fang@Sun.COM
20568099SQuaker.Fang@Sun.COM err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
20578099SQuaker.Fang@Sun.COM wldp_length, wldp_buf);
20588099SQuaker.Fang@Sun.COM RAL_LOCK(sc);
20598099SQuaker.Fang@Sun.COM if (err == ENETRESET) {
20608099SQuaker.Fang@Sun.COM if (RAL_IS_RUNNING(sc)) {
20618099SQuaker.Fang@Sun.COM RAL_UNLOCK(sc);
20628099SQuaker.Fang@Sun.COM (void) ural_init(sc);
20638099SQuaker.Fang@Sun.COM (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
20648099SQuaker.Fang@Sun.COM RAL_LOCK(sc);
20658099SQuaker.Fang@Sun.COM }
20668099SQuaker.Fang@Sun.COM err = 0;
20678099SQuaker.Fang@Sun.COM }
20688099SQuaker.Fang@Sun.COM RAL_UNLOCK(sc);
20698099SQuaker.Fang@Sun.COM
20708099SQuaker.Fang@Sun.COM return (err);
20718099SQuaker.Fang@Sun.COM }
20728099SQuaker.Fang@Sun.COM
20738099SQuaker.Fang@Sun.COM static int
ural_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)20748099SQuaker.Fang@Sun.COM ural_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2075*11878SVenu.Iyer@Sun.COM uint_t wldp_length, void *wldp_buf)
20768099SQuaker.Fang@Sun.COM {
20778099SQuaker.Fang@Sun.COM struct ural_softc *sc = (struct ural_softc *)arg;
20788099SQuaker.Fang@Sun.COM int err;
20798099SQuaker.Fang@Sun.COM
20808099SQuaker.Fang@Sun.COM err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
2081*11878SVenu.Iyer@Sun.COM wldp_length, wldp_buf);
20828099SQuaker.Fang@Sun.COM
20838099SQuaker.Fang@Sun.COM return (err);
20848099SQuaker.Fang@Sun.COM }
20858099SQuaker.Fang@Sun.COM
20866629Szf162725 static void
ural_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t mph)2087*11878SVenu.Iyer@Sun.COM ural_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
2088*11878SVenu.Iyer@Sun.COM mac_prop_info_handle_t mph)
2089*11878SVenu.Iyer@Sun.COM {
2090*11878SVenu.Iyer@Sun.COM struct ural_softc *sc = (struct ural_softc *)arg;
2091*11878SVenu.Iyer@Sun.COM
2092*11878SVenu.Iyer@Sun.COM ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph);
2093*11878SVenu.Iyer@Sun.COM }
2094*11878SVenu.Iyer@Sun.COM
2095*11878SVenu.Iyer@Sun.COM static void
ural_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)20966629Szf162725 ural_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
20976629Szf162725 {
20986629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
20996629Szf162725 struct ieee80211com *ic = &sc->sc_ic;
21006629Szf162725 int err;
21016629Szf162725
21026629Szf162725 err = ieee80211_ioctl(ic, wq, mp);
21036629Szf162725 RAL_LOCK(sc);
21046629Szf162725 if (err == ENETRESET) {
21056629Szf162725 if (RAL_IS_RUNNING(sc)) {
21066629Szf162725 RAL_UNLOCK(sc);
21076629Szf162725 (void) ural_init(sc);
21086629Szf162725 (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
21096629Szf162725 RAL_LOCK(sc);
21106629Szf162725 }
21116629Szf162725 }
21126629Szf162725 RAL_UNLOCK(sc);
21136629Szf162725 }
21146629Szf162725
21156629Szf162725 static int
ural_m_stat(void * arg,uint_t stat,uint64_t * val)21166629Szf162725 ural_m_stat(void *arg, uint_t stat, uint64_t *val)
21176629Szf162725 {
21186629Szf162725 struct ural_softc *sc = (struct ural_softc *)arg;
21196629Szf162725 ieee80211com_t *ic = &sc->sc_ic;
21206629Szf162725 ieee80211_node_t *ni = ic->ic_bss;
21216629Szf162725 struct ieee80211_rateset *rs = &ni->in_rates;
21226629Szf162725
21236629Szf162725 RAL_LOCK(sc);
21246629Szf162725 switch (stat) {
21256629Szf162725 case MAC_STAT_IFSPEED:
21266629Szf162725 *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
21276629Szf162725 (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL)
21286890Sql147931 : ic->ic_fixed_rate) / 2 * 1000000;
21296629Szf162725 break;
21306629Szf162725 case MAC_STAT_NOXMTBUF:
21316629Szf162725 *val = sc->sc_tx_nobuf;
21326629Szf162725 break;
21336629Szf162725 case MAC_STAT_NORCVBUF:
21346629Szf162725 *val = sc->sc_rx_nobuf;
21356629Szf162725 break;
21366629Szf162725 case MAC_STAT_IERRORS:
21376629Szf162725 *val = sc->sc_rx_err;
21386629Szf162725 break;
21396629Szf162725 case MAC_STAT_RBYTES:
21406629Szf162725 *val = ic->ic_stats.is_rx_bytes;
21416629Szf162725 break;
21426629Szf162725 case MAC_STAT_IPACKETS:
21436629Szf162725 *val = ic->ic_stats.is_rx_frags;
21446629Szf162725 break;
21456629Szf162725 case MAC_STAT_OBYTES:
21466629Szf162725 *val = ic->ic_stats.is_tx_bytes;
21476629Szf162725 break;
21486629Szf162725 case MAC_STAT_OPACKETS:
21496629Szf162725 *val = ic->ic_stats.is_tx_frags;
21506629Szf162725 break;
21516629Szf162725 case MAC_STAT_OERRORS:
21526629Szf162725 case WIFI_STAT_TX_FAILED:
21536629Szf162725 *val = sc->sc_tx_err;
21546629Szf162725 break;
21556629Szf162725 case WIFI_STAT_TX_RETRANS:
21566629Szf162725 *val = sc->sc_tx_retries;
21576629Szf162725 break;
21586629Szf162725 case WIFI_STAT_FCS_ERRORS:
21596629Szf162725 case WIFI_STAT_WEP_ERRORS:
21606629Szf162725 case WIFI_STAT_TX_FRAGS:
21616629Szf162725 case WIFI_STAT_MCAST_TX:
21626629Szf162725 case WIFI_STAT_RTS_SUCCESS:
21636629Szf162725 case WIFI_STAT_RTS_FAILURE:
21646629Szf162725 case WIFI_STAT_ACK_FAILURE:
21656629Szf162725 case WIFI_STAT_RX_FRAGS:
21666629Szf162725 case WIFI_STAT_MCAST_RX:
21676629Szf162725 case WIFI_STAT_RX_DUPS:
21686629Szf162725 RAL_UNLOCK(sc);
21696629Szf162725 return (ieee80211_stat(ic, stat, val));
21706629Szf162725 default:
21716629Szf162725 RAL_UNLOCK(sc);
21726629Szf162725 return (ENOTSUP);
21736629Szf162725 }
21746629Szf162725 RAL_UNLOCK(sc);
21756629Szf162725
21766629Szf162725 return (0);
21776629Szf162725 }
21786629Szf162725
21796629Szf162725
21806629Szf162725 static int
ural_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)21816629Szf162725 ural_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
21826629Szf162725 {
21836629Szf162725 struct ural_softc *sc;
21846629Szf162725 struct ieee80211com *ic;
21856629Szf162725 int err, i;
21866629Szf162725 int instance;
21876629Szf162725
21886629Szf162725 char strbuf[32];
21896629Szf162725
21906629Szf162725 wifi_data_t wd = { 0 };
21916629Szf162725 mac_register_t *macp;
21926629Szf162725
21939345SQuaker.Fang@Sun.COM switch (cmd) {
21949345SQuaker.Fang@Sun.COM case DDI_ATTACH:
21959345SQuaker.Fang@Sun.COM break;
21969345SQuaker.Fang@Sun.COM case DDI_RESUME:
21979345SQuaker.Fang@Sun.COM sc = ddi_get_soft_state(ural_soft_state_p,
21989345SQuaker.Fang@Sun.COM ddi_get_instance(devinfo));
21999345SQuaker.Fang@Sun.COM ASSERT(sc != NULL);
22009345SQuaker.Fang@Sun.COM ural_resume(sc);
22019345SQuaker.Fang@Sun.COM return (DDI_SUCCESS);
22029345SQuaker.Fang@Sun.COM default:
22036629Szf162725 return (DDI_FAILURE);
22049345SQuaker.Fang@Sun.COM }
22056629Szf162725
22066629Szf162725 instance = ddi_get_instance(devinfo);
22076629Szf162725
22086629Szf162725 if (ddi_soft_state_zalloc(ural_soft_state_p, instance) != DDI_SUCCESS) {
22099345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_MSG, "ural_attach(): "
22106629Szf162725 "unable to alloc soft_state_p\n");
22116629Szf162725 return (DDI_FAILURE);
22126629Szf162725 }
22136629Szf162725
22146629Szf162725 sc = ddi_get_soft_state(ural_soft_state_p, instance);
22156629Szf162725 ic = (ieee80211com_t *)&sc->sc_ic;
22166629Szf162725 sc->sc_dev = devinfo;
22176629Szf162725
22186629Szf162725 if (usb_client_attach(devinfo, USBDRV_VERSION, 0) != USB_SUCCESS) {
22199345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
22206629Szf162725 "ural_attach(): usb_client_attach failed\n");
22216629Szf162725 goto fail1;
22226629Szf162725 }
22236629Szf162725
22246629Szf162725 if (usb_get_dev_data(devinfo, &sc->sc_udev,
22256629Szf162725 USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) {
22266629Szf162725 sc->sc_udev = NULL;
22276629Szf162725 goto fail2;
22286629Szf162725 }
22296629Szf162725
22306629Szf162725 mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
22316629Szf162725 mutex_init(&sc->tx_lock, NULL, MUTEX_DRIVER, NULL);
22326629Szf162725 mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL);
22336629Szf162725
22346629Szf162725 /* retrieve RT2570 rev. no */
22356629Szf162725 sc->asic_rev = ural_read(sc, RAL_MAC_CSR0);
22366629Szf162725
22376629Szf162725 /* retrieve MAC address and various other things from EEPROM */
22386629Szf162725 ural_read_eeprom(sc);
22396629Szf162725
22409345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_MSG, "ural: MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
22416629Szf162725 sc->asic_rev, ural_get_rf(sc->rf_rev));
22426629Szf162725
22436629Szf162725 ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
22446629Szf162725 ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
22456629Szf162725 ic->ic_state = IEEE80211_S_INIT;
22466629Szf162725
22476629Szf162725 ic->ic_maxrssi = 63;
22486629Szf162725 ic->ic_set_shortslot = ural_update_slot;
22496629Szf162725 ic->ic_xmit = ural_send;
22506629Szf162725
22516629Szf162725 /* set device capabilities */
22526629Szf162725 ic->ic_caps =
22536629Szf162725 IEEE80211_C_TXPMGT | /* tx power management */
22546629Szf162725 IEEE80211_C_SHPREAMBLE | /* short preamble supported */
22556629Szf162725 IEEE80211_C_SHSLOT; /* short slot time supported */
22566629Szf162725
22576629Szf162725 ic->ic_caps |= IEEE80211_C_WPA; /* Support WPA/WPA2 */
22586629Szf162725
22596629Szf162725 #define IEEE80211_CHAN_A \
22606629Szf162725 (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
22616629Szf162725
22626629Szf162725 if (sc->rf_rev == RAL_RF_5222) {
22636629Szf162725 /* set supported .11a rates */
22646629Szf162725 ic->ic_sup_rates[IEEE80211_MODE_11A] = ural_rateset_11a;
22656629Szf162725
22666629Szf162725 /* set supported .11a channels */
22676629Szf162725 for (i = 36; i <= 64; i += 4) {
22686629Szf162725 ic->ic_sup_channels[i].ich_freq =
22696629Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
22706629Szf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A;
22716629Szf162725 }
22726629Szf162725 for (i = 100; i <= 140; i += 4) {
22736629Szf162725 ic->ic_sup_channels[i].ich_freq =
22746629Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
22756629Szf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A;
22766629Szf162725 }
22776629Szf162725 for (i = 149; i <= 161; i += 4) {
22786629Szf162725 ic->ic_sup_channels[i].ich_freq =
22796629Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
22806629Szf162725 ic->ic_sup_channels[i].ich_flags = IEEE80211_CHAN_A;
22816629Szf162725 }
22826629Szf162725 }
22836629Szf162725
22846629Szf162725 /* set supported .11b and .11g rates */
22856629Szf162725 ic->ic_sup_rates[IEEE80211_MODE_11B] = ural_rateset_11b;
22866629Szf162725 ic->ic_sup_rates[IEEE80211_MODE_11G] = ural_rateset_11g;
22876629Szf162725
22886629Szf162725 /* set supported .11b and .11g channels (1 through 14) */
22896629Szf162725 for (i = 1; i <= 14; i++) {
22906629Szf162725 ic->ic_sup_channels[i].ich_freq =
22916629Szf162725 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
22926629Szf162725 ic->ic_sup_channels[i].ich_flags =
22936629Szf162725 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
22946629Szf162725 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
22956629Szf162725 }
22966629Szf162725
22976629Szf162725 ieee80211_attach(ic);
22986629Szf162725
22996629Szf162725 /* register WPA door */
23006629Szf162725 ieee80211_register_door(ic, ddi_driver_name(devinfo),
23016629Szf162725 ddi_get_instance(devinfo));
23026629Szf162725
23036629Szf162725 /* override state transition machine */
23046629Szf162725 sc->sc_newstate = ic->ic_newstate;
23056629Szf162725 ic->ic_newstate = ural_newstate;
23066629Szf162725 ic->ic_watchdog = ural_watchdog;
23076629Szf162725 ieee80211_media_init(ic);
23086629Szf162725 ic->ic_def_txkey = 0;
23096629Szf162725
23106629Szf162725 sc->sc_rcr = 0;
23116629Szf162725 sc->dwelltime = 300;
23129345SQuaker.Fang@Sun.COM sc->sc_flags &= 0;
23136629Szf162725
23146629Szf162725 /*
23156629Szf162725 * Provide initial settings for the WiFi plugin; whenever this
23166629Szf162725 * information changes, we need to call mac_plugindata_update()
23176629Szf162725 */
23186629Szf162725 wd.wd_opmode = ic->ic_opmode;
23196629Szf162725 wd.wd_secalloc = WIFI_SEC_NONE;
23206629Szf162725 IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
23216629Szf162725
23226629Szf162725 if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
23239345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_attach(): "
23246629Szf162725 "MAC version mismatch\n");
23256629Szf162725 goto fail3;
23266629Szf162725 }
23276629Szf162725
23286629Szf162725 macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
23296629Szf162725 macp->m_driver = sc;
23306629Szf162725 macp->m_dip = devinfo;
23316629Szf162725 macp->m_src_addr = ic->ic_macaddr;
23326629Szf162725 macp->m_callbacks = &ural_m_callbacks;
23336629Szf162725 macp->m_min_sdu = 0;
23346629Szf162725 macp->m_max_sdu = IEEE80211_MTU;
23356629Szf162725 macp->m_pdata = &wd;
23366629Szf162725 macp->m_pdata_size = sizeof (wd);
23376629Szf162725
23386629Szf162725 err = mac_register(macp, &ic->ic_mach);
23396629Szf162725 mac_free(macp);
23406629Szf162725 if (err != 0) {
23419345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ural_attach(): "
23426629Szf162725 "mac_register() err %x\n", err);
23436629Szf162725 goto fail3;
23446629Szf162725 }
23456629Szf162725
23469345SQuaker.Fang@Sun.COM if (usb_register_hotplug_cbs(devinfo, ural_disconnect,
23479345SQuaker.Fang@Sun.COM ural_reconnect) != USB_SUCCESS) {
23489345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR,
23496629Szf162725 "ural: ural_attach() failed to register events");
23506629Szf162725 goto fail4;
23516629Szf162725 }
23526629Szf162725
23536629Szf162725 /*
23546629Szf162725 * Create minor node of type DDI_NT_NET_WIFI
23556629Szf162725 */
23566629Szf162725 (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
23576629Szf162725 "ural", instance);
23586629Szf162725 err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
23596629Szf162725 instance + 1, DDI_NT_NET_WIFI, 0);
23606629Szf162725
23616629Szf162725 if (err != DDI_SUCCESS)
23629345SQuaker.Fang@Sun.COM ral_debug(RAL_DBG_ERR, "ddi_create_minor_node() failed\n");
23636629Szf162725
23646629Szf162725 /*
23656629Szf162725 * Notify link is down now
23666629Szf162725 */
23676629Szf162725 mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
23686629Szf162725
23696629Szf162725 return (DDI_SUCCESS);
23706629Szf162725 fail4:
23716629Szf162725 (void) mac_unregister(ic->ic_mach);
23726629Szf162725 fail3:
23736629Szf162725 mutex_destroy(&sc->sc_genlock);
23746629Szf162725 mutex_destroy(&sc->tx_lock);
23756629Szf162725 mutex_destroy(&sc->rx_lock);
23766629Szf162725 fail2:
23776629Szf162725 usb_client_detach(sc->sc_dev, sc->sc_udev);
23786629Szf162725 fail1:
23796629Szf162725 ddi_soft_state_free(ural_soft_state_p, ddi_get_instance(devinfo));
23806629Szf162725
23816629Szf162725 return (DDI_FAILURE);
23826629Szf162725 }
23836629Szf162725
23846629Szf162725 static int
ural_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)23856629Szf162725 ural_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
23866629Szf162725 {
23876629Szf162725 struct ural_softc *sc;
23886629Szf162725
23896629Szf162725 sc = ddi_get_soft_state(ural_soft_state_p, ddi_get_instance(devinfo));
23909345SQuaker.Fang@Sun.COM ASSERT(sc != NULL);
23919345SQuaker.Fang@Sun.COM
23929345SQuaker.Fang@Sun.COM switch (cmd) {
23939345SQuaker.Fang@Sun.COM case DDI_DETACH:
23949345SQuaker.Fang@Sun.COM break;
23959345SQuaker.Fang@Sun.COM case DDI_SUSPEND:
23969345SQuaker.Fang@Sun.COM if (RAL_IS_RUNNING(sc))
23979345SQuaker.Fang@Sun.COM (void) ural_stop(sc);
23989345SQuaker.Fang@Sun.COM return (DDI_SUCCESS);
23999345SQuaker.Fang@Sun.COM default:
24006629Szf162725 return (DDI_FAILURE);
24019345SQuaker.Fang@Sun.COM }
24026629Szf162725
24037507SXinghua.Wen@Sun.COM if (mac_disable(sc->sc_ic.ic_mach) != 0)
24047507SXinghua.Wen@Sun.COM return (DDI_FAILURE);
24057507SXinghua.Wen@Sun.COM
24066629Szf162725 ural_stop(sc);
24076629Szf162725 usb_unregister_hotplug_cbs(devinfo);
24086629Szf162725
24096629Szf162725 /*
24106629Szf162725 * Unregister from the MAC layer subsystem
24116629Szf162725 */
24127507SXinghua.Wen@Sun.COM (void) mac_unregister(sc->sc_ic.ic_mach);
24136629Szf162725
24146629Szf162725 /*
24156629Szf162725 * detach ieee80211 layer
24166629Szf162725 */
24176629Szf162725 ieee80211_detach(&sc->sc_ic);
24186629Szf162725
24196629Szf162725 mutex_destroy(&sc->sc_genlock);
24206629Szf162725 mutex_destroy(&sc->tx_lock);
24216629Szf162725 mutex_destroy(&sc->rx_lock);
24226629Szf162725
24236629Szf162725 /* pipes will be close in ural_stop() */
24246629Szf162725 usb_client_detach(devinfo, sc->sc_udev);
24256629Szf162725 sc->sc_udev = NULL;
24266629Szf162725
24276629Szf162725 ddi_remove_minor_node(devinfo, NULL);
24286629Szf162725 ddi_soft_state_free(ural_soft_state_p, ddi_get_instance(devinfo));
24296629Szf162725
24306629Szf162725 return (DDI_SUCCESS);
24316629Szf162725 }
24326629Szf162725
24336629Szf162725 int
_info(struct modinfo * modinfop)24346629Szf162725 _info(struct modinfo *modinfop)
24356629Szf162725 {
24366629Szf162725 return (mod_info(&modlinkage, modinfop));
24376629Szf162725 }
24386629Szf162725
24396629Szf162725 int
_init(void)24406629Szf162725 _init(void)
24416629Szf162725 {
24426629Szf162725 int status;
24436629Szf162725
24446629Szf162725 status = ddi_soft_state_init(&ural_soft_state_p,
24456629Szf162725 sizeof (struct ural_softc), 1);
24466629Szf162725 if (status != 0)
24476629Szf162725 return (status);
24486629Szf162725
24496629Szf162725 mac_init_ops(&ural_dev_ops, "ural");
24506629Szf162725 status = mod_install(&modlinkage);
24516629Szf162725 if (status != 0) {
24526629Szf162725 mac_fini_ops(&ural_dev_ops);
24536629Szf162725 ddi_soft_state_fini(&ural_soft_state_p);
24546629Szf162725 }
24556629Szf162725 return (status);
24566629Szf162725 }
24576629Szf162725
24586629Szf162725 int
_fini(void)24596629Szf162725 _fini(void)
24606629Szf162725 {
24616629Szf162725 int status;
24626629Szf162725
24636629Szf162725 status = mod_remove(&modlinkage);
24646629Szf162725 if (status == 0) {
24656629Szf162725 mac_fini_ops(&ural_dev_ops);
24666629Szf162725 ddi_soft_state_fini(&ural_soft_state_p);
24676629Szf162725 }
24686629Szf162725 return (status);
24696629Szf162725 }
2470