19485SMikore.Li@Sun.COM /*
2*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
39485SMikore.Li@Sun.COM * Use is subject to license terms.
49485SMikore.Li@Sun.COM */
59485SMikore.Li@Sun.COM
69485SMikore.Li@Sun.COM /*
79485SMikore.Li@Sun.COM * Copyright (c) 2008 Weongyo Jeong
89485SMikore.Li@Sun.COM * All rights reserved.
99485SMikore.Li@Sun.COM *
109485SMikore.Li@Sun.COM * Redistribution and use in source and binary forms, with or without
119485SMikore.Li@Sun.COM * modification, are permitted provided that the following conditions
129485SMikore.Li@Sun.COM * are met:
139485SMikore.Li@Sun.COM * 1. Redistributions of source code must retain the above copyright
149485SMikore.Li@Sun.COM * notice, this list of conditions and the following disclaimer,
159485SMikore.Li@Sun.COM * without modification.
169485SMikore.Li@Sun.COM * 2. Redistributions in binary form must reproduce at minimum a disclaimer
179485SMikore.Li@Sun.COM * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
189485SMikore.Li@Sun.COM * redistribution must be conditioned upon including a substantially
199485SMikore.Li@Sun.COM * similar Disclaimer requirement for further binary redistribution.
209485SMikore.Li@Sun.COM *
219485SMikore.Li@Sun.COM * NO WARRANTY
229485SMikore.Li@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
239485SMikore.Li@Sun.COM * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
249485SMikore.Li@Sun.COM * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
259485SMikore.Li@Sun.COM * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
269485SMikore.Li@Sun.COM * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
279485SMikore.Li@Sun.COM * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
289485SMikore.Li@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
299485SMikore.Li@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
309485SMikore.Li@Sun.COM * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
319485SMikore.Li@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
329485SMikore.Li@Sun.COM * THE POSSIBILITY OF SUCH DAMAGES.
339485SMikore.Li@Sun.COM */
349485SMikore.Li@Sun.COM #include <sys/sysmacros.h>
359485SMikore.Li@Sun.COM #include <sys/strsubr.h>
369485SMikore.Li@Sun.COM #include <sys/strsun.h>
379485SMikore.Li@Sun.COM #include <sys/mac_provider.h>
389485SMikore.Li@Sun.COM #include <sys/mac_wifi.h>
399485SMikore.Li@Sun.COM #include <sys/net80211.h>
409485SMikore.Li@Sun.COM #define USBDRV_MAJOR_VER 2
419485SMikore.Li@Sun.COM #define USBDRV_MINOR_VER 0
429485SMikore.Li@Sun.COM #include <sys/usb/usba.h>
439485SMikore.Li@Sun.COM #include <sys/usb/usba/usba_types.h>
449485SMikore.Li@Sun.COM
459485SMikore.Li@Sun.COM #include "urtw_reg.h"
469485SMikore.Li@Sun.COM #include "urtw_var.h"
479485SMikore.Li@Sun.COM
489485SMikore.Li@Sun.COM static void *urtw_soft_state_p = NULL;
499485SMikore.Li@Sun.COM
509485SMikore.Li@Sun.COM #define URTW_TXBUF_SIZE (IEEE80211_MAX_LEN)
519485SMikore.Li@Sun.COM #define URTW_RXBUF_SIZE (URTW_TXBUF_SIZE)
529485SMikore.Li@Sun.COM /*
539485SMikore.Li@Sun.COM * device operations
549485SMikore.Li@Sun.COM */
559485SMikore.Li@Sun.COM static int urtw_attach(dev_info_t *, ddi_attach_cmd_t);
569485SMikore.Li@Sun.COM static int urtw_detach(dev_info_t *, ddi_detach_cmd_t);
579485SMikore.Li@Sun.COM
589485SMikore.Li@Sun.COM /*
599485SMikore.Li@Sun.COM * Module Loading Data & Entry Points
609485SMikore.Li@Sun.COM */
619485SMikore.Li@Sun.COM DDI_DEFINE_STREAM_OPS(urtw_dev_ops, nulldev, nulldev, urtw_attach,
629485SMikore.Li@Sun.COM urtw_detach, nodev, NULL, D_MP, NULL, ddi_quiesce_not_needed);
639485SMikore.Li@Sun.COM
649485SMikore.Li@Sun.COM static struct modldrv urtw_modldrv = {
659485SMikore.Li@Sun.COM &mod_driverops, /* Type of module. This one is a driver */
6610364SMikore.Li@Sun.COM "RTL8187L/B driver v1.2", /* short description */
679485SMikore.Li@Sun.COM &urtw_dev_ops /* driver specific ops */
689485SMikore.Li@Sun.COM };
699485SMikore.Li@Sun.COM
709485SMikore.Li@Sun.COM static struct modlinkage modlinkage = {
719485SMikore.Li@Sun.COM MODREV_1,
729485SMikore.Li@Sun.COM (void *)&urtw_modldrv,
739485SMikore.Li@Sun.COM NULL
749485SMikore.Li@Sun.COM };
759485SMikore.Li@Sun.COM
769485SMikore.Li@Sun.COM static int urtw_m_stat(void *, uint_t, uint64_t *);
779485SMikore.Li@Sun.COM static int urtw_m_start(void *);
789485SMikore.Li@Sun.COM static void urtw_m_stop(void *);
799485SMikore.Li@Sun.COM static int urtw_m_promisc(void *, boolean_t);
809485SMikore.Li@Sun.COM static int urtw_m_multicst(void *, boolean_t, const uint8_t *);
819485SMikore.Li@Sun.COM static int urtw_m_unicst(void *, const uint8_t *);
829485SMikore.Li@Sun.COM static mblk_t *urtw_m_tx(void *, mblk_t *);
839485SMikore.Li@Sun.COM static void urtw_m_ioctl(void *, queue_t *, mblk_t *);
849485SMikore.Li@Sun.COM static int urtw_m_setprop(void *, const char *, mac_prop_id_t,
859485SMikore.Li@Sun.COM uint_t, const void *);
86*11878SVenu.Iyer@Sun.COM static int urtw_m_getprop(void *, const char *, mac_prop_id_t,
87*11878SVenu.Iyer@Sun.COM uint_t, void *);
88*11878SVenu.Iyer@Sun.COM static void urtw_m_propinfo(void *, const char *, mac_prop_id_t,
89*11878SVenu.Iyer@Sun.COM mac_prop_info_handle_t);
909485SMikore.Li@Sun.COM
919485SMikore.Li@Sun.COM static mac_callbacks_t urtw_m_callbacks = {
92*11878SVenu.Iyer@Sun.COM MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
939485SMikore.Li@Sun.COM urtw_m_stat,
949485SMikore.Li@Sun.COM urtw_m_start,
959485SMikore.Li@Sun.COM urtw_m_stop,
969485SMikore.Li@Sun.COM urtw_m_promisc,
979485SMikore.Li@Sun.COM urtw_m_multicst,
989485SMikore.Li@Sun.COM urtw_m_unicst,
999485SMikore.Li@Sun.COM urtw_m_tx,
100*11878SVenu.Iyer@Sun.COM NULL,
1019485SMikore.Li@Sun.COM urtw_m_ioctl,
1029485SMikore.Li@Sun.COM NULL,
1039485SMikore.Li@Sun.COM NULL,
1049485SMikore.Li@Sun.COM NULL,
1059485SMikore.Li@Sun.COM urtw_m_setprop,
106*11878SVenu.Iyer@Sun.COM urtw_m_getprop,
107*11878SVenu.Iyer@Sun.COM urtw_m_propinfo
1089485SMikore.Li@Sun.COM };
1099485SMikore.Li@Sun.COM
1109485SMikore.Li@Sun.COM static int urtw_tx_start(struct urtw_softc *, mblk_t *, int);
1119485SMikore.Li@Sun.COM static int urtw_rx_start(struct urtw_softc *);
1129485SMikore.Li@Sun.COM
1139485SMikore.Li@Sun.COM
1149485SMikore.Li@Sun.COM /*
11510364SMikore.Li@Sun.COM * Supported rates for 802.11b/g modes (in 500Kbps unit).
1169485SMikore.Li@Sun.COM */
1179485SMikore.Li@Sun.COM static const struct ieee80211_rateset urtw_rateset_11b =
1189485SMikore.Li@Sun.COM { 4, { 2, 4, 11, 22 } };
1199485SMikore.Li@Sun.COM
1209485SMikore.Li@Sun.COM static const struct ieee80211_rateset urtw_rateset_11g =
1219485SMikore.Li@Sun.COM { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
1229485SMikore.Li@Sun.COM
12310364SMikore.Li@Sun.COM #define USB_VENDOR_DICKSMITH 0x1371 /* Dick Smith Electronics */
12410364SMikore.Li@Sun.COM #define USB_VENDOR_LOGITEC 0x0789 /* Logitec */
12510364SMikore.Li@Sun.COM #define USB_VENDOR_NETGEAR 0x0846 /* BayNETGEAR */
12610364SMikore.Li@Sun.COM #define USB_VENDOR_REALTEK 0x0bda /* Realtek */
12710364SMikore.Li@Sun.COM #define USB_VENDOR_SPHAIRON 0x114b /* Sphairon Access Systems */
12810364SMikore.Li@Sun.COM #define USB_VENDOR_SURECOM 0x0769 /* Surecom Technology */
12910364SMikore.Li@Sun.COM #define USB_VENDOR_BELKIN 0x050d /* Belkin Components */
13010364SMikore.Li@Sun.COM #define USB_VENDOR_SITECOMEU 0x0df6 /* Sitecom Europe */
13110364SMikore.Li@Sun.COM
13210364SMikore.Li@Sun.COM #define USB_PRODUCT_SPHAIRON_RTL8187 0x0150 /* RTL8187 */
13310364SMikore.Li@Sun.COM #define USB_PRODUCT_DICKSMITH_RTL8187 0x9401 /* RTL8187 */
13410364SMikore.Li@Sun.COM #define USB_PRODUCT_LOGITEC_RTL8187 0x010c /* RTL8187 */
13510364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187 0x8187 /* RTL8187 */
13610364SMikore.Li@Sun.COM #define USB_PRODUCT_NETGEAR_WG111V2 0x6a00 /* WG111v2 */
13710364SMikore.Li@Sun.COM #define USB_PRODUCT_SURECOM_EP9001G2A 0x11f2 /* EP-9001-G rev 2A */
13810364SMikore.Li@Sun.COM #define USB_PRODUCT_BELKIN_F5D7050E 0x705e /* F5D705E 54g */
13910364SMikore.Li@Sun.COM #define USB_PRODUCT_NETGEAR_WG111V3 0x4260 /* WG111v3 */
14010364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187B_0 0x8189 /* RTL8187B */
14110364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187B_1 0x8197 /* RTL8187B */
14210364SMikore.Li@Sun.COM #define USB_PRODUCT_REALTEK_RTL8187B_2 0x8198 /* RTL8187B */
14310364SMikore.Li@Sun.COM #define USB_PRODUCT_SITECOMEU_WL168 0x0028 /* WL-168 */
14410364SMikore.Li@Sun.COM
14510364SMikore.Li@Sun.COM #define USB_PRODUCT_ANY 0xffff
14610364SMikore.Li@Sun.COM
14710364SMikore.Li@Sun.COM struct usb_devno {
14810364SMikore.Li@Sun.COM uint16_t v;
14910364SMikore.Li@Sun.COM uint16_t p;
15010364SMikore.Li@Sun.COM };
15110364SMikore.Li@Sun.COM
15210364SMikore.Li@Sun.COM /*
15310364SMikore.Li@Sun.COM * Recognized device vendors/products.
15410364SMikore.Li@Sun.COM */
15510364SMikore.Li@Sun.COM static struct urtw_type {
15610364SMikore.Li@Sun.COM struct usb_devno dev;
15710364SMikore.Li@Sun.COM uint8_t rev;
15810364SMikore.Li@Sun.COM } urtw_devs[] = {
15910364SMikore.Li@Sun.COM #define URTW_DEV_RTL8187(v, p) \
16010364SMikore.Li@Sun.COM { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187 }
16110364SMikore.Li@Sun.COM #define URTW_DEV_RTL8187B(v, p) \
16210364SMikore.Li@Sun.COM { { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, URTW_HWREV_8187B }
16310364SMikore.Li@Sun.COM /* Realtek RTL8187 devices. */
16410364SMikore.Li@Sun.COM URTW_DEV_RTL8187(DICKSMITH, RTL8187),
16510364SMikore.Li@Sun.COM URTW_DEV_RTL8187(LOGITEC, RTL8187),
16610364SMikore.Li@Sun.COM URTW_DEV_RTL8187(NETGEAR, WG111V2),
16710364SMikore.Li@Sun.COM URTW_DEV_RTL8187(REALTEK, RTL8187),
16810364SMikore.Li@Sun.COM URTW_DEV_RTL8187(SPHAIRON, RTL8187),
16910364SMikore.Li@Sun.COM URTW_DEV_RTL8187(SURECOM, EP9001G2A),
17010364SMikore.Li@Sun.COM /* Realtek RTL8187B devices. */
17110364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(BELKIN, F5D7050E),
17210364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(NETGEAR, WG111V3),
17310364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(REALTEK, RTL8187B_0),
17410364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(REALTEK, RTL8187B_1),
17510364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(REALTEK, RTL8187B_2),
17610364SMikore.Li@Sun.COM URTW_DEV_RTL8187B(SITECOMEU, WL168)
17710364SMikore.Li@Sun.COM #undef URTW_DEV_RTL8187
17810364SMikore.Li@Sun.COM #undef URTW_DEV_RTL8187B
17910364SMikore.Li@Sun.COM };
18010364SMikore.Li@Sun.COM
18110364SMikore.Li@Sun.COM /*
18210364SMikore.Li@Sun.COM * Search for a vendor/product pair in an array. The item size is
18310364SMikore.Li@Sun.COM * given as an argument.
18410364SMikore.Li@Sun.COM */
18510364SMikore.Li@Sun.COM struct urtw_type *
usb_match_device(struct urtw_type * tbl,uint32_t nentries,uint16_t vendor,uint16_t product)18610364SMikore.Li@Sun.COM usb_match_device(struct urtw_type *tbl, uint32_t nentries,
18710364SMikore.Li@Sun.COM uint16_t vendor, uint16_t product)
18810364SMikore.Li@Sun.COM {
18910364SMikore.Li@Sun.COM while (nentries-- > 0) {
19010364SMikore.Li@Sun.COM uint16_t tproduct = tbl[nentries].dev.p;
19110364SMikore.Li@Sun.COM if (tbl[nentries].dev.v == vendor &&
19210364SMikore.Li@Sun.COM (tproduct == product || tproduct == USB_PRODUCT_ANY))
19310364SMikore.Li@Sun.COM return (&tbl[nentries]);
19410364SMikore.Li@Sun.COM }
19510364SMikore.Li@Sun.COM return (NULL);
19610364SMikore.Li@Sun.COM }
19710364SMikore.Li@Sun.COM
19810364SMikore.Li@Sun.COM #define usb_lookup(tbl, vendor, product) \
19910364SMikore.Li@Sun.COM usb_match_device(tbl, sizeof (tbl) / sizeof ((tbl)[0]), \
20010364SMikore.Li@Sun.COM (vendor), (product))
20110364SMikore.Li@Sun.COM
20210364SMikore.Li@Sun.COM #define urtw_lookup(v, p) (usb_lookup(urtw_devs, v, p))
2039485SMikore.Li@Sun.COM
2049485SMikore.Li@Sun.COM struct urtw_pair {
2059485SMikore.Li@Sun.COM uint32_t reg;
2069485SMikore.Li@Sun.COM uint32_t val;
2079485SMikore.Li@Sun.COM };
2089485SMikore.Li@Sun.COM
20910364SMikore.Li@Sun.COM struct urtw_pair_idx {
21010364SMikore.Li@Sun.COM uint8_t reg;
21110364SMikore.Li@Sun.COM uint8_t val;
21210364SMikore.Li@Sun.COM uint8_t idx;
21310364SMikore.Li@Sun.COM };
21410364SMikore.Li@Sun.COM
21510364SMikore.Li@Sun.COM static struct urtw_pair_idx urtw_8187b_regtbl[] = {
21610364SMikore.Li@Sun.COM { 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
21710364SMikore.Li@Sun.COM { 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
21810364SMikore.Li@Sun.COM { 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 },
21910364SMikore.Li@Sun.COM { 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 },
22010364SMikore.Li@Sun.COM { 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 },
22110364SMikore.Li@Sun.COM { 0xff, 0x00, 0 },
22210364SMikore.Li@Sun.COM
22310364SMikore.Li@Sun.COM { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, { 0x5a, 0x4b, 1 },
22410364SMikore.Li@Sun.COM { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, { 0x61, 0x09, 1 },
22510364SMikore.Li@Sun.COM { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, { 0xce, 0x0f, 1 },
22610364SMikore.Li@Sun.COM { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, { 0xe1, 0x0f, 1 },
22710364SMikore.Li@Sun.COM { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, { 0xf1, 0x01, 1 },
22810364SMikore.Li@Sun.COM { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, { 0xf4, 0x04, 1 },
22910364SMikore.Li@Sun.COM { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, { 0xf7, 0x07, 1 },
23010364SMikore.Li@Sun.COM { 0xf8, 0x08, 1 },
23110364SMikore.Li@Sun.COM
23210364SMikore.Li@Sun.COM { 0x4e, 0x00, 2 }, { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 },
23310364SMikore.Li@Sun.COM { 0x22, 0x68, 2 }, { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 },
23410364SMikore.Li@Sun.COM { 0x25, 0x7d, 2 }, { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 },
23510364SMikore.Li@Sun.COM { 0x4d, 0x08, 2 }, { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 },
23610364SMikore.Li@Sun.COM { 0x52, 0x04, 2 }, { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 },
23710364SMikore.Li@Sun.COM { 0x55, 0x23, 2 }, { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 },
23810364SMikore.Li@Sun.COM { 0x58, 0x08, 2 }, { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 },
23910364SMikore.Li@Sun.COM { 0x5b, 0x08, 2 }, { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 },
24010364SMikore.Li@Sun.COM { 0x62, 0x08, 2 }, { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 },
24110364SMikore.Li@Sun.COM { 0x72, 0x56, 2 }, { 0x73, 0x9a, 2 },
24210364SMikore.Li@Sun.COM
24310364SMikore.Li@Sun.COM { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, { 0x5b, 0x40, 0 },
24410364SMikore.Li@Sun.COM { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, { 0x88, 0x54, 0 },
24510364SMikore.Li@Sun.COM { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, { 0x8d, 0x00, 0 },
24610364SMikore.Li@Sun.COM { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, { 0x96, 0x00, 0 },
24710364SMikore.Li@Sun.COM { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, { 0x9f, 0x10, 0 },
24810364SMikore.Li@Sun.COM { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, { 0xdb, 0x00, 0 },
24910364SMikore.Li@Sun.COM { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 },
25010364SMikore.Li@Sun.COM
25110364SMikore.Li@Sun.COM { 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
25210364SMikore.Li@Sun.COM { 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
25310364SMikore.Li@Sun.COM };
25410364SMikore.Li@Sun.COM
2559485SMikore.Li@Sun.COM static uint8_t urtw_8225_agc[] = {
2569485SMikore.Li@Sun.COM 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b,
2579485SMikore.Li@Sun.COM 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
2589485SMikore.Li@Sun.COM 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85,
2599485SMikore.Li@Sun.COM 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a,
2609485SMikore.Li@Sun.COM 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f,
2619485SMikore.Li@Sun.COM 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24,
2629485SMikore.Li@Sun.COM 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19,
2639485SMikore.Li@Sun.COM 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
2649485SMikore.Li@Sun.COM 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
2659485SMikore.Li@Sun.COM 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2669485SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
2679485SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
2689485SMikore.Li@Sun.COM };
2699485SMikore.Li@Sun.COM
27010364SMikore.Li@Sun.COM static uint8_t urtw_8225v2_agc[] = {
27110364SMikore.Li@Sun.COM 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57,
27210364SMikore.Li@Sun.COM 0x55, 0x53, 0x51, 0x4f, 0x4d, 0x4b, 0x49, 0x47,
27310364SMikore.Li@Sun.COM 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
27410364SMikore.Li@Sun.COM 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27,
27510364SMikore.Li@Sun.COM 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17,
27610364SMikore.Li@Sun.COM 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
27710364SMikore.Li@Sun.COM 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
27810364SMikore.Li@Sun.COM 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
27910364SMikore.Li@Sun.COM 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
28010364SMikore.Li@Sun.COM 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
28110364SMikore.Li@Sun.COM 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a,
28210364SMikore.Li@Sun.COM 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
28310364SMikore.Li@Sun.COM 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f,
28410364SMikore.Li@Sun.COM 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
28510364SMikore.Li@Sun.COM 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
28610364SMikore.Li@Sun.COM 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
28710364SMikore.Li@Sun.COM };
28810364SMikore.Li@Sun.COM
28910364SMikore.Li@Sun.COM static uint8_t urtw_8225v2_ofdm[] = {
29010364SMikore.Li@Sun.COM 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
29110364SMikore.Li@Sun.COM 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
29210364SMikore.Li@Sun.COM 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
29310364SMikore.Li@Sun.COM 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
29410364SMikore.Li@Sun.COM 0x0a, 0xe1, 0x2c, 0x8a, 0x86, 0x83, 0x34, 0x0f,
29510364SMikore.Li@Sun.COM 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
29610364SMikore.Li@Sun.COM 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
29710364SMikore.Li@Sun.COM 0x6d, 0x3c, 0xfb, 0x07
29810364SMikore.Li@Sun.COM };
29910364SMikore.Li@Sun.COM
3009485SMikore.Li@Sun.COM static uint32_t urtw_8225_channel[] = {
3019485SMikore.Li@Sun.COM 0x0000, /* dummy channel 0 */
3029485SMikore.Li@Sun.COM 0x085c, /* 1 */
3039485SMikore.Li@Sun.COM 0x08dc, /* 2 */
3049485SMikore.Li@Sun.COM 0x095c, /* 3 */
3059485SMikore.Li@Sun.COM 0x09dc, /* 4 */
3069485SMikore.Li@Sun.COM 0x0a5c, /* 5 */
3079485SMikore.Li@Sun.COM 0x0adc, /* 6 */
3089485SMikore.Li@Sun.COM 0x0b5c, /* 7 */
3099485SMikore.Li@Sun.COM 0x0bdc, /* 8 */
3109485SMikore.Li@Sun.COM 0x0c5c, /* 9 */
3119485SMikore.Li@Sun.COM 0x0cdc, /* 10 */
3129485SMikore.Li@Sun.COM 0x0d5c, /* 11 */
3139485SMikore.Li@Sun.COM 0x0ddc, /* 12 */
3149485SMikore.Li@Sun.COM 0x0e5c, /* 13 */
3159485SMikore.Li@Sun.COM 0x0f72, /* 14 */
3169485SMikore.Li@Sun.COM };
3179485SMikore.Li@Sun.COM
3189485SMikore.Li@Sun.COM static uint8_t urtw_8225_gain[] = {
3199485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
3209485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
3219485SMikore.Li@Sun.COM 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
3229485SMikore.Li@Sun.COM 0x33, 0x80, 0x79, 0xc5, /* -78dbm */
3239485SMikore.Li@Sun.COM 0x43, 0x78, 0x76, 0xc5, /* -74dbm */
3249485SMikore.Li@Sun.COM 0x53, 0x60, 0x73, 0xc5, /* -70dbm */
3259485SMikore.Li@Sun.COM 0x63, 0x58, 0x70, 0xc5, /* -66dbm */
3269485SMikore.Li@Sun.COM };
3279485SMikore.Li@Sun.COM
3289485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part1[] = {
3299485SMikore.Li@Sun.COM { 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
3309485SMikore.Li@Sun.COM { 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a },
3319485SMikore.Li@Sun.COM { 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 },
3329485SMikore.Li@Sun.COM { 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 },
3339485SMikore.Li@Sun.COM };
3349485SMikore.Li@Sun.COM
3359485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part2[] = {
3369485SMikore.Li@Sun.COM { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 },
3379485SMikore.Li@Sun.COM { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 },
3389485SMikore.Li@Sun.COM { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 },
3399485SMikore.Li@Sun.COM { 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 },
3409485SMikore.Li@Sun.COM { 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 },
3419485SMikore.Li@Sun.COM { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef },
3429485SMikore.Li@Sun.COM { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 },
3439485SMikore.Li@Sun.COM { 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 },
3449485SMikore.Li@Sun.COM { 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 },
3459485SMikore.Li@Sun.COM { 0x27, 0x88 }
3469485SMikore.Li@Sun.COM };
3479485SMikore.Li@Sun.COM
3489485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225_rf_part3[] = {
3499485SMikore.Li@Sun.COM { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 },
3509485SMikore.Li@Sun.COM { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b },
3519485SMikore.Li@Sun.COM { 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 },
3529485SMikore.Li@Sun.COM { 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d },
3539485SMikore.Li@Sun.COM { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e },
3549485SMikore.Li@Sun.COM { 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a },
3559485SMikore.Li@Sun.COM { 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 }
3569485SMikore.Li@Sun.COM };
3579485SMikore.Li@Sun.COM
3589485SMikore.Li@Sun.COM static uint16_t urtw_8225_rxgain[] = {
3599485SMikore.Li@Sun.COM 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
3609485SMikore.Li@Sun.COM 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
3619485SMikore.Li@Sun.COM 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
3629485SMikore.Li@Sun.COM 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
3639485SMikore.Li@Sun.COM 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
3649485SMikore.Li@Sun.COM 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
3659485SMikore.Li@Sun.COM 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
3669485SMikore.Li@Sun.COM 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
3679485SMikore.Li@Sun.COM 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
3689485SMikore.Li@Sun.COM 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
3699485SMikore.Li@Sun.COM 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
3709485SMikore.Li@Sun.COM 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
3719485SMikore.Li@Sun.COM };
3729485SMikore.Li@Sun.COM
3739485SMikore.Li@Sun.COM static uint8_t urtw_8225_threshold[] = {
3749485SMikore.Li@Sun.COM 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd,
3759485SMikore.Li@Sun.COM };
3769485SMikore.Li@Sun.COM
3779485SMikore.Li@Sun.COM static uint8_t urtw_8225_tx_gain_cck_ofdm[] = {
3789485SMikore.Li@Sun.COM 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
3799485SMikore.Li@Sun.COM };
3809485SMikore.Li@Sun.COM
3819485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_cck[] = {
3829485SMikore.Li@Sun.COM 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
3839485SMikore.Li@Sun.COM 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
3849485SMikore.Li@Sun.COM 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
3859485SMikore.Li@Sun.COM 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
3869485SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
3879485SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
3889485SMikore.Li@Sun.COM };
3899485SMikore.Li@Sun.COM
3909485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_cck_ch14[] = {
3919485SMikore.Li@Sun.COM 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
3929485SMikore.Li@Sun.COM 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
3939485SMikore.Li@Sun.COM 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
3949485SMikore.Li@Sun.COM 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
3959485SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
3969485SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
3979485SMikore.Li@Sun.COM };
3989485SMikore.Li@Sun.COM
3999485SMikore.Li@Sun.COM static uint8_t urtw_8225_txpwr_ofdm[] = {
4009485SMikore.Li@Sun.COM 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
4019485SMikore.Li@Sun.COM };
4029485SMikore.Li@Sun.COM
4039485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_gain_bg[] = {
4049485SMikore.Li@Sun.COM 0x23, 0x15, 0xa5, /* -82-1dbm */
4059485SMikore.Li@Sun.COM 0x23, 0x15, 0xb5, /* -82-2dbm */
4069485SMikore.Li@Sun.COM 0x23, 0x15, 0xc5, /* -82-3dbm */
4079485SMikore.Li@Sun.COM 0x33, 0x15, 0xc5, /* -78dbm */
4089485SMikore.Li@Sun.COM 0x43, 0x15, 0xc5, /* -74dbm */
4099485SMikore.Li@Sun.COM 0x53, 0x15, 0xc5, /* -70dbm */
4109485SMikore.Li@Sun.COM 0x63, 0x15, 0xc5, /* -66dbm */
4119485SMikore.Li@Sun.COM };
4129485SMikore.Li@Sun.COM
4139485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part1[] = {
4149485SMikore.Li@Sun.COM { 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
4159485SMikore.Li@Sun.COM { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a },
4169485SMikore.Li@Sun.COM { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb },
4179485SMikore.Li@Sun.COM { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 }
4189485SMikore.Li@Sun.COM };
4199485SMikore.Li@Sun.COM
4209485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part2[] = {
4219485SMikore.Li@Sun.COM { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 },
4229485SMikore.Li@Sun.COM { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 },
4239485SMikore.Li@Sun.COM { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 },
4249485SMikore.Li@Sun.COM { 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 },
4259485SMikore.Li@Sun.COM { 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 },
4269485SMikore.Li@Sun.COM { 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 },
4279485SMikore.Li@Sun.COM { 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 },
4289485SMikore.Li@Sun.COM { 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 },
4299485SMikore.Li@Sun.COM { 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 },
4309485SMikore.Li@Sun.COM { 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 }
4319485SMikore.Li@Sun.COM };
4329485SMikore.Li@Sun.COM
4339485SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_rf_part3[] = {
4349485SMikore.Li@Sun.COM { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 },
4359485SMikore.Li@Sun.COM { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 },
4369485SMikore.Li@Sun.COM { 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 },
4379485SMikore.Li@Sun.COM { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 },
4389485SMikore.Li@Sun.COM { 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d },
4399485SMikore.Li@Sun.COM { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 },
4409485SMikore.Li@Sun.COM { 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 },
4419485SMikore.Li@Sun.COM { 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 }
4429485SMikore.Li@Sun.COM };
4439485SMikore.Li@Sun.COM
4449485SMikore.Li@Sun.COM static uint16_t urtw_8225v2_rxgain[] = {
44510364SMikore.Li@Sun.COM 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
44610364SMikore.Li@Sun.COM 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
44710364SMikore.Li@Sun.COM 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
44810364SMikore.Li@Sun.COM 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
44910364SMikore.Li@Sun.COM 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
45010364SMikore.Li@Sun.COM 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
45110364SMikore.Li@Sun.COM 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
45210364SMikore.Li@Sun.COM 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
45310364SMikore.Li@Sun.COM 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
45410364SMikore.Li@Sun.COM 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
4559485SMikore.Li@Sun.COM 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
4569485SMikore.Li@Sun.COM 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
4579485SMikore.Li@Sun.COM };
4589485SMikore.Li@Sun.COM
4599485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = {
4609485SMikore.Li@Sun.COM 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
4619485SMikore.Li@Sun.COM 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
4629485SMikore.Li@Sun.COM 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
4639485SMikore.Li@Sun.COM 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
4649485SMikore.Li@Sun.COM 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
4659485SMikore.Li@Sun.COM 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
4669485SMikore.Li@Sun.COM };
4679485SMikore.Li@Sun.COM
4689485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_txpwr_cck[] = {
46910364SMikore.Li@Sun.COM 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
47010364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
47110364SMikore.Li@Sun.COM 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
47210364SMikore.Li@Sun.COM 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
4739485SMikore.Li@Sun.COM };
4749485SMikore.Li@Sun.COM
4759485SMikore.Li@Sun.COM static uint8_t urtw_8225v2_txpwr_cck_ch14[] = {
47610364SMikore.Li@Sun.COM 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
47710364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
47810364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
47910364SMikore.Li@Sun.COM 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
48010364SMikore.Li@Sun.COM };
48110364SMikore.Li@Sun.COM
48210364SMikore.Li@Sun.COM static struct urtw_pair urtw_8225v2_b_rf[] = {
48310364SMikore.Li@Sun.COM { 0x00, 0x00b7 }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 },
48410364SMikore.Li@Sun.COM { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a },
48510364SMikore.Li@Sun.COM { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb },
48610364SMikore.Li@Sun.COM { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 },
48710364SMikore.Li@Sun.COM { 0x00, 0x01b7 }
4889485SMikore.Li@Sun.COM };
4899485SMikore.Li@Sun.COM
4909485SMikore.Li@Sun.COM static struct urtw_pair urtw_ratetable[] = {
4919485SMikore.Li@Sun.COM { 2, 0 }, { 4, 1 }, { 11, 2 }, { 12, 4 }, { 18, 5 },
4929485SMikore.Li@Sun.COM { 22, 3 }, { 24, 6 }, { 36, 7 }, { 48, 8 }, { 72, 9 },
4939485SMikore.Li@Sun.COM { 96, 10 }, { 108, 11 }
4949485SMikore.Li@Sun.COM };
4959485SMikore.Li@Sun.COM
49610364SMikore.Li@Sun.COM static int urtw_8187_init(void *);
4979485SMikore.Li@Sun.COM static void urtw_stop(struct urtw_softc *);
4989485SMikore.Li@Sun.COM static int urtw_set_channel(struct urtw_softc *);
4999485SMikore.Li@Sun.COM static void
5009485SMikore.Li@Sun.COM urtw_rxeof(usb_pipe_handle_t, usb_bulk_req_t *);
5019485SMikore.Li@Sun.COM static int
5029485SMikore.Li@Sun.COM urtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
50310364SMikore.Li@Sun.COM static usbd_status
50410364SMikore.Li@Sun.COM urtw_read8_c(struct urtw_softc *, int, uint8_t *, uint8_t);
50510364SMikore.Li@Sun.COM static usbd_status
50610364SMikore.Li@Sun.COM urtw_read16_c(struct urtw_softc *, int, uint16_t *, uint8_t);
50710364SMikore.Li@Sun.COM static usbd_status
50810364SMikore.Li@Sun.COM urtw_read32_c(struct urtw_softc *, int, uint32_t *, uint8_t);
50910364SMikore.Li@Sun.COM static usbd_status
51010364SMikore.Li@Sun.COM urtw_write8_c(struct urtw_softc *, int, uint8_t, uint8_t);
51110364SMikore.Li@Sun.COM static usbd_status
51210364SMikore.Li@Sun.COM urtw_write16_c(struct urtw_softc *, int, uint16_t, uint8_t);
51310364SMikore.Li@Sun.COM static usbd_status
51410364SMikore.Li@Sun.COM urtw_write32_c(struct urtw_softc *, int, uint32_t, uint8_t);
5159485SMikore.Li@Sun.COM static usbd_status urtw_eprom_cs(struct urtw_softc *, int);
5169485SMikore.Li@Sun.COM static usbd_status urtw_eprom_ck(struct urtw_softc *);
5179485SMikore.Li@Sun.COM static usbd_status urtw_eprom_sendbits(struct urtw_softc *, int16_t *,
5189485SMikore.Li@Sun.COM int);
5199485SMikore.Li@Sun.COM static usbd_status urtw_eprom_read32(struct urtw_softc *, uint32_t,
5209485SMikore.Li@Sun.COM uint32_t *);
5219485SMikore.Li@Sun.COM static usbd_status urtw_eprom_readbit(struct urtw_softc *, int16_t *);
5229485SMikore.Li@Sun.COM static usbd_status urtw_eprom_writebit(struct urtw_softc *, int16_t);
5239485SMikore.Li@Sun.COM static usbd_status urtw_get_macaddr(struct urtw_softc *);
5249485SMikore.Li@Sun.COM static usbd_status urtw_get_txpwr(struct urtw_softc *);
5259485SMikore.Li@Sun.COM static usbd_status urtw_get_rfchip(struct urtw_softc *);
5269485SMikore.Li@Sun.COM static usbd_status urtw_led_init(struct urtw_softc *);
5279485SMikore.Li@Sun.COM static usbd_status
5289485SMikore.Li@Sun.COM urtw_8225_read(struct urtw_softc *, uint8_t, uint32_t *);
52910364SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_init(struct urtw_rf *);
53010364SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_set_chan(struct urtw_rf *, int);
53110364SMikore.Li@Sun.COM static usbd_status urtw_8225_rf_set_sens(struct urtw_rf *);
53210364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_rf_init(struct urtw_rf *);
53310364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_rf_set_chan(struct urtw_rf *, int);
5349485SMikore.Li@Sun.COM static usbd_status urtw_open_pipes(struct urtw_softc *);
5359485SMikore.Li@Sun.COM static void urtw_close_pipes(struct urtw_softc *);
5369485SMikore.Li@Sun.COM static void urtw_led_launch(void *);
5379485SMikore.Li@Sun.COM
53810364SMikore.Li@Sun.COM static void urtw_8187b_update_wmm(struct urtw_softc *);
53910364SMikore.Li@Sun.COM static usbd_status urtw_8187b_reset(struct urtw_softc *);
54010364SMikore.Li@Sun.COM static int urtw_8187b_init(void *);
54110364SMikore.Li@Sun.COM static void urtw_8225v2_b_config_mac(struct urtw_softc *);
54210364SMikore.Li@Sun.COM static void urtw_8225v2_b_init_rfe(struct urtw_softc *);
54310364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_b_update_chan(struct urtw_softc *);
54410364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_b_rf_init(struct urtw_rf *);
54510364SMikore.Li@Sun.COM static usbd_status urtw_8225v2_b_rf_set_chan(struct urtw_rf *, int);
54610364SMikore.Li@Sun.COM static void urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *, int);
54710364SMikore.Li@Sun.COM
5489485SMikore.Li@Sun.COM #ifdef DEBUG
5499485SMikore.Li@Sun.COM
5509485SMikore.Li@Sun.COM #define URTW_DEBUG_XMIT 0x00000001
5519485SMikore.Li@Sun.COM #define URTW_DEBUG_RECV 0x00000002
5529485SMikore.Li@Sun.COM #define URTW_DEBUG_LED 0x00000004
5539485SMikore.Li@Sun.COM #define URTW_DEBUG_GLD 0x00000008
5549485SMikore.Li@Sun.COM #define URTW_DEBUG_RF 0x00000010
5559485SMikore.Li@Sun.COM #define URTW_DEBUG_ATTACH 0x00000020
5569485SMikore.Li@Sun.COM #define URTW_DEBUG_ACTIVE 0x00000040
5579485SMikore.Li@Sun.COM #define URTW_DEBUG_HWTYPE 0x00000080
55810364SMikore.Li@Sun.COM #define URTW_DEBUG_DEVREQ 0x00000100
5599485SMikore.Li@Sun.COM #define URTW_DEBUG_HOTPLUG 0x00000200
56010364SMikore.Li@Sun.COM #define URTW_DEBUG_STATE 0x00000400
5619485SMikore.Li@Sun.COM #define URTW_DEBUG_TX_PROC 0x00000800
5629485SMikore.Li@Sun.COM #define URTW_DEBUG_RX_PROC 0x00001000
5639485SMikore.Li@Sun.COM #define URTW_DEBUG_EEPROM 0x00002000
5649485SMikore.Li@Sun.COM #define URTW_DEBUG_RESET 0x00004000
5659485SMikore.Li@Sun.COM #define URTW_DEBUG_ANY 0xffffffff
5669485SMikore.Li@Sun.COM
5679485SMikore.Li@Sun.COM uint32_t urtw8187_dbg_flags = 0;
5689485SMikore.Li@Sun.COM static void
urtw8187_dbg(dev_info_t * dip,int level,const char * fmt,...)5699485SMikore.Li@Sun.COM urtw8187_dbg(dev_info_t *dip, int level, const char *fmt, ...)
5709485SMikore.Li@Sun.COM {
5719485SMikore.Li@Sun.COM char msg_buffer[255];
5729485SMikore.Li@Sun.COM va_list ap;
5739485SMikore.Li@Sun.COM
5749485SMikore.Li@Sun.COM if (dip == NULL) {
5759485SMikore.Li@Sun.COM return;
5769485SMikore.Li@Sun.COM }
5779485SMikore.Li@Sun.COM
5789485SMikore.Li@Sun.COM va_start(ap, fmt);
5799485SMikore.Li@Sun.COM (void) vsprintf(msg_buffer, fmt, ap);
5809485SMikore.Li@Sun.COM cmn_err(level, "%s%d: %s", ddi_get_name(dip),
5819485SMikore.Li@Sun.COM ddi_get_instance(dip), msg_buffer);
5829485SMikore.Li@Sun.COM va_end(ap);
5839485SMikore.Li@Sun.COM }
5849485SMikore.Li@Sun.COM
5859485SMikore.Li@Sun.COM #define URTW8187_DBG(l, x) do {\
5869485SMikore.Li@Sun.COM _NOTE(CONSTANTCONDITION) \
5879485SMikore.Li@Sun.COM if ((l) & urtw8187_dbg_flags) \
5889485SMikore.Li@Sun.COM urtw8187_dbg x;\
5899485SMikore.Li@Sun.COM _NOTE(CONSTANTCONDITION) \
5909485SMikore.Li@Sun.COM } while (0)
5919485SMikore.Li@Sun.COM #else
5929485SMikore.Li@Sun.COM #define URTW8187_DBG(l, x)
5939485SMikore.Li@Sun.COM #endif
5949485SMikore.Li@Sun.COM
5959485SMikore.Li@Sun.COM static usbd_status
urtw_led_init(struct urtw_softc * sc)5969485SMikore.Li@Sun.COM urtw_led_init(struct urtw_softc *sc)
5979485SMikore.Li@Sun.COM {
5989485SMikore.Li@Sun.COM uint32_t rev;
5999485SMikore.Li@Sun.COM usbd_status error;
6009485SMikore.Li@Sun.COM
60110364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_PSR, &sc->sc_psr, 0))
6029485SMikore.Li@Sun.COM goto fail;
6039485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev);
6049485SMikore.Li@Sun.COM if (error != 0)
6059485SMikore.Li@Sun.COM goto fail;
6069485SMikore.Li@Sun.COM
6079485SMikore.Li@Sun.COM switch (rev & URTW_EPROM_CID_MASK) {
6089485SMikore.Li@Sun.COM case URTW_EPROM_CID_ALPHA0:
6099485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE1;
6109485SMikore.Li@Sun.COM break;
6119485SMikore.Li@Sun.COM case URTW_EPROM_CID_SERCOMM_PS:
6129485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE3;
6139485SMikore.Li@Sun.COM break;
6149485SMikore.Li@Sun.COM case URTW_EPROM_CID_HW_LED:
6159485SMikore.Li@Sun.COM sc->sc_strategy = URTW_HW_LED;
6169485SMikore.Li@Sun.COM break;
6179485SMikore.Li@Sun.COM case URTW_EPROM_CID_RSVD0:
6189485SMikore.Li@Sun.COM case URTW_EPROM_CID_RSVD1:
6199485SMikore.Li@Sun.COM default:
6209485SMikore.Li@Sun.COM sc->sc_strategy = URTW_SW_LED_MODE0;
6219485SMikore.Li@Sun.COM break;
6229485SMikore.Li@Sun.COM }
6239485SMikore.Li@Sun.COM
6249485SMikore.Li@Sun.COM sc->sc_gpio_ledpin = URTW_LED_PIN_GPIO0;
6259485SMikore.Li@Sun.COM
6269485SMikore.Li@Sun.COM fail:
6279485SMikore.Li@Sun.COM return (error);
6289485SMikore.Li@Sun.COM }
6299485SMikore.Li@Sun.COM
6309485SMikore.Li@Sun.COM static usbd_status
urtw_8225_write_s16(struct urtw_softc * sc,uint8_t addr,int index,uint16_t * data)6319485SMikore.Li@Sun.COM urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
6329485SMikore.Li@Sun.COM uint16_t *data)
6339485SMikore.Li@Sun.COM {
6349485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
6359485SMikore.Li@Sun.COM usb_cr_t cr;
6369485SMikore.Li@Sun.COM usb_cb_flags_t cf;
6379485SMikore.Li@Sun.COM mblk_t *mp = 0;
6389485SMikore.Li@Sun.COM uint16_t data16;
6399485SMikore.Li@Sun.COM usbd_status error;
6409485SMikore.Li@Sun.COM
6419485SMikore.Li@Sun.COM data16 = *data;
6429485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
6439485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
6449485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ;
6459485SMikore.Li@Sun.COM req.wValue = addr;
6469485SMikore.Li@Sun.COM req.wIndex = (uint16_t)index;
6479485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t);
6489485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE;
6499485SMikore.Li@Sun.COM
6509485SMikore.Li@Sun.COM mp = allocb(sizeof (uint16_t), BPRI_MED);
6519485SMikore.Li@Sun.COM if (mp == 0) {
6529485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_8225_write_s16: allocb failed\n");
6539485SMikore.Li@Sun.COM return (-1);
6549485SMikore.Li@Sun.COM }
6559485SMikore.Li@Sun.COM *(mp->b_rptr) = (data16 & 0x00ff);
6569485SMikore.Li@Sun.COM *(mp->b_rptr + 1) = (data16 & 0xff00) >> 8;
6579485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint16_t);
6589485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
6599485SMikore.Li@Sun.COM &cr, &cf, 0);
6609485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
6619485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
6629485SMikore.Li@Sun.COM "urtw_8225_write_s16: could not set regs:"
6639485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf));
6649485SMikore.Li@Sun.COM }
6659485SMikore.Li@Sun.COM if (mp)
6669485SMikore.Li@Sun.COM freemsg(mp);
6679485SMikore.Li@Sun.COM return (error);
6689485SMikore.Li@Sun.COM
6699485SMikore.Li@Sun.COM }
6709485SMikore.Li@Sun.COM
6719485SMikore.Li@Sun.COM static usbd_status
urtw_8225_read(struct urtw_softc * sc,uint8_t addr,uint32_t * data)6729485SMikore.Li@Sun.COM urtw_8225_read(struct urtw_softc *sc, uint8_t addr, uint32_t *data)
6739485SMikore.Li@Sun.COM {
6749485SMikore.Li@Sun.COM int i;
6759485SMikore.Li@Sun.COM int16_t bit;
6769485SMikore.Li@Sun.COM uint8_t rlen = 12, wlen = 6;
6779485SMikore.Li@Sun.COM uint16_t o1, o2, o3, tmp;
6789485SMikore.Li@Sun.COM uint32_t d2w = ((uint32_t)(addr & 0x1f)) << 27;
6799485SMikore.Li@Sun.COM uint32_t mask = 0x80000000, value = 0;
6809485SMikore.Li@Sun.COM usbd_status error;
6819485SMikore.Li@Sun.COM
68210364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &o1, 0))
6839485SMikore.Li@Sun.COM goto fail;
68410364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &o2, 0))
6859485SMikore.Li@Sun.COM goto fail;
68610364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &o3, 0))
6879485SMikore.Li@Sun.COM goto fail;
68810364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2 | 0xf, 0))
6899485SMikore.Li@Sun.COM goto fail;
69010364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3 | 0xf, 0))
6919485SMikore.Li@Sun.COM goto fail;
6929485SMikore.Li@Sun.COM o1 &= ~0xf;
6939485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
69410364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_EN, 0))
6959485SMikore.Li@Sun.COM goto fail;
6969485SMikore.Li@Sun.COM DELAY(5);
69710364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, o1, 0))
6989485SMikore.Li@Sun.COM goto fail;
6999485SMikore.Li@Sun.COM DELAY(5);
7009485SMikore.Li@Sun.COM
7019485SMikore.Li@Sun.COM for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) {
7029485SMikore.Li@Sun.COM bit = ((d2w & mask) != 0) ? 1 : 0;
7039485SMikore.Li@Sun.COM
70410364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
70510364SMikore.Li@Sun.COM bit | o1, 0))
7069485SMikore.Li@Sun.COM goto fail;
7079485SMikore.Li@Sun.COM DELAY(2);
70810364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
70910364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
7109485SMikore.Li@Sun.COM goto fail;
7119485SMikore.Li@Sun.COM DELAY(2);
71210364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
71310364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
7149485SMikore.Li@Sun.COM goto fail;
7159485SMikore.Li@Sun.COM DELAY(2);
7169485SMikore.Li@Sun.COM mask = mask >> 1;
7179485SMikore.Li@Sun.COM if (i == 2)
7189485SMikore.Li@Sun.COM break;
7199485SMikore.Li@Sun.COM bit = ((d2w & mask) != 0) ? 1 : 0;
72010364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
72110364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
7229485SMikore.Li@Sun.COM goto fail;
7239485SMikore.Li@Sun.COM DELAY(2);
72410364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
72510364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_CLK, 0))
7269485SMikore.Li@Sun.COM goto fail;
7279485SMikore.Li@Sun.COM DELAY(2);
72810364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
72910364SMikore.Li@Sun.COM bit | o1, 0))
7309485SMikore.Li@Sun.COM goto fail;
7319485SMikore.Li@Sun.COM DELAY(1);
7329485SMikore.Li@Sun.COM }
7339485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
73410364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
7359485SMikore.Li@Sun.COM goto fail;
7369485SMikore.Li@Sun.COM DELAY(2);
7379485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
73810364SMikore.Li@Sun.COM bit | o1 | URTW_BB_HOST_BANG_RW, 0))
7399485SMikore.Li@Sun.COM goto fail;
7409485SMikore.Li@Sun.COM DELAY(2);
7419485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
74210364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW, 0))
7439485SMikore.Li@Sun.COM goto fail;
7449485SMikore.Li@Sun.COM DELAY(2);
7459485SMikore.Li@Sun.COM
7469485SMikore.Li@Sun.COM mask = 0x800;
7479485SMikore.Li@Sun.COM for (i = 0; i < rlen; i++, mask = mask >> 1) {
7489485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
74910364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW, 0))
7509485SMikore.Li@Sun.COM goto fail;
7519485SMikore.Li@Sun.COM DELAY(2);
7529485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
75310364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
7549485SMikore.Li@Sun.COM goto fail;
7559485SMikore.Li@Sun.COM DELAY(2);
7569485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
75710364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
7589485SMikore.Li@Sun.COM goto fail;
7599485SMikore.Li@Sun.COM DELAY(2);
7609485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
76110364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK, 0))
7629485SMikore.Li@Sun.COM goto fail;
7639485SMikore.Li@Sun.COM DELAY(2);
7649485SMikore.Li@Sun.COM
76510364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_INPUT, &tmp, 0))
7669485SMikore.Li@Sun.COM goto fail;
7679485SMikore.Li@Sun.COM value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0);
7689485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
76910364SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_RW, 0))
7709485SMikore.Li@Sun.COM goto fail;
7719485SMikore.Li@Sun.COM DELAY(2);
7729485SMikore.Li@Sun.COM }
7739485SMikore.Li@Sun.COM
7749485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
7759485SMikore.Li@Sun.COM o1 | URTW_BB_HOST_BANG_EN |
77610364SMikore.Li@Sun.COM URTW_BB_HOST_BANG_RW, 0))
7779485SMikore.Li@Sun.COM goto fail;
7789485SMikore.Li@Sun.COM DELAY(2);
7799485SMikore.Li@Sun.COM
78010364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, o2, 0))
7819485SMikore.Li@Sun.COM goto fail;
78210364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, o3, 0))
7839485SMikore.Li@Sun.COM goto fail;
78410364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x3a0, 0);
7859485SMikore.Li@Sun.COM
7869485SMikore.Li@Sun.COM if (data != NULL)
7879485SMikore.Li@Sun.COM *data = value;
7889485SMikore.Li@Sun.COM fail:
7899485SMikore.Li@Sun.COM return (error);
7909485SMikore.Li@Sun.COM }
7919485SMikore.Li@Sun.COM
7929485SMikore.Li@Sun.COM static void
urtw_delay_ms(int t)7939485SMikore.Li@Sun.COM urtw_delay_ms(int t)
7949485SMikore.Li@Sun.COM {
7959485SMikore.Li@Sun.COM DELAY(t * 1000);
7969485SMikore.Li@Sun.COM }
7979485SMikore.Li@Sun.COM
7989485SMikore.Li@Sun.COM static usbd_status
urtw_8225_write_c(struct urtw_softc * sc,uint8_t addr,uint16_t data)7999485SMikore.Li@Sun.COM urtw_8225_write_c(struct urtw_softc *sc, uint8_t addr, uint16_t data)
8009485SMikore.Li@Sun.COM {
8019485SMikore.Li@Sun.COM uint16_t d80, d82, d84;
8029485SMikore.Li@Sun.COM usbd_status error;
8039485SMikore.Li@Sun.COM
80410364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_OUTPUT, &d80, 0))
8059485SMikore.Li@Sun.COM goto fail;
8069485SMikore.Li@Sun.COM d80 &= 0xfff3;
80710364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_ENABLE, &d82, 0))
8089485SMikore.Li@Sun.COM goto fail;
80910364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_RF_PINS_SELECT, &d84, 0))
8109485SMikore.Li@Sun.COM goto fail;
8119485SMikore.Li@Sun.COM d84 &= 0xfff0;
8129485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE,
81310364SMikore.Li@Sun.COM d82 | 0x0007, 0))
8149485SMikore.Li@Sun.COM goto fail;
8159485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT,
81610364SMikore.Li@Sun.COM d84 | 0x0007, 0))
8179485SMikore.Li@Sun.COM goto fail;
8189485SMikore.Li@Sun.COM
8199485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
82010364SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN, 0))
8219485SMikore.Li@Sun.COM goto fail;
82210364SMikore.Li@Sun.COM urtw_delay_ms(2);
82310364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, d80, 0))
8249485SMikore.Li@Sun.COM goto fail;
8259485SMikore.Li@Sun.COM
8269485SMikore.Li@Sun.COM error = urtw_8225_write_s16(sc, addr, 0x8225, &data);
8279485SMikore.Li@Sun.COM if (error != 0)
8289485SMikore.Li@Sun.COM goto fail;
8299485SMikore.Li@Sun.COM
8309485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
83110364SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN, 0))
8329485SMikore.Li@Sun.COM goto fail;
8339485SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT,
83410364SMikore.Li@Sun.COM d80 | URTW_BB_HOST_BANG_EN, 0))
8359485SMikore.Li@Sun.COM goto fail;
83610364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, d84, 0);
8379485SMikore.Li@Sun.COM urtw_delay_ms(2);
8389485SMikore.Li@Sun.COM fail:
8399485SMikore.Li@Sun.COM return (error);
8409485SMikore.Li@Sun.COM }
8419485SMikore.Li@Sun.COM
8429485SMikore.Li@Sun.COM static usbd_status
urtw_8225_isv2(struct urtw_softc * sc,int * ret)8439485SMikore.Li@Sun.COM urtw_8225_isv2(struct urtw_softc *sc, int *ret)
8449485SMikore.Li@Sun.COM {
8459485SMikore.Li@Sun.COM uint32_t data;
8469485SMikore.Li@Sun.COM usbd_status error;
8479485SMikore.Li@Sun.COM
8489485SMikore.Li@Sun.COM *ret = 1;
8499485SMikore.Li@Sun.COM
85010364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0080, 0))
8519485SMikore.Li@Sun.COM goto fail;
85210364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x0080, 0))
8539485SMikore.Li@Sun.COM goto fail;
85410364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x0080, 0))
8559485SMikore.Li@Sun.COM goto fail;
8569485SMikore.Li@Sun.COM urtw_delay_ms(300);
8579485SMikore.Li@Sun.COM
8589485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x1b7))
8599485SMikore.Li@Sun.COM goto fail;
8609485SMikore.Li@Sun.COM
8619485SMikore.Li@Sun.COM error = urtw_8225_read(sc, 0x8, &data);
8629485SMikore.Li@Sun.COM if (error != 0)
8639485SMikore.Li@Sun.COM goto fail;
8649485SMikore.Li@Sun.COM if (data != 0x588)
8659485SMikore.Li@Sun.COM *ret = 0;
8669485SMikore.Li@Sun.COM else {
8679485SMikore.Li@Sun.COM error = urtw_8225_read(sc, 0x9, &data);
8689485SMikore.Li@Sun.COM if (error != 0)
8699485SMikore.Li@Sun.COM goto fail;
8709485SMikore.Li@Sun.COM if (data != 0x700)
8719485SMikore.Li@Sun.COM *ret = 0;
8729485SMikore.Li@Sun.COM }
8739485SMikore.Li@Sun.COM
8749485SMikore.Li@Sun.COM error = urtw_8225_write_c(sc, 0x0, 0xb7);
8759485SMikore.Li@Sun.COM fail:
8769485SMikore.Li@Sun.COM return (error);
8779485SMikore.Li@Sun.COM }
8789485SMikore.Li@Sun.COM
8799485SMikore.Li@Sun.COM static usbd_status
urtw_get_rfchip(struct urtw_softc * sc)8809485SMikore.Li@Sun.COM urtw_get_rfchip(struct urtw_softc *sc)
8819485SMikore.Li@Sun.COM {
88210364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf;
8839485SMikore.Li@Sun.COM int ret;
8849485SMikore.Li@Sun.COM uint32_t data;
8859485SMikore.Li@Sun.COM usbd_status error;
8869485SMikore.Li@Sun.COM
88710364SMikore.Li@Sun.COM rf->rf_sc = sc;
88810364SMikore.Li@Sun.COM
88910364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
89010364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data);
89110364SMikore.Li@Sun.COM if (error != 0) {
89210364SMikore.Li@Sun.COM cmn_err(CE_WARN, "RF ID read failed\n");
89310364SMikore.Li@Sun.COM return (-1);
89410364SMikore.Li@Sun.COM }
89510364SMikore.Li@Sun.COM switch (data & 0xff) {
89610364SMikore.Li@Sun.COM case URTW_EPROM_RFCHIPID_RTL8225U:
89710364SMikore.Li@Sun.COM error = urtw_8225_isv2(sc, &ret);
89810364SMikore.Li@Sun.COM if (error != 0) {
89910364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE,
90010364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
90110364SMikore.Li@Sun.COM "8225 version check failed\n"));
90210364SMikore.Li@Sun.COM goto fail;
90310364SMikore.Li@Sun.COM }
90410364SMikore.Li@Sun.COM if (ret == 0) {
90510364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE,
90610364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
90710364SMikore.Li@Sun.COM "8225 detected\n"));
90810364SMikore.Li@Sun.COM rf->init = urtw_8225_rf_init;
90910364SMikore.Li@Sun.COM rf->set_chan = urtw_8225_rf_set_chan;
91010364SMikore.Li@Sun.COM rf->set_sens = urtw_8225_rf_set_sens;
91110364SMikore.Li@Sun.COM } else {
91210364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE,
91310364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
91410364SMikore.Li@Sun.COM "8225 v2 detected\n"));
91510364SMikore.Li@Sun.COM rf->init = urtw_8225v2_rf_init;
91610364SMikore.Li@Sun.COM rf->set_chan = urtw_8225v2_rf_set_chan;
91710364SMikore.Li@Sun.COM rf->set_sens = NULL;
91810364SMikore.Li@Sun.COM }
91910364SMikore.Li@Sun.COM break;
92010364SMikore.Li@Sun.COM default:
9219485SMikore.Li@Sun.COM goto fail;
9229485SMikore.Li@Sun.COM }
92310364SMikore.Li@Sun.COM } else {
92410364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE,
92510364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
92610364SMikore.Li@Sun.COM "8225 v2 [b] detected\n"));
92710364SMikore.Li@Sun.COM rf->init = urtw_8225v2_b_rf_init;
92810364SMikore.Li@Sun.COM rf->set_chan = urtw_8225v2_b_rf_set_chan;
92910364SMikore.Li@Sun.COM rf->set_sens = NULL;
9309485SMikore.Li@Sun.COM }
9319485SMikore.Li@Sun.COM
93210364SMikore.Li@Sun.COM rf->max_sens = URTW_8225_RF_MAX_SENS;
93310364SMikore.Li@Sun.COM rf->sens = URTW_8225_RF_DEF_SENS;
93410364SMikore.Li@Sun.COM
93510364SMikore.Li@Sun.COM return (0);
93610364SMikore.Li@Sun.COM
9379485SMikore.Li@Sun.COM fail:
93810364SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported RF chip %d\n", data & 0xff);
93910364SMikore.Li@Sun.COM return (-1);
9409485SMikore.Li@Sun.COM }
9419485SMikore.Li@Sun.COM
9429485SMikore.Li@Sun.COM static usbd_status
urtw_get_txpwr(struct urtw_softc * sc)9439485SMikore.Li@Sun.COM urtw_get_txpwr(struct urtw_softc *sc)
9449485SMikore.Li@Sun.COM {
9459485SMikore.Li@Sun.COM int i, j;
9469485SMikore.Li@Sun.COM uint32_t data;
9479485SMikore.Li@Sun.COM usbd_status error;
9489485SMikore.Li@Sun.COM
9499485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW_BASE, &data);
9509485SMikore.Li@Sun.COM if (error != 0)
9519485SMikore.Li@Sun.COM goto fail;
9529485SMikore.Li@Sun.COM sc->sc_txpwr_cck_base = data & 0xf;
9539485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm_base = (data >> 4) & 0xf;
9549485SMikore.Li@Sun.COM
9559485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 6; i += 2, j++) {
9569485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW0 + j, &data);
9579485SMikore.Li@Sun.COM if (error != 0)
9589485SMikore.Li@Sun.COM goto fail;
9599485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i] = data & 0xf;
9609485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 1] = (data & 0xf00) >> 8;
9619485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i] = (data & 0xf0) >> 4;
9629485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 1] = (data & 0xf000) >> 12;
9639485SMikore.Li@Sun.COM }
9649485SMikore.Li@Sun.COM for (i = 1, j = 0; i < 4; i += 2, j++) {
9659485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW1 + j, &data);
9669485SMikore.Li@Sun.COM if (error != 0)
9679485SMikore.Li@Sun.COM goto fail;
9689485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6] = data & 0xf;
9699485SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 1] = (data & 0xf00) >> 8;
9709485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4;
9719485SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12;
9729485SMikore.Li@Sun.COM }
97310364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
97410364SMikore.Li@Sun.COM for (i = 1, j = 0; i < 4; i += 2, j++) {
97510364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j,
97610364SMikore.Li@Sun.COM &data);
97710364SMikore.Li@Sun.COM if (error != 0)
97810364SMikore.Li@Sun.COM goto fail;
97910364SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf;
98010364SMikore.Li@Sun.COM sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8;
98110364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4;
98210364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[i + 6 + 4 + 1] =
98310364SMikore.Li@Sun.COM (data & 0xf000) >> 12;
98410364SMikore.Li@Sun.COM }
98510364SMikore.Li@Sun.COM } else {
98610364SMikore.Li@Sun.COM /* Channel 11. */
98710364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, 0x1b, &data);
9889485SMikore.Li@Sun.COM if (error != 0)
9899485SMikore.Li@Sun.COM goto fail;
99010364SMikore.Li@Sun.COM sc->sc_txpwr_cck[11] = data & 0xf;
99110364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[11] = (data & 0xf0) >> 4;
99210364SMikore.Li@Sun.COM
99310364SMikore.Li@Sun.COM /* Channel 12. */
99410364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, 0xa, &data);
99510364SMikore.Li@Sun.COM if (error != 0)
99610364SMikore.Li@Sun.COM goto fail;
99710364SMikore.Li@Sun.COM sc->sc_txpwr_cck[12] = data & 0xf;
99810364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[12] = (data & 0xf0) >> 4;
99910364SMikore.Li@Sun.COM
100010364SMikore.Li@Sun.COM /* Channel 13, 14. */
100110364SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, 0x1c, &data);
100210364SMikore.Li@Sun.COM if (error != 0)
100310364SMikore.Li@Sun.COM goto fail;
100410364SMikore.Li@Sun.COM sc->sc_txpwr_cck[13] = data & 0xf;
100510364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[13] = (data & 0xf0) >> 4;
100610364SMikore.Li@Sun.COM sc->sc_txpwr_cck[14] = (data & 0xf00) >> 8;
100710364SMikore.Li@Sun.COM sc->sc_txpwr_ofdm[14] = (data & 0xf000) >> 12;
10089485SMikore.Li@Sun.COM }
10099485SMikore.Li@Sun.COM fail:
10109485SMikore.Li@Sun.COM return (error);
10119485SMikore.Li@Sun.COM }
10129485SMikore.Li@Sun.COM
101310364SMikore.Li@Sun.COM
10149485SMikore.Li@Sun.COM static usbd_status
urtw_get_macaddr(struct urtw_softc * sc)10159485SMikore.Li@Sun.COM urtw_get_macaddr(struct urtw_softc *sc)
10169485SMikore.Li@Sun.COM {
10179485SMikore.Li@Sun.COM uint32_t data;
10189485SMikore.Li@Sun.COM usbd_status error;
10199485SMikore.Li@Sun.COM uint8_t *m = 0;
10209485SMikore.Li@Sun.COM
10219485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data);
10229485SMikore.Li@Sun.COM if (error != 0)
10239485SMikore.Li@Sun.COM goto fail;
10249485SMikore.Li@Sun.COM sc->sc_bssid[0] = data & 0xff;
10259485SMikore.Li@Sun.COM sc->sc_bssid[1] = (data & 0xff00) >> 8;
10269485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data);
10279485SMikore.Li@Sun.COM if (error != 0)
10289485SMikore.Li@Sun.COM goto fail;
10299485SMikore.Li@Sun.COM sc->sc_bssid[2] = data & 0xff;
10309485SMikore.Li@Sun.COM sc->sc_bssid[3] = (data & 0xff00) >> 8;
10319485SMikore.Li@Sun.COM error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data);
10329485SMikore.Li@Sun.COM if (error != 0)
10339485SMikore.Li@Sun.COM goto fail;
10349485SMikore.Li@Sun.COM sc->sc_bssid[4] = data & 0xff;
10359485SMikore.Li@Sun.COM sc->sc_bssid[5] = (data & 0xff00) >> 8;
10369485SMikore.Li@Sun.COM bcopy(sc->sc_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
10379485SMikore.Li@Sun.COM m = sc->sc_bssid;
10389485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT,
10399485SMikore.Li@Sun.COM "MAC: %x:%x:%x:%x:%x:%x\n",
10409485SMikore.Li@Sun.COM m[0], m[1], m[2], m[3], m[4], m[5]));
10419485SMikore.Li@Sun.COM fail:
10429485SMikore.Li@Sun.COM return (error);
10439485SMikore.Li@Sun.COM }
10449485SMikore.Li@Sun.COM
10459485SMikore.Li@Sun.COM static usbd_status
urtw_eprom_read32(struct urtw_softc * sc,uint32_t addr,uint32_t * data)10469485SMikore.Li@Sun.COM urtw_eprom_read32(struct urtw_softc *sc, uint32_t addr, uint32_t *data)
10479485SMikore.Li@Sun.COM {
10489485SMikore.Li@Sun.COM #define URTW_READCMD_LEN 3
10499485SMikore.Li@Sun.COM int addrlen, i;
10509485SMikore.Li@Sun.COM int16_t addrstr[8], data16, readcmd[] = { 1, 1, 0 };
10519485SMikore.Li@Sun.COM usbd_status error;
10529485SMikore.Li@Sun.COM
10539485SMikore.Li@Sun.COM /* NB: make sure the buffer is initialized */
10549485SMikore.Li@Sun.COM *data = 0;
10559485SMikore.Li@Sun.COM
10569485SMikore.Li@Sun.COM /* enable EPROM programming */
10579485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EPROM_CMD,
105810364SMikore.Li@Sun.COM URTW_EPROM_CMD_PROGRAM_MODE, 0))
10599485SMikore.Li@Sun.COM goto fail;
10609485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY);
10619485SMikore.Li@Sun.COM
10629485SMikore.Li@Sun.COM error = urtw_eprom_cs(sc, URTW_EPROM_ENABLE);
10639485SMikore.Li@Sun.COM if (error != 0)
10649485SMikore.Li@Sun.COM goto fail;
10659485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc);
10669485SMikore.Li@Sun.COM if (error != 0)
10679485SMikore.Li@Sun.COM goto fail;
10689485SMikore.Li@Sun.COM error = urtw_eprom_sendbits(sc, readcmd, URTW_READCMD_LEN);
10699485SMikore.Li@Sun.COM if (error != 0)
10709485SMikore.Li@Sun.COM goto fail;
10719485SMikore.Li@Sun.COM if (sc->sc_epromtype == URTW_EEPROM_93C56) {
10729485SMikore.Li@Sun.COM addrlen = 8;
10739485SMikore.Li@Sun.COM addrstr[0] = addr & (1 << 7);
10749485SMikore.Li@Sun.COM addrstr[1] = addr & (1 << 6);
10759485SMikore.Li@Sun.COM addrstr[2] = addr & (1 << 5);
10769485SMikore.Li@Sun.COM addrstr[3] = addr & (1 << 4);
10779485SMikore.Li@Sun.COM addrstr[4] = addr & (1 << 3);
10789485SMikore.Li@Sun.COM addrstr[5] = addr & (1 << 2);
10799485SMikore.Li@Sun.COM addrstr[6] = addr & (1 << 1);
10809485SMikore.Li@Sun.COM addrstr[7] = addr & (1 << 0);
10819485SMikore.Li@Sun.COM } else {
10829485SMikore.Li@Sun.COM addrlen = 6;
10839485SMikore.Li@Sun.COM addrstr[0] = addr & (1 << 5);
10849485SMikore.Li@Sun.COM addrstr[1] = addr & (1 << 4);
10859485SMikore.Li@Sun.COM addrstr[2] = addr & (1 << 3);
10869485SMikore.Li@Sun.COM addrstr[3] = addr & (1 << 2);
10879485SMikore.Li@Sun.COM addrstr[4] = addr & (1 << 1);
10889485SMikore.Li@Sun.COM addrstr[5] = addr & (1 << 0);
10899485SMikore.Li@Sun.COM }
10909485SMikore.Li@Sun.COM error = urtw_eprom_sendbits(sc, addrstr, addrlen);
10919485SMikore.Li@Sun.COM if (error != 0)
10929485SMikore.Li@Sun.COM goto fail;
10939485SMikore.Li@Sun.COM
10949485SMikore.Li@Sun.COM error = urtw_eprom_writebit(sc, 0);
10959485SMikore.Li@Sun.COM if (error != 0)
10969485SMikore.Li@Sun.COM goto fail;
10979485SMikore.Li@Sun.COM
10989485SMikore.Li@Sun.COM for (i = 0; i < 16; i++) {
10999485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc);
11009485SMikore.Li@Sun.COM if (error != 0)
11019485SMikore.Li@Sun.COM goto fail;
11029485SMikore.Li@Sun.COM error = urtw_eprom_readbit(sc, &data16);
11039485SMikore.Li@Sun.COM if (error != 0)
11049485SMikore.Li@Sun.COM goto fail;
11059485SMikore.Li@Sun.COM
11069485SMikore.Li@Sun.COM (*data) |= (data16 << (15 - i));
11079485SMikore.Li@Sun.COM }
11089485SMikore.Li@Sun.COM
11099485SMikore.Li@Sun.COM error = urtw_eprom_cs(sc, URTW_EPROM_DISABLE);
11109485SMikore.Li@Sun.COM if (error != 0)
11119485SMikore.Li@Sun.COM goto fail;
11129485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc);
11139485SMikore.Li@Sun.COM if (error != 0)
11149485SMikore.Li@Sun.COM goto fail;
11159485SMikore.Li@Sun.COM
11169485SMikore.Li@Sun.COM /* now disable EPROM programming */
111710364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD,
111810364SMikore.Li@Sun.COM URTW_EPROM_CMD_NORMAL_MODE, 0);
11199485SMikore.Li@Sun.COM fail:
11209485SMikore.Li@Sun.COM return (error);
11219485SMikore.Li@Sun.COM #undef URTW_READCMD_LEN
11229485SMikore.Li@Sun.COM }
11239485SMikore.Li@Sun.COM
11249485SMikore.Li@Sun.COM static usbd_status
urtw_eprom_readbit(struct urtw_softc * sc,int16_t * data)11259485SMikore.Li@Sun.COM urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data)
11269485SMikore.Li@Sun.COM {
11279485SMikore.Li@Sun.COM uint8_t data8;
11289485SMikore.Li@Sun.COM usbd_status error;
11299485SMikore.Li@Sun.COM
113010364SMikore.Li@Sun.COM error = urtw_read8_c(sc, URTW_EPROM_CMD, &data8, 0);
11319485SMikore.Li@Sun.COM *data = (data8 & URTW_EPROM_READBIT) ? 1 : 0;
11329485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY);
11339485SMikore.Li@Sun.COM return (error);
11349485SMikore.Li@Sun.COM }
11359485SMikore.Li@Sun.COM
11369485SMikore.Li@Sun.COM static usbd_status
urtw_eprom_sendbits(struct urtw_softc * sc,int16_t * buf,int buflen)11379485SMikore.Li@Sun.COM urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen)
11389485SMikore.Li@Sun.COM {
11399485SMikore.Li@Sun.COM int i = 0;
11409485SMikore.Li@Sun.COM usbd_status error;
11419485SMikore.Li@Sun.COM
11429485SMikore.Li@Sun.COM for (i = 0; i < buflen; i++) {
11439485SMikore.Li@Sun.COM error = urtw_eprom_writebit(sc, buf[i]);
11449485SMikore.Li@Sun.COM if (error != 0)
11459485SMikore.Li@Sun.COM goto fail;
11469485SMikore.Li@Sun.COM error = urtw_eprom_ck(sc);
11479485SMikore.Li@Sun.COM if (error != 0)
11489485SMikore.Li@Sun.COM goto fail;
11499485SMikore.Li@Sun.COM }
11509485SMikore.Li@Sun.COM fail:
11519485SMikore.Li@Sun.COM return (error);
11529485SMikore.Li@Sun.COM }
11539485SMikore.Li@Sun.COM
11549485SMikore.Li@Sun.COM static usbd_status
urtw_eprom_writebit(struct urtw_softc * sc,int16_t bit)11559485SMikore.Li@Sun.COM urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit)
11569485SMikore.Li@Sun.COM {
11579485SMikore.Li@Sun.COM uint8_t data;
11589485SMikore.Li@Sun.COM usbd_status error;
11599485SMikore.Li@Sun.COM
116010364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
11619485SMikore.Li@Sun.COM goto fail;
11629485SMikore.Li@Sun.COM if (bit != 0)
11639485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD,
116410364SMikore.Li@Sun.COM data | URTW_EPROM_WRITEBIT, 0);
11659485SMikore.Li@Sun.COM else
11669485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD,
116710364SMikore.Li@Sun.COM data & ~URTW_EPROM_WRITEBIT, 0);
11689485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY);
11699485SMikore.Li@Sun.COM fail:
11709485SMikore.Li@Sun.COM return (error);
11719485SMikore.Li@Sun.COM }
11729485SMikore.Li@Sun.COM
11739485SMikore.Li@Sun.COM static usbd_status
urtw_eprom_ck(struct urtw_softc * sc)11749485SMikore.Li@Sun.COM urtw_eprom_ck(struct urtw_softc *sc)
11759485SMikore.Li@Sun.COM {
11769485SMikore.Li@Sun.COM uint8_t data;
11779485SMikore.Li@Sun.COM usbd_status error;
11789485SMikore.Li@Sun.COM
11799485SMikore.Li@Sun.COM /* masking */
118010364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
11819485SMikore.Li@Sun.COM goto fail;
118210364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK, 0))
11839485SMikore.Li@Sun.COM goto fail;
11849485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY);
11859485SMikore.Li@Sun.COM /* unmasking */
118610364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
11879485SMikore.Li@Sun.COM goto fail;
118810364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK, 0);
11899485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY);
11909485SMikore.Li@Sun.COM fail:
11919485SMikore.Li@Sun.COM return (error);
11929485SMikore.Li@Sun.COM }
11939485SMikore.Li@Sun.COM
11949485SMikore.Li@Sun.COM static usbd_status
urtw_eprom_cs(struct urtw_softc * sc,int able)11959485SMikore.Li@Sun.COM urtw_eprom_cs(struct urtw_softc *sc, int able)
11969485SMikore.Li@Sun.COM {
11979485SMikore.Li@Sun.COM uint8_t data;
11989485SMikore.Li@Sun.COM usbd_status error;
11999485SMikore.Li@Sun.COM
120010364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
12019485SMikore.Li@Sun.COM goto fail;
12029485SMikore.Li@Sun.COM if (able == URTW_EPROM_ENABLE)
12039485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD,
120410364SMikore.Li@Sun.COM data | URTW_EPROM_CS, 0);
12059485SMikore.Li@Sun.COM else
12069485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD,
120710364SMikore.Li@Sun.COM data & ~URTW_EPROM_CS, 0);
12089485SMikore.Li@Sun.COM DELAY(URTW_EPROM_DELAY);
12099485SMikore.Li@Sun.COM fail:
12109485SMikore.Li@Sun.COM return (error);
12119485SMikore.Li@Sun.COM }
12129485SMikore.Li@Sun.COM
12139485SMikore.Li@Sun.COM static usbd_status
urtw_read8_c(struct urtw_softc * sc,int val,uint8_t * data,uint8_t idx)121410364SMikore.Li@Sun.COM urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data, uint8_t idx)
12159485SMikore.Li@Sun.COM {
12169485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
12179485SMikore.Li@Sun.COM usb_cr_t cr;
12189485SMikore.Li@Sun.COM usb_cb_flags_t cf;
12199485SMikore.Li@Sun.COM mblk_t *mp = NULL;
12209485SMikore.Li@Sun.COM usbd_status error;
12219485SMikore.Li@Sun.COM
12229485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
12239485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE;
12249485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ;
12259485SMikore.Li@Sun.COM req.wValue = val | 0xff00;
122610364SMikore.Li@Sun.COM req.wIndex = idx & 0x03;
12279485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t);
12289485SMikore.Li@Sun.COM
12299485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
12309485SMikore.Li@Sun.COM &cr, &cf, 0);
12319485SMikore.Li@Sun.COM
12329485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
12339485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
12349485SMikore.Li@Sun.COM "urtw_read8_c: get regs req failed :"
12359485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf));
12369485SMikore.Li@Sun.COM return (error);
12379485SMikore.Li@Sun.COM }
12389485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint8_t));
12399485SMikore.Li@Sun.COM if (mp)
12409485SMikore.Li@Sun.COM freemsg(mp);
12419485SMikore.Li@Sun.COM return (error);
12429485SMikore.Li@Sun.COM }
12439485SMikore.Li@Sun.COM
12449485SMikore.Li@Sun.COM static usbd_status
urtw_read8e(struct urtw_softc * sc,int val,uint8_t * data)12459485SMikore.Li@Sun.COM urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data)
12469485SMikore.Li@Sun.COM {
12479485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
12489485SMikore.Li@Sun.COM usb_cr_t cr;
12499485SMikore.Li@Sun.COM usb_cb_flags_t cf;
12509485SMikore.Li@Sun.COM mblk_t *mp = NULL;
12519485SMikore.Li@Sun.COM usbd_status error;
12529485SMikore.Li@Sun.COM
12539485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
12549485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE;
12559485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ;
12569485SMikore.Li@Sun.COM req.wValue = val | 0xfe00;
12579485SMikore.Li@Sun.COM req.wIndex = 0;
12589485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t);
12599485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING;
12609485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
12619485SMikore.Li@Sun.COM &cr, &cf, 0);
12629485SMikore.Li@Sun.COM
12639485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
12649485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
12659485SMikore.Li@Sun.COM "urtw_read8e: get regs req failed :"
12669485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf));
12679485SMikore.Li@Sun.COM return (error);
12689485SMikore.Li@Sun.COM }
12699485SMikore.Li@Sun.COM
12709485SMikore.Li@Sun.COM if (mp) {
12719485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint8_t));
12729485SMikore.Li@Sun.COM freemsg(mp);
12739485SMikore.Li@Sun.COM }
12749485SMikore.Li@Sun.COM return (error);
12759485SMikore.Li@Sun.COM }
12769485SMikore.Li@Sun.COM
12779485SMikore.Li@Sun.COM static usbd_status
urtw_read16_c(struct urtw_softc * sc,int val,uint16_t * data,uint8_t idx)127810364SMikore.Li@Sun.COM urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data, uint8_t idx)
12799485SMikore.Li@Sun.COM {
12809485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
12819485SMikore.Li@Sun.COM usb_cr_t cr;
12829485SMikore.Li@Sun.COM usb_cb_flags_t cf;
12839485SMikore.Li@Sun.COM mblk_t *mp = NULL;
12849485SMikore.Li@Sun.COM usbd_status error;
12859485SMikore.Li@Sun.COM
12869485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
12879485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE;
12889485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ;
12899485SMikore.Li@Sun.COM req.wValue = val | 0xff00;
129010364SMikore.Li@Sun.COM req.wIndex = idx & 0x03;
12919485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t);
12929485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING;
12939485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
12949485SMikore.Li@Sun.COM &cr, &cf, 0);
12959485SMikore.Li@Sun.COM
12969485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
12979485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
12989485SMikore.Li@Sun.COM "urtw_read16_c: get regs req failed :"
12999485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n",
13009485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf));
13019485SMikore.Li@Sun.COM return (error);
13029485SMikore.Li@Sun.COM }
13039485SMikore.Li@Sun.COM if (mp) {
13049485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint16_t));
13059485SMikore.Li@Sun.COM freemsg(mp);
13069485SMikore.Li@Sun.COM }
13079485SMikore.Li@Sun.COM return (error);
13089485SMikore.Li@Sun.COM }
13099485SMikore.Li@Sun.COM
13109485SMikore.Li@Sun.COM static usbd_status
urtw_read32_c(struct urtw_softc * sc,int val,uint32_t * data,uint8_t idx)131110364SMikore.Li@Sun.COM urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data, uint8_t idx)
13129485SMikore.Li@Sun.COM {
13139485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
13149485SMikore.Li@Sun.COM usb_cr_t cr;
13159485SMikore.Li@Sun.COM usb_cb_flags_t cf;
13169485SMikore.Li@Sun.COM mblk_t *mp = NULL;
13179485SMikore.Li@Sun.COM usbd_status error;
13189485SMikore.Li@Sun.COM
13199485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
13209485SMikore.Li@Sun.COM req.bmRequestType = UT_READ_VENDOR_DEVICE;
13219485SMikore.Li@Sun.COM req.bRequest = URTW_8187_GETREGS_REQ;
13229485SMikore.Li@Sun.COM req.wValue = val | 0xff00;
132310364SMikore.Li@Sun.COM req.wIndex = idx & 0x03;
13249485SMikore.Li@Sun.COM req.wLength = sizeof (uint32_t);
13259485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_AUTOCLEARING;
13269485SMikore.Li@Sun.COM
13279485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
13289485SMikore.Li@Sun.COM &cr, &cf, 0);
13299485SMikore.Li@Sun.COM
13309485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
13319485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
13329485SMikore.Li@Sun.COM "urtw_read32_c: get regs req failed :"
13339485SMikore.Li@Sun.COM " cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf));
13349485SMikore.Li@Sun.COM return (error);
13359485SMikore.Li@Sun.COM }
13369485SMikore.Li@Sun.COM
13379485SMikore.Li@Sun.COM if (mp) {
13389485SMikore.Li@Sun.COM bcopy(mp->b_rptr, data, sizeof (uint32_t));
13399485SMikore.Li@Sun.COM freemsg(mp);
13409485SMikore.Li@Sun.COM }
13419485SMikore.Li@Sun.COM return (error);
13429485SMikore.Li@Sun.COM }
13439485SMikore.Li@Sun.COM
13449485SMikore.Li@Sun.COM static usbd_status
urtw_write8_c(struct urtw_softc * sc,int val,uint8_t data,uint8_t idx)134510364SMikore.Li@Sun.COM urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data, uint8_t idx)
13469485SMikore.Li@Sun.COM {
13479485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
13489485SMikore.Li@Sun.COM usb_cr_t cr;
13499485SMikore.Li@Sun.COM usb_cb_flags_t cf;
13509485SMikore.Li@Sun.COM mblk_t *mp = 0;
13519485SMikore.Li@Sun.COM int error;
13529485SMikore.Li@Sun.COM
13539485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
13549485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
13559485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ;
13569485SMikore.Li@Sun.COM req.wValue = val | 0xff00;
135710364SMikore.Li@Sun.COM req.wIndex = idx & 0x03;
13589485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t);
13599485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE;
13609485SMikore.Li@Sun.COM
13619485SMikore.Li@Sun.COM mp = allocb(sizeof (uint32_t), BPRI_MED);
13629485SMikore.Li@Sun.COM if (mp == NULL) {
13639485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write8_c: failed alloc mblk.");
13649485SMikore.Li@Sun.COM return (-1);
13659485SMikore.Li@Sun.COM }
13669485SMikore.Li@Sun.COM *(uint8_t *)(mp->b_rptr) = data;
13679485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint8_t);
13689485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
13699485SMikore.Li@Sun.COM &cr, &cf, 0);
13709485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
13719485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
13729485SMikore.Li@Sun.COM "urtw_write8_c: could not set regs:"
13739485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n", usb_str_cr(cr), cr, cf));
13749485SMikore.Li@Sun.COM }
13759485SMikore.Li@Sun.COM if (mp)
13769485SMikore.Li@Sun.COM freemsg(mp);
13779485SMikore.Li@Sun.COM return (error);
13789485SMikore.Li@Sun.COM }
13799485SMikore.Li@Sun.COM
13809485SMikore.Li@Sun.COM static usbd_status
urtw_write8e(struct urtw_softc * sc,int val,uint8_t data)13819485SMikore.Li@Sun.COM urtw_write8e(struct urtw_softc *sc, int val, uint8_t data)
13829485SMikore.Li@Sun.COM {
13839485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
13849485SMikore.Li@Sun.COM usb_cr_t cr;
13859485SMikore.Li@Sun.COM usb_cb_flags_t cf;
13869485SMikore.Li@Sun.COM mblk_t *mp = 0;
13879485SMikore.Li@Sun.COM int error;
13889485SMikore.Li@Sun.COM
13899485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
13909485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
13919485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ;
13929485SMikore.Li@Sun.COM req.wValue = val | 0xfe00;
13939485SMikore.Li@Sun.COM req.wIndex = 0;
13949485SMikore.Li@Sun.COM req.wLength = sizeof (uint8_t);
13959485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE;
13969485SMikore.Li@Sun.COM
13979485SMikore.Li@Sun.COM mp = allocb(sizeof (uint8_t), BPRI_MED);
13989485SMikore.Li@Sun.COM if (mp == NULL) {
13999485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write8e: failed alloc mblk.");
14009485SMikore.Li@Sun.COM return (-1);
14019485SMikore.Li@Sun.COM }
14029485SMikore.Li@Sun.COM *(mp->b_rptr) = data;
14039485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint8_t);
14049485SMikore.Li@Sun.COM
14059485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
14069485SMikore.Li@Sun.COM &cr, &cf, 0);
14079485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
14089485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
14099485SMikore.Li@Sun.COM "urtw_write8e: could not set regs:"
14109485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n",
14119485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf));
14129485SMikore.Li@Sun.COM }
14139485SMikore.Li@Sun.COM if (mp)
14149485SMikore.Li@Sun.COM freemsg(mp);
14159485SMikore.Li@Sun.COM return (error);
14169485SMikore.Li@Sun.COM }
14179485SMikore.Li@Sun.COM
14189485SMikore.Li@Sun.COM static usbd_status
urtw_write16_c(struct urtw_softc * sc,int val,uint16_t data,uint8_t idx)141910364SMikore.Li@Sun.COM urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data, uint8_t idx)
14209485SMikore.Li@Sun.COM {
14219485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
14229485SMikore.Li@Sun.COM usb_cr_t cr;
14239485SMikore.Li@Sun.COM usb_cb_flags_t cf;
14249485SMikore.Li@Sun.COM mblk_t *mp = 0;
14259485SMikore.Li@Sun.COM int error;
14269485SMikore.Li@Sun.COM
14279485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
14289485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
14299485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ;
14309485SMikore.Li@Sun.COM req.wValue = val | 0xff00;
143110364SMikore.Li@Sun.COM req.wIndex = idx & 0x03;
14329485SMikore.Li@Sun.COM req.wLength = sizeof (uint16_t);
14339485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE;
14349485SMikore.Li@Sun.COM
14359485SMikore.Li@Sun.COM mp = allocb(sizeof (uint16_t), BPRI_MED);
14369485SMikore.Li@Sun.COM if (mp == NULL) {
14379485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write16_c: failed alloc mblk.");
14389485SMikore.Li@Sun.COM return (-1);
14399485SMikore.Li@Sun.COM }
14409485SMikore.Li@Sun.COM *(uint16_t *)(uintptr_t)(mp->b_rptr) = data;
14419485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint16_t);
14429485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
14439485SMikore.Li@Sun.COM &cr, &cf, 0);
14449485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
14459485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
14469485SMikore.Li@Sun.COM "urtw_write16_c: could not set regs:"
14479485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n",
14489485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf));
14499485SMikore.Li@Sun.COM }
14509485SMikore.Li@Sun.COM if (mp)
14519485SMikore.Li@Sun.COM freemsg(mp);
14529485SMikore.Li@Sun.COM return (error);
14539485SMikore.Li@Sun.COM }
14549485SMikore.Li@Sun.COM
14559485SMikore.Li@Sun.COM static usbd_status
urtw_write32_c(struct urtw_softc * sc,int val,uint32_t data,uint8_t idx)145610364SMikore.Li@Sun.COM urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data, uint8_t idx)
14579485SMikore.Li@Sun.COM {
14589485SMikore.Li@Sun.COM usb_ctrl_setup_t req;
14599485SMikore.Li@Sun.COM usb_cr_t cr;
14609485SMikore.Li@Sun.COM usb_cb_flags_t cf;
14619485SMikore.Li@Sun.COM mblk_t *mp = 0;
14629485SMikore.Li@Sun.COM int error;
14639485SMikore.Li@Sun.COM
14649485SMikore.Li@Sun.COM bzero(&req, sizeof (req));
14659485SMikore.Li@Sun.COM req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
14669485SMikore.Li@Sun.COM req.bRequest = URTW_8187_SETREGS_REQ;
14679485SMikore.Li@Sun.COM req.wValue = val | 0xff00;
146810364SMikore.Li@Sun.COM req.wIndex = idx & 0x03;
14699485SMikore.Li@Sun.COM req.wLength = sizeof (uint32_t);
14709485SMikore.Li@Sun.COM req.attrs = USB_ATTRS_NONE;
14719485SMikore.Li@Sun.COM
14729485SMikore.Li@Sun.COM mp = allocb(sizeof (uint32_t), BPRI_MED);
14739485SMikore.Li@Sun.COM if (mp == NULL) {
14749485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_write32_c: failed alloc mblk.");
14759485SMikore.Li@Sun.COM return (-1);
14769485SMikore.Li@Sun.COM }
14779485SMikore.Li@Sun.COM *(uint32_t *)(uintptr_t)(mp->b_rptr) = data;
14789485SMikore.Li@Sun.COM mp->b_wptr += sizeof (uint32_t);
14799485SMikore.Li@Sun.COM error = usb_pipe_ctrl_xfer_wait(sc->sc_udev->dev_default_ph, &req, &mp,
14809485SMikore.Li@Sun.COM &cr, &cf, 0);
14819485SMikore.Li@Sun.COM if (error != USB_SUCCESS) {
14829485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_DEVREQ, (sc->sc_dev, CE_CONT,
14839485SMikore.Li@Sun.COM "urtw_write32_c: could not set regs:"
14849485SMikore.Li@Sun.COM "cr:%s(%d), cf:(%x)\n",
14859485SMikore.Li@Sun.COM usb_str_cr(cr), cr, cf));
14869485SMikore.Li@Sun.COM }
14879485SMikore.Li@Sun.COM
14889485SMikore.Li@Sun.COM if (mp)
14899485SMikore.Li@Sun.COM freemsg(mp);
14909485SMikore.Li@Sun.COM return (error);
14919485SMikore.Li@Sun.COM }
14929485SMikore.Li@Sun.COM
14939485SMikore.Li@Sun.COM static usbd_status
urtw_set_mode(struct urtw_softc * sc,uint32_t mode)14949485SMikore.Li@Sun.COM urtw_set_mode(struct urtw_softc *sc, uint32_t mode)
14959485SMikore.Li@Sun.COM {
14969485SMikore.Li@Sun.COM uint8_t data;
14979485SMikore.Li@Sun.COM usbd_status error;
14989485SMikore.Li@Sun.COM
149910364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_EPROM_CMD, &data, 0))
15009485SMikore.Li@Sun.COM goto fail;
15019485SMikore.Li@Sun.COM data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT);
15029485SMikore.Li@Sun.COM data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK);
150310364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_EPROM_CMD, data, 0);
15049485SMikore.Li@Sun.COM fail:
15059485SMikore.Li@Sun.COM return (error);
15069485SMikore.Li@Sun.COM }
15079485SMikore.Li@Sun.COM
15089485SMikore.Li@Sun.COM static usbd_status
urtw_8180_set_anaparam(struct urtw_softc * sc,uint32_t val)15099485SMikore.Li@Sun.COM urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val)
15109485SMikore.Li@Sun.COM {
15119485SMikore.Li@Sun.COM uint8_t data;
15129485SMikore.Li@Sun.COM usbd_status error;
15139485SMikore.Li@Sun.COM
15149485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
15159485SMikore.Li@Sun.COM if (error)
15169485SMikore.Li@Sun.COM goto fail;
15179485SMikore.Li@Sun.COM
151810364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
15199485SMikore.Li@Sun.COM goto fail;
15209485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3,
152110364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE, 0))
15229485SMikore.Li@Sun.COM goto fail;
152310364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_ANAPARAM, val, 0))
15249485SMikore.Li@Sun.COM goto fail;
152510364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
15269485SMikore.Li@Sun.COM goto fail;
15279485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3,
152810364SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0))
15299485SMikore.Li@Sun.COM goto fail;
15309485SMikore.Li@Sun.COM
15319485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
15329485SMikore.Li@Sun.COM if (error)
15339485SMikore.Li@Sun.COM goto fail;
15349485SMikore.Li@Sun.COM fail:
15359485SMikore.Li@Sun.COM return (error);
15369485SMikore.Li@Sun.COM }
15379485SMikore.Li@Sun.COM
15389485SMikore.Li@Sun.COM static usbd_status
urtw_8185_set_anaparam2(struct urtw_softc * sc,uint32_t val)15399485SMikore.Li@Sun.COM urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val)
15409485SMikore.Li@Sun.COM {
15419485SMikore.Li@Sun.COM uint8_t data;
15429485SMikore.Li@Sun.COM usbd_status error;
15439485SMikore.Li@Sun.COM
15449485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
15459485SMikore.Li@Sun.COM if (error)
15469485SMikore.Li@Sun.COM goto fail;
15479485SMikore.Li@Sun.COM
154810364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
15499485SMikore.Li@Sun.COM goto fail;
15509485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3,
155110364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE, 0))
15529485SMikore.Li@Sun.COM goto fail;
155310364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_ANAPARAM2, val, 0))
15549485SMikore.Li@Sun.COM goto fail;
155510364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CONFIG3, &data, 0))
15569485SMikore.Li@Sun.COM goto fail;
15579485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3,
155810364SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0))
15599485SMikore.Li@Sun.COM goto fail;
15609485SMikore.Li@Sun.COM
15619485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
15629485SMikore.Li@Sun.COM if (error)
15639485SMikore.Li@Sun.COM goto fail;
15649485SMikore.Li@Sun.COM fail:
15659485SMikore.Li@Sun.COM return (error);
15669485SMikore.Li@Sun.COM }
15679485SMikore.Li@Sun.COM
15689485SMikore.Li@Sun.COM static usbd_status
urtw_intr_disable(struct urtw_softc * sc)15699485SMikore.Li@Sun.COM urtw_intr_disable(struct urtw_softc *sc)
15709485SMikore.Li@Sun.COM {
15719485SMikore.Li@Sun.COM usbd_status error;
15729485SMikore.Li@Sun.COM
157310364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_INTR_MASK, 0, 0);
15749485SMikore.Li@Sun.COM return (error);
15759485SMikore.Li@Sun.COM }
15769485SMikore.Li@Sun.COM
15779485SMikore.Li@Sun.COM static usbd_status
urtw_8187_reset(struct urtw_softc * sc)157810364SMikore.Li@Sun.COM urtw_8187_reset(struct urtw_softc *sc)
15799485SMikore.Li@Sun.COM {
15809485SMikore.Li@Sun.COM uint8_t data;
15819485SMikore.Li@Sun.COM usbd_status error;
15829485SMikore.Li@Sun.COM
158310364SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON);
15849485SMikore.Li@Sun.COM if (error)
15859485SMikore.Li@Sun.COM goto fail;
158610364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
15879485SMikore.Li@Sun.COM if (error)
15889485SMikore.Li@Sun.COM goto fail;
15899485SMikore.Li@Sun.COM
15909485SMikore.Li@Sun.COM error = urtw_intr_disable(sc);
15919485SMikore.Li@Sun.COM if (error)
15929485SMikore.Li@Sun.COM goto fail;
15939485SMikore.Li@Sun.COM urtw_delay_ms(50);
15949485SMikore.Li@Sun.COM
15959485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x10);
15969485SMikore.Li@Sun.COM if (error != 0)
15979485SMikore.Li@Sun.COM goto fail;
15989485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x11);
15999485SMikore.Li@Sun.COM if (error != 0)
16009485SMikore.Li@Sun.COM goto fail;
16019485SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x18, 0x00);
16029485SMikore.Li@Sun.COM if (error != 0)
16039485SMikore.Li@Sun.COM goto fail;
16049485SMikore.Li@Sun.COM urtw_delay_ms(50);
16059485SMikore.Li@Sun.COM
160610364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data, 0))
16079485SMikore.Li@Sun.COM goto fail;
16089485SMikore.Li@Sun.COM data = (data & 2) | URTW_CMD_RST;
160910364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CMD, data, 0))
16109485SMikore.Li@Sun.COM goto fail;
16119485SMikore.Li@Sun.COM urtw_delay_ms(50);
16129485SMikore.Li@Sun.COM
161310364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data, 0))
16149485SMikore.Li@Sun.COM goto fail;
16159485SMikore.Li@Sun.COM if (data & URTW_CMD_RST) {
16169485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw reset timeout\n");
16179485SMikore.Li@Sun.COM goto fail;
16189485SMikore.Li@Sun.COM }
16199485SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD);
16209485SMikore.Li@Sun.COM if (error)
16219485SMikore.Li@Sun.COM goto fail;
16229485SMikore.Li@Sun.COM urtw_delay_ms(50);
16239485SMikore.Li@Sun.COM
162410364SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON);
16259485SMikore.Li@Sun.COM if (error)
16269485SMikore.Li@Sun.COM goto fail;
162710364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
16289485SMikore.Li@Sun.COM if (error)
16299485SMikore.Li@Sun.COM goto fail;
16309485SMikore.Li@Sun.COM fail:
16319485SMikore.Li@Sun.COM return (error);
16329485SMikore.Li@Sun.COM }
16339485SMikore.Li@Sun.COM
16349485SMikore.Li@Sun.COM static usbd_status
urtw_led_on(struct urtw_softc * sc,int type)16359485SMikore.Li@Sun.COM urtw_led_on(struct urtw_softc *sc, int type)
16369485SMikore.Li@Sun.COM {
16379485SMikore.Li@Sun.COM if (type == URTW_LED_GPIO) {
16389485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledpin) {
16399485SMikore.Li@Sun.COM case URTW_LED_PIN_GPIO0:
164010364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0x01, 0);
164110364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x00, 0);
16429485SMikore.Li@Sun.COM break;
16439485SMikore.Li@Sun.COM default:
16449485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED PIN type 0x%x",
16459485SMikore.Li@Sun.COM sc->sc_gpio_ledpin);
16469485SMikore.Li@Sun.COM /* never reach */
16479485SMikore.Li@Sun.COM }
16489485SMikore.Li@Sun.COM } else {
16499485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED type 0x%x", type);
16509485SMikore.Li@Sun.COM /* never reach */
16519485SMikore.Li@Sun.COM }
16529485SMikore.Li@Sun.COM
16539485SMikore.Li@Sun.COM sc->sc_gpio_ledon = 1;
16549485SMikore.Li@Sun.COM return (0);
16559485SMikore.Li@Sun.COM }
16569485SMikore.Li@Sun.COM
16579485SMikore.Li@Sun.COM static usbd_status
urtw_led_off(struct urtw_softc * sc,int type)16589485SMikore.Li@Sun.COM urtw_led_off(struct urtw_softc *sc, int type)
16599485SMikore.Li@Sun.COM {
16609485SMikore.Li@Sun.COM if (type == URTW_LED_GPIO) {
16619485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledpin) {
16629485SMikore.Li@Sun.COM case URTW_LED_PIN_GPIO0:
166310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0x01, 0);
166410364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GP_ENABLE, 0x01, 0);
16659485SMikore.Li@Sun.COM break;
16669485SMikore.Li@Sun.COM default:
16679485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED PIN type 0x%x",
16689485SMikore.Li@Sun.COM sc->sc_gpio_ledpin);
16699485SMikore.Li@Sun.COM /* never reach */
16709485SMikore.Li@Sun.COM }
16719485SMikore.Li@Sun.COM } else {
16729485SMikore.Li@Sun.COM cmn_err(CE_WARN, "unsupported LED type 0x%x", type);
16739485SMikore.Li@Sun.COM /* never reach */
16749485SMikore.Li@Sun.COM }
16759485SMikore.Li@Sun.COM
16769485SMikore.Li@Sun.COM sc->sc_gpio_ledon = 0;
16779485SMikore.Li@Sun.COM return (0);
16789485SMikore.Li@Sun.COM }
16799485SMikore.Li@Sun.COM
16809485SMikore.Li@Sun.COM static usbd_status
urtw_led_mode0(struct urtw_softc * sc,int mode)16819485SMikore.Li@Sun.COM urtw_led_mode0(struct urtw_softc *sc, int mode)
16829485SMikore.Li@Sun.COM {
16839485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
16849485SMikore.Li@Sun.COM "urtw_led_mode0: mode = %d\n", mode));
16859485SMikore.Li@Sun.COM switch (mode) {
16869485SMikore.Li@Sun.COM case URTW_LED_CTL_POWER_ON:
16879485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK;
16889485SMikore.Li@Sun.COM break;
16899485SMikore.Li@Sun.COM case URTW_LED_CTL_TX:
16909485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress == 1)
16919485SMikore.Li@Sun.COM return (0);
16929485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL;
16939485SMikore.Li@Sun.COM sc->sc_gpio_blinktime =
16949485SMikore.Li@Sun.COM (sc->sc_ic.ic_state == IEEE80211_S_RUN ? 4:2);
16959485SMikore.Li@Sun.COM break;
16969485SMikore.Li@Sun.COM case URTW_LED_CTL_LINK:
16979485SMikore.Li@Sun.COM sc->sc_gpio_ledstate = URTW_LED_ON;
16989485SMikore.Li@Sun.COM break;
16999485SMikore.Li@Sun.COM default:
17009485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported LED mode 0x%x", mode);
17019485SMikore.Li@Sun.COM /* never reach */
17029485SMikore.Li@Sun.COM }
17039485SMikore.Li@Sun.COM
17049485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledstate) {
17059485SMikore.Li@Sun.COM case URTW_LED_ON:
17069485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress != 0)
17079485SMikore.Li@Sun.COM break;
17089485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO);
17099485SMikore.Li@Sun.COM break;
17109485SMikore.Li@Sun.COM case URTW_LED_BLINK_NORMAL:
17119485SMikore.Li@Sun.COM if (sc->sc_gpio_ledinprogress != 0)
17129485SMikore.Li@Sun.COM break;
17139485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 1;
17149485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ?
17159485SMikore.Li@Sun.COM URTW_LED_OFF : URTW_LED_ON;
17169485SMikore.Li@Sun.COM URTW_LEDLOCK(sc);
17179485SMikore.Li@Sun.COM if (sc->sc_led_ch == 0) {
17189485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
17199485SMikore.Li@Sun.COM "urtw_led_mode0: restart led timer\n"));
17209485SMikore.Li@Sun.COM sc->sc_led_ch = timeout(urtw_led_launch,
17219485SMikore.Li@Sun.COM (void *)sc,
17229485SMikore.Li@Sun.COM drv_usectohz((sc->sc_ic.ic_state ==
17239485SMikore.Li@Sun.COM IEEE80211_S_RUN) ?
17249485SMikore.Li@Sun.COM URTW_LED_LINKON_BLINK :
17259485SMikore.Li@Sun.COM URTW_LED_LINKOFF_BLINK));
17269485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0;
17279485SMikore.Li@Sun.COM }
17289485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc);
17299485SMikore.Li@Sun.COM break;
17309485SMikore.Li@Sun.COM case URTW_LED_POWER_ON_BLINK:
17319485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO);
17329485SMikore.Li@Sun.COM urtw_delay_ms(100);
17339485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO);
17349485SMikore.Li@Sun.COM break;
17359485SMikore.Li@Sun.COM default:
17369485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
17379485SMikore.Li@Sun.COM "urtw_led_mode0: unknown LED status 0x%x",
17389485SMikore.Li@Sun.COM sc->sc_gpio_ledstate));
17399485SMikore.Li@Sun.COM }
17409485SMikore.Li@Sun.COM return (0);
17419485SMikore.Li@Sun.COM }
17429485SMikore.Li@Sun.COM
17439485SMikore.Li@Sun.COM static usbd_status
urtw_led_mode1(struct urtw_softc * sc,int mode)17449485SMikore.Li@Sun.COM urtw_led_mode1(struct urtw_softc *sc, int mode)
17459485SMikore.Li@Sun.COM {
17469485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode);
17479485SMikore.Li@Sun.COM return (USBD_INVAL);
17489485SMikore.Li@Sun.COM }
17499485SMikore.Li@Sun.COM
17509485SMikore.Li@Sun.COM static usbd_status
urtw_led_mode2(struct urtw_softc * sc,int mode)17519485SMikore.Li@Sun.COM urtw_led_mode2(struct urtw_softc *sc, int mode)
17529485SMikore.Li@Sun.COM {
17539485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode);
17549485SMikore.Li@Sun.COM return (USBD_INVAL);
17559485SMikore.Li@Sun.COM }
17569485SMikore.Li@Sun.COM
17579485SMikore.Li@Sun.COM static usbd_status
urtw_led_mode3(struct urtw_softc * sc,int mode)17589485SMikore.Li@Sun.COM urtw_led_mode3(struct urtw_softc *sc, int mode)
17599485SMikore.Li@Sun.COM {
17609485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw sc %p, mode %d not supported", (void *)sc, mode);
17619485SMikore.Li@Sun.COM return (USBD_INVAL);
17629485SMikore.Li@Sun.COM }
17639485SMikore.Li@Sun.COM
17649485SMikore.Li@Sun.COM static usbd_status
urtw_led_blink(struct urtw_softc * sc)17659485SMikore.Li@Sun.COM urtw_led_blink(struct urtw_softc *sc)
17669485SMikore.Li@Sun.COM {
17679485SMikore.Li@Sun.COM uint8_t ing = 0;
17689485SMikore.Li@Sun.COM
17699485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
17709485SMikore.Li@Sun.COM "urtw_led_blink: gpio_blinkstate %d\n",
17719485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate));
17729485SMikore.Li@Sun.COM if (sc->sc_gpio_blinkstate == URTW_LED_ON)
17739485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO);
17749485SMikore.Li@Sun.COM else
17759485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO);
17769485SMikore.Li@Sun.COM sc->sc_gpio_blinktime--;
17779485SMikore.Li@Sun.COM if (sc->sc_gpio_blinktime == 0)
17789485SMikore.Li@Sun.COM ing = 1;
17799485SMikore.Li@Sun.COM else {
17809485SMikore.Li@Sun.COM if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL &&
17819485SMikore.Li@Sun.COM sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY &&
17829485SMikore.Li@Sun.COM sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3)
17839485SMikore.Li@Sun.COM ing = 1;
17849485SMikore.Li@Sun.COM }
17859485SMikore.Li@Sun.COM if (ing == 1) {
17869485SMikore.Li@Sun.COM if (sc->sc_gpio_ledstate == URTW_LED_ON &&
17879485SMikore.Li@Sun.COM sc->sc_gpio_ledon == 0)
17889485SMikore.Li@Sun.COM (void) urtw_led_on(sc, URTW_LED_GPIO);
17899485SMikore.Li@Sun.COM else if (sc->sc_gpio_ledstate == URTW_LED_OFF &&
17909485SMikore.Li@Sun.COM sc->sc_gpio_ledon == 1)
17919485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO);
17929485SMikore.Li@Sun.COM
17939485SMikore.Li@Sun.COM sc->sc_gpio_blinktime = 0;
17949485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0;
17959485SMikore.Li@Sun.COM return (0);
17969485SMikore.Li@Sun.COM }
17979485SMikore.Li@Sun.COM
17989485SMikore.Li@Sun.COM sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ?
17999485SMikore.Li@Sun.COM URTW_LED_ON : URTW_LED_OFF;
18009485SMikore.Li@Sun.COM
18019485SMikore.Li@Sun.COM switch (sc->sc_gpio_ledstate) {
18029485SMikore.Li@Sun.COM case URTW_LED_BLINK_NORMAL:
18039485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
18049485SMikore.Li@Sun.COM "URTW_LED_BLINK_NORMAL\n"));
18059485SMikore.Li@Sun.COM return (1);
18069485SMikore.Li@Sun.COM default:
18079485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
18089485SMikore.Li@Sun.COM "unknown LED status 0x%x", sc->sc_gpio_ledstate));
18099485SMikore.Li@Sun.COM }
18109485SMikore.Li@Sun.COM return (0);
18119485SMikore.Li@Sun.COM }
18129485SMikore.Li@Sun.COM
18139485SMikore.Li@Sun.COM static usbd_status
urtw_led_ctl(struct urtw_softc * sc,int mode)18149485SMikore.Li@Sun.COM urtw_led_ctl(struct urtw_softc *sc, int mode)
18159485SMikore.Li@Sun.COM {
18169485SMikore.Li@Sun.COM usbd_status error = 0;
18179485SMikore.Li@Sun.COM
18189485SMikore.Li@Sun.COM switch (sc->sc_strategy) {
18199485SMikore.Li@Sun.COM case URTW_SW_LED_MODE0:
18209485SMikore.Li@Sun.COM error = urtw_led_mode0(sc, mode);
18219485SMikore.Li@Sun.COM break;
18229485SMikore.Li@Sun.COM case URTW_SW_LED_MODE1:
18239485SMikore.Li@Sun.COM error = urtw_led_mode1(sc, mode);
18249485SMikore.Li@Sun.COM break;
18259485SMikore.Li@Sun.COM case URTW_SW_LED_MODE2:
18269485SMikore.Li@Sun.COM error = urtw_led_mode2(sc, mode);
18279485SMikore.Li@Sun.COM break;
18289485SMikore.Li@Sun.COM case URTW_SW_LED_MODE3:
18299485SMikore.Li@Sun.COM error = urtw_led_mode3(sc, mode);
18309485SMikore.Li@Sun.COM break;
18319485SMikore.Li@Sun.COM default:
18329485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported LED mode %d\n", sc->sc_strategy);
18339485SMikore.Li@Sun.COM /* never reach */
18349485SMikore.Li@Sun.COM return (-1);
18359485SMikore.Li@Sun.COM }
18369485SMikore.Li@Sun.COM
18379485SMikore.Li@Sun.COM return (error);
18389485SMikore.Li@Sun.COM }
18399485SMikore.Li@Sun.COM
18409485SMikore.Li@Sun.COM static usbd_status
urtw_update_msr(struct urtw_softc * sc,int nstate)18419485SMikore.Li@Sun.COM urtw_update_msr(struct urtw_softc *sc, int nstate)
18429485SMikore.Li@Sun.COM {
18439485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
18449485SMikore.Li@Sun.COM uint8_t data;
18459485SMikore.Li@Sun.COM usbd_status error;
18469485SMikore.Li@Sun.COM
184710364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_MSR, &data, 0))
18489485SMikore.Li@Sun.COM goto fail;
18499485SMikore.Li@Sun.COM data &= ~URTW_MSR_LINK_MASK;
18509485SMikore.Li@Sun.COM
185110364SMikore.Li@Sun.COM /* Should always be set. */
185210364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B)
185310364SMikore.Li@Sun.COM data |= URTW_MSR_LINK_ENEDCA;
185410364SMikore.Li@Sun.COM
18559485SMikore.Li@Sun.COM if (nstate == IEEE80211_S_RUN) {
18569485SMikore.Li@Sun.COM switch (ic->ic_opmode) {
18579485SMikore.Li@Sun.COM case IEEE80211_M_STA:
18589485SMikore.Li@Sun.COM case IEEE80211_M_MONITOR:
18599485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_STA;
18609485SMikore.Li@Sun.COM break;
18619485SMikore.Li@Sun.COM case IEEE80211_M_IBSS:
18629485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_ADHOC;
18639485SMikore.Li@Sun.COM break;
18649485SMikore.Li@Sun.COM case IEEE80211_M_HOSTAP:
18659485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_HOSTAP;
18669485SMikore.Li@Sun.COM break;
18679485SMikore.Li@Sun.COM default:
18689485SMikore.Li@Sun.COM cmn_err(CE_CONT, "unsupported operation mode 0x%x\n",
18699485SMikore.Li@Sun.COM ic->ic_opmode);
18709485SMikore.Li@Sun.COM return (-1);
18719485SMikore.Li@Sun.COM }
18729485SMikore.Li@Sun.COM } else
18739485SMikore.Li@Sun.COM data |= URTW_MSR_LINK_NONE;
18749485SMikore.Li@Sun.COM
187510364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_MSR, data, 0);
18769485SMikore.Li@Sun.COM fail:
18779485SMikore.Li@Sun.COM return (error);
18789485SMikore.Li@Sun.COM }
18799485SMikore.Li@Sun.COM
18809485SMikore.Li@Sun.COM static uint16_t
urtw_rate2rtl(int rate)18819485SMikore.Li@Sun.COM urtw_rate2rtl(int rate)
18829485SMikore.Li@Sun.COM {
18839485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0]))
18849485SMikore.Li@Sun.COM int i;
18859485SMikore.Li@Sun.COM
18869485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_ratetable); i++) {
18879485SMikore.Li@Sun.COM if (rate == urtw_ratetable[i].reg)
18889485SMikore.Li@Sun.COM return (urtw_ratetable[i].val);
18899485SMikore.Li@Sun.COM }
18909485SMikore.Li@Sun.COM return (3);
18919485SMikore.Li@Sun.COM #undef N
18929485SMikore.Li@Sun.COM }
18939485SMikore.Li@Sun.COM
18949485SMikore.Li@Sun.COM static uint16_t
urtw_rtl2rate(int rate)18959485SMikore.Li@Sun.COM urtw_rtl2rate(int rate)
18969485SMikore.Li@Sun.COM {
18979485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0]))
18989485SMikore.Li@Sun.COM int i;
18999485SMikore.Li@Sun.COM
19009485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_ratetable); i++) {
19019485SMikore.Li@Sun.COM if (rate == urtw_ratetable[i].val)
19029485SMikore.Li@Sun.COM return (urtw_ratetable[i].reg);
19039485SMikore.Li@Sun.COM }
19049485SMikore.Li@Sun.COM
19059485SMikore.Li@Sun.COM return (0);
19069485SMikore.Li@Sun.COM #undef N
19079485SMikore.Li@Sun.COM }
19089485SMikore.Li@Sun.COM
19099485SMikore.Li@Sun.COM static usbd_status
urtw_set_rate(struct urtw_softc * sc)19109485SMikore.Li@Sun.COM urtw_set_rate(struct urtw_softc *sc)
19119485SMikore.Li@Sun.COM {
19129485SMikore.Li@Sun.COM int i, basic_rate, min_rr_rate, max_rr_rate;
19139485SMikore.Li@Sun.COM uint16_t data;
19149485SMikore.Li@Sun.COM usbd_status error;
19159485SMikore.Li@Sun.COM
19169485SMikore.Li@Sun.COM basic_rate = urtw_rate2rtl(48);
19179485SMikore.Li@Sun.COM min_rr_rate = urtw_rate2rtl(12);
19189485SMikore.Li@Sun.COM max_rr_rate = urtw_rate2rtl(48);
19199485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RESP_RATE,
19209485SMikore.Li@Sun.COM max_rr_rate << URTW_RESP_MAX_RATE_SHIFT |
192110364SMikore.Li@Sun.COM min_rr_rate << URTW_RESP_MIN_RATE_SHIFT, 0))
19229485SMikore.Li@Sun.COM goto fail;
19239485SMikore.Li@Sun.COM
192410364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0))
19259485SMikore.Li@Sun.COM goto fail;
19269485SMikore.Li@Sun.COM data &= ~URTW_BRSR_MBR_8185;
19279485SMikore.Li@Sun.COM
19289485SMikore.Li@Sun.COM for (i = 0; i <= basic_rate; i++)
19299485SMikore.Li@Sun.COM data |= (1 << i);
19309485SMikore.Li@Sun.COM
193110364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_BRSR, data, 0);
19329485SMikore.Li@Sun.COM fail:
19339485SMikore.Li@Sun.COM return (error);
19349485SMikore.Li@Sun.COM }
19359485SMikore.Li@Sun.COM
19369485SMikore.Li@Sun.COM static usbd_status
urtw_intr_enable(struct urtw_softc * sc)19379485SMikore.Li@Sun.COM urtw_intr_enable(struct urtw_softc *sc)
19389485SMikore.Li@Sun.COM {
19399485SMikore.Li@Sun.COM usbd_status error;
19409485SMikore.Li@Sun.COM
194110364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_INTR_MASK, 0xffff, 0);
19429485SMikore.Li@Sun.COM return (error);
19439485SMikore.Li@Sun.COM }
19449485SMikore.Li@Sun.COM
19459485SMikore.Li@Sun.COM static usbd_status
urtw_rx_setconf(struct urtw_softc * sc)19469485SMikore.Li@Sun.COM urtw_rx_setconf(struct urtw_softc *sc)
19479485SMikore.Li@Sun.COM {
19489485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
19499485SMikore.Li@Sun.COM uint32_t data, a, b;
19509485SMikore.Li@Sun.COM usbd_status error;
19519485SMikore.Li@Sun.COM
195210364SMikore.Li@Sun.COM if (urtw_read32_c(sc, URTW_RX, &data, 0))
19539485SMikore.Li@Sun.COM goto fail;
19549485SMikore.Li@Sun.COM data = data &~ URTW_RX_FILTER_MASK;
19559485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA;
19569485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST;
19579485SMikore.Li@Sun.COM
19589485SMikore.Li@Sun.COM if (ic->ic_opmode == IEEE80211_M_MONITOR) {
19599485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_ICVERR;
19609485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_PWR;
19619485SMikore.Li@Sun.COM }
19629485SMikore.Li@Sun.COM if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR)
19639485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_CRCERR;
19649485SMikore.Li@Sun.COM data = data | URTW_RX_FILTER_NICMAC;
19659485SMikore.Li@Sun.COM data = data | URTW_RX_CHECK_BSSID;
19669485SMikore.Li@Sun.COM data = data &~ URTW_RX_FIFO_THRESHOLD_MASK;
19679485SMikore.Li@Sun.COM data = data | URTW_RX_FIFO_THRESHOLD_NONE | URTW_RX_AUTORESETPHY;
19689485SMikore.Li@Sun.COM data = data &~ URTW_MAX_RX_DMA_MASK;
19699485SMikore.Li@Sun.COM a = URTW_MAX_RX_DMA_2048;
19709485SMikore.Li@Sun.COM b = 0x80000000;
19719485SMikore.Li@Sun.COM data = data | a | b;
19729485SMikore.Li@Sun.COM
197310364SMikore.Li@Sun.COM error = urtw_write32_c(sc, URTW_RX, data, 0);
19749485SMikore.Li@Sun.COM fail:
19759485SMikore.Li@Sun.COM return (error);
19769485SMikore.Li@Sun.COM }
19779485SMikore.Li@Sun.COM
19789485SMikore.Li@Sun.COM static usbd_status
urtw_rx_enable(struct urtw_softc * sc)19799485SMikore.Li@Sun.COM urtw_rx_enable(struct urtw_softc *sc)
19809485SMikore.Li@Sun.COM {
19819485SMikore.Li@Sun.COM int i;
19829485SMikore.Li@Sun.COM usbd_status error;
19839485SMikore.Li@Sun.COM uint8_t data;
19849485SMikore.Li@Sun.COM
19859485SMikore.Li@Sun.COM sc->rx_queued = 0;
19869485SMikore.Li@Sun.COM for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++) {
19879485SMikore.Li@Sun.COM if (urtw_rx_start(sc) != 0) {
19889485SMikore.Li@Sun.COM return (USB_FAILURE);
19899485SMikore.Li@Sun.COM }
19909485SMikore.Li@Sun.COM }
19919485SMikore.Li@Sun.COM
19929485SMikore.Li@Sun.COM error = urtw_rx_setconf(sc);
19939485SMikore.Li@Sun.COM if (error != 0)
19949485SMikore.Li@Sun.COM goto fail;
19959485SMikore.Li@Sun.COM
199610364SMikore.Li@Sun.COM if (error = urtw_read8_c(sc, URTW_CMD, &data, 0))
19979485SMikore.Li@Sun.COM goto fail;
199810364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE, 0);
19999485SMikore.Li@Sun.COM fail:
20009485SMikore.Li@Sun.COM return (error);
20019485SMikore.Li@Sun.COM }
20029485SMikore.Li@Sun.COM
200310364SMikore.Li@Sun.COM void
urtw_tx_enable(struct urtw_softc * sc)20049485SMikore.Li@Sun.COM urtw_tx_enable(struct urtw_softc *sc)
20059485SMikore.Li@Sun.COM {
20069485SMikore.Li@Sun.COM uint8_t data8;
20079485SMikore.Li@Sun.COM uint32_t data;
200810364SMikore.Li@Sun.COM
200910364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
201010364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CW_CONF, &data8, 0);
201110364SMikore.Li@Sun.COM data8 &= ~(URTW_CW_CONF_PERPACKET_CW |
201210364SMikore.Li@Sun.COM URTW_CW_CONF_PERPACKET_RETRY);
201310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CW_CONF, data8, 0);
201410364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_TX_AGC_CTL, &data8, 0);
201510364SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN;
201610364SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL;
201710364SMikore.Li@Sun.COM data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT;
201810364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_AGC_CTL, data8, 0);
201910364SMikore.Li@Sun.COM
202010364SMikore.Li@Sun.COM (void) urtw_read32_c(sc, URTW_TX_CONF, &data, 0);
202110364SMikore.Li@Sun.COM data &= ~URTW_TX_LOOPBACK_MASK;
202210364SMikore.Li@Sun.COM data |= URTW_TX_LOOPBACK_NONE;
202310364SMikore.Li@Sun.COM data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK);
202410364SMikore.Li@Sun.COM data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT;
202510364SMikore.Li@Sun.COM data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT;
202610364SMikore.Li@Sun.COM data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK);
202710364SMikore.Li@Sun.COM data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW;
202810364SMikore.Li@Sun.COM data &= ~URTW_TX_SWPLCPLEN;
202910364SMikore.Li@Sun.COM data |= URTW_TX_NOICV;
203010364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_TX_CONF, data, 0);
203110364SMikore.Li@Sun.COM } else {
203210364SMikore.Li@Sun.COM data = URTW_TX_DURPROCMODE | URTW_TX_DISREQQSIZE |
203310364SMikore.Li@Sun.COM URTW_TX_MXDMA_2048 | URTW_TX_SHORTRETRY |
203410364SMikore.Li@Sun.COM URTW_TX_LONGRETRY;
203510364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_TX_CONF, data, 0);
203610364SMikore.Li@Sun.COM }
203710364SMikore.Li@Sun.COM
203810364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CMD, &data8, 0);
203910364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE, 0);
20409485SMikore.Li@Sun.COM }
20419485SMikore.Li@Sun.COM
20429485SMikore.Li@Sun.COM static int
urtw_8187_init(void * arg)204310364SMikore.Li@Sun.COM urtw_8187_init(void *arg)
20449485SMikore.Li@Sun.COM {
20459485SMikore.Li@Sun.COM struct urtw_softc *sc = arg;
20469485SMikore.Li@Sun.COM usbd_status error;
204710364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf;
204810364SMikore.Li@Sun.COM int i;
20499485SMikore.Li@Sun.COM
20509485SMikore.Li@Sun.COM urtw_stop(sc);
20519485SMikore.Li@Sun.COM URTW_LOCK(sc);
205210364SMikore.Li@Sun.COM error = urtw_8187_reset(sc);
205310364SMikore.Li@Sun.COM if (error)
205410364SMikore.Li@Sun.COM goto fail;
205510364SMikore.Li@Sun.COM
205610364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x85, 0, 0);
205710364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_GPIO, 0, 0);
205810364SMikore.Li@Sun.COM
205910364SMikore.Li@Sun.COM /* for led */
206010364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x85, 4, 0);
206110364SMikore.Li@Sun.COM error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON);
20629485SMikore.Li@Sun.COM if (error != 0)
20639485SMikore.Li@Sun.COM goto fail;
206410364SMikore.Li@Sun.COM
206510364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
206610364SMikore.Li@Sun.COM if (error)
206710364SMikore.Li@Sun.COM goto fail;
206810364SMikore.Li@Sun.COM
206910364SMikore.Li@Sun.COM /* applying MAC address again. */
207010364SMikore.Li@Sun.COM for (i = 0; i < IEEE80211_ADDR_LEN; i++)
207110364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_MAC0 + i,
207210364SMikore.Li@Sun.COM sc->sc_ic.ic_macaddr[i], 0);
207310364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
207410364SMikore.Li@Sun.COM if (error)
207510364SMikore.Li@Sun.COM goto fail;
207610364SMikore.Li@Sun.COM
207710364SMikore.Li@Sun.COM error = urtw_update_msr(sc, IEEE80211_S_INIT);
207810364SMikore.Li@Sun.COM if (error)
207910364SMikore.Li@Sun.COM goto fail;
208010364SMikore.Li@Sun.COM
208110364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_INT_TIMEOUT, 0, 0);
208210364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_WPA_CONFIG, 0, 0);
208310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_RATE_FALLBACK, 0x81, 0);
208410364SMikore.Li@Sun.COM error = urtw_set_rate(sc);
208510364SMikore.Li@Sun.COM if (error != 0)
208610364SMikore.Li@Sun.COM goto fail;
208710364SMikore.Li@Sun.COM
208810364SMikore.Li@Sun.COM error = rf->init(rf);
208910364SMikore.Li@Sun.COM if (error != 0)
209010364SMikore.Li@Sun.COM goto fail;
209110364SMikore.Li@Sun.COM if (rf->set_sens != NULL)
209210364SMikore.Li@Sun.COM rf->set_sens(rf);
209310364SMikore.Li@Sun.COM
209410364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x5e, 1, 0);
209510364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0xfe, 0x10, 0);
209610364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TALLY_SEL, 0x80, 0);
209710364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xff, 0x60, 0);
209810364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x5e, 0, 0);
209910364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x85, 4, 0);
210010364SMikore.Li@Sun.COM
210110364SMikore.Li@Sun.COM error = urtw_intr_enable(sc);
210210364SMikore.Li@Sun.COM if (error != 0)
210310364SMikore.Li@Sun.COM goto fail;
210410364SMikore.Li@Sun.COM
210510364SMikore.Li@Sun.COM error = urtw_open_pipes(sc);
21069485SMikore.Li@Sun.COM if (error != 0)
21079485SMikore.Li@Sun.COM goto fail;
21089485SMikore.Li@Sun.COM sc->sc_tx_low_queued = 0;
21099485SMikore.Li@Sun.COM sc->sc_tx_normal_queued = 0;
21109485SMikore.Li@Sun.COM error = urtw_rx_enable(sc);
21119485SMikore.Li@Sun.COM if (error != 0)
21129485SMikore.Li@Sun.COM goto fail;
211310364SMikore.Li@Sun.COM urtw_tx_enable(sc);
21149485SMikore.Li@Sun.COM
21159485SMikore.Li@Sun.COM if (error == 0) {
21169485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev,
211710364SMikore.Li@Sun.COM CE_CONT, "urtw_8187_init: succesfully done\n"));
21189485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_RUNNING;
21199485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
21209485SMikore.Li@Sun.COM return (error);
21219485SMikore.Li@Sun.COM }
21229485SMikore.Li@Sun.COM
21239485SMikore.Li@Sun.COM fail:
21249485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
21259485SMikore.Li@Sun.COM urtw_stop(sc);
212610364SMikore.Li@Sun.COM return (EIO);
21279485SMikore.Li@Sun.COM }
21289485SMikore.Li@Sun.COM
21299485SMikore.Li@Sun.COM
21309485SMikore.Li@Sun.COM static usbd_status
urtw_8225_usb_init(struct urtw_softc * sc)21319485SMikore.Li@Sun.COM urtw_8225_usb_init(struct urtw_softc *sc)
21329485SMikore.Li@Sun.COM {
21339485SMikore.Li@Sun.COM uint8_t data;
21349485SMikore.Li@Sun.COM usbd_status error;
21359485SMikore.Li@Sun.COM
213610364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 0, 0))
21379485SMikore.Li@Sun.COM goto fail;
213810364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0, 0))
21399485SMikore.Li@Sun.COM goto fail;
21409485SMikore.Li@Sun.COM if (error = urtw_read8e(sc, 0x53, &data))
21419485SMikore.Li@Sun.COM goto fail;
21429485SMikore.Li@Sun.COM if (error = urtw_write8e(sc, 0x53, data | (1 << 7)))
21439485SMikore.Li@Sun.COM goto fail;
214410364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_RF_PINS_SELECT + 1, 4, 0))
21459485SMikore.Li@Sun.COM goto fail;
214610364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GPIO, 0x20, 0))
21479485SMikore.Li@Sun.COM goto fail;
214810364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_GP_ENABLE, 0, 0))
21499485SMikore.Li@Sun.COM goto fail;
215010364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x80, 0))
21519485SMikore.Li@Sun.COM goto fail;
215210364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x80, 0))
21539485SMikore.Li@Sun.COM goto fail;
215410364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x80, 0);
21559485SMikore.Li@Sun.COM
21569485SMikore.Li@Sun.COM urtw_delay_ms(100);
21579485SMikore.Li@Sun.COM fail:
21589485SMikore.Li@Sun.COM return (error);
21599485SMikore.Li@Sun.COM }
21609485SMikore.Li@Sun.COM
21619485SMikore.Li@Sun.COM static usbd_status
urtw_8185_rf_pins_enable(struct urtw_softc * sc)21629485SMikore.Li@Sun.COM urtw_8185_rf_pins_enable(struct urtw_softc *sc)
21639485SMikore.Li@Sun.COM {
21649485SMikore.Li@Sun.COM usbd_status error = 0;
21659485SMikore.Li@Sun.COM
216610364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1ff7, 0);
21679485SMikore.Li@Sun.COM return (error);
21689485SMikore.Li@Sun.COM }
21699485SMikore.Li@Sun.COM
21709485SMikore.Li@Sun.COM static usbd_status
urtw_8187_write_phy(struct urtw_softc * sc,uint8_t addr,uint32_t data)21719485SMikore.Li@Sun.COM urtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data)
21729485SMikore.Li@Sun.COM {
21739485SMikore.Li@Sun.COM uint32_t phyw;
21749485SMikore.Li@Sun.COM usbd_status error;
21759485SMikore.Li@Sun.COM
21769485SMikore.Li@Sun.COM phyw = ((data << 8) | (addr | 0x80));
217710364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7f, ((phyw & 0xff000000) >> 24), 0))
21789485SMikore.Li@Sun.COM goto fail;
217910364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7e, ((phyw & 0x00ff0000) >> 16), 0))
218010364SMikore.Li@Sun.COM goto fail;
218110364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x7d, ((phyw & 0x0000ff00) >> 8), 0))
21829485SMikore.Li@Sun.COM goto fail;
218310364SMikore.Li@Sun.COM error = urtw_write8_c(sc, 0x7c, (phyw & 0x000000ff), 0);
218410364SMikore.Li@Sun.COM /*
218510364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187.
218610364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 1);
218710364SMikore.Li@Sun.COM */
21889485SMikore.Li@Sun.COM fail:
21899485SMikore.Li@Sun.COM return (error);
21909485SMikore.Li@Sun.COM }
21919485SMikore.Li@Sun.COM
21929485SMikore.Li@Sun.COM static usbd_status
urtw_8187_write_phy_ofdm_c(struct urtw_softc * sc,uint8_t addr,uint32_t data)21939485SMikore.Li@Sun.COM urtw_8187_write_phy_ofdm_c(struct urtw_softc *sc, uint8_t addr, uint32_t data)
21949485SMikore.Li@Sun.COM {
21959485SMikore.Li@Sun.COM data = data & 0xff;
21969485SMikore.Li@Sun.COM return (urtw_8187_write_phy(sc, addr, data));
21979485SMikore.Li@Sun.COM }
21989485SMikore.Li@Sun.COM
21999485SMikore.Li@Sun.COM static usbd_status
urtw_8187_write_phy_cck_c(struct urtw_softc * sc,uint8_t addr,uint32_t data)22009485SMikore.Li@Sun.COM urtw_8187_write_phy_cck_c(struct urtw_softc *sc, uint8_t addr, uint32_t data)
22019485SMikore.Li@Sun.COM {
22029485SMikore.Li@Sun.COM data = data & 0xff;
22039485SMikore.Li@Sun.COM return (urtw_8187_write_phy(sc, addr, (data | 0x10000)));
22049485SMikore.Li@Sun.COM }
22059485SMikore.Li@Sun.COM
22069485SMikore.Li@Sun.COM static usbd_status
urtw_8225_setgain(struct urtw_softc * sc,int16_t gain)22079485SMikore.Li@Sun.COM urtw_8225_setgain(struct urtw_softc *sc, int16_t gain)
22089485SMikore.Li@Sun.COM {
22099485SMikore.Li@Sun.COM usbd_status error;
22109485SMikore.Li@Sun.COM
22119485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x0d,
22129485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4]))
22139485SMikore.Li@Sun.COM goto fail;
22149485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1b,
22159485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 2]))
22169485SMikore.Li@Sun.COM goto fail;
22179485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1d,
22189485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 3]))
22199485SMikore.Li@Sun.COM goto fail;
22209485SMikore.Li@Sun.COM error = urtw_8187_write_phy_ofdm_c(sc, 0x23,
22219485SMikore.Li@Sun.COM urtw_8225_gain[gain * 4 + 1]);
22229485SMikore.Li@Sun.COM fail:
22239485SMikore.Li@Sun.COM return (error);
22249485SMikore.Li@Sun.COM }
22259485SMikore.Li@Sun.COM
22269485SMikore.Li@Sun.COM static usbd_status
urtw_8225_set_txpwrlvl(struct urtw_softc * sc,int chan)22279485SMikore.Li@Sun.COM urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan)
22289485SMikore.Li@Sun.COM {
22299485SMikore.Li@Sun.COM int i, idx, set;
22309485SMikore.Li@Sun.COM uint8_t *cck_pwltable;
22319485SMikore.Li@Sun.COM uint8_t cck_pwrlvl_max, ofdm_pwrlvl_min, ofdm_pwrlvl_max;
22329485SMikore.Li@Sun.COM uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
22339485SMikore.Li@Sun.COM uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
22349485SMikore.Li@Sun.COM usbd_status error;
22359485SMikore.Li@Sun.COM
22369485SMikore.Li@Sun.COM cck_pwrlvl_max = 11;
22379485SMikore.Li@Sun.COM ofdm_pwrlvl_max = 25; /* 12 -> 25 */
22389485SMikore.Li@Sun.COM ofdm_pwrlvl_min = 10;
22399485SMikore.Li@Sun.COM
22409485SMikore.Li@Sun.COM /* CCK power setting */
22419485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ?
22429485SMikore.Li@Sun.COM cck_pwrlvl_max : cck_pwrlvl;
22439485SMikore.Li@Sun.COM idx = cck_pwrlvl % 6;
22449485SMikore.Li@Sun.COM set = cck_pwrlvl / 6;
22459485SMikore.Li@Sun.COM cck_pwltable = (chan == 14) ? urtw_8225_txpwr_cck_ch14 :
22469485SMikore.Li@Sun.COM urtw_8225_txpwr_cck;
22479485SMikore.Li@Sun.COM
22489485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK,
224910364SMikore.Li@Sun.COM urtw_8225_tx_gain_cck_ofdm[set] >> 1, 0))
22509485SMikore.Li@Sun.COM goto fail;
22519485SMikore.Li@Sun.COM for (i = 0; i < 8; i++) {
22529485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i,
22539485SMikore.Li@Sun.COM cck_pwltable[idx * 8 + i]))
22549485SMikore.Li@Sun.COM goto fail;
22559485SMikore.Li@Sun.COM }
22569485SMikore.Li@Sun.COM urtw_delay_ms(1);
22579485SMikore.Li@Sun.COM /* OFDM power setting */
22589485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
22599485SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
22609485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
22619485SMikore.Li@Sun.COM idx = ofdm_pwrlvl % 6;
22629485SMikore.Li@Sun.COM set = ofdm_pwrlvl / 6;
22639485SMikore.Li@Sun.COM
226410364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
22659485SMikore.Li@Sun.COM if (error)
22669485SMikore.Li@Sun.COM goto fail;
22679485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42))
22689485SMikore.Li@Sun.COM goto fail;
22699485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 6, 0))
22709485SMikore.Li@Sun.COM goto fail;
22719485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 8, 0))
22729485SMikore.Li@Sun.COM goto fail;
22739485SMikore.Li@Sun.COM
22749485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM,
227510364SMikore.Li@Sun.COM urtw_8225_tx_gain_cck_ofdm[set] >> 1, 0))
22769485SMikore.Li@Sun.COM goto fail;
22779485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x5,
22789485SMikore.Li@Sun.COM urtw_8225_txpwr_ofdm[idx]))
22799485SMikore.Li@Sun.COM goto fail;
22809485SMikore.Li@Sun.COM error = urtw_8187_write_phy_ofdm_c(sc, 0x7,
22819485SMikore.Li@Sun.COM urtw_8225_txpwr_ofdm[idx]);
22829485SMikore.Li@Sun.COM urtw_delay_ms(1);
22839485SMikore.Li@Sun.COM fail:
22849485SMikore.Li@Sun.COM return (error);
22859485SMikore.Li@Sun.COM }
22869485SMikore.Li@Sun.COM
22879485SMikore.Li@Sun.COM static usbd_status
urtw_8185_tx_antenna(struct urtw_softc * sc,uint8_t ant)22889485SMikore.Li@Sun.COM urtw_8185_tx_antenna(struct urtw_softc *sc, uint8_t ant)
22899485SMikore.Li@Sun.COM {
22909485SMikore.Li@Sun.COM usbd_status error;
22919485SMikore.Li@Sun.COM
229210364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_TX_ANTENNA, ant, 0);
22939485SMikore.Li@Sun.COM urtw_delay_ms(1);
22949485SMikore.Li@Sun.COM return (error);
22959485SMikore.Li@Sun.COM }
22969485SMikore.Li@Sun.COM
22979485SMikore.Li@Sun.COM static usbd_status
urtw_8225_rf_init(struct urtw_rf * rf)229810364SMikore.Li@Sun.COM urtw_8225_rf_init(struct urtw_rf *rf)
22999485SMikore.Li@Sun.COM {
23009485SMikore.Li@Sun.COM #define N(a) (sizeof (a) / sizeof ((a)[0]))
23019485SMikore.Li@Sun.COM int i;
23029485SMikore.Li@Sun.COM uint16_t data;
23039485SMikore.Li@Sun.COM usbd_status error;
230410364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
230510364SMikore.Li@Sun.COM
230610364SMikore.Li@Sun.COM error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON);
23079485SMikore.Li@Sun.COM if (error)
23089485SMikore.Li@Sun.COM goto fail;
23099485SMikore.Li@Sun.COM
23109485SMikore.Li@Sun.COM if (error = urtw_8225_usb_init(sc))
23119485SMikore.Li@Sun.COM goto fail;
231210364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008, 0))
23139485SMikore.Li@Sun.COM goto fail;
231410364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0))
23159485SMikore.Li@Sun.COM goto fail;
231610364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff, 0))
23179485SMikore.Li@Sun.COM goto fail;
231810364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044, 0))
23199485SMikore.Li@Sun.COM goto fail;
23209485SMikore.Li@Sun.COM
23219485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG))
23229485SMikore.Li@Sun.COM goto fail;
232310364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44, 0))
23249485SMikore.Li@Sun.COM goto fail;
23259485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL))
23269485SMikore.Li@Sun.COM goto fail;
23279485SMikore.Li@Sun.COM if (error = urtw_8185_rf_pins_enable(sc))
23289485SMikore.Li@Sun.COM goto fail;
23299485SMikore.Li@Sun.COM urtw_delay_ms(100);
23309485SMikore.Li@Sun.COM
23319485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part1); i++) {
23329485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, urtw_8225_rf_part1[i].reg,
23339485SMikore.Li@Sun.COM urtw_8225_rf_part1[i].val))
23349485SMikore.Li@Sun.COM goto fail;
23359485SMikore.Li@Sun.COM urtw_delay_ms(1);
23369485SMikore.Li@Sun.COM }
23379485SMikore.Li@Sun.COM urtw_delay_ms(50);
23389485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0xc4d))
23399485SMikore.Li@Sun.COM goto fail;
23409485SMikore.Li@Sun.COM urtw_delay_ms(50);
23419485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0x44d))
23429485SMikore.Li@Sun.COM goto fail;
23439485SMikore.Li@Sun.COM urtw_delay_ms(50);
23449485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x127))
23459485SMikore.Li@Sun.COM goto fail;
23469485SMikore.Li@Sun.COM
23479485SMikore.Li@Sun.COM for (i = 0; i < 95; i++) {
23489485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1)))
23499485SMikore.Li@Sun.COM goto fail;
23509485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, urtw_8225_rxgain[i]))
23519485SMikore.Li@Sun.COM goto fail;
23529485SMikore.Li@Sun.COM }
23539485SMikore.Li@Sun.COM
23549485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x27))
23559485SMikore.Li@Sun.COM goto fail;
23569485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x22f))
23579485SMikore.Li@Sun.COM goto fail;
23589485SMikore.Li@Sun.COM
23599485SMikore.Li@Sun.COM for (i = 0; i < 128; i++) {
23609485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xb,
23619485SMikore.Li@Sun.COM urtw_8225_agc[i]))
23629485SMikore.Li@Sun.COM goto fail;
23639485SMikore.Li@Sun.COM urtw_delay_ms(1);
23649485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xa,
23659485SMikore.Li@Sun.COM (uint8_t)i + 0x80))
23669485SMikore.Li@Sun.COM goto fail;
23679485SMikore.Li@Sun.COM urtw_delay_ms(1);
23689485SMikore.Li@Sun.COM }
23699485SMikore.Li@Sun.COM
23709485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part2); i++) {
23719485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc,
23729485SMikore.Li@Sun.COM urtw_8225_rf_part2[i].reg,
23739485SMikore.Li@Sun.COM urtw_8225_rf_part2[i].val))
23749485SMikore.Li@Sun.COM goto fail;
23759485SMikore.Li@Sun.COM urtw_delay_ms(1);
23769485SMikore.Li@Sun.COM }
23779485SMikore.Li@Sun.COM error = urtw_8225_setgain(sc, 4);
23789485SMikore.Li@Sun.COM if (error)
23799485SMikore.Li@Sun.COM goto fail;
23809485SMikore.Li@Sun.COM
23819485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225_rf_part3); i++) {
23829485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc,
23839485SMikore.Li@Sun.COM urtw_8225_rf_part3[i].reg,
23849485SMikore.Li@Sun.COM urtw_8225_rf_part3[i].val))
23859485SMikore.Li@Sun.COM goto fail;
23869485SMikore.Li@Sun.COM urtw_delay_ms(1);
23879485SMikore.Li@Sun.COM }
23889485SMikore.Li@Sun.COM
238910364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x5b, 0x0d, 0))
23909485SMikore.Li@Sun.COM goto fail;
23919485SMikore.Li@Sun.COM if (error = urtw_8225_set_txpwrlvl(sc, 1))
23929485SMikore.Li@Sun.COM goto fail;
23939485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x10, 0x9b))
23949485SMikore.Li@Sun.COM goto fail;
23959485SMikore.Li@Sun.COM urtw_delay_ms(1);
23969485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x26, 0x90))
23979485SMikore.Li@Sun.COM goto fail;
23989485SMikore.Li@Sun.COM urtw_delay_ms(1);
23999485SMikore.Li@Sun.COM
24009485SMikore.Li@Sun.COM /* TX ant A, 0x0 for B */
24019485SMikore.Li@Sun.COM if (error = urtw_8185_tx_antenna(sc, 0x3))
24029485SMikore.Li@Sun.COM goto fail;
240310364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, 0x94, 0x3dc00002, 0))
24049485SMikore.Li@Sun.COM goto fail;
24059485SMikore.Li@Sun.COM
240610364SMikore.Li@Sun.COM error = urtw_8225_rf_set_chan(rf,
240710364SMikore.Li@Sun.COM ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan));
24089485SMikore.Li@Sun.COM fail:
24099485SMikore.Li@Sun.COM return (error);
24109485SMikore.Li@Sun.COM #undef N
24119485SMikore.Li@Sun.COM }
24129485SMikore.Li@Sun.COM
24139485SMikore.Li@Sun.COM static usbd_status
urtw_8225_rf_set_chan(struct urtw_rf * rf,int chan)241410364SMikore.Li@Sun.COM urtw_8225_rf_set_chan(struct urtw_rf *rf, int chan)
24159485SMikore.Li@Sun.COM {
24169485SMikore.Li@Sun.COM #define IEEE80211_CHAN_G \
24179485SMikore.Li@Sun.COM (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
24189485SMikore.Li@Sun.COM #define IEEE80211_IS_CHAN_G(_c) \
24199485SMikore.Li@Sun.COM (((_c)->ich_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
24209485SMikore.Li@Sun.COM
242110364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
24229485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
24239485SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan;
24249485SMikore.Li@Sun.COM short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0;
24259485SMikore.Li@Sun.COM usbd_status error;
24269485SMikore.Li@Sun.COM
24279485SMikore.Li@Sun.COM if (error = urtw_8225_set_txpwrlvl(sc, chan))
24289485SMikore.Li@Sun.COM goto fail;
24299485SMikore.Li@Sun.COM if (urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan]))
24309485SMikore.Li@Sun.COM goto fail;
24319485SMikore.Li@Sun.COM urtw_delay_ms(10);
24329485SMikore.Li@Sun.COM
243310364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SIFS, 0x22, 0))
24349485SMikore.Li@Sun.COM goto fail;
24359485SMikore.Li@Sun.COM
24369485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_ASSOC &&
24379485SMikore.Li@Sun.COM ic->ic_flags & IEEE80211_F_SHSLOT)
243810364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x9, 0))
24399485SMikore.Li@Sun.COM goto fail;
24409485SMikore.Li@Sun.COM else
244110364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x14, 0))
24429485SMikore.Li@Sun.COM goto fail;
24439485SMikore.Li@Sun.COM if (gset) {
24449485SMikore.Li@Sun.COM /* for G */
244510364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x14, 0))
24469485SMikore.Li@Sun.COM goto fail;
244710364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14, 0))
24489485SMikore.Li@Sun.COM goto fail;
244910364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CW_VAL, 0x73, 0);
24509485SMikore.Li@Sun.COM } else {
24519485SMikore.Li@Sun.COM /* for B */
245210364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x24, 0))
24539485SMikore.Li@Sun.COM goto fail;
245410364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24, 0))
24559485SMikore.Li@Sun.COM goto fail;
245610364SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5, 0);
24579485SMikore.Li@Sun.COM }
24589485SMikore.Li@Sun.COM
24599485SMikore.Li@Sun.COM fail:
24609485SMikore.Li@Sun.COM return (error);
24619485SMikore.Li@Sun.COM }
24629485SMikore.Li@Sun.COM
24639485SMikore.Li@Sun.COM static usbd_status
urtw_8225_rf_set_sens(struct urtw_rf * rf)246410364SMikore.Li@Sun.COM urtw_8225_rf_set_sens(struct urtw_rf *rf)
24659485SMikore.Li@Sun.COM {
24669485SMikore.Li@Sun.COM usbd_status error;
246710364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
246810364SMikore.Li@Sun.COM
246910364SMikore.Li@Sun.COM if (rf->sens < 0 || rf->sens > 6)
24709485SMikore.Li@Sun.COM return (-1);
24719485SMikore.Li@Sun.COM
247210364SMikore.Li@Sun.COM if (rf->sens > 4)
24739485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0c, 0x850))
24749485SMikore.Li@Sun.COM goto fail;
24759485SMikore.Li@Sun.COM else
24769485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0c, 0x50))
24779485SMikore.Li@Sun.COM goto fail;
24789485SMikore.Li@Sun.COM
247910364SMikore.Li@Sun.COM rf->sens = 6 - rf->sens;
248010364SMikore.Li@Sun.COM if (error = urtw_8225_setgain(sc, rf->sens))
24819485SMikore.Li@Sun.COM goto fail;
248210364SMikore.Li@Sun.COM error = urtw_8187_write_phy_cck_c(sc, 0x41,
248310364SMikore.Li@Sun.COM urtw_8225_threshold[rf->sens]);
24849485SMikore.Li@Sun.COM fail:
24859485SMikore.Li@Sun.COM return (error);
24869485SMikore.Li@Sun.COM }
24879485SMikore.Li@Sun.COM
24889485SMikore.Li@Sun.COM static void
urtw_stop(struct urtw_softc * sc)24899485SMikore.Li@Sun.COM urtw_stop(struct urtw_softc *sc)
24909485SMikore.Li@Sun.COM {
24919485SMikore.Li@Sun.COM URTW_LOCK(sc);
24929485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_RUNNING;
24939485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
24949485SMikore.Li@Sun.COM urtw_close_pipes(sc);
24959485SMikore.Li@Sun.COM }
24969485SMikore.Li@Sun.COM
24979485SMikore.Li@Sun.COM static int
urtw_isbmode(uint16_t rate)24989485SMikore.Li@Sun.COM urtw_isbmode(uint16_t rate)
24999485SMikore.Li@Sun.COM {
25009485SMikore.Li@Sun.COM
25019485SMikore.Li@Sun.COM rate = urtw_rtl2rate(rate);
25029485SMikore.Li@Sun.COM
25039485SMikore.Li@Sun.COM return ((rate <= 22 && rate != 12 && rate != 18)?(1) : (0));
25049485SMikore.Li@Sun.COM }
25059485SMikore.Li@Sun.COM
25069485SMikore.Li@Sun.COM /* ARGSUSED */
25079485SMikore.Li@Sun.COM static void
urtw_rxeof(usb_pipe_handle_t pipe,usb_bulk_req_t * req)25089485SMikore.Li@Sun.COM urtw_rxeof(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
25099485SMikore.Li@Sun.COM {
25109485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private;
25119485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
25129485SMikore.Li@Sun.COM int actlen, len, flen, rssi;
25139485SMikore.Li@Sun.COM uint8_t *desc, rate;
25149485SMikore.Li@Sun.COM struct ieee80211_frame *wh;
25159485SMikore.Li@Sun.COM struct ieee80211_node *ni = 0;
25169485SMikore.Li@Sun.COM mblk_t *mp = 0;
25179485SMikore.Li@Sun.COM uint8_t *rxbuf;
25189485SMikore.Li@Sun.COM
25199485SMikore.Li@Sun.COM mp = req->bulk_data;
25209485SMikore.Li@Sun.COM req->bulk_data = NULL;
25219485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK ||
25229485SMikore.Li@Sun.COM mp == NULL) {
25239485SMikore.Li@Sun.COM sc->sc_rx_err++;
25249485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT,
252510364SMikore.Li@Sun.COM "urtw_rxeof failed! %d, mp %p\n",
252610364SMikore.Li@Sun.COM req->bulk_completion_reason, mp));
25279485SMikore.Li@Sun.COM req->bulk_data = mp;
25289485SMikore.Li@Sun.COM goto fail;
25299485SMikore.Li@Sun.COM }
25309485SMikore.Li@Sun.COM
25319485SMikore.Li@Sun.COM actlen = MBLKL(mp);
25329485SMikore.Li@Sun.COM rxbuf = (uint8_t *)mp->b_rptr;
25339485SMikore.Li@Sun.COM
253410364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187)
253510364SMikore.Li@Sun.COM /* 4 dword and 4 byte CRC */
253610364SMikore.Li@Sun.COM len = actlen - (4 * 4);
253710364SMikore.Li@Sun.COM else
253810364SMikore.Li@Sun.COM /* 5 dword and 4 byte CRC */
253910364SMikore.Li@Sun.COM len = actlen - (4 * 5);
254010364SMikore.Li@Sun.COM
25419485SMikore.Li@Sun.COM desc = rxbuf + len;
25429485SMikore.Li@Sun.COM flen = ((desc[1] & 0x0f) << 8) + (desc[0] & 0xff);
25439485SMikore.Li@Sun.COM if (flen > actlen) {
25449485SMikore.Li@Sun.COM cmn_err(CE_CONT, "urtw_rxeof: impossible: flen %d, actlen %d\n",
25459485SMikore.Li@Sun.COM flen, actlen);
25469485SMikore.Li@Sun.COM sc->sc_rx_err++;
25479485SMikore.Li@Sun.COM req->bulk_data = mp;
25489485SMikore.Li@Sun.COM goto fail;
25499485SMikore.Li@Sun.COM }
25509485SMikore.Li@Sun.COM
25519485SMikore.Li@Sun.COM rate = (desc[2] & 0xf0) >> 4;
255210364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
255310364SMikore.Li@Sun.COM rssi = (desc[6] & 0xfe) >> 1;
255410364SMikore.Li@Sun.COM
255510364SMikore.Li@Sun.COM /* XXX correct? */
255610364SMikore.Li@Sun.COM if (!urtw_isbmode(rate)) {
255710364SMikore.Li@Sun.COM rssi = (rssi > 90) ? 90 : ((rssi < 25) ? 25 : rssi);
255810364SMikore.Li@Sun.COM rssi = ((90 - rssi) * 100) / 65;
255910364SMikore.Li@Sun.COM } else {
256010364SMikore.Li@Sun.COM rssi = (rssi > 90) ? 95 : ((rssi < 30) ? 30 : rssi);
256110364SMikore.Li@Sun.COM rssi = ((95 - rssi) * 100) / 65;
256210364SMikore.Li@Sun.COM }
25639485SMikore.Li@Sun.COM } else {
256410364SMikore.Li@Sun.COM rssi = 14 + desc[13]/2;
256510364SMikore.Li@Sun.COM if (rssi >= 95)
256610364SMikore.Li@Sun.COM rssi = 95;
256710364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT,
256810364SMikore.Li@Sun.COM "urtw_rxeof: rssi %u\n", rssi));
25699485SMikore.Li@Sun.COM }
25709485SMikore.Li@Sun.COM
25719485SMikore.Li@Sun.COM mp->b_wptr = mp->b_rptr + flen - 4;
25729485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)mp->b_rptr;
25739485SMikore.Li@Sun.COM if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK)
25749485SMikore.Li@Sun.COM == IEEE80211_FC0_TYPE_DATA) {
25759485SMikore.Li@Sun.COM sc->sc_currate = (rate > 0) ? rate : sc->sc_currate;
25769485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RX_PROC, (sc->sc_dev, CE_CONT,
25779485SMikore.Li@Sun.COM "urtw_rxeof: update sc_currate to %u\n",
25789485SMikore.Li@Sun.COM sc->sc_currate));
25799485SMikore.Li@Sun.COM }
25809485SMikore.Li@Sun.COM ni = ieee80211_find_rxnode(ic, wh);
25819485SMikore.Li@Sun.COM
25829485SMikore.Li@Sun.COM /* send the frame to the 802.11 layer */
25839485SMikore.Li@Sun.COM (void) ieee80211_input(ic, mp, ni, rssi, 0);
25849485SMikore.Li@Sun.COM
25859485SMikore.Li@Sun.COM /* node is no longer needed */
25869485SMikore.Li@Sun.COM ieee80211_free_node(ni);
25879485SMikore.Li@Sun.COM fail:
25889485SMikore.Li@Sun.COM mutex_enter(&sc->rx_lock);
25899485SMikore.Li@Sun.COM sc->rx_queued--;
25909485SMikore.Li@Sun.COM mutex_exit(&sc->rx_lock);
25919485SMikore.Li@Sun.COM usb_free_bulk_req(req);
25929485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && !URTW_IS_SUSPENDING(sc))
25939485SMikore.Li@Sun.COM (void) urtw_rx_start(sc);
25949485SMikore.Li@Sun.COM }
25959485SMikore.Li@Sun.COM
25969485SMikore.Li@Sun.COM static usbd_status
urtw_8225v2_setgain(struct urtw_softc * sc,int16_t gain)25979485SMikore.Li@Sun.COM urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain)
25989485SMikore.Li@Sun.COM {
25999485SMikore.Li@Sun.COM uint8_t *gainp;
26009485SMikore.Li@Sun.COM usbd_status error;
26019485SMikore.Li@Sun.COM
26029485SMikore.Li@Sun.COM /* XXX for A? */
26039485SMikore.Li@Sun.COM gainp = urtw_8225v2_gain_bg;
26049485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x0d, gainp[gain * 3]))
26059485SMikore.Li@Sun.COM goto fail;
26069485SMikore.Li@Sun.COM urtw_delay_ms(1);
26079485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1b, gainp[gain * 3 + 1]))
26089485SMikore.Li@Sun.COM urtw_delay_ms(1);
26099485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x1d, gainp[gain * 3 + 2]))
26109485SMikore.Li@Sun.COM goto fail;
26119485SMikore.Li@Sun.COM urtw_delay_ms(1);
26129485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x21, 0x17))
26139485SMikore.Li@Sun.COM goto fail;
26149485SMikore.Li@Sun.COM urtw_delay_ms(1);
26159485SMikore.Li@Sun.COM fail:
26169485SMikore.Li@Sun.COM return (error);
26179485SMikore.Li@Sun.COM }
26189485SMikore.Li@Sun.COM
26199485SMikore.Li@Sun.COM static usbd_status
urtw_8225v2_set_txpwrlvl(struct urtw_softc * sc,int chan)26209485SMikore.Li@Sun.COM urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan)
26219485SMikore.Li@Sun.COM {
26229485SMikore.Li@Sun.COM int i;
26239485SMikore.Li@Sun.COM uint8_t *cck_pwrtable;
26249485SMikore.Li@Sun.COM uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10;
26259485SMikore.Li@Sun.COM uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
26269485SMikore.Li@Sun.COM uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
26279485SMikore.Li@Sun.COM usbd_status error;
26289485SMikore.Li@Sun.COM
26299485SMikore.Li@Sun.COM /* CCK power setting */
26309485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ?
26319485SMikore.Li@Sun.COM cck_pwrlvl_max : cck_pwrlvl;
26329485SMikore.Li@Sun.COM cck_pwrlvl += sc->sc_txpwr_cck_base;
26339485SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
26349485SMikore.Li@Sun.COM cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
26359485SMikore.Li@Sun.COM urtw_8225v2_txpwr_cck;
26369485SMikore.Li@Sun.COM
26379485SMikore.Li@Sun.COM for (i = 0; i < 8; i++) {
26389485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x44 + i,
26399485SMikore.Li@Sun.COM cck_pwrtable[i]))
26409485SMikore.Li@Sun.COM goto fail;
26419485SMikore.Li@Sun.COM }
26429485SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_TX_GAIN_CCK,
264310364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl], 0))
26449485SMikore.Li@Sun.COM goto fail;
26459485SMikore.Li@Sun.COM urtw_delay_ms(1);
26469485SMikore.Li@Sun.COM
26479485SMikore.Li@Sun.COM /* OFDM power setting */
26489485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
26499485SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
26509485SMikore.Li@Sun.COM ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
26519485SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
26529485SMikore.Li@Sun.COM
265310364SMikore.Li@Sun.COM error = urtw_8185_set_anaparam2(sc, URTW_8187_8225_ANAPARAM2_ON);
26549485SMikore.Li@Sun.COM if (error)
26559485SMikore.Li@Sun.COM goto fail;
26569485SMikore.Li@Sun.COM
26579485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 2, 0x42))
26589485SMikore.Li@Sun.COM goto fail;
26599485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 5, 0x0))
26609485SMikore.Li@Sun.COM goto fail;
26619485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 6, 0x40))
26629485SMikore.Li@Sun.COM goto fail;
26639485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 7, 0x0))
26649485SMikore.Li@Sun.COM goto fail;
26659485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 8, 0x40))
26669485SMikore.Li@Sun.COM goto fail;
26679485SMikore.Li@Sun.COM
26689485SMikore.Li@Sun.COM error = urtw_write8_c(sc, URTW_TX_GAIN_OFDM,
266910364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl], 0);
26709485SMikore.Li@Sun.COM urtw_delay_ms(1);
26719485SMikore.Li@Sun.COM fail:
26729485SMikore.Li@Sun.COM return (error);
26739485SMikore.Li@Sun.COM }
26749485SMikore.Li@Sun.COM
26759485SMikore.Li@Sun.COM static usbd_status
urtw_8225v2_rf_init(struct urtw_rf * rf)267610364SMikore.Li@Sun.COM urtw_8225v2_rf_init(struct urtw_rf *rf)
26779485SMikore.Li@Sun.COM {
26789485SMikore.Li@Sun.COM #define N(a) (sizeof (a)/ sizeof ((a)[0]))
26799485SMikore.Li@Sun.COM int i;
26809485SMikore.Li@Sun.COM uint16_t data;
26819485SMikore.Li@Sun.COM uint32_t data32;
26829485SMikore.Li@Sun.COM usbd_status error;
268310364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
268410364SMikore.Li@Sun.COM
268510364SMikore.Li@Sun.COM if (error = urtw_8180_set_anaparam(sc, URTW_8187_8225_ANAPARAM_ON))
26869485SMikore.Li@Sun.COM goto fail;
26879485SMikore.Li@Sun.COM if (error = urtw_8225_usb_init(sc))
26889485SMikore.Li@Sun.COM goto fail;
268910364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_TIMING, 0x000a8008, 0))
26909485SMikore.Li@Sun.COM goto fail;
269110364SMikore.Li@Sun.COM if (error = urtw_read16_c(sc, URTW_BRSR, &data, 0))
26929485SMikore.Li@Sun.COM goto fail;
269310364SMikore.Li@Sun.COM if (error = urtw_write16_c(sc, URTW_BRSR, 0xffff, 0))
26949485SMikore.Li@Sun.COM goto fail;
269510364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_RF_PARA, 0x100044, 0))
26969485SMikore.Li@Sun.COM goto fail;
26979485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG))
26989485SMikore.Li@Sun.COM goto fail;
269910364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CONFIG3, 0x44, 0))
27009485SMikore.Li@Sun.COM goto fail;
27019485SMikore.Li@Sun.COM if (error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL))
27029485SMikore.Li@Sun.COM goto fail;
27039485SMikore.Li@Sun.COM if (error = urtw_8185_rf_pins_enable(sc))
27049485SMikore.Li@Sun.COM goto fail;
27059485SMikore.Li@Sun.COM
27069485SMikore.Li@Sun.COM urtw_delay_ms(500);
27079485SMikore.Li@Sun.COM
27089485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part1); i++) {
27099485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, urtw_8225v2_rf_part1[i].reg,
27109485SMikore.Li@Sun.COM urtw_8225v2_rf_part1[i].val))
27119485SMikore.Li@Sun.COM goto fail;
27129485SMikore.Li@Sun.COM urtw_delay_ms(1);
27139485SMikore.Li@Sun.COM }
27149485SMikore.Li@Sun.COM urtw_delay_ms(100);
27159485SMikore.Li@Sun.COM
27169485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x1b7))
27179485SMikore.Li@Sun.COM goto fail;
27189485SMikore.Li@Sun.COM
27199485SMikore.Li@Sun.COM for (i = 0; i < 95; i++) {
27209485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1)))
27219485SMikore.Li@Sun.COM goto fail;
27229485SMikore.Li@Sun.COM urtw_delay_ms(1);
27239485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, urtw_8225v2_rxgain[i]))
27249485SMikore.Li@Sun.COM goto fail;
27259485SMikore.Li@Sun.COM urtw_delay_ms(1);
27269485SMikore.Li@Sun.COM }
27279485SMikore.Li@Sun.COM
27289485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x3, 0x2))
27299485SMikore.Li@Sun.COM goto fail;
27309485SMikore.Li@Sun.COM urtw_delay_ms(1);
27319485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x5, 0x4))
27329485SMikore.Li@Sun.COM goto fail;
27339485SMikore.Li@Sun.COM urtw_delay_ms(1);
27349485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0xb7))
27359485SMikore.Li@Sun.COM goto fail;
27369485SMikore.Li@Sun.COM urtw_delay_ms(1);
27379485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0xc4d))
27389485SMikore.Li@Sun.COM goto fail;
27399485SMikore.Li@Sun.COM urtw_delay_ms(100);
27409485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x2, 0x44d))
27419485SMikore.Li@Sun.COM goto fail;
27429485SMikore.Li@Sun.COM urtw_delay_ms(100);
27439485SMikore.Li@Sun.COM
27449485SMikore.Li@Sun.COM if (error = urtw_8225_read(sc, 0x6, &data32))
27459485SMikore.Li@Sun.COM goto fail;
27469485SMikore.Li@Sun.COM if (data32 != 0xe6) {
27479485SMikore.Li@Sun.COM error = (-1);
27489485SMikore.Li@Sun.COM cmn_err(CE_WARN, "expect 0xe6!! (0x%x)\n", data32);
27499485SMikore.Li@Sun.COM goto fail;
27509485SMikore.Li@Sun.COM }
27519485SMikore.Li@Sun.COM if (!(data32 & 0x80)) {
27529485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x02, 0x0c4d))
27539485SMikore.Li@Sun.COM goto fail;
27549485SMikore.Li@Sun.COM urtw_delay_ms(200);
27559485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x02, 0x044d))
27569485SMikore.Li@Sun.COM goto fail;
27579485SMikore.Li@Sun.COM urtw_delay_ms(100);
27589485SMikore.Li@Sun.COM if (error = urtw_8225_read(sc, 0x6, &data32))
27599485SMikore.Li@Sun.COM goto fail;
27609485SMikore.Li@Sun.COM if (!(data32 & 0x80))
27619485SMikore.Li@Sun.COM cmn_err(CE_CONT, "RF calibration failed\n");
27629485SMikore.Li@Sun.COM }
27639485SMikore.Li@Sun.COM urtw_delay_ms(200);
27649485SMikore.Li@Sun.COM
27659485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x0, 0x2bf))
27669485SMikore.Li@Sun.COM goto fail;
27679485SMikore.Li@Sun.COM for (i = 0; i < 128; i++) {
27689485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xb,
27699485SMikore.Li@Sun.COM urtw_8225_agc[i]))
27709485SMikore.Li@Sun.COM goto fail;
27719485SMikore.Li@Sun.COM urtw_delay_ms(1);
27729485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0xa,
27739485SMikore.Li@Sun.COM (uint8_t)i + 0x80))
27749485SMikore.Li@Sun.COM goto fail;
27759485SMikore.Li@Sun.COM urtw_delay_ms(1);
27769485SMikore.Li@Sun.COM }
27779485SMikore.Li@Sun.COM urtw_delay_ms(1);
27789485SMikore.Li@Sun.COM
27799485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part2); i++) {
27809485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc,
27819485SMikore.Li@Sun.COM urtw_8225v2_rf_part2[i].reg,
27829485SMikore.Li@Sun.COM urtw_8225v2_rf_part2[i].val))
27839485SMikore.Li@Sun.COM goto fail;
27849485SMikore.Li@Sun.COM urtw_delay_ms(1);
27859485SMikore.Li@Sun.COM }
27869485SMikore.Li@Sun.COM error = urtw_8225v2_setgain(sc, 4);
27879485SMikore.Li@Sun.COM if (error)
27889485SMikore.Li@Sun.COM goto fail;
27899485SMikore.Li@Sun.COM
27909485SMikore.Li@Sun.COM for (i = 0; i < N(urtw_8225v2_rf_part3); i++) {
27919485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc,
27929485SMikore.Li@Sun.COM urtw_8225v2_rf_part3[i].reg,
27939485SMikore.Li@Sun.COM urtw_8225v2_rf_part3[i].val))
27949485SMikore.Li@Sun.COM goto fail;
27959485SMikore.Li@Sun.COM urtw_delay_ms(1);
27969485SMikore.Li@Sun.COM }
27979485SMikore.Li@Sun.COM
279810364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, 0x5b, 0x0d, 0))
27999485SMikore.Li@Sun.COM goto fail;
28009485SMikore.Li@Sun.COM if (error = urtw_8225v2_set_txpwrlvl(sc, 1))
28019485SMikore.Li@Sun.COM goto fail;
28029485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_cck_c(sc, 0x10, 0x9b))
28039485SMikore.Li@Sun.COM goto fail;
28049485SMikore.Li@Sun.COM urtw_delay_ms(1);
28059485SMikore.Li@Sun.COM if (error = urtw_8187_write_phy_ofdm_c(sc, 0x26, 0x90))
28069485SMikore.Li@Sun.COM goto fail;
28079485SMikore.Li@Sun.COM urtw_delay_ms(1);
28089485SMikore.Li@Sun.COM
28099485SMikore.Li@Sun.COM /* TX ant A, 0x0 for B */
28109485SMikore.Li@Sun.COM if (error = urtw_8185_tx_antenna(sc, 0x3))
28119485SMikore.Li@Sun.COM goto fail;
281210364SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, 0x94, 0x3dc00002, 0))
28139485SMikore.Li@Sun.COM goto fail;
28149485SMikore.Li@Sun.COM
281510364SMikore.Li@Sun.COM error = urtw_8225_rf_set_chan(rf,
281610364SMikore.Li@Sun.COM ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan));
28179485SMikore.Li@Sun.COM fail:
28189485SMikore.Li@Sun.COM return (error);
28199485SMikore.Li@Sun.COM #undef N
28209485SMikore.Li@Sun.COM }
28219485SMikore.Li@Sun.COM
28229485SMikore.Li@Sun.COM static usbd_status
urtw_8225v2_rf_set_chan(struct urtw_rf * rf,int chan)282310364SMikore.Li@Sun.COM urtw_8225v2_rf_set_chan(struct urtw_rf *rf, int chan)
28249485SMikore.Li@Sun.COM {
282510364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
28269485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
28279485SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan;
28289485SMikore.Li@Sun.COM short gset = (IEEE80211_IS_CHAN_G(c)) ? 1 : 0;
28299485SMikore.Li@Sun.COM usbd_status error;
28309485SMikore.Li@Sun.COM
28319485SMikore.Li@Sun.COM if (error = urtw_8225v2_set_txpwrlvl(sc, chan))
28329485SMikore.Li@Sun.COM goto fail;
28339485SMikore.Li@Sun.COM
28349485SMikore.Li@Sun.COM if (error = urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan]))
28359485SMikore.Li@Sun.COM goto fail;
28369485SMikore.Li@Sun.COM
28379485SMikore.Li@Sun.COM urtw_delay_ms(10);
28389485SMikore.Li@Sun.COM
283910364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SIFS, 0x22, 0))
28409485SMikore.Li@Sun.COM goto fail;
28419485SMikore.Li@Sun.COM
28429485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_ASSOC &&
28439485SMikore.Li@Sun.COM ic->ic_flags & IEEE80211_F_SHSLOT) {
284410364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x9, 0))
28459485SMikore.Li@Sun.COM goto fail;
28469485SMikore.Li@Sun.COM } else
284710364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_SLOT, 0x14, 0))
28489485SMikore.Li@Sun.COM goto fail;
28499485SMikore.Li@Sun.COM if (gset) {
28509485SMikore.Li@Sun.COM /* for G */
285110364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x14, 0))
28529485SMikore.Li@Sun.COM goto fail;
285310364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x14, 0))
28549485SMikore.Li@Sun.COM goto fail;
285510364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_VAL, 0x73, 0))
28569485SMikore.Li@Sun.COM goto fail;
28579485SMikore.Li@Sun.COM } else {
28589485SMikore.Li@Sun.COM /* for B */
285910364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_DIFS, 0x24, 0))
28609485SMikore.Li@Sun.COM goto fail;
286110364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_EIFS, 0x5b - 0x24, 0))
28629485SMikore.Li@Sun.COM goto fail;
286310364SMikore.Li@Sun.COM if (error = urtw_write8_c(sc, URTW_CW_VAL, 0xa5, 0))
28649485SMikore.Li@Sun.COM goto fail;
28659485SMikore.Li@Sun.COM }
28669485SMikore.Li@Sun.COM
28679485SMikore.Li@Sun.COM fail:
28689485SMikore.Li@Sun.COM return (error);
28699485SMikore.Li@Sun.COM }
28709485SMikore.Li@Sun.COM
28719485SMikore.Li@Sun.COM static int
urtw_set_channel(struct urtw_softc * sc)28729485SMikore.Li@Sun.COM urtw_set_channel(struct urtw_softc *sc)
28739485SMikore.Li@Sun.COM {
28749485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
287510364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf;
28769485SMikore.Li@Sun.COM uint32_t data;
28779485SMikore.Li@Sun.COM usbd_status error;
28789485SMikore.Li@Sun.COM
287910364SMikore.Li@Sun.COM if (error = urtw_read32_c(sc, URTW_TX_CONF, &data, 0))
28809485SMikore.Li@Sun.COM goto fail;
28819485SMikore.Li@Sun.COM data &= ~URTW_TX_LOOPBACK_MASK;
28829485SMikore.Li@Sun.COM if (error = urtw_write32_c(sc, URTW_TX_CONF,
288310364SMikore.Li@Sun.COM data | URTW_TX_LOOPBACK_MAC, 0))
28849485SMikore.Li@Sun.COM goto fail;
288510364SMikore.Li@Sun.COM error = rf->set_chan(rf, ieee80211_chan2ieee(ic, ic->ic_curchan));
28869485SMikore.Li@Sun.COM if (error)
28879485SMikore.Li@Sun.COM goto fail;
288810364SMikore.Li@Sun.COM urtw_delay_ms(20);
288910364SMikore.Li@Sun.COM error = urtw_write32_c(sc, URTW_TX_CONF,
289010364SMikore.Li@Sun.COM data | URTW_TX_LOOPBACK_NONE, 0);
28919485SMikore.Li@Sun.COM fail:
28929485SMikore.Li@Sun.COM return (error);
28939485SMikore.Li@Sun.COM }
28949485SMikore.Li@Sun.COM
28959485SMikore.Li@Sun.COM /* ARGSUSED */
28969485SMikore.Li@Sun.COM static void
urtw_txeof_low(usb_pipe_handle_t pipe,usb_bulk_req_t * req)28979485SMikore.Li@Sun.COM urtw_txeof_low(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
28989485SMikore.Li@Sun.COM {
28999485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private;
29009485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
29019485SMikore.Li@Sun.COM
29029485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT,
29039485SMikore.Li@Sun.COM "urtw_txeof_low(): cr:%s(%d), flags:0x%x, tx_queued:%d",
29049485SMikore.Li@Sun.COM usb_str_cr(req->bulk_completion_reason),
29059485SMikore.Li@Sun.COM req->bulk_completion_reason,
29069485SMikore.Li@Sun.COM req->bulk_cb_flags,
29079485SMikore.Li@Sun.COM sc->sc_tx_low_queued));
29089485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock);
29099485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK) {
29109485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++;
29119485SMikore.Li@Sun.COM goto fail;
29129485SMikore.Li@Sun.COM }
29139485SMikore.Li@Sun.COM
29149485SMikore.Li@Sun.COM if (sc->sc_need_sched) {
29159485SMikore.Li@Sun.COM sc->sc_need_sched = 0;
29169485SMikore.Li@Sun.COM mac_tx_update(ic->ic_mach);
29179485SMikore.Li@Sun.COM }
29189485SMikore.Li@Sun.COM fail:
29199485SMikore.Li@Sun.COM sc->sc_tx_low_queued--;
29209485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock);
29219485SMikore.Li@Sun.COM usb_free_bulk_req(req);
29229485SMikore.Li@Sun.COM }
29239485SMikore.Li@Sun.COM
29249485SMikore.Li@Sun.COM /* ARGSUSED */
29259485SMikore.Li@Sun.COM static void
urtw_txeof_normal(usb_pipe_handle_t pipe,usb_bulk_req_t * req)29269485SMikore.Li@Sun.COM urtw_txeof_normal(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
29279485SMikore.Li@Sun.COM {
29289485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)req->bulk_client_private;
29299485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
29309485SMikore.Li@Sun.COM
29319485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT,
29329485SMikore.Li@Sun.COM "urtw_txeof_normal(): cr:%s(%d), flags:0x%x, tx_queued:%d",
29339485SMikore.Li@Sun.COM usb_str_cr(req->bulk_completion_reason),
29349485SMikore.Li@Sun.COM req->bulk_completion_reason,
29359485SMikore.Li@Sun.COM req->bulk_cb_flags,
29369485SMikore.Li@Sun.COM sc->sc_tx_normal_queued));
29379485SMikore.Li@Sun.COM
29389485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock);
29399485SMikore.Li@Sun.COM if (req->bulk_completion_reason != USB_CR_OK) {
29409485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++;
29419485SMikore.Li@Sun.COM goto fail;
29429485SMikore.Li@Sun.COM }
29439485SMikore.Li@Sun.COM
29449485SMikore.Li@Sun.COM if (sc->sc_need_sched) {
29459485SMikore.Li@Sun.COM sc->sc_need_sched = 0;
29469485SMikore.Li@Sun.COM mac_tx_update(ic->ic_mach);
29479485SMikore.Li@Sun.COM }
29489485SMikore.Li@Sun.COM fail:
29499485SMikore.Li@Sun.COM sc->sc_tx_normal_queued--;
29509485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock);
29519485SMikore.Li@Sun.COM usb_free_bulk_req(req);
29529485SMikore.Li@Sun.COM }
29539485SMikore.Li@Sun.COM
29549485SMikore.Li@Sun.COM
29559485SMikore.Li@Sun.COM static int
urtw_get_rate(struct ieee80211com * ic)29569485SMikore.Li@Sun.COM urtw_get_rate(struct ieee80211com *ic)
29579485SMikore.Li@Sun.COM {
29589485SMikore.Li@Sun.COM uint8_t (*rates)[IEEE80211_RATE_MAXSIZE];
29599485SMikore.Li@Sun.COM int rate;
29609485SMikore.Li@Sun.COM
29619485SMikore.Li@Sun.COM rates = &ic->ic_bss->in_rates.ir_rates;
29629485SMikore.Li@Sun.COM
29639485SMikore.Li@Sun.COM if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
29649485SMikore.Li@Sun.COM rate = ic->ic_fixed_rate;
29659485SMikore.Li@Sun.COM else if (ic->ic_state == IEEE80211_S_RUN)
29669485SMikore.Li@Sun.COM rate = (*rates)[ic->ic_bss->in_txrate];
29679485SMikore.Li@Sun.COM else
29689485SMikore.Li@Sun.COM rate = 0;
29699485SMikore.Li@Sun.COM return (rate & IEEE80211_RATE_VAL);
29709485SMikore.Li@Sun.COM }
29719485SMikore.Li@Sun.COM
297210364SMikore.Li@Sun.COM void
urtw_8187b_update_wmm(struct urtw_softc * sc)297310364SMikore.Li@Sun.COM urtw_8187b_update_wmm(struct urtw_softc *sc)
297410364SMikore.Li@Sun.COM {
297510364SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
297610364SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan;
297710364SMikore.Li@Sun.COM uint32_t data;
297810364SMikore.Li@Sun.COM uint8_t aifs, sifs, slot, ecwmin, ecwmax;
297910364SMikore.Li@Sun.COM
298010364SMikore.Li@Sun.COM sifs = 0xa;
298110364SMikore.Li@Sun.COM if (IEEE80211_IS_CHAN_G(c))
298210364SMikore.Li@Sun.COM slot = 0x9;
298310364SMikore.Li@Sun.COM else
298410364SMikore.Li@Sun.COM slot = 0x14;
298510364SMikore.Li@Sun.COM
298610364SMikore.Li@Sun.COM aifs = (2 * slot) + sifs;
298710364SMikore.Li@Sun.COM ecwmin = 3;
298810364SMikore.Li@Sun.COM ecwmax = 7;
298910364SMikore.Li@Sun.COM
299010364SMikore.Li@Sun.COM data = ((uint32_t)aifs << 0) | /* AIFS, offset 0 */
299110364SMikore.Li@Sun.COM ((uint32_t)ecwmin << 8) | /* ECW minimum, offset 8 */
299210364SMikore.Li@Sun.COM ((uint32_t)ecwmax << 12); /* ECW maximum, offset 16 */
299310364SMikore.Li@Sun.COM
299410364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_VO, data, 0);
299510364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_VI, data, 0);
299610364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_BE, data, 0);
299710364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_AC_BK, data, 0);
299810364SMikore.Li@Sun.COM }
299910364SMikore.Li@Sun.COM
300010364SMikore.Li@Sun.COM usbd_status
urtw_8187b_reset(struct urtw_softc * sc)300110364SMikore.Li@Sun.COM urtw_8187b_reset(struct urtw_softc *sc)
300210364SMikore.Li@Sun.COM {
300310364SMikore.Li@Sun.COM uint8_t data;
300410364SMikore.Li@Sun.COM usbd_status error;
300510364SMikore.Li@Sun.COM
300610364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
300710364SMikore.Li@Sun.COM if (error)
300810364SMikore.Li@Sun.COM goto fail;
300910364SMikore.Li@Sun.COM
301010364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0);
301110364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG3,
301210364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE |
301310364SMikore.Li@Sun.COM URTW_CONFIG3_GNT_SELECT, 0);
301410364SMikore.Li@Sun.COM
301510364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_ANAPARAM2,
301610364SMikore.Li@Sun.COM URTW_8187B_8225_ANAPARAM2_ON, 0);
301710364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_ANAPARAM,
301810364SMikore.Li@Sun.COM URTW_8187B_8225_ANAPARAM_ON, 0);
301910364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_ANAPARAM3,
302010364SMikore.Li@Sun.COM URTW_8187B_8225_ANAPARAM3_ON, 0);
302110364SMikore.Li@Sun.COM
302210364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x61, 0x10, 0);
302310364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, 0x62, &data, 0);
302410364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x62, data & ~(1 << 5), 0);
302510364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x62, data | (1 << 5), 0);
302610364SMikore.Li@Sun.COM
302710364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0);
302810364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG3,
302910364SMikore.Li@Sun.COM data & ~URTW_CONFIG3_ANAPARAM_WRITE, 0);
303010364SMikore.Li@Sun.COM
303110364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
303210364SMikore.Li@Sun.COM if (error)
303310364SMikore.Li@Sun.COM goto fail;
303410364SMikore.Li@Sun.COM
303510364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CMD, &data, 0);
303610364SMikore.Li@Sun.COM data = (data & 2) | URTW_CMD_RST;
303710364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CMD, data, 0);
303810364SMikore.Li@Sun.COM urtw_delay_ms(100);
303910364SMikore.Li@Sun.COM
304010364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CMD, &data, 0);
304110364SMikore.Li@Sun.COM if (data & URTW_CMD_RST) {
304210364SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw: 8187b reset timeout\n");
304310364SMikore.Li@Sun.COM goto fail;
304410364SMikore.Li@Sun.COM }
304510364SMikore.Li@Sun.COM
304610364SMikore.Li@Sun.COM fail:
304710364SMikore.Li@Sun.COM return (error);
304810364SMikore.Li@Sun.COM }
304910364SMikore.Li@Sun.COM
305010364SMikore.Li@Sun.COM static int
urtw_8187b_init(void * arg)305110364SMikore.Li@Sun.COM urtw_8187b_init(void *arg)
305210364SMikore.Li@Sun.COM {
305310364SMikore.Li@Sun.COM struct urtw_softc *sc = arg;
305410364SMikore.Li@Sun.COM struct urtw_rf *rf = &sc->sc_rf;
305510364SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
305610364SMikore.Li@Sun.COM int i;
305710364SMikore.Li@Sun.COM uint8_t data;
305810364SMikore.Li@Sun.COM usbd_status error;
305910364SMikore.Li@Sun.COM
306010364SMikore.Li@Sun.COM urtw_stop(sc);
306110364SMikore.Li@Sun.COM URTW_LOCK(sc);
306210364SMikore.Li@Sun.COM urtw_8187b_update_wmm(sc);
306310364SMikore.Li@Sun.COM error = urtw_8187b_reset(sc);
306410364SMikore.Li@Sun.COM if (error)
306510364SMikore.Li@Sun.COM goto fail;
306610364SMikore.Li@Sun.COM
306710364SMikore.Li@Sun.COM error = urtw_open_pipes(sc);
306810364SMikore.Li@Sun.COM if (error != 0)
306910364SMikore.Li@Sun.COM goto fail;
307010364SMikore.Li@Sun.COM /* Applying MAC address again. */
307110364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
307210364SMikore.Li@Sun.COM if (error)
307310364SMikore.Li@Sun.COM goto fail;
307410364SMikore.Li@Sun.COM for (i = 0; i < IEEE80211_ADDR_LEN; i++)
307510364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_MAC0 + i,
307610364SMikore.Li@Sun.COM ic->ic_macaddr[i], 0);
307710364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
307810364SMikore.Li@Sun.COM if (error)
307910364SMikore.Li@Sun.COM goto fail;
308010364SMikore.Li@Sun.COM
308110364SMikore.Li@Sun.COM error = urtw_update_msr(sc, IEEE80211_S_INIT);
308210364SMikore.Li@Sun.COM if (error)
308310364SMikore.Li@Sun.COM goto fail;
308410364SMikore.Li@Sun.COM
308510364SMikore.Li@Sun.COM error = rf->init(rf);
308610364SMikore.Li@Sun.COM if (error != 0)
308710364SMikore.Li@Sun.COM goto fail;
308810364SMikore.Li@Sun.COM error = urtw_intr_enable(sc);
308910364SMikore.Li@Sun.COM if (error != 0)
309010364SMikore.Li@Sun.COM goto fail;
309110364SMikore.Li@Sun.COM
309210364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x41, 0xf4);
309310364SMikore.Li@Sun.COM if (error != 0)
309410364SMikore.Li@Sun.COM goto fail;
309510364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x40, 0x00);
309610364SMikore.Li@Sun.COM if (error != 0)
309710364SMikore.Li@Sun.COM goto fail;
309810364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x00);
309910364SMikore.Li@Sun.COM if (error != 0)
310010364SMikore.Li@Sun.COM goto fail;
310110364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x01);
310210364SMikore.Li@Sun.COM if (error != 0)
310310364SMikore.Li@Sun.COM goto fail;
310410364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x40, 0x0f);
310510364SMikore.Li@Sun.COM if (error != 0)
310610364SMikore.Li@Sun.COM goto fail;
310710364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x00);
310810364SMikore.Li@Sun.COM if (error != 0)
310910364SMikore.Li@Sun.COM goto fail;
311010364SMikore.Li@Sun.COM error = urtw_write8e(sc, 0x42, 0x01);
311110364SMikore.Li@Sun.COM if (error != 0)
311210364SMikore.Li@Sun.COM goto fail;
311310364SMikore.Li@Sun.COM
311410364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, 0xdb, &data, 0);
311510364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xdb, data | (1 << 2), 0);
311610364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x72, 0x59fa, 3);
311710364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x74, 0x59d2, 3);
311810364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x76, 0x59d2, 3);
311910364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x78, 0x19fa, 3);
312010364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x7a, 0x19fa, 3);
312110364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0x7c, 0x00d0, 3);
312210364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x61, 0, 0);
312310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x80, 0x0f, 1);
312410364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x83, 0x03, 1);
312510364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xda, 0x10, 0);
312610364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0x4d, 0x08, 2);
312710364SMikore.Li@Sun.COM
312810364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_HSSI_PARA, 0x0600321b, 0);
312910364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, 0xec, 0x0800, 1);
313010364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_ACM_CONTROL, 0, 0);
313110364SMikore.Li@Sun.COM
313210364SMikore.Li@Sun.COM sc->sc_tx_low_queued = 0;
313310364SMikore.Li@Sun.COM sc->sc_tx_normal_queued = 0;
313410364SMikore.Li@Sun.COM error = urtw_rx_enable(sc);
313510364SMikore.Li@Sun.COM if (error != 0)
313610364SMikore.Li@Sun.COM goto fail;
313710364SMikore.Li@Sun.COM urtw_tx_enable(sc);
313810364SMikore.Li@Sun.COM
313910364SMikore.Li@Sun.COM if (error == 0) {
314010364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev,
314110364SMikore.Li@Sun.COM CE_CONT, "urtw_8187b_init: done\n"));
314210364SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_RUNNING;
314310364SMikore.Li@Sun.COM URTW_UNLOCK(sc);
314410364SMikore.Li@Sun.COM return (error);
314510364SMikore.Li@Sun.COM }
314610364SMikore.Li@Sun.COM
314710364SMikore.Li@Sun.COM fail:
314810364SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_8187b_init failed\n");
314910364SMikore.Li@Sun.COM URTW_UNLOCK(sc);
315010364SMikore.Li@Sun.COM urtw_stop(sc);
315110364SMikore.Li@Sun.COM return (EIO);
315210364SMikore.Li@Sun.COM }
315310364SMikore.Li@Sun.COM
315410364SMikore.Li@Sun.COM void
urtw_8225v2_b_config_mac(struct urtw_softc * sc)315510364SMikore.Li@Sun.COM urtw_8225v2_b_config_mac(struct urtw_softc *sc)
315610364SMikore.Li@Sun.COM {
315710364SMikore.Li@Sun.COM int i;
315810364SMikore.Li@Sun.COM int nitems = sizeof (urtw_8187b_regtbl)
315910364SMikore.Li@Sun.COM / sizeof ((urtw_8187b_regtbl)[0]);
316010364SMikore.Li@Sun.COM
316110364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) {
316210364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, urtw_8187b_regtbl[i].reg,
316310364SMikore.Li@Sun.COM urtw_8187b_regtbl[i].val, urtw_8187b_regtbl[i].idx);
316410364SMikore.Li@Sun.COM }
316510364SMikore.Li@Sun.COM
316610364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_TID_AC_MAP, 0xfa50, 0);
316710364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_INT_MIG, 0, 0);
316810364SMikore.Li@Sun.COM
316910364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, 0xf0, 0, 1);
317010364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, 0xf4, 0, 1);
317110364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, 0xf8, 0, 1);
317210364SMikore.Li@Sun.COM
317310364SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_RF_TIMING, 0x00004001, 0);
317410364SMikore.Li@Sun.COM }
317510364SMikore.Li@Sun.COM
317610364SMikore.Li@Sun.COM void
urtw_8225v2_b_init_rfe(struct urtw_softc * sc)317710364SMikore.Li@Sun.COM urtw_8225v2_b_init_rfe(struct urtw_softc *sc)
317810364SMikore.Li@Sun.COM {
317910364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RF_PINS_OUTPUT, 0x0480, 0);
318010364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RF_PINS_SELECT, 0x2488, 0);
318110364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RF_PINS_ENABLE, 0x1fff, 0);
318210364SMikore.Li@Sun.COM urtw_delay_ms(100);
318310364SMikore.Li@Sun.COM }
318410364SMikore.Li@Sun.COM
318510364SMikore.Li@Sun.COM usbd_status
urtw_8225v2_b_update_chan(struct urtw_softc * sc)318610364SMikore.Li@Sun.COM urtw_8225v2_b_update_chan(struct urtw_softc *sc)
318710364SMikore.Li@Sun.COM {
318810364SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
318910364SMikore.Li@Sun.COM struct ieee80211_channel *c = ic->ic_curchan;
319010364SMikore.Li@Sun.COM uint8_t aifs, difs, eifs, sifs, slot;
319110364SMikore.Li@Sun.COM
319210364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_SIFS, 0x22, 0);
319310364SMikore.Li@Sun.COM
319410364SMikore.Li@Sun.COM sifs = 0xa;
319510364SMikore.Li@Sun.COM if (IEEE80211_IS_CHAN_G(c)) {
319610364SMikore.Li@Sun.COM slot = 0x9;
319710364SMikore.Li@Sun.COM difs = 0x1c;
319810364SMikore.Li@Sun.COM eifs = 0x5b;
319910364SMikore.Li@Sun.COM } else {
320010364SMikore.Li@Sun.COM slot = 0x14;
320110364SMikore.Li@Sun.COM difs = 0x32;
320210364SMikore.Li@Sun.COM eifs = 0x5b;
320310364SMikore.Li@Sun.COM }
320410364SMikore.Li@Sun.COM aifs = (2 * slot) + sifs;
320510364SMikore.Li@Sun.COM
320610364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_SLOT, slot, 0);
320710364SMikore.Li@Sun.COM
320810364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_VO, aifs, 0);
320910364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_VI, aifs, 0);
321010364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_BE, aifs, 0);
321110364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_AC_BK, aifs, 0);
321210364SMikore.Li@Sun.COM
321310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_DIFS, difs, 0);
321410364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_8187B_EIFS, eifs, 0);
321510364SMikore.Li@Sun.COM return (0);
321610364SMikore.Li@Sun.COM }
321710364SMikore.Li@Sun.COM
321810364SMikore.Li@Sun.COM usbd_status
urtw_8225v2_b_rf_init(struct urtw_rf * rf)321910364SMikore.Li@Sun.COM urtw_8225v2_b_rf_init(struct urtw_rf *rf)
322010364SMikore.Li@Sun.COM {
322110364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
322210364SMikore.Li@Sun.COM int i, nitems;
322310364SMikore.Li@Sun.COM uint8_t data;
322410364SMikore.Li@Sun.COM usbd_status error;
322510364SMikore.Li@Sun.COM
322610364SMikore.Li@Sun.COM /* Set up ACK rate, retry limit, TX AGC, TX antenna. */
322710364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_8187B_BRSR, 0x0fff, 0);
322810364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CW_CONF, &data, 0);
322910364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CW_CONF, data |
323010364SMikore.Li@Sun.COM URTW_CW_CONF_PERPACKET_RETRY, 0);
323110364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_TX_AGC_CTL, &data, 0);
323210364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_AGC_CTL, data |
323310364SMikore.Li@Sun.COM URTW_TX_AGC_CTL_PERPACKET_GAIN |
323410364SMikore.Li@Sun.COM URTW_TX_AGC_CTL_PERPACKET_ANTSEL, 0);
323510364SMikore.Li@Sun.COM
323610364SMikore.Li@Sun.COM /* Auto rate fallback control. */
323710364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_ARFR, 0x0fff, 1); /* 1M ~ 54M */
323810364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_RATE_FALLBACK, &data, 0);
323910364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_RATE_FALLBACK, data |
324010364SMikore.Li@Sun.COM URTW_RATE_FALLBACK_ENABLE, 0);
324110364SMikore.Li@Sun.COM
324210364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_BEACON_INTERVAL, 0x3ff, 0);
324310364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_ATIM_WND, 2, 0);
324410364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_FEMR, 0xffff, 1);
324510364SMikore.Li@Sun.COM
324610364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
324710364SMikore.Li@Sun.COM if (error)
324810364SMikore.Li@Sun.COM goto fail;
324910364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG1, &data, 0);
325010364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG1, (data & 0x3f) | 0x80, 0);
325110364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
325210364SMikore.Li@Sun.COM if (error)
325310364SMikore.Li@Sun.COM goto fail;
325410364SMikore.Li@Sun.COM
325510364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_WPA_CONFIG, 0, 0);
325610364SMikore.Li@Sun.COM urtw_8225v2_b_config_mac(sc);
325710364SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_RFSW_CTRL, 0x569a, 2);
325810364SMikore.Li@Sun.COM
325910364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG);
326010364SMikore.Li@Sun.COM if (error)
326110364SMikore.Li@Sun.COM goto fail;
326210364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_CONFIG3, &data, 0);
326310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_CONFIG3,
326410364SMikore.Li@Sun.COM data | URTW_CONFIG3_ANAPARAM_WRITE, 0);
326510364SMikore.Li@Sun.COM error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
326610364SMikore.Li@Sun.COM if (error)
326710364SMikore.Li@Sun.COM goto fail;
326810364SMikore.Li@Sun.COM
326910364SMikore.Li@Sun.COM urtw_8225v2_b_init_rfe(sc);
327010364SMikore.Li@Sun.COM
327110364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_b_rf) / sizeof ((urtw_8225v2_b_rf)[0]);
327210364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) {
327310364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, urtw_8225v2_b_rf[i].reg,
327410364SMikore.Li@Sun.COM urtw_8225v2_b_rf[i].val);
327510364SMikore.Li@Sun.COM }
327610364SMikore.Li@Sun.COM
327710364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_rxgain) / sizeof ((urtw_8225v2_rxgain)[0]);
327810364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) {
327910364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x1, (uint8_t)(i + 1));
328010364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x2, urtw_8225v2_rxgain[i]);
328110364SMikore.Li@Sun.COM }
328210364SMikore.Li@Sun.COM
328310364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x03, 0x080);
328410364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x05, 0x004);
328510364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x00, 0x0b7);
328610364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x02, 0xc4d);
328710364SMikore.Li@Sun.COM urtw_delay_ms(10);
328810364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x02, 0x44d);
328910364SMikore.Li@Sun.COM urtw_delay_ms(10);
329010364SMikore.Li@Sun.COM (void) urtw_8225_write_c(sc, 0x00, 0x2bf);
329110364SMikore.Li@Sun.COM urtw_delay_ms(10);
329210364SMikore.Li@Sun.COM
329310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_CCK, 0x03, 0);
329410364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_OFDM, 0x07, 0);
329510364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_ANTENNA, 0x03, 0);
329610364SMikore.Li@Sun.COM
329710364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x80, 0x12);
329810364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_agc) / sizeof ((urtw_8225v2_agc)[0]);
329910364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) {
330010364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x0f, urtw_8225v2_agc[i]);
330110364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x0e, (uint8_t)i + 0x80);
330210364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x0e, 0);
330310364SMikore.Li@Sun.COM }
330410364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x80, 0x10);
330510364SMikore.Li@Sun.COM
330610364SMikore.Li@Sun.COM nitems = sizeof (urtw_8225v2_ofdm) / sizeof ((urtw_8225v2_ofdm)[0]);
330710364SMikore.Li@Sun.COM for (i = 0; i < nitems; i++) {
330810364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, i, urtw_8225v2_ofdm[i]);
330910364SMikore.Li@Sun.COM }
331010364SMikore.Li@Sun.COM (void) urtw_8225v2_b_update_chan(sc);
331110364SMikore.Li@Sun.COM
331210364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x97, 0x46);
331310364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0xa4, 0xb6);
331410364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x85, 0xfc);
331510364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_cck_c(sc, 0xc1, 0x88);
331610364SMikore.Li@Sun.COM
331710364SMikore.Li@Sun.COM error = urtw_8225v2_b_rf_set_chan(rf,
331810364SMikore.Li@Sun.COM ieee80211_chan2ieee(&sc->sc_ic, sc->sc_ic.ic_curchan));
331910364SMikore.Li@Sun.COM fail:
332010364SMikore.Li@Sun.COM return (error);
332110364SMikore.Li@Sun.COM }
332210364SMikore.Li@Sun.COM
332310364SMikore.Li@Sun.COM static usbd_status
urtw_8225v2_b_rf_set_chan(struct urtw_rf * rf,int chan)332410364SMikore.Li@Sun.COM urtw_8225v2_b_rf_set_chan(struct urtw_rf *rf, int chan)
332510364SMikore.Li@Sun.COM {
332610364SMikore.Li@Sun.COM struct urtw_softc *sc = rf->rf_sc;
332710364SMikore.Li@Sun.COM int error = 0;
332810364SMikore.Li@Sun.COM
332910364SMikore.Li@Sun.COM urtw_8225v2_b_set_txpwrlvl(sc, chan);
333010364SMikore.Li@Sun.COM error = urtw_8225_write_c(sc, 0x7, urtw_8225_channel[chan]);
333110364SMikore.Li@Sun.COM if (error)
333210364SMikore.Li@Sun.COM goto fail;
333310364SMikore.Li@Sun.COM /*
333410364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187.
333510364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 10);
333610364SMikore.Li@Sun.COM */
333710364SMikore.Li@Sun.COM
333810364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_VO, 0x5114, 0);
333910364SMikore.Li@Sun.COM if (error)
334010364SMikore.Li@Sun.COM goto fail;
334110364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_VI, 0x5114, 0);
334210364SMikore.Li@Sun.COM if (error)
334310364SMikore.Li@Sun.COM goto fail;
334410364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_BE, 0x5114, 0);
334510364SMikore.Li@Sun.COM if (error)
334610364SMikore.Li@Sun.COM goto fail;
334710364SMikore.Li@Sun.COM error = urtw_write16_c(sc, URTW_AC_BK, 0x5114, 0);
334810364SMikore.Li@Sun.COM fail:
334910364SMikore.Li@Sun.COM return (error);
335010364SMikore.Li@Sun.COM }
335110364SMikore.Li@Sun.COM
335210364SMikore.Li@Sun.COM void
urtw_8225v2_b_set_txpwrlvl(struct urtw_softc * sc,int chan)335310364SMikore.Li@Sun.COM urtw_8225v2_b_set_txpwrlvl(struct urtw_softc *sc, int chan)
335410364SMikore.Li@Sun.COM {
335510364SMikore.Li@Sun.COM int i;
335610364SMikore.Li@Sun.COM uint8_t *cck_pwrtable;
335710364SMikore.Li@Sun.COM uint8_t cck_pwrlvl_min, cck_pwrlvl_max, ofdm_pwrlvl_min,
335810364SMikore.Li@Sun.COM ofdm_pwrlvl_max;
335910364SMikore.Li@Sun.COM int8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff;
336010364SMikore.Li@Sun.COM int8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff;
336110364SMikore.Li@Sun.COM
336210364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B_B) {
336310364SMikore.Li@Sun.COM cck_pwrlvl_min = 0;
336410364SMikore.Li@Sun.COM cck_pwrlvl_max = 15;
336510364SMikore.Li@Sun.COM ofdm_pwrlvl_min = 2;
336610364SMikore.Li@Sun.COM ofdm_pwrlvl_max = 17;
336710364SMikore.Li@Sun.COM } else {
336810364SMikore.Li@Sun.COM cck_pwrlvl_min = 7;
336910364SMikore.Li@Sun.COM cck_pwrlvl_max = 22;
337010364SMikore.Li@Sun.COM ofdm_pwrlvl_min = 10;
337110364SMikore.Li@Sun.COM ofdm_pwrlvl_max = 25;
337210364SMikore.Li@Sun.COM }
337310364SMikore.Li@Sun.COM
337410364SMikore.Li@Sun.COM /* CCK power setting */
337510364SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > (cck_pwrlvl_max - cck_pwrlvl_min)) ?
337610364SMikore.Li@Sun.COM cck_pwrlvl_max : (cck_pwrlvl + cck_pwrlvl_min);
337710364SMikore.Li@Sun.COM
337810364SMikore.Li@Sun.COM cck_pwrlvl += sc->sc_txpwr_cck_base;
337910364SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl;
338010364SMikore.Li@Sun.COM cck_pwrlvl = (cck_pwrlvl < 0) ? 0 : cck_pwrlvl;
338110364SMikore.Li@Sun.COM
338210364SMikore.Li@Sun.COM cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 :
338310364SMikore.Li@Sun.COM urtw_8225v2_txpwr_cck;
338410364SMikore.Li@Sun.COM
338510364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B_B) {
338610364SMikore.Li@Sun.COM if (cck_pwrlvl > 7 && cck_pwrlvl <= 11)
338710364SMikore.Li@Sun.COM cck_pwrtable += 8;
338810364SMikore.Li@Sun.COM if (cck_pwrlvl > 11)
338910364SMikore.Li@Sun.COM cck_pwrtable += 16;
339010364SMikore.Li@Sun.COM } else {
339110364SMikore.Li@Sun.COM if (cck_pwrlvl > 5 && cck_pwrlvl <= 11)
339210364SMikore.Li@Sun.COM cck_pwrtable += 8;
339310364SMikore.Li@Sun.COM if (cck_pwrlvl > 12 && cck_pwrlvl <= 17)
339410364SMikore.Li@Sun.COM cck_pwrtable += 16;
339510364SMikore.Li@Sun.COM if (cck_pwrlvl > 17)
339610364SMikore.Li@Sun.COM cck_pwrtable += 24;
339710364SMikore.Li@Sun.COM }
339810364SMikore.Li@Sun.COM
339910364SMikore.Li@Sun.COM for (i = 0; i < 8; i++) {
340010364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_cck_c(sc, 0x44 + i, cck_pwrtable[i]);
340110364SMikore.Li@Sun.COM }
340210364SMikore.Li@Sun.COM
340310364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_CCK,
340410364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1, 0);
340510364SMikore.Li@Sun.COM /*
340610364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187.
340710364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 1);
340810364SMikore.Li@Sun.COM */
340910364SMikore.Li@Sun.COM
341010364SMikore.Li@Sun.COM /* OFDM power setting */
341110364SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ?
341210364SMikore.Li@Sun.COM ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min;
341310364SMikore.Li@Sun.COM
341410364SMikore.Li@Sun.COM ofdm_pwrlvl += sc->sc_txpwr_ofdm_base;
341510364SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl;
341610364SMikore.Li@Sun.COM ofdm_pwrlvl = (ofdm_pwrlvl < 0) ? 0 : ofdm_pwrlvl;
341710364SMikore.Li@Sun.COM
341810364SMikore.Li@Sun.COM (void) urtw_write8_c(sc, URTW_TX_GAIN_OFDM,
341910364SMikore.Li@Sun.COM urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1, 0);
342010364SMikore.Li@Sun.COM
342110364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187B_B) {
342210364SMikore.Li@Sun.COM if (ofdm_pwrlvl <= 11) {
342310364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x60);
342410364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x60);
342510364SMikore.Li@Sun.COM } else {
342610364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x5c);
342710364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x5c);
342810364SMikore.Li@Sun.COM }
342910364SMikore.Li@Sun.COM } else {
343010364SMikore.Li@Sun.COM if (ofdm_pwrlvl <= 11) {
343110364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x5c);
343210364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x5c);
343310364SMikore.Li@Sun.COM } else if (ofdm_pwrlvl <= 17) {
343410364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x54);
343510364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x54);
343610364SMikore.Li@Sun.COM } else {
343710364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x87, 0x50);
343810364SMikore.Li@Sun.COM (void) urtw_8187_write_phy_ofdm_c(sc, 0x89, 0x50);
343910364SMikore.Li@Sun.COM }
344010364SMikore.Li@Sun.COM }
344110364SMikore.Li@Sun.COM
344210364SMikore.Li@Sun.COM /*
344310364SMikore.Li@Sun.COM * Delay removed from 8185 to 8187.
344410364SMikore.Li@Sun.COM * usbd_delay_ms(sc->sc_udev, 1);
344510364SMikore.Li@Sun.COM */
344610364SMikore.Li@Sun.COM }
344710364SMikore.Li@Sun.COM
344810364SMikore.Li@Sun.COM
34499485SMikore.Li@Sun.COM static int
urtw_send(ieee80211com_t * ic,mblk_t * mp,uint8_t type)34509485SMikore.Li@Sun.COM urtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
34519485SMikore.Li@Sun.COM {
34529485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)ic;
34539485SMikore.Li@Sun.COM struct ieee80211_frame *wh;
34549485SMikore.Li@Sun.COM struct ieee80211_key *k;
34559485SMikore.Li@Sun.COM struct ieee80211_node *ni = NULL;
34569485SMikore.Li@Sun.COM uint8_t *buf;
34579485SMikore.Li@Sun.COM mblk_t *m = 0, *m0, *mtx;
34589485SMikore.Li@Sun.COM int off, mblen, xferlen, err = 0, priority = 0;
34599485SMikore.Li@Sun.COM
34609485SMikore.Li@Sun.COM mutex_enter(&sc->tx_lock);
34619485SMikore.Li@Sun.COM priority = (type == IEEE80211_FC0_TYPE_DATA) ?
34629485SMikore.Li@Sun.COM LOW_PRIORITY_PIPE: NORMAL_PRIORITY_PIPE;
34639485SMikore.Li@Sun.COM
34649485SMikore.Li@Sun.COM if (URTW_IS_SUSPENDING(sc)) {
34659485SMikore.Li@Sun.COM err = 0;
34669485SMikore.Li@Sun.COM goto failed;
34679485SMikore.Li@Sun.COM }
34689485SMikore.Li@Sun.COM
34699485SMikore.Li@Sun.COM if (((priority)? sc->sc_tx_normal_queued : sc->sc_tx_low_queued) >=
34709485SMikore.Li@Sun.COM URTW_TX_DATA_LIST_COUNT) {
34719485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT,
34729485SMikore.Li@Sun.COM "urtw_send(): no TX buffer!\n"));
34739485SMikore.Li@Sun.COM sc->sc_tx_nobuf++;
34749485SMikore.Li@Sun.COM err = ENOMEM;
34759485SMikore.Li@Sun.COM goto failed;
34769485SMikore.Li@Sun.COM }
34779485SMikore.Li@Sun.COM
34789485SMikore.Li@Sun.COM m = allocb(URTW_TXBUF_SIZE, BPRI_MED);
34799485SMikore.Li@Sun.COM if (m == NULL) {
34809485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_send(): can't alloc mblk.\n");
34819485SMikore.Li@Sun.COM err = ENOMEM;
34829485SMikore.Li@Sun.COM goto failed;
34839485SMikore.Li@Sun.COM }
34849485SMikore.Li@Sun.COM
34859485SMikore.Li@Sun.COM for (off = 0, m0 = mp; m0 != NULL; m0 = m0->b_cont) {
34869485SMikore.Li@Sun.COM mblen = (uintptr_t)m0->b_wptr - (uintptr_t)m0->b_rptr;
34879485SMikore.Li@Sun.COM (void) bcopy(m0->b_rptr, m->b_rptr + off, mblen);
34889485SMikore.Li@Sun.COM off += mblen;
34899485SMikore.Li@Sun.COM }
34909485SMikore.Li@Sun.COM m->b_wptr += off;
34919485SMikore.Li@Sun.COM
34929485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)m->b_rptr;
34939485SMikore.Li@Sun.COM
34949485SMikore.Li@Sun.COM ni = ieee80211_find_txnode(ic, wh->i_addr1);
34959485SMikore.Li@Sun.COM if (ni == NULL) {
34969485SMikore.Li@Sun.COM err = ENXIO;
34979485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++;
34989485SMikore.Li@Sun.COM goto failed;
34999485SMikore.Li@Sun.COM }
35009485SMikore.Li@Sun.COM
35019485SMikore.Li@Sun.COM if ((type & IEEE80211_FC0_TYPE_MASK) ==
35029485SMikore.Li@Sun.COM IEEE80211_FC0_TYPE_DATA) {
35039485SMikore.Li@Sun.COM (void) ieee80211_encap(ic, m, ni);
35049485SMikore.Li@Sun.COM }
35059485SMikore.Li@Sun.COM
35069485SMikore.Li@Sun.COM if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
35079485SMikore.Li@Sun.COM k = ieee80211_crypto_encap(ic, m);
35089485SMikore.Li@Sun.COM if (k == NULL) {
35099485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++;
35109485SMikore.Li@Sun.COM err = ENXIO;
35119485SMikore.Li@Sun.COM goto failed;
35129485SMikore.Li@Sun.COM }
35139485SMikore.Li@Sun.COM /* packet header may have moved, reset our local pointer */
35149485SMikore.Li@Sun.COM wh = (struct ieee80211_frame *)m->b_rptr;
35159485SMikore.Li@Sun.COM }
35169485SMikore.Li@Sun.COM
351710364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187)
351810364SMikore.Li@Sun.COM xferlen = MBLKL(m) + 4 * 3;
351910364SMikore.Li@Sun.COM else
352010364SMikore.Li@Sun.COM xferlen = MBLKL(m) + 4 * 8;
352110364SMikore.Li@Sun.COM
35229485SMikore.Li@Sun.COM if ((0 == xferlen % 64) || (0 == xferlen % 512))
35239485SMikore.Li@Sun.COM xferlen += 1;
35249485SMikore.Li@Sun.COM
35259485SMikore.Li@Sun.COM mtx = allocb(xferlen, BPRI_MED);
35269485SMikore.Li@Sun.COM buf = mtx->b_rptr;
35279485SMikore.Li@Sun.COM
35289485SMikore.Li@Sun.COM bzero(buf, xferlen);
35299485SMikore.Li@Sun.COM buf[0] = MBLKL(m) & 0xff;
35309485SMikore.Li@Sun.COM buf[1] = (MBLKL(m) & 0x0f00) >> 8;
35319485SMikore.Li@Sun.COM buf[1] |= (1 << 7);
35329485SMikore.Li@Sun.COM
35339485SMikore.Li@Sun.COM /* XXX sc_preamble_mode is always 2. */
35349485SMikore.Li@Sun.COM if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG)
35359485SMikore.Li@Sun.COM buf[2] |= (1 << 1);
35369485SMikore.Li@Sun.COM /* RTS rate - 10 means we use a basic rate. */
35379485SMikore.Li@Sun.COM buf[2] |= (urtw_rate2rtl(2) << 3);
35389485SMikore.Li@Sun.COM /*
35399485SMikore.Li@Sun.COM * XXX currently TX rate control depends on the rate value of
35409485SMikore.Li@Sun.COM * RX descriptor because I don't know how to we can control TX rate
35419485SMikore.Li@Sun.COM * in more smart way. Please fix me you find a thing.
35429485SMikore.Li@Sun.COM */
35439485SMikore.Li@Sun.COM if ((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) {
35449485SMikore.Li@Sun.COM buf[3] = urtw_rate2rtl(MAX(2, urtw_get_rate(ic)));
35459485SMikore.Li@Sun.COM } else
354610603SMikore.Li@Sun.COM buf[3] = 0;
354710364SMikore.Li@Sun.COM
354810364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
354910364SMikore.Li@Sun.COM buf[8] = 3; /* CW minimum */
355010364SMikore.Li@Sun.COM buf[8] |= (7 << 4); /* CW maximum */
355110364SMikore.Li@Sun.COM buf[9] |= 11; /* retry limitation */
355210364SMikore.Li@Sun.COM bcopy(m->b_rptr, &buf[12], MBLKL(m));
355310364SMikore.Li@Sun.COM } else {
355410364SMikore.Li@Sun.COM buf[21] |= 11; /* retry limitation */
355510364SMikore.Li@Sun.COM bcopy(m->b_rptr, &buf[32], MBLKL(m));
355610364SMikore.Li@Sun.COM }
35579485SMikore.Li@Sun.COM
35589485SMikore.Li@Sun.COM (void) urtw_led_ctl(sc, URTW_LED_CTL_TX);
35599485SMikore.Li@Sun.COM mtx->b_wptr = mtx->b_rptr + xferlen;
35609485SMikore.Li@Sun.COM
35619485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_XMIT, (sc->sc_dev, CE_CONT,
356210364SMikore.Li@Sun.COM "sending frame len=%u rate=%u xfer len=%u\n",
35639485SMikore.Li@Sun.COM MBLKL(m), buf[3], xferlen));
35649485SMikore.Li@Sun.COM
35659485SMikore.Li@Sun.COM err = urtw_tx_start(sc, mtx, priority);
35669485SMikore.Li@Sun.COM if (!err) {
35679485SMikore.Li@Sun.COM ic->ic_stats.is_tx_frags++;
35689485SMikore.Li@Sun.COM ic->ic_stats.is_tx_bytes += MBLKL(m);
35699485SMikore.Li@Sun.COM } else {
35709485SMikore.Li@Sun.COM ic->ic_stats.is_tx_failed++;
35719485SMikore.Li@Sun.COM }
35729485SMikore.Li@Sun.COM
35739485SMikore.Li@Sun.COM failed:
35749485SMikore.Li@Sun.COM if (ni != NULL)
35759485SMikore.Li@Sun.COM ieee80211_free_node(ni);
35769485SMikore.Li@Sun.COM
35779485SMikore.Li@Sun.COM if ((mp) &&
35789485SMikore.Li@Sun.COM ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA ||
35799485SMikore.Li@Sun.COM err == DDI_SUCCESS)) {
35809485SMikore.Li@Sun.COM freemsg(mp);
35819485SMikore.Li@Sun.COM }
35829485SMikore.Li@Sun.COM if (m) freemsg(m);
35839485SMikore.Li@Sun.COM
35849485SMikore.Li@Sun.COM if (((type & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) &&
35859485SMikore.Li@Sun.COM (err != 0)) {
35869485SMikore.Li@Sun.COM sc->sc_need_sched = 1;
35879485SMikore.Li@Sun.COM }
35889485SMikore.Li@Sun.COM mutex_exit(&sc->tx_lock);
35899485SMikore.Li@Sun.COM return (err);
35909485SMikore.Li@Sun.COM }
35919485SMikore.Li@Sun.COM
35929485SMikore.Li@Sun.COM static void
urtw_next_scan(void * arg)35939485SMikore.Li@Sun.COM urtw_next_scan(void *arg)
35949485SMikore.Li@Sun.COM {
35959485SMikore.Li@Sun.COM ieee80211com_t *ic = arg;
35969485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
35979485SMikore.Li@Sun.COM
35989485SMikore.Li@Sun.COM if (URTW_IS_NOT_RUNNING(sc)) {
35999485SMikore.Li@Sun.COM sc->sc_scan_id = 0;
36009485SMikore.Li@Sun.COM return;
36019485SMikore.Li@Sun.COM }
36029485SMikore.Li@Sun.COM
36039485SMikore.Li@Sun.COM if (ic->ic_state == IEEE80211_S_SCAN) {
36049485SMikore.Li@Sun.COM (void) ieee80211_next_scan(ic);
36059485SMikore.Li@Sun.COM }
36069485SMikore.Li@Sun.COM sc->sc_scan_id = 0;
36079485SMikore.Li@Sun.COM }
36089485SMikore.Li@Sun.COM
36099485SMikore.Li@Sun.COM static void
urtw_led_launch(void * arg)36109485SMikore.Li@Sun.COM urtw_led_launch(void *arg)
36119485SMikore.Li@Sun.COM {
36129485SMikore.Li@Sun.COM struct urtw_softc *sc = arg;
36139485SMikore.Li@Sun.COM ieee80211com_t *ic = &sc->sc_ic;
36149485SMikore.Li@Sun.COM int error = 0;
36159485SMikore.Li@Sun.COM
36169485SMikore.Li@Sun.COM URTW_LEDLOCK(sc);
36179485SMikore.Li@Sun.COM if ((sc->sc_strategy != URTW_SW_LED_MODE0) ||
36189485SMikore.Li@Sun.COM URTW_IS_NOT_RUNNING(sc) ||
36199485SMikore.Li@Sun.COM URTW_IS_SUSPENDING(sc)) {
36209485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
36219485SMikore.Li@Sun.COM "failed process LED strategy 0x%x, run?%d",
36229485SMikore.Li@Sun.COM sc->sc_strategy,
36239485SMikore.Li@Sun.COM sc->sc_flags));
36249485SMikore.Li@Sun.COM sc->sc_led_ch = 0;
36259485SMikore.Li@Sun.COM sc->sc_gpio_ledinprogress = 0;
36269485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc);
36279485SMikore.Li@Sun.COM return;
36289485SMikore.Li@Sun.COM }
36299485SMikore.Li@Sun.COM error = urtw_led_blink(sc);
36309485SMikore.Li@Sun.COM if (error) {
36319485SMikore.Li@Sun.COM sc->sc_led_ch = timeout(urtw_led_launch, (void *)sc,
36329485SMikore.Li@Sun.COM drv_usectohz((ic->ic_state == IEEE80211_S_RUN) ?
36339485SMikore.Li@Sun.COM URTW_LED_LINKON_BLINK: URTW_LED_LINKOFF_BLINK));
36349485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
36359485SMikore.Li@Sun.COM "try again led launch"));
36369485SMikore.Li@Sun.COM } else {
36379485SMikore.Li@Sun.COM sc->sc_led_ch = 0;
36389485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_LED, (sc->sc_dev, CE_CONT,
36399485SMikore.Li@Sun.COM "exit led launch"));
36409485SMikore.Li@Sun.COM }
36419485SMikore.Li@Sun.COM URTW_LEDUNLOCK(sc);
36429485SMikore.Li@Sun.COM }
36439485SMikore.Li@Sun.COM
36449485SMikore.Li@Sun.COM static int
urtw_newstate(struct ieee80211com * ic,enum ieee80211_state nstate,int arg)36459485SMikore.Li@Sun.COM urtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
36469485SMikore.Li@Sun.COM {
36479485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)ic;
36489485SMikore.Li@Sun.COM struct ieee80211_node *ni;
36499485SMikore.Li@Sun.COM int error = 0;
36509485SMikore.Li@Sun.COM
36519485SMikore.Li@Sun.COM if (sc->sc_scan_id != 0) {
36529485SMikore.Li@Sun.COM (void) untimeout(sc->sc_scan_id);
36539485SMikore.Li@Sun.COM sc->sc_scan_id = 0;
36549485SMikore.Li@Sun.COM }
36559485SMikore.Li@Sun.COM URTW_LOCK(sc);
36569485SMikore.Li@Sun.COM switch (nstate) {
36579485SMikore.Li@Sun.COM case IEEE80211_S_INIT:
36589485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
36599485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "-> IEEE80211_S_INIT...arg(%d)\n",
36609485SMikore.Li@Sun.COM arg));
366110364SMikore.Li@Sun.COM if (sc->sc_flags & URTW_FLAG_HP)
366210364SMikore.Li@Sun.COM break;
36639485SMikore.Li@Sun.COM (void) urtw_update_msr(sc, nstate);
36649485SMikore.Li@Sun.COM (void) urtw_led_off(sc, URTW_LED_GPIO);
36659485SMikore.Li@Sun.COM break;
36669485SMikore.Li@Sun.COM
36679485SMikore.Li@Sun.COM case IEEE80211_S_SCAN:
36689485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
36699485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
36709485SMikore.Li@Sun.COM "-> IEEE80211_S_SCAN...arg(%d)...[%d]\n",
36719485SMikore.Li@Sun.COM arg, ieee80211_chan2ieee(ic, ic->ic_curchan)));
36729485SMikore.Li@Sun.COM error = urtw_set_channel(sc);
36739485SMikore.Li@Sun.COM if (error) {
36749485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
36759485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "scan setchan failed"));
36769485SMikore.Li@Sun.COM break;
36779485SMikore.Li@Sun.COM }
36789485SMikore.Li@Sun.COM sc->sc_scan_id = timeout(urtw_next_scan, (void *)sc,
36799485SMikore.Li@Sun.COM drv_usectohz(sc->dwelltime * 1000));
36809485SMikore.Li@Sun.COM break;
36819485SMikore.Li@Sun.COM
36829485SMikore.Li@Sun.COM case IEEE80211_S_AUTH:
36839485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT,
368410364SMikore.Li@Sun.COM "-> IEEE80211_S_AUTH ...arg(%d), chan (%d)\n", arg,
368510364SMikore.Li@Sun.COM ieee80211_chan2ieee(ic, ic->ic_curchan)));
36869485SMikore.Li@Sun.COM error = urtw_set_channel(sc);
36879485SMikore.Li@Sun.COM if (error) {
36889485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
36899485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "auth setchan failed"));
36909485SMikore.Li@Sun.COM }
36919485SMikore.Li@Sun.COM break;
36929485SMikore.Li@Sun.COM
36939485SMikore.Li@Sun.COM case IEEE80211_S_ASSOC:
36949485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT,
369510364SMikore.Li@Sun.COM "-> IEEE80211_S_ASSOC ...arg(%d), chan (%d)\n", arg,
369610364SMikore.Li@Sun.COM ieee80211_chan2ieee(ic, ic->ic_curchan)));
36979485SMikore.Li@Sun.COM error = urtw_set_channel(sc);
36989485SMikore.Li@Sun.COM if (error) {
36999485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
37009485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "assoc setchan failed"));
37019485SMikore.Li@Sun.COM }
37029485SMikore.Li@Sun.COM break;
37039485SMikore.Li@Sun.COM
37049485SMikore.Li@Sun.COM case IEEE80211_S_RUN:
37059485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
370610364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
370710364SMikore.Li@Sun.COM "-> IEEE80211_S_RUN ...arg(%d), chan (%d)\n",
370810364SMikore.Li@Sun.COM arg, ieee80211_chan2ieee(ic, ic->ic_curchan)));
37099485SMikore.Li@Sun.COM error = urtw_set_channel(sc);
37109485SMikore.Li@Sun.COM if (error) {
37119485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE,
37129485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "run setchan failed"));
37139485SMikore.Li@Sun.COM goto fail;
37149485SMikore.Li@Sun.COM }
37159485SMikore.Li@Sun.COM ni = ic->ic_bss;
37169485SMikore.Li@Sun.COM /* setting bssid. */
37179485SMikore.Li@Sun.COM (void) urtw_write32_c(sc, URTW_BSSID,
371810364SMikore.Li@Sun.COM ((uint32_t *)(uintptr_t)ni->in_bssid)[0], 0);
37199485SMikore.Li@Sun.COM (void) urtw_write16_c(sc, URTW_BSSID + 4,
372010364SMikore.Li@Sun.COM ((uint16_t *)(uintptr_t)ni->in_bssid)[2], 0);
37219485SMikore.Li@Sun.COM (void) urtw_update_msr(sc, nstate);
37229485SMikore.Li@Sun.COM
37239485SMikore.Li@Sun.COM ni->in_txrate = ni->in_rates.ir_nrates - 1;
37249485SMikore.Li@Sun.COM break;
37259485SMikore.Li@Sun.COM }
37269485SMikore.Li@Sun.COM fail:
37279485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
37289485SMikore.Li@Sun.COM
372910364SMikore.Li@Sun.COM if (error) {
373010364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_STATE, (sc->sc_dev, CE_CONT,
373110364SMikore.Li@Sun.COM "-> newstate error...arg(%d)\n", error));
37329485SMikore.Li@Sun.COM return (EIO);
373310364SMikore.Li@Sun.COM }
37349485SMikore.Li@Sun.COM error = sc->sc_newstate(ic, nstate, arg);
37359485SMikore.Li@Sun.COM return (error);
37369485SMikore.Li@Sun.COM }
37379485SMikore.Li@Sun.COM
37389485SMikore.Li@Sun.COM static void
urtw_close_pipes(struct urtw_softc * sc)37399485SMikore.Li@Sun.COM urtw_close_pipes(struct urtw_softc *sc)
37409485SMikore.Li@Sun.COM {
37419485SMikore.Li@Sun.COM usb_flags_t flags = USB_FLAGS_SLEEP;
37429485SMikore.Li@Sun.COM
37439485SMikore.Li@Sun.COM if (sc->sc_rxpipe != NULL) {
37449485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev,
37459485SMikore.Li@Sun.COM sc->sc_rxpipe, flags, NULL, 0);
37469485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev,
37479485SMikore.Li@Sun.COM sc->sc_rxpipe, flags, NULL, 0);
37489485SMikore.Li@Sun.COM sc->sc_rxpipe = NULL;
37499485SMikore.Li@Sun.COM }
37509485SMikore.Li@Sun.COM
37519485SMikore.Li@Sun.COM if (sc->sc_txpipe_low != NULL) {
37529485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev,
37539485SMikore.Li@Sun.COM sc->sc_txpipe_low, flags, NULL, 0);
37549485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev,
37559485SMikore.Li@Sun.COM sc->sc_txpipe_low, flags, NULL, 0);
37569485SMikore.Li@Sun.COM sc->sc_txpipe_low = NULL;
37579485SMikore.Li@Sun.COM }
37589485SMikore.Li@Sun.COM
37599485SMikore.Li@Sun.COM if (sc->sc_txpipe_normal != NULL) {
37609485SMikore.Li@Sun.COM usb_pipe_reset(sc->sc_dev,
37619485SMikore.Li@Sun.COM sc->sc_txpipe_normal, flags, NULL, 0);
37629485SMikore.Li@Sun.COM usb_pipe_close(sc->sc_dev,
37639485SMikore.Li@Sun.COM sc->sc_txpipe_normal, flags, NULL, 0);
37649485SMikore.Li@Sun.COM sc->sc_txpipe_normal = NULL;
37659485SMikore.Li@Sun.COM }
37669485SMikore.Li@Sun.COM }
37679485SMikore.Li@Sun.COM
37689485SMikore.Li@Sun.COM static int
urtw_open_pipes(struct urtw_softc * sc)37699485SMikore.Li@Sun.COM urtw_open_pipes(struct urtw_softc *sc)
37709485SMikore.Li@Sun.COM {
37719485SMikore.Li@Sun.COM usb_ep_data_t *ep_node;
37729485SMikore.Li@Sun.COM usb_pipe_policy_t policy;
37739485SMikore.Li@Sun.COM int err;
377410364SMikore.Li@Sun.COM uint_t skip = 0;
37759485SMikore.Li@Sun.COM
37769485SMikore.Li@Sun.COM if (sc->sc_rxpipe || sc->sc_txpipe_low || sc->sc_txpipe_normal)
37779485SMikore.Li@Sun.COM return (USB_SUCCESS);
37789485SMikore.Li@Sun.COM
377910364SMikore.Li@Sun.COM if ((sc->sc_hwrev & URTW_HWREV_8187) == 0) {
378010364SMikore.Li@Sun.COM skip = 2;
378110364SMikore.Li@Sun.COM }
37829485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0,
378310364SMikore.Li@Sun.COM LOW_PRIORITY_PIPE + skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
37849485SMikore.Li@Sun.COM
37859485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t));
37869485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT;
37879485SMikore.Li@Sun.COM
37889485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev,
37899485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
37909485SMikore.Li@Sun.COM &sc->sc_txpipe_low)) != USB_SUCCESS) {
37919485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT,
37929485SMikore.Li@Sun.COM "urtw_open_pipes(): %x low priority pipe open failed\n",
37939485SMikore.Li@Sun.COM err));
37949485SMikore.Li@Sun.COM goto fail;
37959485SMikore.Li@Sun.COM }
37969485SMikore.Li@Sun.COM
37979485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0,
379810364SMikore.Li@Sun.COM NORMAL_PRIORITY_PIPE + skip, USB_EP_ATTR_BULK, USB_EP_DIR_OUT);
37999485SMikore.Li@Sun.COM
38009485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t));
38019485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_TX_DATA_LIST_COUNT;
38029485SMikore.Li@Sun.COM
38039485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev,
38049485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
38059485SMikore.Li@Sun.COM &sc->sc_txpipe_normal)) != USB_SUCCESS) {
38069485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT,
38079485SMikore.Li@Sun.COM "urtw_open_pipes(): %x failed to open high tx pipe\n",
38089485SMikore.Li@Sun.COM err));
38099485SMikore.Li@Sun.COM goto fail;
38109485SMikore.Li@Sun.COM }
38119485SMikore.Li@Sun.COM
38129485SMikore.Li@Sun.COM ep_node = usb_lookup_ep_data(sc->sc_dev, sc->sc_udev, 0, 0, 0,
38139485SMikore.Li@Sun.COM USB_EP_ATTR_BULK, USB_EP_DIR_IN);
38149485SMikore.Li@Sun.COM
38159485SMikore.Li@Sun.COM bzero(&policy, sizeof (usb_pipe_policy_t));
38169485SMikore.Li@Sun.COM policy.pp_max_async_reqs = URTW_RX_DATA_LIST_COUNT;
38179485SMikore.Li@Sun.COM
38189485SMikore.Li@Sun.COM if ((err = usb_pipe_open(sc->sc_dev,
38199485SMikore.Li@Sun.COM &ep_node->ep_descr, &policy, USB_FLAGS_SLEEP,
38209485SMikore.Li@Sun.COM &sc->sc_rxpipe)) != USB_SUCCESS) {
38219485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT,
38229485SMikore.Li@Sun.COM "urtw_open_pipes(): %x failed to open rx pipe\n", err));
38239485SMikore.Li@Sun.COM goto fail;
38249485SMikore.Li@Sun.COM }
38259485SMikore.Li@Sun.COM
38269485SMikore.Li@Sun.COM return (USB_SUCCESS);
38279485SMikore.Li@Sun.COM
38289485SMikore.Li@Sun.COM fail:
38299485SMikore.Li@Sun.COM urtw_close_pipes(sc);
38309485SMikore.Li@Sun.COM return (USB_FAILURE);
38319485SMikore.Li@Sun.COM }
38329485SMikore.Li@Sun.COM
38339485SMikore.Li@Sun.COM static int
urtw_tx_start(struct urtw_softc * sc,mblk_t * mp,int priority)38349485SMikore.Li@Sun.COM urtw_tx_start(struct urtw_softc *sc, mblk_t *mp, int priority)
38359485SMikore.Li@Sun.COM {
38369485SMikore.Li@Sun.COM usb_bulk_req_t *req;
38379485SMikore.Li@Sun.COM int err;
38389485SMikore.Li@Sun.COM
38399485SMikore.Li@Sun.COM req = usb_alloc_bulk_req(sc->sc_dev, 0, USB_FLAGS_SLEEP);
38409485SMikore.Li@Sun.COM if (req == NULL) {
38419485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT,
38429485SMikore.Li@Sun.COM "urtw_tx_start(): failed to allocate req"));
38439485SMikore.Li@Sun.COM freemsg(mp);
38449485SMikore.Li@Sun.COM return (-1);
38459485SMikore.Li@Sun.COM }
38469485SMikore.Li@Sun.COM
38479485SMikore.Li@Sun.COM req->bulk_len = MBLKL(mp);
38489485SMikore.Li@Sun.COM req->bulk_data = mp;
38499485SMikore.Li@Sun.COM req->bulk_client_private = (usb_opaque_t)sc;
38509485SMikore.Li@Sun.COM req->bulk_timeout = URTW_TX_TIMEOUT;
38519485SMikore.Li@Sun.COM req->bulk_attributes = USB_ATTRS_AUTOCLEARING;
38529485SMikore.Li@Sun.COM req->bulk_cb = (priority)?urtw_txeof_normal : urtw_txeof_low;
38539485SMikore.Li@Sun.COM req->bulk_exc_cb = (priority)?urtw_txeof_normal: urtw_txeof_low;
38549485SMikore.Li@Sun.COM req->bulk_completion_reason = 0;
38559485SMikore.Li@Sun.COM req->bulk_cb_flags = 0;
38569485SMikore.Li@Sun.COM
38579485SMikore.Li@Sun.COM if ((err = usb_pipe_bulk_xfer(
38589485SMikore.Li@Sun.COM (priority)?sc->sc_txpipe_normal:sc->sc_txpipe_low, req, 0))
38599485SMikore.Li@Sun.COM != USB_SUCCESS) {
38609485SMikore.Li@Sun.COM sc->sc_ic.ic_stats.is_tx_failed++;
38619485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_TX_PROC, (sc->sc_dev, CE_CONT,
38629485SMikore.Li@Sun.COM "urtw_tx_start: failed to do tx xfer, %d", err));
38639485SMikore.Li@Sun.COM usb_free_bulk_req(req);
38649485SMikore.Li@Sun.COM return (EIO);
38659485SMikore.Li@Sun.COM }
38669485SMikore.Li@Sun.COM
38679485SMikore.Li@Sun.COM if (priority) {
38689485SMikore.Li@Sun.COM sc->sc_tx_normal_queued++;
38699485SMikore.Li@Sun.COM } else {
38709485SMikore.Li@Sun.COM sc->sc_tx_low_queued++;
38719485SMikore.Li@Sun.COM }
38729485SMikore.Li@Sun.COM
38739485SMikore.Li@Sun.COM return (0);
38749485SMikore.Li@Sun.COM }
38759485SMikore.Li@Sun.COM
38769485SMikore.Li@Sun.COM static int
urtw_rx_start(struct urtw_softc * sc)38779485SMikore.Li@Sun.COM urtw_rx_start(struct urtw_softc *sc)
38789485SMikore.Li@Sun.COM {
38799485SMikore.Li@Sun.COM usb_bulk_req_t *req;
38809485SMikore.Li@Sun.COM int err;
38819485SMikore.Li@Sun.COM
38829485SMikore.Li@Sun.COM req = usb_alloc_bulk_req(sc->sc_dev, URTW_RXBUF_SIZE, USB_FLAGS_SLEEP);
38839485SMikore.Li@Sun.COM if (req == NULL) {
38849485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RECV, (sc->sc_dev, CE_CONT,
38859485SMikore.Li@Sun.COM "urtw_rx_start(): failed to allocate req"));
38869485SMikore.Li@Sun.COM return (-1);
38879485SMikore.Li@Sun.COM }
38889485SMikore.Li@Sun.COM
38899485SMikore.Li@Sun.COM req->bulk_len = URTW_RXBUF_SIZE;
38909485SMikore.Li@Sun.COM req->bulk_client_private = (usb_opaque_t)sc;
38919485SMikore.Li@Sun.COM req->bulk_timeout = 0;
38929485SMikore.Li@Sun.COM req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK |
38939485SMikore.Li@Sun.COM USB_ATTRS_AUTOCLEARING;
38949485SMikore.Li@Sun.COM req->bulk_cb = urtw_rxeof;
38959485SMikore.Li@Sun.COM req->bulk_exc_cb = urtw_rxeof;
38969485SMikore.Li@Sun.COM req->bulk_completion_reason = 0;
38979485SMikore.Li@Sun.COM req->bulk_cb_flags = 0;
38989485SMikore.Li@Sun.COM
38999485SMikore.Li@Sun.COM err = usb_pipe_bulk_xfer(sc->sc_rxpipe, req, 0);
39009485SMikore.Li@Sun.COM
39019485SMikore.Li@Sun.COM if (err != USB_SUCCESS) {
39029485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_RECV, (sc->sc_dev, CE_CONT,
39039485SMikore.Li@Sun.COM "urtw_rx_start: failed to do rx xfer, %d", err));
39049485SMikore.Li@Sun.COM usb_free_bulk_req(req);
39059485SMikore.Li@Sun.COM return (-1);
39069485SMikore.Li@Sun.COM }
39079485SMikore.Li@Sun.COM
39089485SMikore.Li@Sun.COM mutex_enter(&sc->rx_lock);
39099485SMikore.Li@Sun.COM sc->rx_queued++;
39109485SMikore.Li@Sun.COM mutex_exit(&sc->rx_lock);
39119485SMikore.Li@Sun.COM
39129485SMikore.Li@Sun.COM return (0);
39139485SMikore.Li@Sun.COM }
39149485SMikore.Li@Sun.COM
39159485SMikore.Li@Sun.COM static int
urtw_disconnect(dev_info_t * devinfo)39169485SMikore.Li@Sun.COM urtw_disconnect(dev_info_t *devinfo)
39179485SMikore.Li@Sun.COM {
39189485SMikore.Li@Sun.COM struct urtw_softc *sc;
39199485SMikore.Li@Sun.COM
39209485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo));
39219485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HOTPLUG,
39229485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw_offline()\n"));
39239485SMikore.Li@Sun.COM
39249485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc)) {
39259485SMikore.Li@Sun.COM urtw_stop(sc);
39269485SMikore.Li@Sun.COM URTW_LOCK(sc);
39279485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE;
39289485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
39299485SMikore.Li@Sun.COM }
393010364SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_HP;
393110364SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
393210364SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic);
39339485SMikore.Li@Sun.COM return (DDI_SUCCESS);
39349485SMikore.Li@Sun.COM }
39359485SMikore.Li@Sun.COM
39369485SMikore.Li@Sun.COM static int
urtw_reconnect(dev_info_t * devinfo)39379485SMikore.Li@Sun.COM urtw_reconnect(dev_info_t *devinfo)
39389485SMikore.Li@Sun.COM {
39399485SMikore.Li@Sun.COM struct urtw_softc *sc;
39409485SMikore.Li@Sun.COM int error = 0;
39419485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo));
39429485SMikore.Li@Sun.COM if (usb_check_same_device(sc->sc_dev, NULL, USB_LOG_L2, -1,
39439485SMikore.Li@Sun.COM USB_CHK_ALL, NULL) != USB_SUCCESS)
39449485SMikore.Li@Sun.COM return (DDI_FAILURE);
39459485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HOTPLUG, (sc->sc_dev, CE_CONT,
39469485SMikore.Li@Sun.COM "urtw_online()\n"));
394710364SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_HP;
39489485SMikore.Li@Sun.COM if (URTW_IS_PLUGIN_ONLINE(sc)) {
394910364SMikore.Li@Sun.COM error = sc->urtw_init(sc);
39509485SMikore.Li@Sun.COM if (!error) {
39519485SMikore.Li@Sun.COM URTW_LOCK(sc);
39529485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE;
39539485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
39549485SMikore.Li@Sun.COM }
39559485SMikore.Li@Sun.COM }
395610364SMikore.Li@Sun.COM return (error? DDI_FAILURE: DDI_SUCCESS);
39579485SMikore.Li@Sun.COM }
39589485SMikore.Li@Sun.COM
39599485SMikore.Li@Sun.COM static mblk_t *
urtw_m_tx(void * arg,mblk_t * mp)39609485SMikore.Li@Sun.COM urtw_m_tx(void *arg, mblk_t *mp)
39619485SMikore.Li@Sun.COM {
39629485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
39639485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
39649485SMikore.Li@Sun.COM mblk_t *next;
39659485SMikore.Li@Sun.COM
39669485SMikore.Li@Sun.COM if ((ic->ic_state != IEEE80211_S_RUN) ||
39679485SMikore.Li@Sun.COM URTW_IS_SUSPENDING(sc)) {
39689485SMikore.Li@Sun.COM freemsgchain(mp);
39699485SMikore.Li@Sun.COM return (NULL);
39709485SMikore.Li@Sun.COM }
39719485SMikore.Li@Sun.COM
39729485SMikore.Li@Sun.COM while (mp != NULL) {
39739485SMikore.Li@Sun.COM next = mp->b_next;
39749485SMikore.Li@Sun.COM mp->b_next = NULL;
39759485SMikore.Li@Sun.COM if (urtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA) != DDI_SUCCESS) {
39769485SMikore.Li@Sun.COM mp->b_next = next;
39779485SMikore.Li@Sun.COM break;
39789485SMikore.Li@Sun.COM }
39799485SMikore.Li@Sun.COM mp = next;
39809485SMikore.Li@Sun.COM }
39819485SMikore.Li@Sun.COM return (mp);
39829485SMikore.Li@Sun.COM }
39839485SMikore.Li@Sun.COM
39849485SMikore.Li@Sun.COM static int
urtw_m_start(void * arg)39859485SMikore.Li@Sun.COM urtw_m_start(void *arg)
39869485SMikore.Li@Sun.COM {
39879485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
39889485SMikore.Li@Sun.COM int error = 0;
39899485SMikore.Li@Sun.COM
39909485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE,
399110364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw_m_start\n"));
399210364SMikore.Li@Sun.COM error = sc->urtw_init(sc);
39939485SMikore.Li@Sun.COM return (error);
39949485SMikore.Li@Sun.COM }
39959485SMikore.Li@Sun.COM
39969485SMikore.Li@Sun.COM static void
urtw_m_stop(void * arg)39979485SMikore.Li@Sun.COM urtw_m_stop(void *arg)
39989485SMikore.Li@Sun.COM {
39999485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
40009485SMikore.Li@Sun.COM
40019485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE, (sc->sc_dev, CE_CONT,
40029485SMikore.Li@Sun.COM "urtw_m_stop()\n"));
40039485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
40049485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic);
40059485SMikore.Li@Sun.COM (void) urtw_stop(sc);
40069485SMikore.Li@Sun.COM }
40079485SMikore.Li@Sun.COM
40089485SMikore.Li@Sun.COM /*ARGSUSED*/
40099485SMikore.Li@Sun.COM static int
urtw_m_unicst(void * arg,const uint8_t * macaddr)40109485SMikore.Li@Sun.COM urtw_m_unicst(void *arg, const uint8_t *macaddr)
40119485SMikore.Li@Sun.COM {
40129485SMikore.Li@Sun.COM return (ENOTSUP);
40139485SMikore.Li@Sun.COM }
40149485SMikore.Li@Sun.COM
40159485SMikore.Li@Sun.COM /*ARGSUSED*/
40169485SMikore.Li@Sun.COM static int
urtw_m_multicst(void * arg,boolean_t add,const uint8_t * macaddr)40179485SMikore.Li@Sun.COM urtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
40189485SMikore.Li@Sun.COM {
40199485SMikore.Li@Sun.COM return (ENOTSUP);
40209485SMikore.Li@Sun.COM }
40219485SMikore.Li@Sun.COM
40229485SMikore.Li@Sun.COM /*ARGSUSED*/
40239485SMikore.Li@Sun.COM static int
urtw_m_promisc(void * arg,boolean_t on)40249485SMikore.Li@Sun.COM urtw_m_promisc(void *arg, boolean_t on)
40259485SMikore.Li@Sun.COM {
40269485SMikore.Li@Sun.COM return (0);
40279485SMikore.Li@Sun.COM }
40289485SMikore.Li@Sun.COM
40299485SMikore.Li@Sun.COM static int
urtw_m_getprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,void * wldp_buf)403010364SMikore.Li@Sun.COM urtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
4031*11878SVenu.Iyer@Sun.COM uint_t wldp_length, void *wldp_buf)
403210364SMikore.Li@Sun.COM {
403310364SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
403410364SMikore.Li@Sun.COM int err = 0;
403510364SMikore.Li@Sun.COM
403610364SMikore.Li@Sun.COM err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num,
4037*11878SVenu.Iyer@Sun.COM wldp_length, wldp_buf);
403810364SMikore.Li@Sun.COM return (err);
403910364SMikore.Li@Sun.COM }
404010364SMikore.Li@Sun.COM
4041*11878SVenu.Iyer@Sun.COM static void
urtw_m_propinfo(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,mac_prop_info_handle_t mph)4042*11878SVenu.Iyer@Sun.COM urtw_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
4043*11878SVenu.Iyer@Sun.COM mac_prop_info_handle_t mph)
4044*11878SVenu.Iyer@Sun.COM {
4045*11878SVenu.Iyer@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
4046*11878SVenu.Iyer@Sun.COM
4047*11878SVenu.Iyer@Sun.COM ieee80211_propinfo(&sc->sc_ic, pr_name, wldp_pr_num, mph);
4048*11878SVenu.Iyer@Sun.COM }
4049*11878SVenu.Iyer@Sun.COM
405010364SMikore.Li@Sun.COM static int
urtw_m_setprop(void * arg,const char * pr_name,mac_prop_id_t wldp_pr_num,uint_t wldp_length,const void * wldp_buf)40519485SMikore.Li@Sun.COM urtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
40529485SMikore.Li@Sun.COM uint_t wldp_length, const void *wldp_buf)
40539485SMikore.Li@Sun.COM {
40549485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
40559485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
40569485SMikore.Li@Sun.COM int err;
40579485SMikore.Li@Sun.COM
40589485SMikore.Li@Sun.COM err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
40599485SMikore.Li@Sun.COM wldp_length, wldp_buf);
406010364SMikore.Li@Sun.COM URTW_LOCK(sc);
40619485SMikore.Li@Sun.COM if (err == ENETRESET) {
406210364SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && ic->ic_des_esslen) {
406310364SMikore.Li@Sun.COM URTW_UNLOCK(sc);
406410364SMikore.Li@Sun.COM err = sc->urtw_init(sc);
406510364SMikore.Li@Sun.COM if (err) {
406610364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE,
406710364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
406810364SMikore.Li@Sun.COM "urtw: setprop failed\n"));
406910364SMikore.Li@Sun.COM return (err);
407010364SMikore.Li@Sun.COM }
40719485SMikore.Li@Sun.COM (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
407210364SMikore.Li@Sun.COM URTW_LOCK(sc);
40739485SMikore.Li@Sun.COM }
40749485SMikore.Li@Sun.COM err = 0;
40759485SMikore.Li@Sun.COM }
407610364SMikore.Li@Sun.COM URTW_UNLOCK(sc);
40779485SMikore.Li@Sun.COM return (err);
40789485SMikore.Li@Sun.COM }
40799485SMikore.Li@Sun.COM
40809485SMikore.Li@Sun.COM static void
urtw_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)40819485SMikore.Li@Sun.COM urtw_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
40829485SMikore.Li@Sun.COM {
40839485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
40849485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
40859485SMikore.Li@Sun.COM int err;
40869485SMikore.Li@Sun.COM
40879485SMikore.Li@Sun.COM err = ieee80211_ioctl(ic, wq, mp);
408810364SMikore.Li@Sun.COM URTW_LOCK(sc);
40899485SMikore.Li@Sun.COM if (err == ENETRESET) {
409010364SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc) && ic->ic_des_esslen) {
409110364SMikore.Li@Sun.COM URTW_UNLOCK(sc);
409210364SMikore.Li@Sun.COM err = sc->urtw_init(sc);
409310364SMikore.Li@Sun.COM if (err) {
409410364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE,
409510364SMikore.Li@Sun.COM (sc->sc_dev,
409610364SMikore.Li@Sun.COM CE_CONT, "urtw: dev init failed\n"));
409710364SMikore.Li@Sun.COM return;
409810364SMikore.Li@Sun.COM }
409910364SMikore.Li@Sun.COM (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
410010364SMikore.Li@Sun.COM URTW_LOCK(sc);
41019485SMikore.Li@Sun.COM }
41029485SMikore.Li@Sun.COM }
410310364SMikore.Li@Sun.COM URTW_UNLOCK(sc);
41049485SMikore.Li@Sun.COM }
41059485SMikore.Li@Sun.COM
41069485SMikore.Li@Sun.COM static int
urtw_m_stat(void * arg,uint_t stat,uint64_t * val)41079485SMikore.Li@Sun.COM urtw_m_stat(void *arg, uint_t stat, uint64_t *val)
41089485SMikore.Li@Sun.COM {
41099485SMikore.Li@Sun.COM struct urtw_softc *sc = (struct urtw_softc *)arg;
41109485SMikore.Li@Sun.COM ieee80211com_t *ic = &sc->sc_ic;
41119485SMikore.Li@Sun.COM ieee80211_node_t *ni = 0;
41129485SMikore.Li@Sun.COM struct ieee80211_rateset *rs = 0;
41139485SMikore.Li@Sun.COM
41149485SMikore.Li@Sun.COM URTW_LOCK(sc);
41159485SMikore.Li@Sun.COM switch (stat) {
41169485SMikore.Li@Sun.COM case MAC_STAT_IFSPEED:
41179485SMikore.Li@Sun.COM ni = ic->ic_bss;
41189485SMikore.Li@Sun.COM rs = &ni->in_rates;
41199485SMikore.Li@Sun.COM *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
41209485SMikore.Li@Sun.COM (rs->ir_rates[ni->in_txrate] & IEEE80211_RATE_VAL)
41219485SMikore.Li@Sun.COM : ic->ic_fixed_rate) / 2 * 1000000;
41229485SMikore.Li@Sun.COM break;
41239485SMikore.Li@Sun.COM case MAC_STAT_NOXMTBUF:
41249485SMikore.Li@Sun.COM *val = sc->sc_tx_nobuf;
41259485SMikore.Li@Sun.COM break;
41269485SMikore.Li@Sun.COM case MAC_STAT_NORCVBUF:
41279485SMikore.Li@Sun.COM *val = sc->sc_rx_nobuf;
41289485SMikore.Li@Sun.COM break;
41299485SMikore.Li@Sun.COM case MAC_STAT_IERRORS:
41309485SMikore.Li@Sun.COM *val = sc->sc_rx_err;
41319485SMikore.Li@Sun.COM break;
41329485SMikore.Li@Sun.COM case MAC_STAT_RBYTES:
41339485SMikore.Li@Sun.COM *val = ic->ic_stats.is_rx_bytes;
41349485SMikore.Li@Sun.COM break;
41359485SMikore.Li@Sun.COM case MAC_STAT_IPACKETS:
41369485SMikore.Li@Sun.COM *val = ic->ic_stats.is_rx_frags;
41379485SMikore.Li@Sun.COM break;
41389485SMikore.Li@Sun.COM case MAC_STAT_OBYTES:
41399485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_bytes;
41409485SMikore.Li@Sun.COM break;
41419485SMikore.Li@Sun.COM case MAC_STAT_OPACKETS:
41429485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_frags;
41439485SMikore.Li@Sun.COM break;
41449485SMikore.Li@Sun.COM case MAC_STAT_OERRORS:
41459485SMikore.Li@Sun.COM *val = ic->ic_stats.is_tx_failed;
41469485SMikore.Li@Sun.COM break;
41479485SMikore.Li@Sun.COM case WIFI_STAT_TX_FRAGS:
41489485SMikore.Li@Sun.COM case WIFI_STAT_MCAST_TX:
41499485SMikore.Li@Sun.COM case WIFI_STAT_TX_FAILED:
41509485SMikore.Li@Sun.COM case WIFI_STAT_TX_RETRANS:
41519485SMikore.Li@Sun.COM case WIFI_STAT_RTS_SUCCESS:
41529485SMikore.Li@Sun.COM case WIFI_STAT_RTS_FAILURE:
41539485SMikore.Li@Sun.COM case WIFI_STAT_ACK_FAILURE:
41549485SMikore.Li@Sun.COM case WIFI_STAT_RX_FRAGS:
41559485SMikore.Li@Sun.COM case WIFI_STAT_MCAST_RX:
41569485SMikore.Li@Sun.COM case WIFI_STAT_FCS_ERRORS:
41579485SMikore.Li@Sun.COM case WIFI_STAT_WEP_ERRORS:
41589485SMikore.Li@Sun.COM case WIFI_STAT_RX_DUPS:
41599485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
41609485SMikore.Li@Sun.COM return (ieee80211_stat(ic, stat, val));
41619485SMikore.Li@Sun.COM default:
41629485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
41639485SMikore.Li@Sun.COM return (ENOTSUP);
41649485SMikore.Li@Sun.COM }
41659485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
41669485SMikore.Li@Sun.COM
41679485SMikore.Li@Sun.COM return (0);
41689485SMikore.Li@Sun.COM }
41699485SMikore.Li@Sun.COM
41709485SMikore.Li@Sun.COM static void
urtw_watchdog(void * arg)41719485SMikore.Li@Sun.COM urtw_watchdog(void *arg)
41729485SMikore.Li@Sun.COM {
41739485SMikore.Li@Sun.COM struct urtw_softc *sc = arg;
41749485SMikore.Li@Sun.COM struct ieee80211com *ic = &sc->sc_ic;
41759485SMikore.Li@Sun.COM
41769485SMikore.Li@Sun.COM ieee80211_stop_watchdog(ic);
41779485SMikore.Li@Sun.COM
41789485SMikore.Li@Sun.COM URTW_LOCK(sc);
41799485SMikore.Li@Sun.COM if (URTW_IS_NOT_RUNNING(sc)) {
41809485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
41819485SMikore.Li@Sun.COM return;
41829485SMikore.Li@Sun.COM }
41839485SMikore.Li@Sun.COM
41849485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
41859485SMikore.Li@Sun.COM switch (ic->ic_state) {
41869485SMikore.Li@Sun.COM case IEEE80211_S_AUTH:
41879485SMikore.Li@Sun.COM case IEEE80211_S_ASSOC:
418810364SMikore.Li@Sun.COM if (ic->ic_bss->in_fails > 0) {
41899485SMikore.Li@Sun.COM ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
419010364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE,
419110364SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT,
419210364SMikore.Li@Sun.COM "urtw: watchdog begin\n"));
419310364SMikore.Li@Sun.COM } else
41949485SMikore.Li@Sun.COM ieee80211_watchdog(ic);
41959485SMikore.Li@Sun.COM break;
41969485SMikore.Li@Sun.COM }
41979485SMikore.Li@Sun.COM }
41989485SMikore.Li@Sun.COM
41999485SMikore.Li@Sun.COM
42009485SMikore.Li@Sun.COM static int
urtw_attach(dev_info_t * devinfo,ddi_attach_cmd_t cmd)42019485SMikore.Li@Sun.COM urtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
42029485SMikore.Li@Sun.COM {
42039485SMikore.Li@Sun.COM struct urtw_softc *sc;
42049485SMikore.Li@Sun.COM struct ieee80211com *ic;
42059485SMikore.Li@Sun.COM int error, i, instance;
42069485SMikore.Li@Sun.COM uint32_t data = 0;
420710364SMikore.Li@Sun.COM uint8_t data8 = 0;
42089485SMikore.Li@Sun.COM char strbuf[32];
42099485SMikore.Li@Sun.COM wifi_data_t wd = { 0 };
42109485SMikore.Li@Sun.COM mac_register_t *macp;
421110364SMikore.Li@Sun.COM struct urtw_type *e = 0;
421210364SMikore.Li@Sun.COM char *urtw_name = NULL;
42139485SMikore.Li@Sun.COM
42149485SMikore.Li@Sun.COM switch (cmd) {
42159485SMikore.Li@Sun.COM case DDI_ATTACH:
42169485SMikore.Li@Sun.COM break;
42179485SMikore.Li@Sun.COM case DDI_RESUME:
42189485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p,
42199485SMikore.Li@Sun.COM ddi_get_instance(devinfo));
42209485SMikore.Li@Sun.COM ASSERT(sc != NULL);
42219485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ACTIVE,
42229485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw: resume\n"));
42239485SMikore.Li@Sun.COM URTW_LOCK(sc);
42249485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_SUSPEND;
42259485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
42269485SMikore.Li@Sun.COM if (URTW_IS_PLUGIN_ONLINE(sc)) {
422710364SMikore.Li@Sun.COM error = sc->urtw_init(sc);
42289485SMikore.Li@Sun.COM if (error == 0) {
42299485SMikore.Li@Sun.COM URTW_LOCK(sc);
42309485SMikore.Li@Sun.COM sc->sc_flags &= ~URTW_FLAG_PLUGIN_ONLINE;
42319485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
42329485SMikore.Li@Sun.COM }
42339485SMikore.Li@Sun.COM }
42349485SMikore.Li@Sun.COM return (DDI_SUCCESS);
42359485SMikore.Li@Sun.COM default:
42369485SMikore.Li@Sun.COM return (DDI_FAILURE);
42379485SMikore.Li@Sun.COM }
42389485SMikore.Li@Sun.COM
42399485SMikore.Li@Sun.COM instance = ddi_get_instance(devinfo);
42409485SMikore.Li@Sun.COM
42419485SMikore.Li@Sun.COM if (ddi_soft_state_zalloc(urtw_soft_state_p, instance) != DDI_SUCCESS) {
42429485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach:unable to alloc soft_state_p\n");
42439485SMikore.Li@Sun.COM return (DDI_FAILURE);
42449485SMikore.Li@Sun.COM }
42459485SMikore.Li@Sun.COM
42469485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, instance);
42479485SMikore.Li@Sun.COM ic = (ieee80211com_t *)&sc->sc_ic;
42489485SMikore.Li@Sun.COM sc->sc_dev = devinfo;
42499485SMikore.Li@Sun.COM
42509485SMikore.Li@Sun.COM if (usb_client_attach(devinfo, USBDRV_VERSION, 0) != USB_SUCCESS) {
42519485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: usb_client_attach failed\n");
42529485SMikore.Li@Sun.COM goto fail1;
42539485SMikore.Li@Sun.COM }
42549485SMikore.Li@Sun.COM
42559485SMikore.Li@Sun.COM if (usb_get_dev_data(devinfo, &sc->sc_udev,
42569485SMikore.Li@Sun.COM USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) {
42579485SMikore.Li@Sun.COM sc->sc_udev = NULL;
42589485SMikore.Li@Sun.COM goto fail2;
42599485SMikore.Li@Sun.COM }
42609485SMikore.Li@Sun.COM
42619485SMikore.Li@Sun.COM mutex_init(&sc->sc_genlock, NULL, MUTEX_DRIVER, NULL);
42629485SMikore.Li@Sun.COM mutex_init(&sc->tx_lock, NULL, MUTEX_DRIVER, NULL);
42639485SMikore.Li@Sun.COM mutex_init(&sc->rx_lock, NULL, MUTEX_DRIVER, NULL);
42649485SMikore.Li@Sun.COM mutex_init(&sc->sc_ledlock, NULL, MUTEX_DRIVER, NULL);
42659485SMikore.Li@Sun.COM
426610364SMikore.Li@Sun.COM e = urtw_lookup(sc->sc_udev->dev_descr->idVendor,
426710364SMikore.Li@Sun.COM sc->sc_udev->dev_descr->idProduct);
426810364SMikore.Li@Sun.COM if (e == NULL) {
426910364SMikore.Li@Sun.COM cmn_err(CE_WARN, "(urtw) unknown device\n");
427010364SMikore.Li@Sun.COM goto fail2;
427110364SMikore.Li@Sun.COM }
427210364SMikore.Li@Sun.COM sc->sc_hwrev = e->rev;
427310364SMikore.Li@Sun.COM
427410364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
427510364SMikore.Li@Sun.COM (void) urtw_read32_c(sc, URTW_TX_CONF, &data, 0);
427610364SMikore.Li@Sun.COM data &= URTW_TX_HWREV_MASK;
427710364SMikore.Li@Sun.COM switch (data) {
427810364SMikore.Li@Sun.COM case URTW_TX_HWREV_8187_D:
427910364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187_D;
428010364SMikore.Li@Sun.COM urtw_name = "RTL8187 rev. D";
428110364SMikore.Li@Sun.COM break;
428210364SMikore.Li@Sun.COM case URTW_TX_HWREV_8187B_D:
428310364SMikore.Li@Sun.COM /*
428410364SMikore.Li@Sun.COM * Detect Realtek RTL8187B devices that use
428510364SMikore.Li@Sun.COM * USB IDs of RTL8187.
428610364SMikore.Li@Sun.COM */
428710364SMikore.Li@Sun.COM sc->sc_hwrev = URTW_HWREV_8187B | URTW_HWREV_8187B_B;
428810364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. B (early)";
428910364SMikore.Li@Sun.COM break;
429010364SMikore.Li@Sun.COM default:
429110364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187_B;
429210364SMikore.Li@Sun.COM urtw_name = "RTL8187 rev. B (default)";
429310364SMikore.Li@Sun.COM break;
429410364SMikore.Li@Sun.COM }
429510364SMikore.Li@Sun.COM } else {
429610364SMikore.Li@Sun.COM /* RTL8187B hwrev register. */
429710364SMikore.Li@Sun.COM (void) urtw_read8_c(sc, URTW_8187B_HWREV, &data8, 0);
429810364SMikore.Li@Sun.COM switch (data8) {
429910364SMikore.Li@Sun.COM case URTW_8187B_HWREV_8187B_B:
430010364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_B;
430110364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. B";
430210364SMikore.Li@Sun.COM break;
430310364SMikore.Li@Sun.COM case URTW_8187B_HWREV_8187B_D:
430410364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_D;
430510364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. D";
430610364SMikore.Li@Sun.COM break;
430710364SMikore.Li@Sun.COM case URTW_8187B_HWREV_8187B_E:
430810364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_E;
430910364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. E";
431010364SMikore.Li@Sun.COM break;
431110364SMikore.Li@Sun.COM default:
431210364SMikore.Li@Sun.COM sc->sc_hwrev |= URTW_HWREV_8187B_B;
431310364SMikore.Li@Sun.COM urtw_name = "RTL8187B rev. B (default)";
431410364SMikore.Li@Sun.COM break;
431510364SMikore.Li@Sun.COM }
431610364SMikore.Li@Sun.COM }
431710364SMikore.Li@Sun.COM
431810364SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT,
431910364SMikore.Li@Sun.COM "urtw_attach: actual device is %s\n", urtw_name));
432010364SMikore.Li@Sun.COM if (sc->sc_hwrev & URTW_HWREV_8187) {
432110364SMikore.Li@Sun.COM sc->urtw_init = urtw_8187_init;
432210364SMikore.Li@Sun.COM } else {
432310364SMikore.Li@Sun.COM sc->urtw_init = urtw_8187b_init;
432410364SMikore.Li@Sun.COM }
432510364SMikore.Li@Sun.COM
432610364SMikore.Li@Sun.COM if (urtw_read32_c(sc, URTW_RX, &data, 0))
43279485SMikore.Li@Sun.COM goto fail3;
43289485SMikore.Li@Sun.COM sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 :
43299485SMikore.Li@Sun.COM URTW_EEPROM_93C46;
43309485SMikore.Li@Sun.COM if (sc->sc_epromtype == URTW_EEPROM_93C56)
43319485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT,
43329485SMikore.Li@Sun.COM "urtw_attach: eprom is 93C56\n"));
43339485SMikore.Li@Sun.COM else
43349485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_HWTYPE, (sc->sc_dev, CE_CONT,
43359485SMikore.Li@Sun.COM "urtw_attach: eprom is 93C46\n"));
43369485SMikore.Li@Sun.COM error = urtw_get_rfchip(sc);
43379485SMikore.Li@Sun.COM if (error != 0)
43389485SMikore.Li@Sun.COM goto fail3;
43399485SMikore.Li@Sun.COM error = urtw_get_macaddr(sc);
43409485SMikore.Li@Sun.COM if (error != 0)
43419485SMikore.Li@Sun.COM goto fail3;
43429485SMikore.Li@Sun.COM error = urtw_get_txpwr(sc);
43439485SMikore.Li@Sun.COM if (error != 0)
43449485SMikore.Li@Sun.COM goto fail3;
43459485SMikore.Li@Sun.COM error = urtw_led_init(sc); /* XXX incompleted */
43469485SMikore.Li@Sun.COM if (error != 0)
43479485SMikore.Li@Sun.COM goto fail3;
43489485SMikore.Li@Sun.COM
43499485SMikore.Li@Sun.COM sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY;
43509485SMikore.Li@Sun.COM sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY;
43519485SMikore.Li@Sun.COM sc->sc_currate = 3;
43529485SMikore.Li@Sun.COM /* XXX for what? */
43539485SMikore.Li@Sun.COM sc->sc_preamble_mode = 2;
43549485SMikore.Li@Sun.COM
43559485SMikore.Li@Sun.COM ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
43569485SMikore.Li@Sun.COM ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
43579485SMikore.Li@Sun.COM ic->ic_state = IEEE80211_S_INIT;
43589485SMikore.Li@Sun.COM
43599485SMikore.Li@Sun.COM ic->ic_maxrssi = 95;
43609485SMikore.Li@Sun.COM ic->ic_xmit = urtw_send;
43619485SMikore.Li@Sun.COM
43629485SMikore.Li@Sun.COM ic->ic_caps |= IEEE80211_C_WPA | /* Support WPA/WPA2 */
43639485SMikore.Li@Sun.COM IEEE80211_C_TXPMGT | /* tx power management */
43649485SMikore.Li@Sun.COM IEEE80211_C_SHPREAMBLE | /* short preamble supported */
43659485SMikore.Li@Sun.COM IEEE80211_C_SHSLOT; /* short slot time supported */
43669485SMikore.Li@Sun.COM /* set supported .11b and .11g rates */
43679485SMikore.Li@Sun.COM ic->ic_sup_rates[IEEE80211_MODE_11B] = urtw_rateset_11b;
43689485SMikore.Li@Sun.COM ic->ic_sup_rates[IEEE80211_MODE_11G] = urtw_rateset_11g;
43699485SMikore.Li@Sun.COM
43709485SMikore.Li@Sun.COM /* set supported .11b and .11g channels (1 through 11) */
43719485SMikore.Li@Sun.COM for (i = 1; i <= 11; i++) {
43729485SMikore.Li@Sun.COM ic->ic_sup_channels[i].ich_freq =
43739485SMikore.Li@Sun.COM ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
43749485SMikore.Li@Sun.COM ic->ic_sup_channels[i].ich_flags =
43759485SMikore.Li@Sun.COM IEEE80211_CHAN_CCK | IEEE80211_CHAN_DYN |
43769485SMikore.Li@Sun.COM IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM;
43779485SMikore.Li@Sun.COM }
43789485SMikore.Li@Sun.COM
43799485SMikore.Li@Sun.COM ieee80211_attach(ic);
438010364SMikore.Li@Sun.COM ic->ic_ibss_chan = &ic->ic_sup_channels[1];
438110364SMikore.Li@Sun.COM ic->ic_curchan = ic->ic_ibss_chan;
43829485SMikore.Li@Sun.COM
43839485SMikore.Li@Sun.COM /* register WPA door */
43849485SMikore.Li@Sun.COM ieee80211_register_door(ic, ddi_driver_name(devinfo),
43859485SMikore.Li@Sun.COM ddi_get_instance(devinfo));
43869485SMikore.Li@Sun.COM
43879485SMikore.Li@Sun.COM /* override state transition machine */
43889485SMikore.Li@Sun.COM sc->sc_newstate = ic->ic_newstate;
43899485SMikore.Li@Sun.COM ic->ic_newstate = urtw_newstate;
43909485SMikore.Li@Sun.COM ic->ic_watchdog = urtw_watchdog;
43919485SMikore.Li@Sun.COM ieee80211_media_init(ic);
43929485SMikore.Li@Sun.COM ic->ic_def_txkey = 0;
43939485SMikore.Li@Sun.COM
439410364SMikore.Li@Sun.COM sc->dwelltime = 250;
43959485SMikore.Li@Sun.COM sc->sc_flags = 0;
43969485SMikore.Li@Sun.COM
43979485SMikore.Li@Sun.COM /*
43989485SMikore.Li@Sun.COM * Provide initial settings for the WiFi plugin; whenever this
43999485SMikore.Li@Sun.COM * information changes, we need to call mac_plugindata_update()
44009485SMikore.Li@Sun.COM */
44019485SMikore.Li@Sun.COM wd.wd_opmode = ic->ic_opmode;
44029485SMikore.Li@Sun.COM wd.wd_secalloc = WIFI_SEC_NONE;
44039485SMikore.Li@Sun.COM IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
44049485SMikore.Li@Sun.COM
44059485SMikore.Li@Sun.COM if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
44069485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, CE_CONT,
44079485SMikore.Li@Sun.COM "MAC version alloc failed\n"));
44089485SMikore.Li@Sun.COM goto fail4;
44099485SMikore.Li@Sun.COM }
44109485SMikore.Li@Sun.COM
44119485SMikore.Li@Sun.COM macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
44129485SMikore.Li@Sun.COM macp->m_driver = sc;
44139485SMikore.Li@Sun.COM macp->m_dip = devinfo;
44149485SMikore.Li@Sun.COM macp->m_src_addr = ic->ic_macaddr;
44159485SMikore.Li@Sun.COM macp->m_callbacks = &urtw_m_callbacks;
44169485SMikore.Li@Sun.COM macp->m_min_sdu = 0;
44179485SMikore.Li@Sun.COM macp->m_max_sdu = IEEE80211_MTU;
44189485SMikore.Li@Sun.COM macp->m_pdata = &wd;
44199485SMikore.Li@Sun.COM macp->m_pdata_size = sizeof (wd);
44209485SMikore.Li@Sun.COM
44219485SMikore.Li@Sun.COM error = mac_register(macp, &ic->ic_mach);
44229485SMikore.Li@Sun.COM mac_free(macp);
44239485SMikore.Li@Sun.COM if (error != 0) {
44249485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: mac_register() err %x\n", error);
44259485SMikore.Li@Sun.COM goto fail4;
44269485SMikore.Li@Sun.COM }
44279485SMikore.Li@Sun.COM
44289485SMikore.Li@Sun.COM if (usb_register_hotplug_cbs(devinfo, urtw_disconnect,
44299485SMikore.Li@Sun.COM urtw_reconnect) != USB_SUCCESS) {
44309485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw_attach: failed to register events");
44319485SMikore.Li@Sun.COM goto fail5;
44329485SMikore.Li@Sun.COM }
44339485SMikore.Li@Sun.COM
44349485SMikore.Li@Sun.COM /*
44359485SMikore.Li@Sun.COM * Create minor node of type DDI_NT_NET_WIFI
44369485SMikore.Li@Sun.COM */
44379485SMikore.Li@Sun.COM (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
44389485SMikore.Li@Sun.COM "urtw", instance);
44399485SMikore.Li@Sun.COM error = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
44409485SMikore.Li@Sun.COM instance + 1, DDI_NT_NET_WIFI, 0);
44419485SMikore.Li@Sun.COM
44429485SMikore.Li@Sun.COM if (error != DDI_SUCCESS)
44439485SMikore.Li@Sun.COM cmn_err(CE_WARN, "urtw: ddi_create_minor_node() failed\n");
44449485SMikore.Li@Sun.COM /*
44459485SMikore.Li@Sun.COM * Notify link is down now
44469485SMikore.Li@Sun.COM */
44479485SMikore.Li@Sun.COM mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
44489485SMikore.Li@Sun.COM
44499485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev, CE_CONT,
44509485SMikore.Li@Sun.COM "urtw_attach: successfully.\n"));
44519485SMikore.Li@Sun.COM return (DDI_SUCCESS);
44529485SMikore.Li@Sun.COM fail5:
445310364SMikore.Li@Sun.COM (void) mac_disable(ic->ic_mach);
44549485SMikore.Li@Sun.COM (void) mac_unregister(ic->ic_mach);
44559485SMikore.Li@Sun.COM fail4:
44569485SMikore.Li@Sun.COM ieee80211_detach(ic);
44579485SMikore.Li@Sun.COM fail3:
44589485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_genlock);
44599485SMikore.Li@Sun.COM mutex_destroy(&sc->tx_lock);
44609485SMikore.Li@Sun.COM mutex_destroy(&sc->rx_lock);
44619485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_ledlock);
44629485SMikore.Li@Sun.COM fail2:
44639485SMikore.Li@Sun.COM usb_client_detach(sc->sc_dev, sc->sc_udev);
44649485SMikore.Li@Sun.COM fail1:
44659485SMikore.Li@Sun.COM ddi_soft_state_free(urtw_soft_state_p, ddi_get_instance(devinfo));
44669485SMikore.Li@Sun.COM
44679485SMikore.Li@Sun.COM return (DDI_FAILURE);
44689485SMikore.Li@Sun.COM }
44699485SMikore.Li@Sun.COM
44709485SMikore.Li@Sun.COM static int
urtw_detach(dev_info_t * devinfo,ddi_detach_cmd_t cmd)44719485SMikore.Li@Sun.COM urtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
44729485SMikore.Li@Sun.COM {
44739485SMikore.Li@Sun.COM struct urtw_softc *sc;
44749485SMikore.Li@Sun.COM
44759485SMikore.Li@Sun.COM sc = ddi_get_soft_state(urtw_soft_state_p, ddi_get_instance(devinfo));
44769485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH, (sc->sc_dev,
44779485SMikore.Li@Sun.COM CE_CONT, "urtw_detach()\n"));
44789485SMikore.Li@Sun.COM
44799485SMikore.Li@Sun.COM switch (cmd) {
44809485SMikore.Li@Sun.COM case DDI_DETACH:
44819485SMikore.Li@Sun.COM break;
44829485SMikore.Li@Sun.COM case DDI_SUSPEND:
44839485SMikore.Li@Sun.COM URTW8187_DBG(URTW_DEBUG_ATTACH,
44849485SMikore.Li@Sun.COM (sc->sc_dev, CE_CONT, "urtw: suspend\n"));
44859485SMikore.Li@Sun.COM
44869485SMikore.Li@Sun.COM ieee80211_new_state(&sc->sc_ic, IEEE80211_S_INIT, -1);
44879485SMikore.Li@Sun.COM ieee80211_stop_watchdog(&sc->sc_ic);
44889485SMikore.Li@Sun.COM
44899485SMikore.Li@Sun.COM URTW_LOCK(sc);
44909485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_SUSPEND;
44919485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
44929485SMikore.Li@Sun.COM if (URTW_IS_RUNNING(sc)) {
44939485SMikore.Li@Sun.COM urtw_stop(sc);
44949485SMikore.Li@Sun.COM URTW_LOCK(sc);
44959485SMikore.Li@Sun.COM sc->sc_flags |= URTW_FLAG_PLUGIN_ONLINE;
44969485SMikore.Li@Sun.COM URTW_UNLOCK(sc);
44979485SMikore.Li@Sun.COM }
44989485SMikore.Li@Sun.COM return (DDI_SUCCESS);
44999485SMikore.Li@Sun.COM default:
45009485SMikore.Li@Sun.COM return (DDI_FAILURE);
45019485SMikore.Li@Sun.COM }
45029485SMikore.Li@Sun.COM
45039485SMikore.Li@Sun.COM if (mac_disable(sc->sc_ic.ic_mach) != 0)
45049485SMikore.Li@Sun.COM return (DDI_FAILURE);
45059485SMikore.Li@Sun.COM urtw_stop(sc);
45069485SMikore.Li@Sun.COM /*
45079485SMikore.Li@Sun.COM * Unregister from the MAC layer subsystem
45089485SMikore.Li@Sun.COM */
45099485SMikore.Li@Sun.COM (void) mac_unregister(sc->sc_ic.ic_mach);
45109485SMikore.Li@Sun.COM
45119485SMikore.Li@Sun.COM ieee80211_detach(&sc->sc_ic);
45129485SMikore.Li@Sun.COM usb_unregister_hotplug_cbs(devinfo);
45139485SMikore.Li@Sun.COM usb_client_detach(devinfo, sc->sc_udev);
45149485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_genlock);
45159485SMikore.Li@Sun.COM mutex_destroy(&sc->tx_lock);
45169485SMikore.Li@Sun.COM mutex_destroy(&sc->rx_lock);
45179485SMikore.Li@Sun.COM mutex_destroy(&sc->sc_ledlock);
45189485SMikore.Li@Sun.COM sc->sc_udev = NULL;
45199485SMikore.Li@Sun.COM
45209485SMikore.Li@Sun.COM ddi_remove_minor_node(devinfo, NULL);
45219485SMikore.Li@Sun.COM ddi_soft_state_free(urtw_soft_state_p, ddi_get_instance(devinfo));
45229485SMikore.Li@Sun.COM
45239485SMikore.Li@Sun.COM return (DDI_SUCCESS);
45249485SMikore.Li@Sun.COM }
45259485SMikore.Li@Sun.COM
45269485SMikore.Li@Sun.COM int
_info(struct modinfo * modinfop)45279485SMikore.Li@Sun.COM _info(struct modinfo *modinfop)
45289485SMikore.Li@Sun.COM {
45299485SMikore.Li@Sun.COM return (mod_info(&modlinkage, modinfop));
45309485SMikore.Li@Sun.COM }
45319485SMikore.Li@Sun.COM
45329485SMikore.Li@Sun.COM int
_init(void)45339485SMikore.Li@Sun.COM _init(void)
45349485SMikore.Li@Sun.COM {
45359485SMikore.Li@Sun.COM int status;
45369485SMikore.Li@Sun.COM
45379485SMikore.Li@Sun.COM status = ddi_soft_state_init(&urtw_soft_state_p,
45389485SMikore.Li@Sun.COM sizeof (struct urtw_softc), 1);
45399485SMikore.Li@Sun.COM if (status != 0)
45409485SMikore.Li@Sun.COM return (status);
45419485SMikore.Li@Sun.COM
45429485SMikore.Li@Sun.COM mac_init_ops(&urtw_dev_ops, "urtw");
45439485SMikore.Li@Sun.COM status = mod_install(&modlinkage);
45449485SMikore.Li@Sun.COM if (status != 0) {
45459485SMikore.Li@Sun.COM mac_fini_ops(&urtw_dev_ops);
45469485SMikore.Li@Sun.COM ddi_soft_state_fini(&urtw_soft_state_p);
45479485SMikore.Li@Sun.COM }
45489485SMikore.Li@Sun.COM return (status);
45499485SMikore.Li@Sun.COM }
45509485SMikore.Li@Sun.COM
45519485SMikore.Li@Sun.COM int
_fini(void)45529485SMikore.Li@Sun.COM _fini(void)
45539485SMikore.Li@Sun.COM {
45549485SMikore.Li@Sun.COM int status;
45559485SMikore.Li@Sun.COM
45569485SMikore.Li@Sun.COM status = mod_remove(&modlinkage);
45579485SMikore.Li@Sun.COM if (status == 0) {
45589485SMikore.Li@Sun.COM mac_fini_ops(&urtw_dev_ops);
45599485SMikore.Li@Sun.COM ddi_soft_state_fini(&urtw_soft_state_p);
45609485SMikore.Li@Sun.COM }
45619485SMikore.Li@Sun.COM return (status);
45629485SMikore.Li@Sun.COM }
4563