if_urtw.c revision 257743
168651Skris/*- 268651Skris * Copyright (c) 2008 Weongyo Jeong <weongyo@FreeBSD.org> 3238405Sjkim * 4238405Sjkim * Permission to use, copy, modify, and distribute this software for any 5238405Sjkim * purpose with or without fee is hereby granted, provided that the above 6238405Sjkim * copyright notice and this permission notice appear in all copies. 768651Skris * 868651Skris * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 968651Skris * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1068651Skris * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1168651Skris * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1268651Skris * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1368651Skris * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1468651Skris * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1568651Skris */ 1668651Skris 1768651Skris#include <sys/cdefs.h> 18109998Smarkm__FBSDID("$FreeBSD: head/sys/dev/usb/wlan/if_urtw.c 257743 2013-11-06 12:57:01Z hselasky $"); 1968651Skris#include <sys/param.h> 2068651Skris#include <sys/sockio.h> 2168651Skris#include <sys/sysctl.h> 2268651Skris#include <sys/lock.h> 2368651Skris#include <sys/mutex.h> 2468651Skris#include <sys/mbuf.h> 25109998Smarkm#include <sys/kernel.h> 2668651Skris#include <sys/socket.h> 2768651Skris#include <sys/systm.h> 28109998Smarkm#include <sys/malloc.h> 2968651Skris#include <sys/module.h> 30109998Smarkm#include <sys/bus.h> 3168651Skris#include <sys/endian.h> 3268651Skris#include <sys/kdb.h> 33109998Smarkm 3468651Skris#include <machine/bus.h> 3568651Skris#include <machine/resource.h> 36109998Smarkm#include <sys/rman.h> 3768651Skris 38109998Smarkm#include <net/if.h> 39109998Smarkm#include <net/if_var.h> 4068651Skris#include <net/if_arp.h> 4168651Skris#include <net/ethernet.h> 4268651Skris#include <net/if_dl.h> 4368651Skris#include <net/if_media.h> 4468651Skris#include <net/if_types.h> 4568651Skris 4668651Skris#ifdef INET 4768651Skris#include <netinet/in.h> 4868651Skris#include <netinet/in_systm.h> 4968651Skris#include <netinet/in_var.h> 5068651Skris#include <netinet/if_ether.h> 5168651Skris#include <netinet/ip.h> 5268651Skris#endif 5368651Skris 5468651Skris#include <net80211/ieee80211_var.h> 55109998Smarkm#include <net80211/ieee80211_regdomain.h> 5668651Skris#include <net80211/ieee80211_radiotap.h> 57109998Smarkm 58109998Smarkm#include <dev/usb/usb.h> 5968651Skris#include <dev/usb/usbdi.h> 6068651Skris#include "usbdevs.h" 6168651Skris 6268651Skris#include <dev/usb/wlan/if_urtwreg.h> 6368651Skris#include <dev/usb/wlan/if_urtwvar.h> 6468651Skris 6568651Skrisstatic SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L"); 6668651Skris#ifdef URTW_DEBUG 6768651Skrisint urtw_debug = 0; 6868651SkrisSYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &urtw_debug, 0, 6968651Skris "control debugging printfs"); 7068651SkrisTUNABLE_INT("hw.usb.urtw.debug", &urtw_debug); 7168651Skrisenum { 7268651Skris URTW_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ 7368651Skris URTW_DEBUG_RECV = 0x00000002, /* basic recv operation */ 7468651Skris URTW_DEBUG_RESET = 0x00000004, /* reset processing */ 7568651Skris URTW_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */ 7668651Skris URTW_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */ 7768651Skris URTW_DEBUG_STATE = 0x00000020, /* 802.11 state transitions */ 78238405Sjkim URTW_DEBUG_STAT = 0x00000040, /* statistic */ 79238405Sjkim URTW_DEBUG_INIT = 0x00000080, /* initialization of dev */ 8068651Skris URTW_DEBUG_TXSTATUS = 0x00000100, /* tx status */ 8168651Skris URTW_DEBUG_ANY = 0xffffffff 8268651Skris}; 8368651Skris#define DPRINTF(sc, m, fmt, ...) do { \ 8468651Skris if (sc->sc_debug & (m)) \ 8568651Skris printf(fmt, __VA_ARGS__); \ 8668651Skris} while (0) 8768651Skris#else 8868651Skris#define DPRINTF(sc, m, fmt, ...) do { \ 89238405Sjkim (void) sc; \ 9068651Skris} while (0) 9168651Skris#endif 9268651Skrisstatic int urtw_preamble_mode = URTW_PREAMBLE_MODE_LONG; 9368651SkrisSYSCTL_INT(_hw_usb_urtw, OID_AUTO, preamble_mode, CTLFLAG_RW | CTLFLAG_TUN, 9468651Skris &urtw_preamble_mode, 0, "set the preable mode (long or short)"); 95109998SmarkmTUNABLE_INT("hw.usb.urtw.preamble_mode", &urtw_preamble_mode); 9668651Skris 9768651Skris/* recognized device vendors/products */ 9868651Skris#define urtw_lookup(v, p) \ 9968651Skris ((const struct urtw_type *)usb_lookup(urtw_devs, v, p)) 10068651Skris#define URTW_DEV_B(v,p) \ 10168651Skris { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187B) } 10268651Skris#define URTW_DEV_L(v,p) \ 10368651Skris { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187L) } 10468651Skris#define URTW_REV_RTL8187B 0 10568651Skris#define URTW_REV_RTL8187L 1 10668651Skrisstatic const STRUCT_USB_HOST_ID urtw_devs[] = { 10768651Skris URTW_DEV_B(NETGEAR, WG111V3), 10868651Skris URTW_DEV_B(REALTEK, RTL8187B_0), 10968651Skris URTW_DEV_B(REALTEK, RTL8187B_1), 11068651Skris URTW_DEV_B(REALTEK, RTL8187B_2), 11168651Skris URTW_DEV_B(SITECOMEU, WL168V4), 11268651Skris URTW_DEV_L(ASUS, P5B_WIFI), 11368651Skris URTW_DEV_L(BELKIN, F5D7050E), 11468651Skris URTW_DEV_L(LINKSYS4, WUSB54GCV2), 11568651Skris URTW_DEV_L(NETGEAR, WG111V2), 11668651Skris URTW_DEV_L(REALTEK, RTL8187), 11768651Skris URTW_DEV_L(SITECOMEU, WL168V1), 11868651Skris URTW_DEV_L(SURECOM, EP9001G2A), 11968651Skris { USB_VPI(USB_VENDOR_OVISLINK, 0x8187, URTW_REV_RTL8187L) }, 12068651Skris { USB_VPI(USB_VENDOR_DICKSMITH, 0x9401, URTW_REV_RTL8187L) }, 12168651Skris { USB_VPI(USB_VENDOR_HP, 0xca02, URTW_REV_RTL8187L) }, 12268651Skris { USB_VPI(USB_VENDOR_LOGITEC, 0x010c, URTW_REV_RTL8187L) }, 12368651Skris { USB_VPI(USB_VENDOR_NETGEAR, 0x6100, URTW_REV_RTL8187L) }, 12468651Skris { USB_VPI(USB_VENDOR_SPHAIRON, 0x0150, URTW_REV_RTL8187L) }, 12568651Skris { USB_VPI(USB_VENDOR_QCOM, 0x6232, URTW_REV_RTL8187L) }, 126160814Ssimon#undef URTW_DEV_L 12768651Skris#undef URTW_DEV_B 12868651Skris}; 129160814Ssimon 13068651Skris#define urtw_read8_m(sc, val, data) do { \ 13168651Skris error = urtw_read8_c(sc, val, data); \ 13268651Skris if (error != 0) \ 133109998Smarkm goto fail; \ 13468651Skris} while (0) 13568651Skris#define urtw_write8_m(sc, val, data) do { \ 13668651Skris error = urtw_write8_c(sc, val, data); \ 13768651Skris if (error != 0) \ 13868651Skris goto fail; \ 13968651Skris} while (0) 14068651Skris#define urtw_read16_m(sc, val, data) do { \ 14168651Skris error = urtw_read16_c(sc, val, data); \ 14268651Skris if (error != 0) \ 14368651Skris goto fail; \ 14468651Skris} while (0) 14568651Skris#define urtw_write16_m(sc, val, data) do { \ 14668651Skris error = urtw_write16_c(sc, val, data); \ 14768651Skris if (error != 0) \ 14868651Skris goto fail; \ 14968651Skris} while (0) 15068651Skris#define urtw_read32_m(sc, val, data) do { \ 15168651Skris error = urtw_read32_c(sc, val, data); \ 15268651Skris if (error != 0) \ 15368651Skris goto fail; \ 15468651Skris} while (0) 15568651Skris#define urtw_write32_m(sc, val, data) do { \ 15668651Skris error = urtw_write32_c(sc, val, data); \ 15768651Skris if (error != 0) \ 15868651Skris goto fail; \ 15968651Skris} while (0) 16068651Skris#define urtw_8187_write_phy_ofdm(sc, val, data) do { \ 16168651Skris error = urtw_8187_write_phy_ofdm_c(sc, val, data); \ 16268651Skris if (error != 0) \ 16368651Skris goto fail; \ 16468651Skris} while (0) 16568651Skris#define urtw_8187_write_phy_cck(sc, val, data) do { \ 16668651Skris error = urtw_8187_write_phy_cck_c(sc, val, data); \ 16768651Skris if (error != 0) \ 16868651Skris goto fail; \ 16968651Skris} while (0) 17068651Skris#define urtw_8225_write(sc, val, data) do { \ 17168651Skris error = urtw_8225_write_c(sc, val, data); \ 17268651Skris if (error != 0) \ 17368651Skris goto fail; \ 17468651Skris} while (0) 175238405Sjkim 17668651Skrisstruct urtw_pair { 17768651Skris uint32_t reg; 17868651Skris uint32_t val; 17968651Skris}; 18068651Skris 18168651Skrisstatic uint8_t urtw_8225_agc[] = { 18268651Skris 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, 18368651Skris 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 18468651Skris 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 18568651Skris 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 18668651Skris 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 18768651Skris 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 188238405Sjkim 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 18968651Skris 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 19068651Skris 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 191238405Sjkim 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 19268651Skris 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 19368651Skris 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 19468651Skris}; 19568651Skris 196160814Ssimonstatic uint8_t urtw_8225z2_agc[] = { 19768651Skris 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 19868651Skris 0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 199109998Smarkm 0x39, 0x37, 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 200109998Smarkm 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 20168651Skris 0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 20268651Skris 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 203160814Ssimon 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x20, 0x21, 0x22, 0x23, 20468651Skris 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a, 20568651Skris 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, 206109998Smarkm 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 20768651Skris 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 20868651Skris 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 20968651Skris}; 21068651Skris 21168651Skrisstatic uint32_t urtw_8225_channel[] = { 212109998Smarkm 0x0000, /* dummy channel 0 */ 21368651Skris 0x085c, /* 1 */ 21468651Skris 0x08dc, /* 2 */ 21568651Skris 0x095c, /* 3 */ 21668651Skris 0x09dc, /* 4 */ 21768651Skris 0x0a5c, /* 5 */ 218109998Smarkm 0x0adc, /* 6 */ 21968651Skris 0x0b5c, /* 7 */ 22068651Skris 0x0bdc, /* 8 */ 22168651Skris 0x0c5c, /* 9 */ 222109998Smarkm 0x0cdc, /* 10 */ 22368651Skris 0x0d5c, /* 11 */ 22468651Skris 0x0ddc, /* 12 */ 22568651Skris 0x0e5c, /* 13 */ 22668651Skris 0x0f72, /* 14 */ 22768651Skris}; 22868651Skris 22968651Skrisstatic uint8_t urtw_8225_gain[] = { 23068651Skris 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ 23168651Skris 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ 23268651Skris 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ 23368651Skris 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ 23468651Skris 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ 23568651Skris 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ 23668651Skris 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ 23768651Skris}; 23868651Skris 23968651Skrisstatic struct urtw_pair urtw_8225_rf_part1[] = { 24068651Skris { 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 24168651Skris { 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a }, 242109998Smarkm { 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 }, 24368651Skris { 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }, 24468651Skris}; 24568651Skris 246238405Sjkimstatic struct urtw_pair urtw_8225_rf_part2[] = { 24768651Skris { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, 24868651Skris { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, 24968651Skris { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 }, 25068651Skris { 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 }, 25168651Skris { 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 }, 25268651Skris { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef }, 25368651Skris { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 }, 25468651Skris { 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 }, 25568651Skris { 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 }, 25668651Skris { 0x27, 0x88 } 25768651Skris}; 25868651Skris 25968651Skrisstatic struct urtw_pair urtw_8225_rf_part3[] = { 26068651Skris { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, 26168651Skris { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b }, 26268651Skris { 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, 26368651Skris { 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d }, 26468651Skris { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e }, 26568651Skris { 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a }, 26668651Skris { 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 } 26768651Skris}; 26868651Skris 26968651Skrisstatic uint16_t urtw_8225_rxgain[] = { 27068651Skris 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 27168651Skris 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, 27268651Skris 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, 27368651Skris 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, 27468651Skris 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, 27568651Skris 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, 27668651Skris 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, 27768651Skris 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, 27868651Skris 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, 27968651Skris 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, 28068651Skris 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, 28168651Skris 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb 28268651Skris}; 28368651Skris 28468651Skrisstatic uint8_t urtw_8225_threshold[] = { 28568651Skris 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, 28668651Skris}; 287142425Snectar 28868651Skrisstatic uint8_t urtw_8225_tx_gain_cck_ofdm[] = { 28968651Skris 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e 29068651Skris}; 29168651Skris 292142425Snectarstatic uint8_t urtw_8225_txpwr_cck[] = { 29368651Skris 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, 29468651Skris 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, 29568651Skris 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, 29668651Skris 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, 297142425Snectar 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, 29868651Skris 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 29968651Skris}; 300142425Snectar 30168651Skrisstatic uint8_t urtw_8225_txpwr_cck_ch14[] = { 30268651Skris 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, 30368651Skris 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, 304109998Smarkm 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, 305109998Smarkm 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, 30668651Skris 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 30768651Skris 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 30868651Skris}; 30968651Skris 31068651Skrisstatic uint8_t urtw_8225_txpwr_ofdm[]={ 311142425Snectar 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 31268651Skris}; 31368651Skris 31468651Skrisstatic uint8_t urtw_8225v2_gain_bg[]={ 31568651Skris 0x23, 0x15, 0xa5, /* -82-1dbm */ 31668651Skris 0x23, 0x15, 0xb5, /* -82-2dbm */ 31768651Skris 0x23, 0x15, 0xc5, /* -82-3dbm */ 318142425Snectar 0x33, 0x15, 0xc5, /* -78dbm */ 31968651Skris 0x43, 0x15, 0xc5, /* -74dbm */ 32068651Skris 0x53, 0x15, 0xc5, /* -70dbm */ 32168651Skris 0x63, 0x15, 0xc5, /* -66dbm */ 32268651Skris}; 32368651Skris 32468651Skrisstatic struct urtw_pair urtw_8225v2_rf_part1[] = { 32568651Skris { 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 32668651Skris { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, 32768651Skris { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, 32868651Skris { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } 32968651Skris}; 33068651Skris 33168651Skrisstatic struct urtw_pair urtw_8225v2b_rf_part0[] = { 33268651Skris { 0x00, 0x00b7 }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, 33368651Skris { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, 33468651Skris { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, 33568651Skris { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } 33668651Skris}; 33768651Skris 33868651Skrisstatic struct urtw_pair urtw_8225v2b_rf_part1[] = { 33968651Skris {0x0f0, 0x32}, {0x0f1, 0x32}, {0x0f2, 0x00}, 34068651Skris {0x0f3, 0x00}, {0x0f4, 0x32}, {0x0f5, 0x43}, 34168651Skris {0x0f6, 0x00}, {0x0f7, 0x00}, {0x0f8, 0x46}, 34268651Skris {0x0f9, 0xa4}, {0x0fa, 0x00}, {0x0fb, 0x00}, 343109998Smarkm {0x0fc, 0x96}, {0x0fd, 0xa4}, {0x0fe, 0x00}, 344109998Smarkm {0x0ff, 0x00}, {0x158, 0x4b}, {0x159, 0x00}, 34568651Skris {0x15a, 0x4b}, {0x15b, 0x00}, {0x160, 0x4b}, 346238405Sjkim {0x161, 0x09}, {0x162, 0x4b}, {0x163, 0x09}, 34768651Skris {0x1ce, 0x0f}, {0x1cf, 0x00}, {0x1e0, 0xff}, 34868651Skris {0x1e1, 0x0f}, {0x1e2, 0x00}, {0x1f0, 0x4e}, 34968651Skris {0x1f1, 0x01}, {0x1f2, 0x02}, {0x1f3, 0x03}, 35068651Skris {0x1f4, 0x04}, {0x1f5, 0x05}, {0x1f6, 0x06}, 35168651Skris {0x1f7, 0x07}, {0x1f8, 0x08}, {0x24e, 0x00}, 35268651Skris {0x20c, 0x04}, {0x221, 0x61}, {0x222, 0x68}, 35368651Skris {0x223, 0x6f}, {0x224, 0x76}, {0x225, 0x7d}, 35468651Skris {0x226, 0x84}, {0x227, 0x8d}, {0x24d, 0x08}, 35568651Skris {0x250, 0x05}, {0x251, 0xf5}, {0x252, 0x04}, 35668651Skris {0x253, 0xa0}, {0x254, 0x1f}, {0x255, 0x23}, 35768651Skris {0x256, 0x45}, {0x257, 0x67}, {0x258, 0x08}, 35868651Skris {0x259, 0x08}, {0x25a, 0x08}, {0x25b, 0x08}, 359238405Sjkim {0x260, 0x08}, {0x261, 0x08}, {0x262, 0x08}, 360109998Smarkm {0x263, 0x08}, {0x264, 0xcf}, {0x272, 0x56}, 361238405Sjkim {0x273, 0x9a}, {0x034, 0xf0}, {0x035, 0x0f}, 362109998Smarkm {0x05b, 0x40}, {0x084, 0x88}, {0x085, 0x24}, 36368651Skris {0x088, 0x54}, {0x08b, 0xb8}, {0x08c, 0x07}, 36468651Skris {0x08d, 0x00}, {0x094, 0x1b}, {0x095, 0x12}, 36568651Skris {0x096, 0x00}, {0x097, 0x06}, {0x09d, 0x1a}, 36668651Skris {0x09f, 0x10}, {0x0b4, 0x22}, {0x0be, 0x80}, 36768651Skris {0x0db, 0x00}, {0x0ee, 0x00}, {0x091, 0x03}, 36868651Skris {0x24c, 0x00}, {0x39f, 0x00}, {0x08c, 0x01}, 369238405Sjkim {0x08d, 0x10}, {0x08e, 0x08}, {0x08f, 0x00} 370109998Smarkm}; 371109998Smarkm 37268651Skrisstatic struct urtw_pair urtw_8225v2_rf_part2[] = { 37368651Skris { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, 37468651Skris { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, 37568651Skris { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 }, 376238405Sjkim { 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, 37768651Skris { 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 }, 37868651Skris { 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, 37968651Skris { 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 }, 38068651Skris { 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 }, 38168651Skris { 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 }, 38268651Skris { 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 } 38368651Skris}; 38468651Skris 38568651Skrisstatic struct urtw_pair urtw_8225v2b_rf_part2[] = { 386109998Smarkm { 0x00, 0x10 }, { 0x01, 0x0d }, { 0x02, 0x01 }, { 0x03, 0x00 }, 38768651Skris { 0x04, 0x14 }, { 0x05, 0xfb }, { 0x06, 0xfb }, { 0x07, 0x60 }, 38868651Skris { 0x08, 0x00 }, { 0x09, 0x60 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, 38968651Skris { 0x0c, 0x00 }, { 0x0d, 0x5c }, { 0x0e, 0x00 }, { 0x0f, 0x00 }, 39068651Skris { 0x10, 0x40 }, { 0x11, 0x00 }, { 0x12, 0x40 }, { 0x13, 0x00 }, 39168651Skris { 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0xa8 }, { 0x17, 0x26 }, 39268651Skris { 0x18, 0x32 }, { 0x19, 0x33 }, { 0x1a, 0x07 }, { 0x1b, 0xa5 }, 39368651Skris { 0x1c, 0x6f }, { 0x1d, 0x55 }, { 0x1e, 0xc8 }, { 0x1f, 0xb3 }, 39468651Skris { 0x20, 0x0a }, { 0x21, 0xe1 }, { 0x22, 0x2C }, { 0x23, 0x8a }, 39568651Skris { 0x24, 0x86 }, { 0x25, 0x83 }, { 0x26, 0x34 }, { 0x27, 0x0f }, 396238405Sjkim { 0x28, 0x4f }, { 0x29, 0x24 }, { 0x2a, 0x6f }, { 0x2b, 0xc2 }, 39768651Skris { 0x2c, 0x6b }, { 0x2d, 0x40 }, { 0x2e, 0x80 }, { 0x2f, 0x00 }, 39868651Skris { 0x30, 0xc0 }, { 0x31, 0xc1 }, { 0x32, 0x58 }, { 0x33, 0xf1 }, 39968651Skris { 0x34, 0x00 }, { 0x35, 0xe4 }, { 0x36, 0x90 }, { 0x37, 0x3e }, 40068651Skris { 0x38, 0x6d }, { 0x39, 0x3c }, { 0x3a, 0xfb }, { 0x3b, 0x07 } 40168651Skris}; 40268651Skris 40368651Skrisstatic struct urtw_pair urtw_8225v2_rf_part3[] = { 40468651Skris { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, 40568651Skris { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 }, 406109998Smarkm { 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 }, 40768651Skris { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 }, 40868651Skris { 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d }, 40968651Skris { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 }, 41068651Skris { 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 }, 41168651Skris { 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 } 41268651Skris}; 41368651Skris 41468651Skrisstatic uint16_t urtw_8225v2_rxgain[] = { 41568651Skris 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, 41668651Skris 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, 41768651Skris 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, 41868651Skris 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, 41968651Skris 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, 42068651Skris 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, 42168651Skris 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, 42268651Skris 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, 42368651Skris 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 42468651Skris 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, 42568651Skris 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, 42668651Skris 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb 42768651Skris}; 42868651Skris 42968651Skrisstatic uint16_t urtw_8225v2b_rxgain[] = { 43068651Skris 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 43168651Skris 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, 43268651Skris 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, 43368651Skris 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, 43468651Skris 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, 43568651Skris 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, 43668651Skris 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, 43768651Skris 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, 43868651Skris 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, 43968651Skris 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, 44068651Skris 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, 44168651Skris 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb 44268651Skris}; 44368651Skris 44468651Skrisstatic uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = { 44568651Skris 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 44668651Skris 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 44768651Skris 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 44868651Skris 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 44968651Skris 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 45068651Skris 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 45168651Skris}; 45268651Skris 45368651Skrisstatic uint8_t urtw_8225v2_txpwr_cck[] = { 45468651Skris 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 45568651Skris}; 45668651Skris 45768651Skrisstatic uint8_t urtw_8225v2_txpwr_cck_ch14[] = { 45868651Skris 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 45968651Skris}; 460109998Smarkm 46168651Skrisstatic uint8_t urtw_8225v2b_txpwr_cck[] = { 46268651Skris 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, 46368651Skris 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, 46468651Skris 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, 46568651Skris 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 46668651Skris}; 46768651Skris 46868651Skrisstatic uint8_t urtw_8225v2b_txpwr_cck_ch14[] = { 46968651Skris 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, 47068651Skris 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, 47168651Skris 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, 472238405Sjkim 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 47368651Skris}; 47468651Skris 47568651Skrisstatic struct urtw_pair urtw_ratetable[] = { 47668651Skris { 2, 0 }, { 4, 1 }, { 11, 2 }, { 12, 4 }, { 18, 5 }, 477160814Ssimon { 22, 3 }, { 24, 6 }, { 36, 7 }, { 48, 8 }, { 72, 9 }, 47868651Skris { 96, 10 }, { 108, 11 } 47968651Skris}; 480109998Smarkm 48189837Skrisstatic const uint8_t urtw_8187b_reg_table[][3] = { 48268651Skris { 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 }, 48368651Skris { 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 }, 48468651Skris { 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 }, 48568651Skris { 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 }, 48668651Skris { 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 }, 48768651Skris { 0xff, 0x00, 0 }, { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, 48868651Skris { 0x5a, 0x4b, 1 }, { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, 48968651Skris { 0x61, 0x09, 1 }, { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, 49068651Skris { 0xce, 0x0f, 1 }, { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, 49168651Skris { 0xe1, 0x0f, 1 }, { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, 492109998Smarkm { 0xf1, 0x01, 1 }, { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, 493109998Smarkm { 0xf4, 0x04, 1 }, { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, 494109998Smarkm { 0xf7, 0x07, 1 }, { 0xf8, 0x08, 1 }, { 0x4e, 0x00, 2 }, 495109998Smarkm { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, { 0x22, 0x68, 2 }, 496109998Smarkm { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, { 0x25, 0x7d, 2 }, 497109998Smarkm { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, { 0x4d, 0x08, 2 }, 498109998Smarkm { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, { 0x52, 0x04, 2 }, 499109998Smarkm { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, { 0x55, 0x23, 2 }, 500109998Smarkm { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, { 0x58, 0x08, 2 }, 50168651Skris { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, { 0x5b, 0x08, 2 }, 50268651Skris { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, { 0x62, 0x08, 2 }, 50368651Skris { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, { 0x72, 0x56, 2 }, 50468651Skris { 0x73, 0x9a, 2 }, { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, 50568651Skris { 0x5b, 0x40, 0 }, { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, 50668651Skris { 0x88, 0x54, 0 }, { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, 507109998Smarkm { 0x8d, 0x00, 0 }, { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, 508109998Smarkm { 0x96, 0x00, 0 }, { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, 50968651Skris { 0x9f, 0x10, 0 }, { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, 51068651Skris { 0xdb, 0x00, 0 }, { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 }, 51168651Skris { 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 }, 51268651Skris { 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 } 51368651Skris}; 51468651Skris 51568651Skrisstatic usb_callback_t urtw_bulk_rx_callback; 51668651Skrisstatic usb_callback_t urtw_bulk_tx_callback; 51768651Skrisstatic usb_callback_t urtw_bulk_tx_status_callback; 51868651Skris 51968651Skrisstatic const struct usb_config urtw_8187b_usbconfig[URTW_8187B_N_XFERS] = { 52068651Skris [URTW_8187B_BULK_RX] = { 52168651Skris .type = UE_BULK, 52268651Skris .endpoint = 0x83, 52368651Skris .direction = UE_DIR_IN, 52468651Skris .bufsize = MCLBYTES, 52568651Skris .flags = { 52668651Skris .ext_buffer = 1, 52768651Skris .pipe_bof = 1, 528109998Smarkm .short_xfer_ok = 1 529109998Smarkm }, 53068651Skris .callback = urtw_bulk_rx_callback 53168651Skris }, 53268651Skris [URTW_8187B_BULK_TX_STATUS] = { 53368651Skris .type = UE_BULK, 53468651Skris .endpoint = 0x89, 53568651Skris .direction = UE_DIR_IN, 53668651Skris .bufsize = sizeof(uint64_t), 53768651Skris .flags = { 53868651Skris .pipe_bof = 1, 53968651Skris .short_xfer_ok = 1 54068651Skris }, 541109998Smarkm .callback = urtw_bulk_tx_status_callback 542109998Smarkm }, 54368651Skris [URTW_8187B_BULK_TX_BE] = { 54468651Skris .type = UE_BULK, 54568651Skris .endpoint = URTW_8187B_TXPIPE_BE, 54668651Skris .direction = UE_DIR_OUT, 54768651Skris .bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT, 54868651Skris .flags = { 54968651Skris .force_short_xfer = 1, 55068651Skris .pipe_bof = 1, 55168651Skris }, 55268651Skris .callback = urtw_bulk_tx_callback, 55368651Skris .timeout = URTW_DATA_TIMEOUT 55468651Skris }, 55568651Skris [URTW_8187B_BULK_TX_BK] = { 55668651Skris .type = UE_BULK, 55768651Skris .endpoint = URTW_8187B_TXPIPE_BK, 55868651Skris .direction = UE_DIR_OUT, 55968651Skris .bufsize = URTW_TX_MAXSIZE, 56068651Skris .flags = { 56168651Skris .ext_buffer = 1, 56268651Skris .force_short_xfer = 1, 56368651Skris .pipe_bof = 1, 56468651Skris }, 56568651Skris .callback = urtw_bulk_tx_callback, 566109998Smarkm .timeout = URTW_DATA_TIMEOUT 56768651Skris }, 56868651Skris [URTW_8187B_BULK_TX_VI] = { 56968651Skris .type = UE_BULK, 57068651Skris .endpoint = URTW_8187B_TXPIPE_VI, 57168651Skris .direction = UE_DIR_OUT, 57268651Skris .bufsize = URTW_TX_MAXSIZE, 57368651Skris .flags = { 57468651Skris .ext_buffer = 1, 57568651Skris .force_short_xfer = 1, 57668651Skris .pipe_bof = 1, 577109998Smarkm }, 578109998Smarkm .callback = urtw_bulk_tx_callback, 57968651Skris .timeout = URTW_DATA_TIMEOUT 58068651Skris }, 58168651Skris [URTW_8187B_BULK_TX_VO] = { 58268651Skris .type = UE_BULK, 58368651Skris .endpoint = URTW_8187B_TXPIPE_VO, 58468651Skris .direction = UE_DIR_OUT, 58568651Skris .bufsize = URTW_TX_MAXSIZE, 58668651Skris .flags = { 58768651Skris .ext_buffer = 1, 58868651Skris .force_short_xfer = 1, 58968651Skris .pipe_bof = 1, 59068651Skris }, 59168651Skris .callback = urtw_bulk_tx_callback, 59268651Skris .timeout = URTW_DATA_TIMEOUT 59368651Skris }, 59468651Skris [URTW_8187B_BULK_TX_EP12] = { 595109998Smarkm .type = UE_BULK, 59668651Skris .endpoint = 0xc, 59768651Skris .direction = UE_DIR_OUT, 59868651Skris .bufsize = URTW_TX_MAXSIZE, 59968651Skris .flags = { 600109998Smarkm .ext_buffer = 1, 60168651Skris .force_short_xfer = 1, 602109998Smarkm .pipe_bof = 1, 60368651Skris }, 60468651Skris .callback = urtw_bulk_tx_callback, 60568651Skris .timeout = URTW_DATA_TIMEOUT 60668651Skris } 60768651Skris}; 60868651Skris 60968651Skrisstatic const struct usb_config urtw_8187l_usbconfig[URTW_8187L_N_XFERS] = { 61068651Skris [URTW_8187L_BULK_RX] = { 61168651Skris .type = UE_BULK, 61268651Skris .endpoint = 0x81, 61368651Skris .direction = UE_DIR_IN, 61468651Skris .bufsize = MCLBYTES, 61568651Skris .flags = { 61668651Skris .ext_buffer = 1, 61768651Skris .pipe_bof = 1, 61868651Skris .short_xfer_ok = 1 61968651Skris }, 62068651Skris .callback = urtw_bulk_rx_callback 621109998Smarkm }, 62268651Skris [URTW_8187L_BULK_TX_LOW] = { 623109998Smarkm .type = UE_BULK, 62468651Skris .endpoint = 0x2, 62568651Skris .direction = UE_DIR_OUT, 62668651Skris .bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT, 627238405Sjkim .flags = { 62868651Skris .force_short_xfer = 1, 62968651Skris .pipe_bof = 1, 63068651Skris }, 63168651Skris .callback = urtw_bulk_tx_callback, 632109998Smarkm .timeout = URTW_DATA_TIMEOUT 63368651Skris }, 63468651Skris [URTW_8187L_BULK_TX_NORMAL] = { 63568651Skris .type = UE_BULK, 63668651Skris .endpoint = 0x3, 63768651Skris .direction = UE_DIR_OUT, 63868651Skris .bufsize = URTW_TX_MAXSIZE, 63968651Skris .flags = { 64068651Skris .ext_buffer = 1, 64168651Skris .force_short_xfer = 1, 64268651Skris .pipe_bof = 1, 64368651Skris }, 64468651Skris .callback = urtw_bulk_tx_callback, 64568651Skris .timeout = URTW_DATA_TIMEOUT 64668651Skris }, 64768651Skris}; 64868651Skris 64968651Skrisstatic struct ieee80211vap *urtw_vap_create(struct ieee80211com *, 65068651Skris const char [IFNAMSIZ], int, enum ieee80211_opmode, 65168651Skris int, const uint8_t [IEEE80211_ADDR_LEN], 65268651Skris const uint8_t [IEEE80211_ADDR_LEN]); 65368651Skrisstatic void urtw_vap_delete(struct ieee80211vap *); 65468651Skrisstatic void urtw_init(void *); 65568651Skrisstatic void urtw_stop(struct ifnet *); 656109998Smarkmstatic void urtw_stop_locked(struct ifnet *); 65768651Skrisstatic int urtw_ioctl(struct ifnet *, u_long, caddr_t); 658109998Smarkmstatic void urtw_start(struct ifnet *); 65968651Skrisstatic int urtw_alloc_rx_data_list(struct urtw_softc *); 66068651Skrisstatic int urtw_alloc_tx_data_list(struct urtw_softc *); 66168651Skrisstatic int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *, 66268651Skris const struct ieee80211_bpf_params *); 66368651Skrisstatic void urtw_scan_start(struct ieee80211com *); 66468651Skrisstatic void urtw_scan_end(struct ieee80211com *); 66568651Skrisstatic void urtw_set_channel(struct ieee80211com *); 66668651Skrisstatic void urtw_update_mcast(struct ifnet *); 667109998Smarkmstatic int urtw_tx_start(struct urtw_softc *, 66868651Skris struct ieee80211_node *, struct mbuf *, 66968651Skris struct urtw_data *, int); 67068651Skrisstatic int urtw_newstate(struct ieee80211vap *, 671109998Smarkm enum ieee80211_state, int); 67268651Skrisstatic void urtw_led_ch(void *); 67368651Skrisstatic void urtw_ledtask(void *, int); 67468651Skrisstatic void urtw_watchdog(void *); 67568651Skrisstatic void urtw_set_multi(void *); 67668651Skrisstatic int urtw_isbmode(uint16_t); 67768651Skrisstatic uint16_t urtw_rate2rtl(uint32_t); 67868651Skrisstatic uint16_t urtw_rtl2rate(uint32_t); 67968651Skrisstatic usb_error_t urtw_set_rate(struct urtw_softc *); 68068651Skrisstatic usb_error_t urtw_update_msr(struct urtw_softc *); 68168651Skrisstatic usb_error_t urtw_read8_c(struct urtw_softc *, int, uint8_t *); 68268651Skrisstatic usb_error_t urtw_read16_c(struct urtw_softc *, int, uint16_t *); 68368651Skrisstatic usb_error_t urtw_read32_c(struct urtw_softc *, int, uint32_t *); 68468651Skrisstatic usb_error_t urtw_write8_c(struct urtw_softc *, int, uint8_t); 68568651Skrisstatic usb_error_t urtw_write16_c(struct urtw_softc *, int, uint16_t); 68668651Skrisstatic usb_error_t urtw_write32_c(struct urtw_softc *, int, uint32_t); 68768651Skrisstatic usb_error_t urtw_eprom_cs(struct urtw_softc *, int); 68868651Skrisstatic usb_error_t urtw_eprom_ck(struct urtw_softc *); 68968651Skrisstatic usb_error_t urtw_eprom_sendbits(struct urtw_softc *, int16_t *, 69068651Skris int); 69168651Skrisstatic usb_error_t urtw_eprom_read32(struct urtw_softc *, uint32_t, 69268651Skris uint32_t *); 693109998Smarkmstatic usb_error_t urtw_eprom_readbit(struct urtw_softc *, int16_t *); 694109998Smarkmstatic usb_error_t urtw_eprom_writebit(struct urtw_softc *, int16_t); 69568651Skrisstatic usb_error_t urtw_get_macaddr(struct urtw_softc *); 69668651Skrisstatic usb_error_t urtw_get_txpwr(struct urtw_softc *); 69768651Skrisstatic usb_error_t urtw_get_rfchip(struct urtw_softc *); 69868651Skrisstatic usb_error_t urtw_led_init(struct urtw_softc *); 69968651Skrisstatic usb_error_t urtw_8185_rf_pins_enable(struct urtw_softc *); 70068651Skrisstatic usb_error_t urtw_8185_tx_antenna(struct urtw_softc *, uint8_t); 70168651Skrisstatic usb_error_t urtw_8187_write_phy(struct urtw_softc *, uint8_t, 70268651Skris uint32_t); 70368651Skrisstatic usb_error_t urtw_8187_write_phy_ofdm_c(struct urtw_softc *, 704109998Smarkm uint8_t, uint32_t); 70568651Skrisstatic usb_error_t urtw_8187_write_phy_cck_c(struct urtw_softc *, uint8_t, 70668651Skris uint32_t); 707238405Sjkimstatic usb_error_t urtw_8225_setgain(struct urtw_softc *, int16_t); 70868651Skrisstatic usb_error_t urtw_8225_usb_init(struct urtw_softc *); 70968651Skrisstatic usb_error_t urtw_8225_write_c(struct urtw_softc *, uint8_t, 71068651Skris uint16_t); 71168651Skrisstatic usb_error_t urtw_8225_write_s16(struct urtw_softc *, uint8_t, int, 71268651Skris uint16_t *); 71368651Skrisstatic usb_error_t urtw_8225_read(struct urtw_softc *, uint8_t, 71468651Skris uint32_t *); 71568651Skrisstatic usb_error_t urtw_8225_rf_init(struct urtw_softc *); 71668651Skrisstatic usb_error_t urtw_8225_rf_set_chan(struct urtw_softc *, int); 71768651Skrisstatic usb_error_t urtw_8225_rf_set_sens(struct urtw_softc *, int); 71868651Skrisstatic usb_error_t urtw_8225_set_txpwrlvl(struct urtw_softc *, int); 71968651Skrisstatic usb_error_t urtw_8225_rf_stop(struct urtw_softc *); 72068651Skrisstatic usb_error_t urtw_8225v2_rf_init(struct urtw_softc *); 72168651Skrisstatic usb_error_t urtw_8225v2_rf_set_chan(struct urtw_softc *, int); 722109998Smarkmstatic usb_error_t urtw_8225v2_set_txpwrlvl(struct urtw_softc *, int); 72368651Skrisstatic usb_error_t urtw_8225v2_setgain(struct urtw_softc *, int16_t); 72468651Skrisstatic usb_error_t urtw_8225_isv2(struct urtw_softc *, int *); 72568651Skrisstatic usb_error_t urtw_8225v2b_rf_init(struct urtw_softc *); 72668651Skrisstatic usb_error_t urtw_8225v2b_rf_set_chan(struct urtw_softc *, int); 72768651Skrisstatic usb_error_t urtw_read8e(struct urtw_softc *, int, uint8_t *); 728194206Ssimonstatic usb_error_t urtw_write8e(struct urtw_softc *, int, uint8_t); 72968651Skrisstatic usb_error_t urtw_8180_set_anaparam(struct urtw_softc *, uint32_t); 73068651Skrisstatic usb_error_t urtw_8185_set_anaparam2(struct urtw_softc *, uint32_t); 73168651Skrisstatic usb_error_t urtw_intr_enable(struct urtw_softc *); 73268651Skrisstatic usb_error_t urtw_intr_disable(struct urtw_softc *); 73368651Skrisstatic usb_error_t urtw_reset(struct urtw_softc *); 73468651Skrisstatic usb_error_t urtw_led_on(struct urtw_softc *, int); 73568651Skrisstatic usb_error_t urtw_led_ctl(struct urtw_softc *, int); 73668651Skrisstatic usb_error_t urtw_led_blink(struct urtw_softc *); 73768651Skrisstatic usb_error_t urtw_led_mode0(struct urtw_softc *, int); 73868651Skrisstatic usb_error_t urtw_led_mode1(struct urtw_softc *, int); 73968651Skrisstatic usb_error_t urtw_led_mode2(struct urtw_softc *, int); 74068651Skrisstatic usb_error_t urtw_led_mode3(struct urtw_softc *, int); 74168651Skrisstatic usb_error_t urtw_rx_setconf(struct urtw_softc *); 74268651Skrisstatic usb_error_t urtw_rx_enable(struct urtw_softc *); 74368651Skrisstatic usb_error_t urtw_tx_enable(struct urtw_softc *sc); 744109998Smarkmstatic void urtw_free_tx_data_list(struct urtw_softc *); 74589837Skrisstatic void urtw_free_rx_data_list(struct urtw_softc *); 74668651Skrisstatic void urtw_free_data_list(struct urtw_softc *, 74768651Skris struct urtw_data data[], int, int); 74868651Skrisstatic usb_error_t urtw_adapter_start(struct urtw_softc *); 74968651Skrisstatic usb_error_t urtw_adapter_start_b(struct urtw_softc *); 75068651Skrisstatic usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t); 75168651Skrisstatic usb_error_t urtw_8187b_cmd_reset(struct urtw_softc *); 75268651Skrisstatic usb_error_t urtw_do_request(struct urtw_softc *, 753109998Smarkm struct usb_device_request *, void *); 75468651Skrisstatic usb_error_t urtw_8225v2b_set_txpwrlvl(struct urtw_softc *, int); 75568651Skrisstatic usb_error_t urtw_led_off(struct urtw_softc *, int); 75668651Skrisstatic void urtw_abort_xfers(struct urtw_softc *); 75768651Skrisstatic struct urtw_data * 75868651Skris urtw_getbuf(struct urtw_softc *sc); 75968651Skrisstatic int urtw_compute_txtime(uint16_t, uint16_t, uint8_t, 76068651Skris uint8_t); 76168651Skrisstatic void urtw_updateslot(struct ifnet *); 762109998Smarkmstatic void urtw_updateslottask(void *, int); 76368651Skrisstatic void urtw_sysctl_node(struct urtw_softc *); 76468651Skris 76568651Skrisstatic int 76668651Skrisurtw_match(device_t dev) 767109998Smarkm{ 76868651Skris struct usb_attach_arg *uaa = device_get_ivars(dev); 769109998Smarkm 770109998Smarkm if (uaa->usb_mode != USB_MODE_HOST) 771109998Smarkm return (ENXIO); 772109998Smarkm if (uaa->info.bConfigIndex != URTW_CONFIG_INDEX) 773109998Smarkm return (ENXIO); 774109998Smarkm if (uaa->info.bIfaceIndex != URTW_IFACE_INDEX) 775109998Smarkm return (ENXIO); 776109998Smarkm 777109998Smarkm return (usbd_lookup_id_by_uaa(urtw_devs, sizeof(urtw_devs), uaa)); 778109998Smarkm} 779109998Smarkm 780109998Smarkmstatic int 781109998Smarkmurtw_attach(device_t dev) 782109998Smarkm{ 783109998Smarkm const struct usb_config *setup_start; 784109998Smarkm int ret = ENXIO; 785109998Smarkm struct urtw_softc *sc = device_get_softc(dev); 786109998Smarkm struct usb_attach_arg *uaa = device_get_ivars(dev); 787109998Smarkm struct ieee80211com *ic; 788109998Smarkm struct ifnet *ifp; 789109998Smarkm uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */ 790109998Smarkm uint16_t n_setup; 791109998Smarkm uint32_t data; 792109998Smarkm usb_error_t error; 793109998Smarkm 794109998Smarkm device_set_usb_desc(dev); 795109998Smarkm 796109998Smarkm sc->sc_dev = dev; 797109998Smarkm sc->sc_udev = uaa->device; 798109998Smarkm if (USB_GET_DRIVER_INFO(uaa) == URTW_REV_RTL8187B) 799109998Smarkm sc->sc_flags |= URTW_RTL8187B; 800109998Smarkm#ifdef URTW_DEBUG 801109998Smarkm sc->sc_debug = urtw_debug; 802109998Smarkm#endif 803109998Smarkm 804109998Smarkm mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, 805194206Ssimon MTX_DEF); 80668651Skris usb_callout_init_mtx(&sc->sc_led_ch, &sc->sc_mtx, 0); 807109998Smarkm TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc); 808109998Smarkm TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc); 809109998Smarkm callout_init(&sc->sc_watchdog_ch, 0); 81068651Skris 81168651Skris if (sc->sc_flags & URTW_RTL8187B) { 812238405Sjkim setup_start = urtw_8187b_usbconfig; 81368651Skris n_setup = URTW_8187B_N_XFERS; 81468651Skris } else { 81568651Skris setup_start = urtw_8187l_usbconfig; 81668651Skris n_setup = URTW_8187L_N_XFERS; 81768651Skris } 81868651Skris 81968651Skris error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, 82068651Skris setup_start, n_setup, sc, &sc->sc_mtx); 82168651Skris if (error) { 82268651Skris device_printf(dev, "could not allocate USB transfers, " 82368651Skris "err=%s\n", usbd_errstr(error)); 824109998Smarkm ret = ENXIO; 82568651Skris goto fail0; 82668651Skris } 82768651Skris 82868651Skris if (sc->sc_flags & URTW_RTL8187B) { 82968651Skris sc->sc_tx_dma_buf = 830194206Ssimon usbd_xfer_get_frame_buffer(sc->sc_xfer[ 83168651Skris URTW_8187B_BULK_TX_BE], 0); 83268651Skris } else { 83368651Skris sc->sc_tx_dma_buf = 83468651Skris usbd_xfer_get_frame_buffer(sc->sc_xfer[ 83568651Skris URTW_8187L_BULK_TX_LOW], 0); 83668651Skris } 83768651Skris 83868651Skris URTW_LOCK(sc); 83968651Skris 84068651Skris urtw_read32_m(sc, URTW_RX, &data); 84168651Skris sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 : 84268651Skris URTW_EEPROM_93C46; 84368651Skris 84468651Skris error = urtw_get_rfchip(sc); 84568651Skris if (error != 0) 846109998Smarkm goto fail; 84789837Skris error = urtw_get_macaddr(sc); 84868651Skris if (error != 0) 84968651Skris goto fail; 85068651Skris error = urtw_get_txpwr(sc); 85168651Skris if (error != 0) 85268651Skris goto fail; 85368651Skris error = urtw_led_init(sc); 85468651Skris if (error != 0) 855109998Smarkm goto fail; 85668651Skris 85768651Skris URTW_UNLOCK(sc); 85868651Skris 85968651Skris sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY; 86068651Skris sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY; 86168651Skris sc->sc_currate = 3; 86268651Skris sc->sc_preamble_mode = urtw_preamble_mode; 86368651Skris 864109998Smarkm ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); 86568651Skris if (ifp == NULL) { 86668651Skris device_printf(sc->sc_dev, "can not allocate ifnet\n"); 86768651Skris ret = ENOMEM; 86868651Skris goto fail1; 869109998Smarkm } 87068651Skris 87168651Skris ifp->if_softc = sc; 87268651Skris if_initname(ifp, "urtw", device_get_unit(sc->sc_dev)); 87368651Skris ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 87468651Skris ifp->if_init = urtw_init; 87568651Skris ifp->if_ioctl = urtw_ioctl; 87668651Skris ifp->if_start = urtw_start; 87768651Skris /* XXX URTW_TX_DATA_LIST_COUNT */ 87868651Skris IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 87968651Skris ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; 88068651Skris IFQ_SET_READY(&ifp->if_snd); 88168651Skris 88268651Skris ic = ifp->if_l2com; 88368651Skris ic->ic_ifp = ifp; 88468651Skris ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 88568651Skris ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 886109998Smarkm 88768651Skris /* set device capabilities */ 888109998Smarkm ic->ic_caps = 88968651Skris IEEE80211_C_STA | /* station mode */ 89068651Skris IEEE80211_C_MONITOR | /* monitor mode supported */ 891109998Smarkm IEEE80211_C_TXPMGT | /* tx power management */ 89268651Skris IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 89368651Skris IEEE80211_C_SHSLOT | /* short slot time supported */ 89468651Skris IEEE80211_C_BGSCAN | /* capable of bg scanning */ 89568651Skris IEEE80211_C_WPA; /* 802.11i */ 89668651Skris 89768651Skris bands = 0; 89868651Skris setbit(&bands, IEEE80211_MODE_11B); 89968651Skris setbit(&bands, IEEE80211_MODE_11G); 90068651Skris ieee80211_init_channels(ic, NULL, &bands); 90168651Skris 90268651Skris ieee80211_ifattach(ic, sc->sc_bssid); 90368651Skris ic->ic_raw_xmit = urtw_raw_xmit; 90468651Skris ic->ic_scan_start = urtw_scan_start; 90568651Skris ic->ic_scan_end = urtw_scan_end; 90668651Skris ic->ic_set_channel = urtw_set_channel; 90768651Skris ic->ic_updateslot = urtw_updateslot; 90868651Skris ic->ic_vap_create = urtw_vap_create; 90968651Skris ic->ic_vap_delete = urtw_vap_delete; 910109998Smarkm ic->ic_update_mcast = urtw_update_mcast; 91168651Skris 91268651Skris ieee80211_radiotap_attach(ic, 91368651Skris &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), 91468651Skris URTW_TX_RADIOTAP_PRESENT, 91568651Skris &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), 91668651Skris URTW_RX_RADIOTAP_PRESENT); 91768651Skris 91868651Skris urtw_sysctl_node(sc); 91968651Skris 92068651Skris if (bootverbose) 92168651Skris ieee80211_announce(ic); 92268651Skris return (0); 92368651Skris 92468651Skrisfail: URTW_UNLOCK(sc); 92568651Skrisfail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? 92668651Skris URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); 92768651Skrisfail0: 92868651Skris return (ret); 92972613Skris} 93068651Skris 93168651Skrisstatic int 932109998Smarkmurtw_detach(device_t dev) 933109998Smarkm{ 93468651Skris struct urtw_softc *sc = device_get_softc(dev); 93568651Skris struct ifnet *ifp = sc->sc_ifp; 93689837Skris struct ieee80211com *ic = ifp->if_l2com; 93789837Skris unsigned int x; 93868651Skris unsigned int n_xfers; 93968651Skris 94068651Skris /* Prevent further ioctls */ 941109998Smarkm URTW_LOCK(sc); 94268651Skris sc->sc_flags |= URTW_DETACHED; 94368651Skris URTW_UNLOCK(sc); 94468651Skris 94568651Skris urtw_stop(ifp); 94668651Skris 94768651Skris ieee80211_draintask(ic, &sc->sc_updateslot_task); 94868651Skris ieee80211_draintask(ic, &sc->sc_led_task); 94968651Skris 95068651Skris usb_callout_drain(&sc->sc_led_ch); 951109998Smarkm callout_drain(&sc->sc_watchdog_ch); 95268651Skris 953238405Sjkim n_xfers = (sc->sc_flags & URTW_RTL8187B) ? 954238405Sjkim URTW_8187B_N_XFERS : URTW_8187L_N_XFERS; 955238405Sjkim 95668651Skris /* prevent further allocations from RX/TX data lists */ 95768651Skris URTW_LOCK(sc); 95868651Skris STAILQ_INIT(&sc->sc_tx_active); 95968651Skris STAILQ_INIT(&sc->sc_tx_inactive); 96068651Skris STAILQ_INIT(&sc->sc_tx_pending); 96168651Skris 96268651Skris STAILQ_INIT(&sc->sc_rx_active); 96368651Skris STAILQ_INIT(&sc->sc_rx_inactive); 96468651Skris URTW_UNLOCK(sc); 965142425Snectar 96668651Skris /* drain USB transfers */ 96768651Skris for (x = 0; x != n_xfers; x++) 96868651Skris usbd_transfer_drain(sc->sc_xfer[x]); 96968651Skris 97068651Skris /* free data buffers */ 97168651Skris URTW_LOCK(sc); 97268651Skris urtw_free_tx_data_list(sc); 97368651Skris urtw_free_rx_data_list(sc); 97468651Skris URTW_UNLOCK(sc); 97568651Skris 97668651Skris /* free USB transfers and some data buffers */ 97768651Skris usbd_transfer_unsetup(sc->sc_xfer, n_xfers); 97868651Skris 97968651Skris ieee80211_ifdetach(ic); 98068651Skris if_free(ifp); 98168651Skris mtx_destroy(&sc->sc_mtx); 98268651Skris return (0); 983109998Smarkm} 98468651Skris 98568651Skrisstatic void 98668651Skrisurtw_free_tx_data_list(struct urtw_softc *sc) 987238405Sjkim{ 988238405Sjkim urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0); 98968651Skris} 99068651Skris 991109998Smarkmstatic void 992109998Smarkmurtw_free_rx_data_list(struct urtw_softc *sc) 99368651Skris{ 99468651Skris urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1); 99568651Skris} 99668651Skris 99768651Skrisstatic void 99868651Skrisurtw_free_data_list(struct urtw_softc *sc, struct urtw_data data[], int ndata, 99968651Skris int fillmbuf) 100068651Skris{ 100168651Skris int i; 100268651Skris 100368651Skris for (i = 0; i < ndata; i++) { 100468651Skris struct urtw_data *dp = &data[i]; 100568651Skris 100668651Skris if (fillmbuf == 1) { 100768651Skris if (dp->m != NULL) { 100868651Skris m_freem(dp->m); 100968651Skris dp->m = NULL; 101068651Skris dp->buf = NULL; 101168651Skris } 101268651Skris } else { 101368651Skris dp->buf = NULL; 101468651Skris } 101568651Skris if (dp->ni != NULL) { 101668651Skris ieee80211_free_node(dp->ni); 1017109998Smarkm dp->ni = NULL; 101868651Skris } 101968651Skris } 102068651Skris} 102168651Skris 102268651Skrisstatic struct ieee80211vap * 102368651Skrisurtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, 102468651Skris enum ieee80211_opmode opmode, int flags, 102568651Skris const uint8_t bssid[IEEE80211_ADDR_LEN], 102668651Skris const uint8_t mac[IEEE80211_ADDR_LEN]) 102768651Skris{ 102868651Skris struct urtw_vap *uvp; 102968651Skris struct ieee80211vap *vap; 103068651Skris 103168651Skris if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ 103268651Skris return (NULL); 103368651Skris uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap), 103468651Skris M_80211_VAP, M_NOWAIT | M_ZERO); 103568651Skris if (uvp == NULL) 103668651Skris return (NULL); 103768651Skris vap = &uvp->vap; 103868651Skris /* enable s/w bmiss handling for sta mode */ 103968651Skris 104068651Skris if (ieee80211_vap_setup(ic, vap, name, unit, opmode, 104168651Skris flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) { 104268651Skris /* out of memory */ 104368651Skris free(uvp, M_80211_VAP); 104468651Skris return (NULL); 104568651Skris } 104668651Skris 104768651Skris /* override state transition machine */ 104868651Skris uvp->newstate = vap->iv_newstate; 104968651Skris vap->iv_newstate = urtw_newstate; 105068651Skris 105168651Skris /* complete setup */ 105268651Skris ieee80211_vap_attach(vap, ieee80211_media_change, 1053238405Sjkim ieee80211_media_status); 105468651Skris ic->ic_opmode = opmode; 105568651Skris return (vap); 105668651Skris} 105768651Skris 105868651Skrisstatic void 105968651Skrisurtw_vap_delete(struct ieee80211vap *vap) 1060142425Snectar{ 106168651Skris struct urtw_vap *uvp = URTW_VAP(vap); 106268651Skris 106368651Skris ieee80211_vap_detach(vap); 106468651Skris free(uvp, M_80211_VAP); 106568651Skris} 106668651Skris 106768651Skrisstatic void 1068298998Sjkimurtw_init_locked(void *arg) 1069298998Sjkim{ 107068651Skris int ret; 107168651Skris struct urtw_softc *sc = arg; 107268651Skris struct ifnet *ifp = sc->sc_ifp; 107368651Skris usb_error_t error; 107468651Skris 107568651Skris if (ifp->if_drv_flags & IFF_DRV_RUNNING) 107668651Skris urtw_stop_locked(ifp); 107768651Skris 107868651Skris error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) : 107968651Skris urtw_adapter_start(sc); 108068651Skris if (error != 0) 108168651Skris goto fail; 108268651Skris 108368651Skris /* reset softc variables */ 108468651Skris sc->sc_txtimer = 0; 108568651Skris 108668651Skris if (!(sc->sc_flags & URTW_INIT_ONCE)) { 108768651Skris ret = urtw_alloc_rx_data_list(sc); 108868651Skris if (ret != 0) 108968651Skris goto fail; 109068651Skris ret = urtw_alloc_tx_data_list(sc); 109168651Skris if (ret != 0) 109268651Skris goto fail; 109368651Skris sc->sc_flags |= URTW_INIT_ONCE; 109468651Skris } 109568651Skris 109668651Skris error = urtw_rx_enable(sc); 109768651Skris if (error != 0) 109868651Skris goto fail; 109968651Skris error = urtw_tx_enable(sc); 110068651Skris if (error != 0) 110168651Skris goto fail; 110268651Skris 110368651Skris if (sc->sc_flags & URTW_RTL8187B) 110468651Skris usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]); 110568651Skris 110668651Skris ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1107160814Ssimon ifp->if_drv_flags |= IFF_DRV_RUNNING; 110868651Skris 110968651Skris callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); 111068651Skrisfail: 111168651Skris return; 111268651Skris} 111368651Skris 111468651Skrisstatic void 111568651Skrisurtw_init(void *arg) 1116298998Sjkim{ 1117298998Sjkim struct urtw_softc *sc = arg; 1118298998Sjkim 1119298998Sjkim URTW_LOCK(sc); 1120238405Sjkim urtw_init_locked(arg); 1121238405Sjkim URTW_UNLOCK(sc); 1122238405Sjkim} 1123238405Sjkim 1124238405Sjkimstatic usb_error_t 112568651Skrisurtw_adapter_start_b(struct urtw_softc *sc) 112668651Skris{ 112768651Skris#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) 112868651Skris uint8_t data8; 112968651Skris usb_error_t error; 1130109998Smarkm 113168651Skris error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 113268651Skris if (error) 1133109998Smarkm goto fail; 113468651Skris 113568651Skris urtw_read8_m(sc, URTW_CONFIG3, &data8); 113668651Skris urtw_write8_m(sc, URTW_CONFIG3, 113768651Skris data8 | URTW_CONFIG3_ANAPARAM_WRITE | URTW_CONFIG3_GNT_SELECT); 113868651Skris urtw_write32_m(sc, URTW_ANAPARAM2, URTW_8187B_8225_ANAPARAM2_ON); 113968651Skris urtw_write32_m(sc, URTW_ANAPARAM, URTW_8187B_8225_ANAPARAM_ON); 1140109998Smarkm urtw_write8_m(sc, URTW_ANAPARAM3, URTW_8187B_8225_ANAPARAM3_ON); 1141109998Smarkm 1142109998Smarkm urtw_write8_m(sc, 0x61, 0x10); 1143109998Smarkm urtw_read8_m(sc, 0x62, &data8); 1144109998Smarkm urtw_write8_m(sc, 0x62, data8 & ~(1 << 5)); 1145109998Smarkm urtw_write8_m(sc, 0x62, data8 | (1 << 5)); 1146109998Smarkm 1147109998Smarkm urtw_read8_m(sc, URTW_CONFIG3, &data8); 114868651Skris data8 &= ~URTW_CONFIG3_ANAPARAM_WRITE; 114968651Skris urtw_write8_m(sc, URTW_CONFIG3, data8); 115068651Skris 115168651Skris error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 115268651Skris if (error) 115368651Skris goto fail; 115468651Skris 115568651Skris error = urtw_8187b_cmd_reset(sc); 115668651Skris if (error) 115768651Skris goto fail; 115868651Skris 115968651Skris error = sc->sc_rf_init(sc); 116068651Skris if (error != 0) 116168651Skris goto fail; 116268651Skris urtw_write8_m(sc, URTW_CMD, URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE); 116368651Skris 116468651Skris /* fix RTL8187B RX stall */ 116568651Skris error = urtw_intr_enable(sc); 116668651Skris if (error) 116768651Skris goto fail; 116868651Skris 116968651Skris error = urtw_write8e(sc, 0x41, 0xf4); 1170109998Smarkm if (error) 1171109998Smarkm goto fail; 1172109998Smarkm error = urtw_write8e(sc, 0x40, 0x00); 117368651Skris if (error) 117468651Skris goto fail; 117568651Skris error = urtw_write8e(sc, 0x42, 0x00); 117668651Skris if (error) 1177109998Smarkm goto fail; 117868651Skris error = urtw_write8e(sc, 0x42, 0x01); 117968651Skris if (error) 118068651Skris goto fail; 118168651Skris error = urtw_write8e(sc, 0x40, 0x0f); 118268651Skris if (error) 118368651Skris goto fail; 118468651Skris error = urtw_write8e(sc, 0x42, 0x00); 1185109998Smarkm if (error) 1186109998Smarkm goto fail; 118768651Skris error = urtw_write8e(sc, 0x42, 0x01); 118868651Skris if (error) 118968651Skris goto fail; 119068651Skris 119168651Skris urtw_read8_m(sc, 0xdb, &data8); 119268651Skris urtw_write8_m(sc, 0xdb, data8 | (1 << 2)); 119368651Skris urtw_write16_m(sc, 0x372, 0x59fa); 119468651Skris urtw_write16_m(sc, 0x374, 0x59d2); 119568651Skris urtw_write16_m(sc, 0x376, 0x59d2); 119668651Skris urtw_write16_m(sc, 0x378, 0x19fa); 119768651Skris urtw_write16_m(sc, 0x37a, 0x19fa); 119868651Skris urtw_write16_m(sc, 0x37c, 0x00d0); 119968651Skris urtw_write8_m(sc, 0x61, 0); 120068651Skris 1201109998Smarkm urtw_write8_m(sc, 0x180, 0x0f); 120268651Skris urtw_write8_m(sc, 0x183, 0x03); 120368651Skris urtw_write8_m(sc, 0xda, 0x10); 120468651Skris urtw_write8_m(sc, 0x24d, 0x08); 1205109998Smarkm urtw_write32_m(sc, URTW_HSSI_PARA, 0x0600321b); 120668651Skris 120768651Skris urtw_write16_m(sc, 0x1ec, 0x800); /* RX MAX SIZE */ 120868651Skrisfail: 120968651Skris return (error); 121068651Skris#undef N 121168651Skris} 121268651Skris 121368651Skrisstatic usb_error_t 121468651Skrisurtw_adapter_start(struct urtw_softc *sc) 121568651Skris{ 121668651Skris usb_error_t error; 121768651Skris 121868651Skris error = urtw_reset(sc); 1219109998Smarkm if (error) 1220109998Smarkm goto fail; 122168651Skris 122268651Skris urtw_write8_m(sc, URTW_ADDR_MAGIC1, 0); 122368651Skris urtw_write8_m(sc, URTW_GPIO, 0); 1224160814Ssimon 1225160814Ssimon /* for led */ 122668651Skris urtw_write8_m(sc, URTW_ADDR_MAGIC1, 4); 122768651Skris error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON); 122868651Skris if (error != 0) 122968651Skris goto fail; 123068651Skris 123168651Skris error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 123268651Skris if (error) 123368651Skris goto fail; 123468651Skris /* applying MAC address again. */ 123568651Skris urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]); 123668651Skris urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff); 123768651Skris error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 1238109998Smarkm if (error) 123968651Skris goto fail; 124068651Skris 124168651Skris error = urtw_update_msr(sc); 124268651Skris if (error) 124368651Skris goto fail; 124468651Skris 124568651Skris urtw_write32_m(sc, URTW_INT_TIMEOUT, 0); 124668651Skris urtw_write8_m(sc, URTW_WPA_CONFIG, 0); 124768651Skris urtw_write8_m(sc, URTW_RATE_FALLBACK, URTW_RATE_FALLBACK_ENABLE | 0x1); 124868651Skris error = urtw_set_rate(sc); 1249109998Smarkm if (error != 0) 1250109998Smarkm goto fail; 125168651Skris 125268651Skris error = sc->sc_rf_init(sc); 125368651Skris if (error != 0) 125468651Skris goto fail; 125568651Skris if (sc->sc_rf_set_sens != NULL) 125668651Skris sc->sc_rf_set_sens(sc, sc->sc_sens); 125768651Skris 1258238405Sjkim /* XXX correct? to call write16 */ 1259238405Sjkim urtw_write16_m(sc, URTW_PSR, 1); 126068651Skris urtw_write16_m(sc, URTW_ADDR_MAGIC2, 0x10); 126168651Skris urtw_write8_m(sc, URTW_TALLY_SEL, 0x80); 126268651Skris urtw_write8_m(sc, URTW_ADDR_MAGIC3, 0x60); 126368651Skris /* XXX correct? to call write16 */ 126468651Skris urtw_write16_m(sc, URTW_PSR, 0); 126568651Skris urtw_write8_m(sc, URTW_ADDR_MAGIC1, 4); 126668651Skris 126768651Skris error = urtw_intr_enable(sc); 126868651Skris if (error != 0) 126968651Skris goto fail; 127068651Skris 127168651Skrisfail: 127268651Skris return (error); 127368651Skris} 127468651Skris 127568651Skrisstatic usb_error_t 127668651Skrisurtw_set_mode(struct urtw_softc *sc, uint32_t mode) 127768651Skris{ 127868651Skris uint8_t data; 127968651Skris usb_error_t error; 128068651Skris 128168651Skris urtw_read8_m(sc, URTW_EPROM_CMD, &data); 128268651Skris data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT); 128368651Skris data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK); 128468651Skris urtw_write8_m(sc, URTW_EPROM_CMD, data); 128568651Skrisfail: 128668651Skris return (error); 128768651Skris} 128868651Skris 128968651Skrisstatic usb_error_t 129068651Skrisurtw_8187b_cmd_reset(struct urtw_softc *sc) 129168651Skris{ 129268651Skris int i; 129368651Skris uint8_t data8; 129468651Skris usb_error_t error; 129568651Skris 129668651Skris /* XXX the code can be duplicate with urtw_reset(). */ 129768651Skris urtw_read8_m(sc, URTW_CMD, &data8); 129868651Skris data8 = (data8 & 0x2) | URTW_CMD_RST; 129968651Skris urtw_write8_m(sc, URTW_CMD, data8); 130068651Skris 130168651Skris for (i = 0; i < 20; i++) { 130268651Skris usb_pause_mtx(&sc->sc_mtx, 2); 130368651Skris urtw_read8_m(sc, URTW_CMD, &data8); 130468651Skris if (!(data8 & URTW_CMD_RST)) 130568651Skris break; 130668651Skris } 130768651Skris if (i >= 20) { 130868651Skris device_printf(sc->sc_dev, "reset timeout\n"); 130968651Skris goto fail; 131068651Skris } 131168651Skrisfail: 131268651Skris return (error); 131368651Skris} 131468651Skris 131568651Skrisstatic usb_error_t 131668651Skrisurtw_do_request(struct urtw_softc *sc, 131768651Skris struct usb_device_request *req, void *data) 131868651Skris{ 131968651Skris usb_error_t err; 132068651Skris int ntries = 10; 132168651Skris 132268651Skris URTW_ASSERT_LOCKED(sc); 132368651Skris 132468651Skris while (ntries--) { 132568651Skris err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, 132668651Skris req, data, 0, NULL, 250 /* ms */); 132768651Skris if (err == 0) 132868651Skris break; 132968651Skris 133068651Skris DPRINTF(sc, URTW_DEBUG_INIT, 133168651Skris "Control request failed, %s (retrying)\n", 133268651Skris usbd_errstr(err)); 133368651Skris usb_pause_mtx(&sc->sc_mtx, hz / 100); 133468651Skris } 133568651Skris return (err); 133668651Skris} 133768651Skris 133868651Skrisstatic void 133968651Skrisurtw_stop_locked(struct ifnet *ifp) 134068651Skris{ 134168651Skris struct urtw_softc *sc = ifp->if_softc; 134268651Skris uint8_t data8; 134368651Skris usb_error_t error; 134468651Skris 134568651Skris ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 134668651Skris 134768651Skris error = urtw_intr_disable(sc); 134868651Skris if (error) 134968651Skris goto fail; 135068651Skris urtw_read8_m(sc, URTW_CMD, &data8); 135168651Skris data8 &= ~(URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE); 135268651Skris urtw_write8_m(sc, URTW_CMD, data8); 135368651Skris 135468651Skris error = sc->sc_rf_stop(sc); 135568651Skris if (error != 0) 135668651Skris goto fail; 135768651Skris 135868651Skris error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 135968651Skris if (error) 136068651Skris goto fail; 136168651Skris urtw_read8_m(sc, URTW_CONFIG4, &data8); 136268651Skris urtw_write8_m(sc, URTW_CONFIG4, data8 | URTW_CONFIG4_VCOOFF); 136368651Skris error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 136468651Skris if (error) 136568651Skris goto fail; 136668651Skrisfail: 136768651Skris if (error) 136868651Skris device_printf(sc->sc_dev, "failed to stop (%s)\n", 136968651Skris usbd_errstr(error)); 137068651Skris 137168651Skris usb_callout_stop(&sc->sc_led_ch); 137268651Skris callout_stop(&sc->sc_watchdog_ch); 137368651Skris 137468651Skris urtw_abort_xfers(sc); 137568651Skris} 137668651Skris 137768651Skrisstatic void 137868651Skrisurtw_stop(struct ifnet *ifp) 137968651Skris{ 138068651Skris struct urtw_softc *sc = ifp->if_softc; 138168651Skris 138268651Skris URTW_LOCK(sc); 138368651Skris urtw_stop_locked(ifp); 138468651Skris URTW_UNLOCK(sc); 138568651Skris} 138668651Skris 138768651Skrisstatic void 138868651Skrisurtw_abort_xfers(struct urtw_softc *sc) 138968651Skris{ 139068651Skris int i, max; 139168651Skris 139268651Skris URTW_ASSERT_LOCKED(sc); 139368651Skris 139468651Skris max = (sc->sc_flags & URTW_RTL8187B) ? URTW_8187B_N_XFERS : 139568651Skris URTW_8187L_N_XFERS; 139668651Skris 139768651Skris /* abort any pending transfers */ 139868651Skris for (i = 0; i < max; i++) 139968651Skris usbd_transfer_stop(sc->sc_xfer[i]); 140068651Skris} 140168651Skris 140268651Skrisstatic int 140368651Skrisurtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 140468651Skris{ 140568651Skris struct urtw_softc *sc = ifp->if_softc; 140668651Skris struct ieee80211com *ic = ifp->if_l2com; 140768651Skris struct ifreq *ifr = (struct ifreq *) data; 140868651Skris int error; 140968651Skris int startall = 0; 141068651Skris 141168651Skris URTW_LOCK(sc); 141268651Skris error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0; 141368651Skris URTW_UNLOCK(sc); 141468651Skris if (error) 141568651Skris return (error); 141668651Skris 141768651Skris switch (cmd) { 141868651Skris case SIOCSIFFLAGS: 141968651Skris if (ifp->if_flags & IFF_UP) { 142068651Skris if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 142168651Skris if ((ifp->if_flags ^ sc->sc_if_flags) & 142268651Skris (IFF_ALLMULTI | IFF_PROMISC)) 142368651Skris urtw_set_multi(sc); 142468651Skris } else { 142568651Skris urtw_init(ifp->if_softc); 142668651Skris startall = 1; 142768651Skris } 142868651Skris } else { 142968651Skris if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1430109998Smarkm urtw_stop(ifp); 1431109998Smarkm } 1432109998Smarkm sc->sc_if_flags = ifp->if_flags; 143368651Skris if (startall) 1434109998Smarkm ieee80211_start_all(ic); 1435109998Smarkm break; 143668651Skris case SIOCGIFMEDIA: 1437109998Smarkm error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 143868651Skris break; 143968651Skris case SIOCGIFADDR: 1440109998Smarkm error = ether_ioctl(ifp, cmd, data); 1441109998Smarkm break; 144268651Skris default: 1443109998Smarkm error = EINVAL; 1444109998Smarkm break; 144568651Skris } 1446109998Smarkm return (error); 144768651Skris} 1448109998Smarkm 144968651Skrisstatic void 145068651Skrisurtw_start(struct ifnet *ifp) 145168651Skris{ 145268651Skris struct urtw_data *bf; 145368651Skris struct urtw_softc *sc = ifp->if_softc; 145468651Skris struct ieee80211_node *ni; 145568651Skris struct mbuf *m; 145668651Skris 145768651Skris if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 145868651Skris return; 145968651Skris 146068651Skris URTW_LOCK(sc); 146168651Skris for (;;) { 146268651Skris IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 146368651Skris if (m == NULL) 146468651Skris break; 146568651Skris bf = urtw_getbuf(sc); 146668651Skris if (bf == NULL) { 146768651Skris IFQ_DRV_PREPEND(&ifp->if_snd, m); 146868651Skris break; 146968651Skris } 147068651Skris 1471109998Smarkm ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; 147268651Skris m->m_pkthdr.rcvif = NULL; 147368651Skris 147468651Skris if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) { 147568651Skris ifp->if_oerrors++; 147668651Skris STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); 147768651Skris ieee80211_free_node(ni); 147868651Skris break; 147968651Skris } 148068651Skris 148168651Skris sc->sc_txtimer = 5; 148268651Skris callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); 148368651Skris } 148468651Skris URTW_UNLOCK(sc); 148568651Skris} 148668651Skris 148768651Skrisstatic int 148868651Skrisurtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[], 148968651Skris int ndata, int maxsz, void *dma_buf) 149068651Skris{ 149168651Skris int i, error; 149268651Skris 149368651Skris for (i = 0; i < ndata; i++) { 149468651Skris struct urtw_data *dp = &data[i]; 149568651Skris 149668651Skris dp->sc = sc; 1497109998Smarkm if (dma_buf == NULL) { 1498109998Smarkm dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1499109998Smarkm if (dp->m == NULL) { 1500109998Smarkm device_printf(sc->sc_dev, 1501109998Smarkm "could not allocate rx mbuf\n"); 150268651Skris error = ENOMEM; 150368651Skris goto fail; 150468651Skris } 150568651Skris dp->buf = mtod(dp->m, uint8_t *); 150668651Skris } else { 150768651Skris dp->m = NULL; 150868651Skris dp->buf = ((uint8_t *)dma_buf) + 150968651Skris (i * maxsz); 151068651Skris } 151168651Skris dp->ni = NULL; 151268651Skris } 151368651Skris return (0); 151468651Skris 151568651Skrisfail: urtw_free_data_list(sc, data, ndata, 1); 151668651Skris return (error); 151768651Skris} 151868651Skris 151968651Skrisstatic int 152068651Skrisurtw_alloc_rx_data_list(struct urtw_softc *sc) 152168651Skris{ 152268651Skris int error, i; 152368651Skris 152468651Skris error = urtw_alloc_data_list(sc, 152568651Skris sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 152668651Skris MCLBYTES, NULL /* mbufs */); 152768651Skris if (error != 0) 152868651Skris return (error); 152968651Skris 153068651Skris STAILQ_INIT(&sc->sc_rx_active); 153168651Skris STAILQ_INIT(&sc->sc_rx_inactive); 153268651Skris 153368651Skris for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++) 153468651Skris STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next); 153568651Skris 153668651Skris return (0); 153768651Skris} 153868651Skris 153968651Skrisstatic int 154068651Skrisurtw_alloc_tx_data_list(struct urtw_softc *sc) 154168651Skris{ 154268651Skris int error, i; 154368651Skris 154468651Skris error = urtw_alloc_data_list(sc, 154568651Skris sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE, 154689837Skris sc->sc_tx_dma_buf /* no mbufs */); 154768651Skris if (error != 0) 1548109998Smarkm return (error); 154968651Skris 155068651Skris STAILQ_INIT(&sc->sc_tx_active); 155168651Skris STAILQ_INIT(&sc->sc_tx_inactive); 1552109998Smarkm STAILQ_INIT(&sc->sc_tx_pending); 155368651Skris 155468651Skris for (i = 0; i < URTW_TX_DATA_LIST_COUNT; i++) 155568651Skris STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], 155668651Skris next); 155768651Skris 155868651Skris return (0); 1559109998Smarkm} 1560109998Smarkm 1561109998Smarkmstatic int 156268651Skrisurtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 156368651Skris const struct ieee80211_bpf_params *params) 156468651Skris{ 156568651Skris struct ieee80211com *ic = ni->ni_ic; 156668651Skris struct ifnet *ifp = ic->ic_ifp; 156768651Skris struct urtw_data *bf; 156868651Skris struct urtw_softc *sc = ifp->if_softc; 156968651Skris 157068651Skris /* prevent management frames from being sent if we're not ready */ 157168651Skris if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 157268651Skris m_freem(m); 157368651Skris ieee80211_free_node(ni); 157468651Skris return ENETDOWN; 157568651Skris } 157668651Skris URTW_LOCK(sc); 157768651Skris bf = urtw_getbuf(sc); 157868651Skris if (bf == NULL) { 1579109998Smarkm ieee80211_free_node(ni); 158068651Skris m_freem(m); 158168651Skris URTW_UNLOCK(sc); 158268651Skris return (ENOBUFS); /* XXX */ 158368651Skris } 158468651Skris 158568651Skris ifp->if_opackets++; 158668651Skris if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) { 158768651Skris ieee80211_free_node(ni); 158868651Skris ifp->if_oerrors++; 158968651Skris STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); 159068651Skris URTW_UNLOCK(sc); 159168651Skris return (EIO); 159268651Skris } 159368651Skris URTW_UNLOCK(sc); 159468651Skris 159568651Skris sc->sc_txtimer = 5; 159668651Skris return (0); 159768651Skris} 159868651Skris 159968651Skrisstatic void 160068651Skrisurtw_scan_start(struct ieee80211com *ic) 160168651Skris{ 160268651Skris 160368651Skris /* XXX do nothing? */ 160468651Skris} 160568651Skris 160668651Skrisstatic void 160768651Skrisurtw_scan_end(struct ieee80211com *ic) 160868651Skris{ 1609109998Smarkm 161068651Skris /* XXX do nothing? */ 161168651Skris} 161268651Skris 161368651Skrisstatic void 161468651Skrisurtw_set_channel(struct ieee80211com *ic) 161568651Skris{ 161668651Skris struct urtw_softc *sc = ic->ic_ifp->if_softc; 161768651Skris struct ifnet *ifp = sc->sc_ifp; 161868651Skris uint32_t data, orig; 161968651Skris usb_error_t error; 162068651Skris 162168651Skris /* 162268651Skris * if the user set a channel explicitly using ifconfig(8) this function 162368651Skris * can be called earlier than we're expected that in some cases the 162468651Skris * initialization would be failed if setting a channel is called before 162568651Skris * the init have done. 162668651Skris */ 162768651Skris if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 162868651Skris return; 162968651Skris 163068651Skris if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan) 163168651Skris return; 163268651Skris 1633109998Smarkm URTW_LOCK(sc); 163468651Skris 163568651Skris /* 163668651Skris * during changing th channel we need to temporarily be disable 1637109998Smarkm * TX. 163868651Skris */ 163968651Skris urtw_read32_m(sc, URTW_TX_CONF, &orig); 164068651Skris data = orig & ~URTW_TX_LOOPBACK_MASK; 1641109998Smarkm urtw_write32_m(sc, URTW_TX_CONF, data | URTW_TX_LOOPBACK_MAC); 164268651Skris 164368651Skris error = sc->sc_rf_set_chan(sc, ieee80211_chan2ieee(ic, ic->ic_curchan)); 164468651Skris if (error != 0) 164568651Skris goto fail; 164668651Skris usb_pause_mtx(&sc->sc_mtx, 10); 164768651Skris urtw_write32_m(sc, URTW_TX_CONF, orig); 164868651Skris 164989837Skris urtw_write16_m(sc, URTW_ATIM_WND, 2); 165068651Skris urtw_write16_m(sc, URTW_ATIM_TR_ITV, 100); 165168651Skris urtw_write16_m(sc, URTW_BEACON_INTERVAL, 100); 165268651Skris urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 100); 165368651Skris 165468651Skrisfail: 165568651Skris URTW_UNLOCK(sc); 165668651Skris 165768651Skris sc->sc_curchan = ic->ic_curchan; 165868651Skris 165968651Skris if (error != 0) 166068651Skris device_printf(sc->sc_dev, "could not change the channel\n"); 1661109998Smarkm} 166268651Skris 166368651Skrisstatic void 166468651Skrisurtw_update_mcast(struct ifnet *ifp) 166568651Skris{ 166668651Skris 166768651Skris /* XXX do nothing? */ 166868651Skris} 1669109998Smarkm 167068651Skrisstatic int 167168651Skrisurtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, 1672109998Smarkm struct urtw_data *data, int prior) 167368651Skris{ 167468651Skris struct ifnet *ifp = sc->sc_ifp; 167568651Skris struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *); 167668651Skris struct ieee80211_key *k; 167768651Skris const struct ieee80211_txparam *tp; 167868651Skris struct ieee80211com *ic = ifp->if_l2com; 167968651Skris struct ieee80211vap *vap = ni->ni_vap; 168068651Skris struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = { 168168651Skris sc->sc_xfer[URTW_8187B_BULK_TX_BE], 168268651Skris sc->sc_xfer[URTW_8187B_BULK_TX_BK], 168368651Skris sc->sc_xfer[URTW_8187B_BULK_TX_VI], 168468651Skris sc->sc_xfer[URTW_8187B_BULK_TX_VO] 168568651Skris }; 168668651Skris struct usb_xfer *xfer; 168768651Skris int dur = 0, rtsdur = 0, rtsenable = 0, ctsenable = 0, rate, 168868651Skris pkttime = 0, txdur = 0, isshort = 0, xferlen; 168968651Skris uint16_t acktime, rtstime, ctstime; 169068651Skris uint32_t flags; 169168651Skris usb_error_t error; 169268651Skris 169368651Skris URTW_ASSERT_LOCKED(sc); 169468651Skris 169568651Skris /* 169668651Skris * Software crypto. 169768651Skris */ 169868651Skris if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 169968651Skris k = ieee80211_crypto_encap(ni, m0); 170068651Skris if (k == NULL) { 170168651Skris device_printf(sc->sc_dev, 170268651Skris "ieee80211_crypto_encap returns NULL.\n"); 170368651Skris /* XXX we don't expect the fragmented frames */ 1704109998Smarkm m_freem(m0); 170568651Skris return (ENOBUFS); 170668651Skris } 1707109998Smarkm 170868651Skris /* in case packet header moved, reset pointer */ 1709109998Smarkm wh = mtod(m0, struct ieee80211_frame *); 171068651Skris } 171168651Skris 171268651Skris if (ieee80211_radiotap_active_vap(vap)) { 171368651Skris struct urtw_tx_radiotap_header *tap = &sc->sc_txtap; 171468651Skris 171568651Skris /* XXX Are variables correct? */ 171668651Skris tap->wt_flags = 0; 171768651Skris tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 171868651Skris tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 171968651Skris 172068651Skris ieee80211_radiotap_tx(vap, m0); 172168651Skris } 172268651Skris 172368651Skris if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT || 172468651Skris (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) { 172568651Skris tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; 172668651Skris rate = tp->mgmtrate; 172768651Skris } else { 172868651Skris tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 172968651Skris /* for data frames */ 173068651Skris if (IEEE80211_IS_MULTICAST(wh->i_addr1)) 173168651Skris rate = tp->mcastrate; 173268651Skris else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) 173368651Skris rate = tp->ucastrate; 173468651Skris else 173568651Skris rate = urtw_rtl2rate(sc->sc_currate); 173668651Skris } 173768651Skris 173868651Skris sc->sc_stats.txrates[sc->sc_currate]++; 173968651Skris 174068651Skris if (IEEE80211_IS_MULTICAST(wh->i_addr1)) 174168651Skris txdur = pkttime = urtw_compute_txtime(m0->m_pkthdr.len + 174268651Skris IEEE80211_CRC_LEN, rate, 0, 0); 174368651Skris else { 174468651Skris acktime = urtw_compute_txtime(14, 2,0, 0); 174568651Skris if ((m0->m_pkthdr.len + 4) > vap->iv_rtsthreshold) { 174668651Skris rtsenable = 1; 1747160814Ssimon ctsenable = 0; 174868651Skris rtstime = urtw_compute_txtime(URTW_ACKCTS_LEN, 2, 0, 0); 174968651Skris ctstime = urtw_compute_txtime(14, 2, 0, 0); 175068651Skris pkttime = urtw_compute_txtime(m0->m_pkthdr.len + 175168651Skris IEEE80211_CRC_LEN, rate, 0, isshort); 175268651Skris rtsdur = ctstime + pkttime + acktime + 175368651Skris 3 * URTW_ASIFS_TIME; 175468651Skris txdur = rtstime + rtsdur; 175568651Skris } else { 1756109998Smarkm rtsenable = ctsenable = rtsdur = 0; 175768651Skris pkttime = urtw_compute_txtime(m0->m_pkthdr.len + 175868651Skris IEEE80211_CRC_LEN, rate, 0, isshort); 175968651Skris txdur = pkttime + URTW_ASIFS_TIME + acktime; 176068651Skris } 176168651Skris 176268651Skris if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) 1763109998Smarkm dur = urtw_compute_txtime(m0->m_pkthdr.len + 176468651Skris IEEE80211_CRC_LEN, rate, 0, isshort) + 1765109998Smarkm 3 * URTW_ASIFS_TIME + 176668651Skris 2 * acktime; 176768651Skris else 176868651Skris dur = URTW_ASIFS_TIME + acktime; 176968651Skris } 1770109998Smarkm *(uint16_t *)wh->i_dur = htole16(dur); 177168651Skris 177268651Skris xferlen = m0->m_pkthdr.len; 177368651Skris xferlen += (sc->sc_flags & URTW_RTL8187B) ? (4 * 8) : (4 * 3); 177468651Skris if ((0 == xferlen % 64) || (0 == xferlen % 512)) 177568651Skris xferlen += 1; 177668651Skris 177768651Skris memset(data->buf, 0, URTW_TX_MAXSIZE); 177868651Skris flags = m0->m_pkthdr.len & 0xfff; 177968651Skris flags |= URTW_TX_FLAG_NO_ENC; 178068651Skris if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 178168651Skris (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) && 178268651Skris (sc->sc_preamble_mode == URTW_PREAMBLE_MODE_SHORT) && 178368651Skris (sc->sc_currate != 0)) 178468651Skris flags |= URTW_TX_FLAG_SPLCP; 178568651Skris if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) 178668651Skris flags |= URTW_TX_FLAG_MOREFRAG; 178768651Skris 1788109998Smarkm flags |= (sc->sc_currate & 0xf) << URTW_TX_FLAG_TXRATE_SHIFT; 178968651Skris 179068651Skris if (sc->sc_flags & URTW_RTL8187B) { 179168651Skris struct urtw_8187b_txhdr *tx; 179268651Skris 179368651Skris tx = (struct urtw_8187b_txhdr *)data->buf; 179468651Skris if (ctsenable) 179568651Skris flags |= URTW_TX_FLAG_CTS; 179668651Skris if (rtsenable) { 179768651Skris flags |= URTW_TX_FLAG_RTS; 179868651Skris flags |= (urtw_rate2rtl(11) & 0xf) << 179968651Skris URTW_TX_FLAG_RTSRATE_SHIFT; 180068651Skris tx->rtsdur = rtsdur; 180168651Skris } 180268651Skris tx->flag = htole32(flags); 180368651Skris tx->txdur = txdur; 180468651Skris if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 180568651Skris IEEE80211_FC0_TYPE_MGT && 1806109998Smarkm (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 1807109998Smarkm IEEE80211_FC0_SUBTYPE_PROBE_RESP) 1808109998Smarkm tx->retry = 1; 1809280297Sjkim else 1810296279Sjkim tx->retry = URTW_TX_MAXRETRY; 1811296279Sjkim m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(tx + 1)); 181268651Skris } else { 1813276861Sjkim struct urtw_8187l_txhdr *tx; 181468651Skris 181568651Skris tx = (struct urtw_8187l_txhdr *)data->buf; 181668651Skris if (rtsenable) { 181768651Skris flags |= URTW_TX_FLAG_RTS; 181868651Skris tx->rtsdur = rtsdur; 181968651Skris } 182068651Skris flags |= (urtw_rate2rtl(11) & 0xf) << URTW_TX_FLAG_RTSRATE_SHIFT; 1821194206Ssimon tx->flag = htole32(flags); 1822109998Smarkm tx->retry = 3; /* CW minimum */ 1823194206Ssimon tx->retry = 7 << 4; /* CW maximum */ 182468651Skris tx->retry = URTW_TX_MAXRETRY << 8; /* retry limitation */ 182568651Skris m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(tx + 1)); 182668651Skris } 182768651Skris 182868651Skris data->buflen = xferlen; 182968651Skris data->ni = ni; 183068651Skris data->m = m0; 183168651Skris 183268651Skris if (sc->sc_flags & URTW_RTL8187B) { 183368651Skris switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 183468651Skris case IEEE80211_FC0_TYPE_CTL: 183568651Skris case IEEE80211_FC0_TYPE_MGT: 183668651Skris xfer = sc->sc_xfer[URTW_8187B_BULK_TX_EP12]; 183768651Skris break; 183868651Skris default: 183968651Skris KASSERT(M_WME_GETAC(m0) < URTW_8187B_TXPIPE_MAX, 184068651Skris ("unsupported WME pipe %d", M_WME_GETAC(m0))); 184168651Skris xfer = rtl8187b_pipes[M_WME_GETAC(m0)]; 184268651Skris break; 184368651Skris } 184468651Skris } else 184568651Skris xfer = (prior == URTW_PRIORITY_LOW) ? 184668651Skris sc->sc_xfer[URTW_8187L_BULK_TX_LOW] : 184768651Skris sc->sc_xfer[URTW_8187L_BULK_TX_NORMAL]; 1848109998Smarkm 184968651Skris STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); 185068651Skris usbd_transfer_start(xfer); 185168651Skris 1852109998Smarkm error = urtw_led_ctl(sc, URTW_LED_CTL_TX); 1853109998Smarkm if (error != 0) 185468651Skris device_printf(sc->sc_dev, "could not control LED (%d)\n", 185568651Skris error); 185668651Skris return (0); 185768651Skris} 185868651Skris 185968651Skrisstatic int 1860109998Smarkmurtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 186168651Skris{ 1862109998Smarkm struct ieee80211com *ic = vap->iv_ic; 186368651Skris struct urtw_softc *sc = ic->ic_ifp->if_softc; 186468651Skris struct urtw_vap *uvp = URTW_VAP(vap); 186568651Skris struct ieee80211_node *ni; 186668651Skris usb_error_t error = 0; 186768651Skris 186868651Skris DPRINTF(sc, URTW_DEBUG_STATE, "%s: %s -> %s\n", __func__, 186968651Skris ieee80211_state_name[vap->iv_state], 187068651Skris ieee80211_state_name[nstate]); 187168651Skris 187268651Skris sc->sc_state = nstate; 187368651Skris 187468651Skris IEEE80211_UNLOCK(ic); 187568651Skris URTW_LOCK(sc); 187668651Skris usb_callout_stop(&sc->sc_led_ch); 1877109998Smarkm callout_stop(&sc->sc_watchdog_ch); 1878109998Smarkm 1879109998Smarkm switch (nstate) { 1880109998Smarkm case IEEE80211_S_INIT: 188168651Skris case IEEE80211_S_SCAN: 188268651Skris case IEEE80211_S_AUTH: 188368651Skris case IEEE80211_S_ASSOC: 188468651Skris break; 188576866Skris case IEEE80211_S_RUN: 188676866Skris ni = ieee80211_ref_node(vap->iv_bss); 188776866Skris /* setting bssid. */ 1888111147Snectar urtw_write32_m(sc, URTW_BSSID, ((uint32_t *)ni->ni_bssid)[0]); 1889111147Snectar urtw_write16_m(sc, URTW_BSSID + 4, 1890111147Snectar ((uint16_t *)ni->ni_bssid)[2]); 1891111147Snectar urtw_update_msr(sc); 1892100928Snectar /* XXX maybe the below would be incorrect. */ 1893100928Snectar urtw_write16_m(sc, URTW_ATIM_WND, 2); 1894111147Snectar urtw_write16_m(sc, URTW_ATIM_TR_ITV, 100); 1895100928Snectar urtw_write16_m(sc, URTW_BEACON_INTERVAL, 0x64); 1896100928Snectar urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 100); 1897111147Snectar error = urtw_led_ctl(sc, URTW_LED_CTL_LINK); 1898100928Snectar if (error != 0) 1899100928Snectar device_printf(sc->sc_dev, 1900111147Snectar "could not control LED (%d)\n", error); 1901111147Snectar ieee80211_free_node(ni); 1902111147Snectar break; 1903111147Snectar default: 1904111147Snectar break; 1905111147Snectar } 1906111147Snectarfail: 1907111147Snectar URTW_UNLOCK(sc); 1908111147Snectar IEEE80211_LOCK(ic); 1909111147Snectar return (uvp->newstate(vap, nstate, arg)); 1910111147Snectar} 1911111147Snectar 1912111147Snectarstatic void 1913111147Snectarurtw_watchdog(void *arg) 1914111147Snectar{ 1915111147Snectar struct urtw_softc *sc = arg; 1916111147Snectar struct ifnet *ifp = sc->sc_ifp; 1917109998Smarkm 1918100928Snectar if (sc->sc_txtimer > 0) { 1919100928Snectar if (--sc->sc_txtimer == 0) { 1920111147Snectar device_printf(sc->sc_dev, "device timeout\n"); 1921111147Snectar ifp->if_oerrors++; 1922111147Snectar return; 1923100928Snectar } 1924111147Snectar callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); 1925111147Snectar } 1926100928Snectar} 1927111147Snectar 1928111147Snectarstatic void 1929111147Snectarurtw_set_multi(void *arg) 1930100928Snectar{ 1931111147Snectar struct urtw_softc *sc = arg; 1932111147Snectar struct ifnet *ifp = sc->sc_ifp; 1933100928Snectar 1934111147Snectar if (!(ifp->if_flags & IFF_UP)) 1935111147Snectar return; 1936100928Snectar 1937111147Snectar /* 1938111147Snectar * XXX don't know how to set a device. Lack of docs. Just try to set 1939111147Snectar * IFF_ALLMULTI flag here. 1940100928Snectar */ 1941111147Snectar ifp->if_flags |= IFF_ALLMULTI; 1942100928Snectar} 1943111147Snectar 1944111147Snectarstatic usb_error_t 1945111147Snectarurtw_set_rate(struct urtw_softc *sc) 194689837Skris{ 194789837Skris int i, basic_rate, min_rr_rate, max_rr_rate; 1948298998Sjkim uint16_t data; 1949109998Smarkm usb_error_t error; 1950109998Smarkm 1951109998Smarkm basic_rate = urtw_rate2rtl(48); 1952111147Snectar min_rr_rate = urtw_rate2rtl(12); 1953111147Snectar max_rr_rate = urtw_rate2rtl(48); 1954109998Smarkm 1955109998Smarkm urtw_write8_m(sc, URTW_RESP_RATE, 1956109998Smarkm max_rr_rate << URTW_RESP_MAX_RATE_SHIFT | 1957109998Smarkm min_rr_rate << URTW_RESP_MIN_RATE_SHIFT); 1958109998Smarkm 1959109998Smarkm urtw_read16_m(sc, URTW_BRSR, &data); 1960109998Smarkm data &= ~URTW_BRSR_MBR_8185; 1961109998Smarkm 1962109998Smarkm for (i = 0; i <= basic_rate; i++) 1963109998Smarkm data |= (1 << i); 1964109998Smarkm 1965109998Smarkm urtw_write16_m(sc, URTW_BRSR, data); 1966111147Snectarfail: 1967109998Smarkm return (error); 1968109998Smarkm} 1969109998Smarkm 1970109998Smarkmstatic uint16_t 1971109998Smarkmurtw_rate2rtl(uint32_t rate) 1972109998Smarkm{ 1973111147Snectar#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) 1974111147Snectar int i; 1975109998Smarkm 1976109998Smarkm for (i = 0; i < N(urtw_ratetable); i++) { 1977109998Smarkm if (rate == urtw_ratetable[i].reg) 1978109998Smarkm return urtw_ratetable[i].val; 1979109998Smarkm } 1980109998Smarkm 1981109998Smarkm return (3); 1982109998Smarkm#undef N 1983109998Smarkm} 1984109998Smarkm 1985109998Smarkmstatic uint16_t 1986109998Smarkmurtw_rtl2rate(uint32_t rate) 1987109998Smarkm{ 1988109998Smarkm#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) 1989109998Smarkm int i; 1990109998Smarkm 1991109998Smarkm for (i = 0; i < N(urtw_ratetable); i++) { 1992109998Smarkm if (rate == urtw_ratetable[i].val) 1993109998Smarkm return urtw_ratetable[i].reg; 1994111147Snectar } 1995109998Smarkm 1996109998Smarkm return (0); 1997109998Smarkm#undef N 1998109998Smarkm} 1999109998Smarkm 2000109998Smarkmstatic usb_error_t 2001109998Smarkmurtw_update_msr(struct urtw_softc *sc) 2002109998Smarkm{ 2003109998Smarkm struct ifnet *ifp = sc->sc_ifp; 2004109998Smarkm struct ieee80211com *ic = ifp->if_l2com; 2005109998Smarkm uint8_t data; 2006109998Smarkm usb_error_t error; 2007109998Smarkm 2008109998Smarkm urtw_read8_m(sc, URTW_MSR, &data); 2009109998Smarkm data &= ~URTW_MSR_LINK_MASK; 2010109998Smarkm 2011109998Smarkm if (sc->sc_state == IEEE80211_S_RUN) { 2012109998Smarkm switch (ic->ic_opmode) { 2013109998Smarkm case IEEE80211_M_STA: 2014109998Smarkm case IEEE80211_M_MONITOR: 2015109998Smarkm data |= URTW_MSR_LINK_STA; 2016109998Smarkm if (sc->sc_flags & URTW_RTL8187B) 2017109998Smarkm data |= URTW_MSR_LINK_ENEDCA; 2018111147Snectar break; 2019109998Smarkm case IEEE80211_M_IBSS: 2020109998Smarkm data |= URTW_MSR_LINK_ADHOC; 2021109998Smarkm break; 2022109998Smarkm case IEEE80211_M_HOSTAP: 2023109998Smarkm data |= URTW_MSR_LINK_HOSTAP; 2024109998Smarkm break; 2025109998Smarkm default: 2026109998Smarkm DPRINTF(sc, URTW_DEBUG_STATE, 2027109998Smarkm "unsupported operation mode 0x%x\n", 2028109998Smarkm ic->ic_opmode); 2029109998Smarkm error = USB_ERR_INVAL; 2030109998Smarkm goto fail; 2031109998Smarkm } 2032109998Smarkm } else 2033109998Smarkm data |= URTW_MSR_LINK_NONE; 2034109998Smarkm 2035109998Smarkm urtw_write8_m(sc, URTW_MSR, data); 2036109998Smarkmfail: 2037109998Smarkm return (error); 2038109998Smarkm} 2039109998Smarkm 2040109998Smarkmstatic usb_error_t 2041109998Smarkmurtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data) 2042109998Smarkm{ 2043109998Smarkm struct usb_device_request req; 2044109998Smarkm usb_error_t error; 2045109998Smarkm 2046111147Snectar URTW_ASSERT_LOCKED(sc); 2047109998Smarkm 2048109998Smarkm req.bmRequestType = UT_READ_VENDOR_DEVICE; 2049109998Smarkm req.bRequest = URTW_8187_GETREGS_REQ; 2050109998Smarkm USETW(req.wValue, (val & 0xff) | 0xff00); 2051109998Smarkm USETW(req.wIndex, (val >> 8) & 0x3); 2052109998Smarkm USETW(req.wLength, sizeof(uint8_t)); 2053109998Smarkm 2054109998Smarkm error = urtw_do_request(sc, &req, data); 2055109998Smarkm return (error); 2056111147Snectar} 2057109998Smarkm 2058109998Smarkmstatic usb_error_t 2059109998Smarkmurtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data) 2060111147Snectar{ 2061109998Smarkm struct usb_device_request req; 2062109998Smarkm usb_error_t error; 2063109998Smarkm 2064109998Smarkm URTW_ASSERT_LOCKED(sc); 2065109998Smarkm 2066109998Smarkm req.bmRequestType = UT_READ_VENDOR_DEVICE; 2067109998Smarkm req.bRequest = URTW_8187_GETREGS_REQ; 2068109998Smarkm USETW(req.wValue, (val & 0xff) | 0xff00); 2069111147Snectar USETW(req.wIndex, (val >> 8) & 0x3); 2070109998Smarkm USETW(req.wLength, sizeof(uint16_t)); 2071109998Smarkm 2072109998Smarkm error = urtw_do_request(sc, &req, data); 2073109998Smarkm return (error); 2074109998Smarkm} 2075109998Smarkm 2076109998Smarkmstatic usb_error_t 2077109998Smarkmurtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data) 2078160814Ssimon{ 2079111147Snectar struct usb_device_request req; 2080109998Smarkm usb_error_t error; 2081109998Smarkm 2082109998Smarkm URTW_ASSERT_LOCKED(sc); 2083109998Smarkm 2084109998Smarkm req.bmRequestType = UT_READ_VENDOR_DEVICE; 2085109998Smarkm req.bRequest = URTW_8187_GETREGS_REQ; 2086109998Smarkm USETW(req.wValue, (val & 0xff) | 0xff00); 2087109998Smarkm USETW(req.wIndex, (val >> 8) & 0x3); 2088238405Sjkim USETW(req.wLength, sizeof(uint32_t)); 2089109998Smarkm 2090109998Smarkm error = urtw_do_request(sc, &req, data); 2091109998Smarkm return (error); 2092109998Smarkm} 2093109998Smarkm 2094109998Smarkmstatic usb_error_t 2095109998Smarkmurtw_write8_c(struct urtw_softc *sc, int val, uint8_t data) 2096194206Ssimon{ 2097109998Smarkm struct usb_device_request req; 2098109998Smarkm 2099109998Smarkm URTW_ASSERT_LOCKED(sc); 2100109998Smarkm 2101109998Smarkm req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2102109998Smarkm req.bRequest = URTW_8187_SETREGS_REQ; 2103109998Smarkm USETW(req.wValue, (val & 0xff) | 0xff00); 2104109998Smarkm USETW(req.wIndex, (val >> 8) & 0x3); 2105111147Snectar USETW(req.wLength, sizeof(uint8_t)); 2106111147Snectar 2107111147Snectar return (urtw_do_request(sc, &req, &data)); 2108111147Snectar} 2109109998Smarkm 2110111147Snectarstatic usb_error_t 2111109998Smarkmurtw_write16_c(struct urtw_softc *sc, int val, uint16_t data) 2112109998Smarkm{ 2113111147Snectar struct usb_device_request req; 2114111147Snectar 2115109998Smarkm URTW_ASSERT_LOCKED(sc); 2116109998Smarkm 2117109998Smarkm req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2118109998Smarkm req.bRequest = URTW_8187_SETREGS_REQ; 2119109998Smarkm USETW(req.wValue, (val & 0xff) | 0xff00); 2120109998Smarkm USETW(req.wIndex, (val >> 8) & 0x3); 2121109998Smarkm USETW(req.wLength, sizeof(uint16_t)); 2122109998Smarkm 2123109998Smarkm return (urtw_do_request(sc, &req, &data)); 2124109998Smarkm} 2125109998Smarkm 2126109998Smarkmstatic usb_error_t 2127111147Snectarurtw_write32_c(struct urtw_softc *sc, int val, uint32_t data) 2128109998Smarkm{ 2129109998Smarkm struct usb_device_request req; 2130109998Smarkm 2131109998Smarkm URTW_ASSERT_LOCKED(sc); 2132109998Smarkm 2133109998Smarkm req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2134109998Smarkm req.bRequest = URTW_8187_SETREGS_REQ; 2135109998Smarkm USETW(req.wValue, (val & 0xff) | 0xff00); 2136109998Smarkm USETW(req.wIndex, (val >> 8) & 0x3); 2137109998Smarkm USETW(req.wLength, sizeof(uint32_t)); 2138109998Smarkm 2139109998Smarkm return (urtw_do_request(sc, &req, &data)); 2140109998Smarkm} 2141109998Smarkm 2142109998Smarkmstatic usb_error_t 2143109998Smarkmurtw_get_macaddr(struct urtw_softc *sc) 2144109998Smarkm{ 2145109998Smarkm uint32_t data; 2146109998Smarkm usb_error_t error; 2147109998Smarkm 2148109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); 2149109998Smarkm if (error != 0) 2150109998Smarkm goto fail; 2151109998Smarkm sc->sc_bssid[0] = data & 0xff; 2152109998Smarkm sc->sc_bssid[1] = (data & 0xff00) >> 8; 2153109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); 2154109998Smarkm if (error != 0) 2155109998Smarkm goto fail; 2156109998Smarkm sc->sc_bssid[2] = data & 0xff; 2157109998Smarkm sc->sc_bssid[3] = (data & 0xff00) >> 8; 2158109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); 2159109998Smarkm if (error != 0) 2160109998Smarkm goto fail; 2161109998Smarkm sc->sc_bssid[4] = data & 0xff; 2162109998Smarkm sc->sc_bssid[5] = (data & 0xff00) >> 8; 2163111147Snectarfail: 2164109998Smarkm return (error); 2165109998Smarkm} 2166109998Smarkm 2167109998Smarkmstatic usb_error_t 2168109998Smarkmurtw_eprom_read32(struct urtw_softc *sc, uint32_t addr, uint32_t *data) 2169109998Smarkm{ 2170109998Smarkm#define URTW_READCMD_LEN 3 2171109998Smarkm int addrlen, i; 2172109998Smarkm int16_t addrstr[8], data16, readcmd[] = { 1, 1, 0 }; 2173109998Smarkm usb_error_t error; 2174109998Smarkm 2175109998Smarkm /* NB: make sure the buffer is initialized */ 2176109998Smarkm *data = 0; 2177109998Smarkm 2178109998Smarkm /* enable EPROM programming */ 2179109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_PROGRAM_MODE); 2180109998Smarkm DELAY(URTW_EPROM_DELAY); 2181109998Smarkm 2182109998Smarkm error = urtw_eprom_cs(sc, URTW_EPROM_ENABLE); 2183109998Smarkm if (error != 0) 2184109998Smarkm goto fail; 2185109998Smarkm error = urtw_eprom_ck(sc); 2186109998Smarkm if (error != 0) 2187109998Smarkm goto fail; 2188109998Smarkm error = urtw_eprom_sendbits(sc, readcmd, URTW_READCMD_LEN); 2189109998Smarkm if (error != 0) 2190109998Smarkm goto fail; 2191111147Snectar if (sc->sc_epromtype == URTW_EEPROM_93C56) { 2192109998Smarkm addrlen = 8; 2193109998Smarkm addrstr[0] = addr & (1 << 7); 2194109998Smarkm addrstr[1] = addr & (1 << 6); 2195109998Smarkm addrstr[2] = addr & (1 << 5); 2196109998Smarkm addrstr[3] = addr & (1 << 4); 2197109998Smarkm addrstr[4] = addr & (1 << 3); 2198109998Smarkm addrstr[5] = addr & (1 << 2); 2199109998Smarkm addrstr[6] = addr & (1 << 1); 2200109998Smarkm addrstr[7] = addr & (1 << 0); 2201109998Smarkm } else { 2202109998Smarkm addrlen=6; 2203109998Smarkm addrstr[0] = addr & (1 << 5); 2204109998Smarkm addrstr[1] = addr & (1 << 4); 2205109998Smarkm addrstr[2] = addr & (1 << 3); 2206109998Smarkm addrstr[3] = addr & (1 << 2); 2207109998Smarkm addrstr[4] = addr & (1 << 1); 2208109998Smarkm addrstr[5] = addr & (1 << 0); 2209109998Smarkm } 2210109998Smarkm error = urtw_eprom_sendbits(sc, addrstr, addrlen); 2211109998Smarkm if (error != 0) 2212109998Smarkm goto fail; 2213111147Snectar 2214109998Smarkm error = urtw_eprom_writebit(sc, 0); 2215109998Smarkm if (error != 0) 2216109998Smarkm goto fail; 2217109998Smarkm 2218109998Smarkm for (i = 0; i < 16; i++) { 2219109998Smarkm error = urtw_eprom_ck(sc); 2220109998Smarkm if (error != 0) 2221109998Smarkm goto fail; 2222109998Smarkm error = urtw_eprom_readbit(sc, &data16); 2223109998Smarkm if (error != 0) 2224109998Smarkm goto fail; 2225109998Smarkm 2226111147Snectar (*data) |= (data16 << (15 - i)); 2227109998Smarkm } 2228109998Smarkm 2229111147Snectar error = urtw_eprom_cs(sc, URTW_EPROM_DISABLE); 2230109998Smarkm if (error != 0) 2231109998Smarkm goto fail; 2232109998Smarkm error = urtw_eprom_ck(sc); 2233111147Snectar if (error != 0) 2234109998Smarkm goto fail; 2235111147Snectar 2236109998Smarkm /* now disable EPROM programming */ 2237109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_NORMAL_MODE); 2238109998Smarkmfail: 2239109998Smarkm return (error); 2240109998Smarkm#undef URTW_READCMD_LEN 2241109998Smarkm} 2242109998Smarkm 2243109998Smarkmstatic usb_error_t 2244109998Smarkmurtw_eprom_cs(struct urtw_softc *sc, int able) 2245109998Smarkm{ 2246109998Smarkm uint8_t data; 2247109998Smarkm usb_error_t error; 2248109998Smarkm 2249109998Smarkm urtw_read8_m(sc, URTW_EPROM_CMD, &data); 2250109998Smarkm if (able == URTW_EPROM_ENABLE) 2251109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS); 2252109998Smarkm else 2253109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS); 2254109998Smarkm DELAY(URTW_EPROM_DELAY); 2255109998Smarkmfail: 2256109998Smarkm return (error); 2257109998Smarkm} 2258109998Smarkm 2259109998Smarkmstatic usb_error_t 2260109998Smarkmurtw_eprom_ck(struct urtw_softc *sc) 2261109998Smarkm{ 2262109998Smarkm uint8_t data; 2263109998Smarkm usb_error_t error; 2264109998Smarkm 2265109998Smarkm /* masking */ 2266109998Smarkm urtw_read8_m(sc, URTW_EPROM_CMD, &data); 2267109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK); 2268109998Smarkm DELAY(URTW_EPROM_DELAY); 2269109998Smarkm /* unmasking */ 2270109998Smarkm urtw_read8_m(sc, URTW_EPROM_CMD, &data); 2271109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK); 2272111147Snectar DELAY(URTW_EPROM_DELAY); 2273109998Smarkmfail: 2274109998Smarkm return (error); 2275109998Smarkm} 2276109998Smarkm 2277109998Smarkmstatic usb_error_t 2278109998Smarkmurtw_eprom_readbit(struct urtw_softc *sc, int16_t *data) 2279109998Smarkm{ 2280109998Smarkm uint8_t data8; 2281109998Smarkm usb_error_t error; 2282109998Smarkm 2283109998Smarkm urtw_read8_m(sc, URTW_EPROM_CMD, &data8); 2284109998Smarkm *data = (data8 & URTW_EPROM_READBIT) ? 1 : 0; 2285109998Smarkm DELAY(URTW_EPROM_DELAY); 2286109998Smarkm 2287109998Smarkmfail: 2288109998Smarkm return (error); 2289109998Smarkm} 2290109998Smarkm 2291109998Smarkmstatic usb_error_t 2292109998Smarkmurtw_eprom_writebit(struct urtw_softc *sc, int16_t bit) 2293109998Smarkm{ 2294109998Smarkm uint8_t data; 2295109998Smarkm usb_error_t error; 2296111147Snectar 2297109998Smarkm urtw_read8_m(sc, URTW_EPROM_CMD, &data); 2298109998Smarkm if (bit != 0) 2299109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT); 2300109998Smarkm else 2301109998Smarkm urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT); 2302111147Snectar DELAY(URTW_EPROM_DELAY); 2303109998Smarkmfail: 2304109998Smarkm return (error); 2305111147Snectar} 2306109998Smarkm 2307109998Smarkmstatic usb_error_t 2308109998Smarkmurtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen) 2309109998Smarkm{ 2310109998Smarkm int i = 0; 2311109998Smarkm usb_error_t error = 0; 2312109998Smarkm 2313109998Smarkm for (i = 0; i < buflen; i++) { 2314109998Smarkm error = urtw_eprom_writebit(sc, buf[i]); 2315109998Smarkm if (error != 0) 2316111147Snectar goto fail; 2317109998Smarkm error = urtw_eprom_ck(sc); 2318109998Smarkm if (error != 0) 2319109998Smarkm goto fail; 2320109998Smarkm } 2321109998Smarkmfail: 2322109998Smarkm return (error); 2323109998Smarkm} 2324109998Smarkm 2325109998Smarkm 2326109998Smarkmstatic usb_error_t 2327109998Smarkmurtw_get_txpwr(struct urtw_softc *sc) 2328109998Smarkm{ 2329109998Smarkm int i, j; 2330109998Smarkm uint32_t data; 2331109998Smarkm usb_error_t error; 2332109998Smarkm 2333109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_TXPW_BASE, &data); 2334109998Smarkm if (error != 0) 2335109998Smarkm goto fail; 2336109998Smarkm sc->sc_txpwr_cck_base = data & 0xf; 2337109998Smarkm sc->sc_txpwr_ofdm_base = (data >> 4) & 0xf; 2338109998Smarkm 2339109998Smarkm for (i = 1, j = 0; i < 6; i += 2, j++) { 2340109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_TXPW0 + j, &data); 2341109998Smarkm if (error != 0) 2342109998Smarkm goto fail; 2343109998Smarkm sc->sc_txpwr_cck[i] = data & 0xf; 2344109998Smarkm sc->sc_txpwr_cck[i + 1] = (data & 0xf00) >> 8; 2345109998Smarkm sc->sc_txpwr_ofdm[i] = (data & 0xf0) >> 4; 2346109998Smarkm sc->sc_txpwr_ofdm[i + 1] = (data & 0xf000) >> 12; 2347109998Smarkm } 2348109998Smarkm for (i = 1, j = 0; i < 4; i += 2, j++) { 2349109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_TXPW1 + j, &data); 2350111147Snectar if (error != 0) 2351109998Smarkm goto fail; 2352109998Smarkm sc->sc_txpwr_cck[i + 6] = data & 0xf; 2353109998Smarkm sc->sc_txpwr_cck[i + 6 + 1] = (data & 0xf00) >> 8; 2354109998Smarkm sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4; 2355109998Smarkm sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12; 2356109998Smarkm } 2357109998Smarkm if (sc->sc_flags & URTW_RTL8187B) { 2358109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2, &data); 2359109998Smarkm if (error != 0) 2360109998Smarkm goto fail; 2361109998Smarkm sc->sc_txpwr_cck[1 + 6 + 4] = data & 0xf; 2362109998Smarkm sc->sc_txpwr_ofdm[1 + 6 + 4] = (data & 0xf0) >> 4; 2363109998Smarkm error = urtw_eprom_read32(sc, 0x0a, &data); 2364109998Smarkm if (error != 0) 2365109998Smarkm goto fail; 2366109998Smarkm sc->sc_txpwr_cck[2 + 6 + 4] = data & 0xf; 2367109998Smarkm sc->sc_txpwr_ofdm[2 + 6 + 4] = (data & 0xf0) >> 4; 2368109998Smarkm error = urtw_eprom_read32(sc, 0x1c, &data); 2369109998Smarkm if (error != 0) 2370109998Smarkm goto fail; 2371109998Smarkm sc->sc_txpwr_cck[3 + 6 + 4] = data & 0xf; 2372109998Smarkm sc->sc_txpwr_cck[3 + 6 + 4 + 1] = (data & 0xf00) >> 8; 2373109998Smarkm sc->sc_txpwr_ofdm[3 + 6 + 4] = (data & 0xf0) >> 4; 2374111147Snectar sc->sc_txpwr_ofdm[3 + 6 + 4 + 1] = (data & 0xf000) >> 12; 2375109998Smarkm } else { 2376109998Smarkm for (i = 1, j = 0; i < 4; i += 2, j++) { 2377109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, 2378109998Smarkm &data); 2379109998Smarkm if (error != 0) 2380109998Smarkm goto fail; 2381109998Smarkm sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; 2382109998Smarkm sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; 2383109998Smarkm sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; 2384109998Smarkm sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = (data & 0xf000) >> 12; 2385109998Smarkm } 2386109998Smarkm } 2387109998Smarkmfail: 2388109998Smarkm return (error); 2389109998Smarkm} 2390109998Smarkm 2391111147Snectar 2392109998Smarkmstatic usb_error_t 2393109998Smarkmurtw_get_rfchip(struct urtw_softc *sc) 2394109998Smarkm{ 2395109998Smarkm int ret; 2396109998Smarkm uint8_t data8; 2397109998Smarkm uint32_t data; 2398109998Smarkm usb_error_t error; 2399109998Smarkm 2400109998Smarkm if (sc->sc_flags & URTW_RTL8187B) { 2401109998Smarkm urtw_read8_m(sc, 0xe1, &data8); 2402111147Snectar switch (data8) { 2403109998Smarkm case 0: 2404109998Smarkm sc->sc_flags |= URTW_RTL8187B_REV_B; 2405109998Smarkm break; 2406109998Smarkm case 1: 2407109998Smarkm sc->sc_flags |= URTW_RTL8187B_REV_D; 2408109998Smarkm break; 2409109998Smarkm case 2: 2410111147Snectar sc->sc_flags |= URTW_RTL8187B_REV_E; 2411109998Smarkm break; 2412109998Smarkm default: 2413109998Smarkm device_printf(sc->sc_dev, "unknown type: %#x\n", data8); 2414109998Smarkm sc->sc_flags |= URTW_RTL8187B_REV_B; 2415111147Snectar break; 2416109998Smarkm } 2417109998Smarkm } else { 2418109998Smarkm urtw_read32_m(sc, URTW_TX_CONF, &data); 2419109998Smarkm switch (data & URTW_TX_HWMASK) { 2420109998Smarkm case URTW_TX_R8187vD_B: 2421109998Smarkm sc->sc_flags |= URTW_RTL8187B; 2422109998Smarkm break; 2423111147Snectar case URTW_TX_R8187vD: 2424111147Snectar break; 2425109998Smarkm default: 2426160814Ssimon device_printf(sc->sc_dev, "unknown RTL8187L type: %#x\n", 2427109998Smarkm data & URTW_TX_HWMASK); 2428109998Smarkm break; 2429109998Smarkm } 2430109998Smarkm } 2431109998Smarkm 2432109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); 2433109998Smarkm if (error != 0) 2434109998Smarkm goto fail; 2435109998Smarkm switch (data & 0xff) { 2436109998Smarkm case URTW_EPROM_RFCHIPID_RTL8225U: 2437109998Smarkm error = urtw_8225_isv2(sc, &ret); 2438109998Smarkm if (error != 0) 2439109998Smarkm goto fail; 2440109998Smarkm if (ret == 0) { 2441109998Smarkm sc->sc_rf_init = urtw_8225_rf_init; 2442109998Smarkm sc->sc_rf_set_sens = urtw_8225_rf_set_sens; 2443109998Smarkm sc->sc_rf_set_chan = urtw_8225_rf_set_chan; 2444109998Smarkm sc->sc_rf_stop = urtw_8225_rf_stop; 2445111147Snectar } else { 2446109998Smarkm sc->sc_rf_init = urtw_8225v2_rf_init; 2447109998Smarkm sc->sc_rf_set_chan = urtw_8225v2_rf_set_chan; 2448109998Smarkm sc->sc_rf_stop = urtw_8225_rf_stop; 2449111147Snectar } 2450109998Smarkm sc->sc_max_sens = URTW_8225_RF_MAX_SENS; 2451109998Smarkm sc->sc_sens = URTW_8225_RF_DEF_SENS; 2452109998Smarkm break; 2453109998Smarkm case URTW_EPROM_RFCHIPID_RTL8225Z2: 2454109998Smarkm sc->sc_rf_init = urtw_8225v2b_rf_init; 2455109998Smarkm sc->sc_rf_set_chan = urtw_8225v2b_rf_set_chan; 2456109998Smarkm sc->sc_max_sens = URTW_8225_RF_MAX_SENS; 2457109998Smarkm sc->sc_sens = URTW_8225_RF_DEF_SENS; 2458111147Snectar sc->sc_rf_stop = urtw_8225_rf_stop; 2459109998Smarkm break; 2460109998Smarkm default: 2461109998Smarkm DPRINTF(sc, URTW_DEBUG_STATE, 2462109998Smarkm "unsupported RF chip %d\n", data & 0xff); 2463109998Smarkm error = USB_ERR_INVAL; 2464109998Smarkm goto fail; 2465109998Smarkm } 2466109998Smarkm 2467109998Smarkm device_printf(sc->sc_dev, "%s rf %s hwrev %s\n", 2468109998Smarkm (sc->sc_flags & URTW_RTL8187B) ? "rtl8187b" : "rtl8187l", 2469109998Smarkm ((data & 0xff) == URTW_EPROM_RFCHIPID_RTL8225U) ? "rtl8225u" : 2470109998Smarkm "rtl8225z2", 2471109998Smarkm (sc->sc_flags & URTW_RTL8187B) ? ((data8 == 0) ? "b" : 2472109998Smarkm (data8 == 1) ? "d" : "e") : "none"); 2473109998Smarkm 2474109998Smarkmfail: 2475109998Smarkm return (error); 2476109998Smarkm} 2477109998Smarkm 2478109998Smarkm 2479109998Smarkmstatic usb_error_t 2480109998Smarkmurtw_led_init(struct urtw_softc *sc) 2481109998Smarkm{ 2482111147Snectar uint32_t rev; 2483109998Smarkm usb_error_t error; 2484109998Smarkm 2485109998Smarkm urtw_read8_m(sc, URTW_PSR, &sc->sc_psr); 2486109998Smarkm error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev); 2487109998Smarkm if (error != 0) 2488109998Smarkm goto fail; 2489109998Smarkm 2490109998Smarkm switch (rev & URTW_EPROM_CID_MASK) { 2491109998Smarkm case URTW_EPROM_CID_ALPHA0: 2492109998Smarkm sc->sc_strategy = URTW_SW_LED_MODE1; 2493109998Smarkm break; 2494111147Snectar case URTW_EPROM_CID_SERCOMM_PS: 2495109998Smarkm sc->sc_strategy = URTW_SW_LED_MODE3; 2496109998Smarkm break; 2497109998Smarkm case URTW_EPROM_CID_HW_LED: 2498109998Smarkm sc->sc_strategy = URTW_HW_LED; 2499109998Smarkm break; 2500109998Smarkm case URTW_EPROM_CID_RSVD0: 2501109998Smarkm case URTW_EPROM_CID_RSVD1: 2502109998Smarkm default: 2503109998Smarkm sc->sc_strategy = URTW_SW_LED_MODE0; 2504109998Smarkm break; 2505109998Smarkm } 2506109998Smarkm 2507109998Smarkm sc->sc_gpio_ledpin = URTW_LED_PIN_GPIO0; 2508111147Snectar 2509109998Smarkmfail: 2510109998Smarkm return (error); 2511109998Smarkm} 2512109998Smarkm 2513109998Smarkm 2514109998Smarkmstatic usb_error_t 2515109998Smarkmurtw_8225_rf_init(struct urtw_softc *sc) 2516109998Smarkm{ 2517109998Smarkm#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) 2518109998Smarkm int i; 2519109998Smarkm uint16_t data; 2520109998Smarkm usb_error_t error; 2521109998Smarkm 2522109998Smarkm error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 2523109998Smarkm if (error) 2524109998Smarkm goto fail; 2525109998Smarkm 2526109998Smarkm error = urtw_8225_usb_init(sc); 2527109998Smarkm if (error) 2528109998Smarkm goto fail; 2529109998Smarkm 2530111147Snectar urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008); 2531111147Snectar urtw_read16_m(sc, URTW_BRSR, &data); /* XXX ??? */ 2532109998Smarkm urtw_write16_m(sc, URTW_BRSR, 0xffff); 2533109998Smarkm urtw_write32_m(sc, URTW_RF_PARA, 0x100044); 2534109998Smarkm 2535109998Smarkm error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 2536109998Smarkm if (error) 2537109998Smarkm goto fail; 2538109998Smarkm urtw_write8_m(sc, URTW_CONFIG3, 0x44); 2539109998Smarkm error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 2540109998Smarkm if (error) 2541109998Smarkm goto fail; 2542109998Smarkm 2543109998Smarkm error = urtw_8185_rf_pins_enable(sc); 2544109998Smarkm if (error) 2545109998Smarkm goto fail; 2546109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1000); 2547109998Smarkm 2548109998Smarkm for (i = 0; i < N(urtw_8225_rf_part1); i++) { 2549109998Smarkm urtw_8225_write(sc, urtw_8225_rf_part1[i].reg, 2550109998Smarkm urtw_8225_rf_part1[i].val); 2551109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2552160814Ssimon } 2553109998Smarkm usb_pause_mtx(&sc->sc_mtx, 100); 2554111147Snectar urtw_8225_write(sc, 2555109998Smarkm URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); 2556109998Smarkm usb_pause_mtx(&sc->sc_mtx, 200); 2557109998Smarkm urtw_8225_write(sc, 2558109998Smarkm URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); 2559109998Smarkm usb_pause_mtx(&sc->sc_mtx, 200); 2560109998Smarkm urtw_8225_write(sc, 2561109998Smarkm URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3); 2562109998Smarkm 2563109998Smarkm for (i = 0; i < 95; i++) { 2564109998Smarkm urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); 2565109998Smarkm urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]); 2566109998Smarkm } 2567109998Smarkm 2568109998Smarkm urtw_8225_write(sc, 2569109998Smarkm URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4); 2570109998Smarkm urtw_8225_write(sc, 2571109998Smarkm URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5); 2572111147Snectar 2573109998Smarkm for (i = 0; i < 128; i++) { 2574109998Smarkm urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]); 2575109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2576109998Smarkm urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80); 2577109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2578109998Smarkm } 2579109998Smarkm 2580109998Smarkm for (i = 0; i < N(urtw_8225_rf_part2); i++) { 2581109998Smarkm urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg, 2582109998Smarkm urtw_8225_rf_part2[i].val); 2583160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 2584109998Smarkm } 2585109998Smarkm 2586109998Smarkm error = urtw_8225_setgain(sc, 4); 2587109998Smarkm if (error) 2588109998Smarkm goto fail; 2589109998Smarkm 2590109998Smarkm for (i = 0; i < N(urtw_8225_rf_part3); i++) { 2591109998Smarkm urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg, 2592109998Smarkm urtw_8225_rf_part3[i].val); 2593109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2594109998Smarkm } 2595109998Smarkm 2596109998Smarkm urtw_write8_m(sc, URTW_TESTR, 0x0d); 2597109998Smarkm 2598109998Smarkm error = urtw_8225_set_txpwrlvl(sc, 1); 2599109998Smarkm if (error) 2600109998Smarkm goto fail; 2601109998Smarkm 2602109998Smarkm urtw_8187_write_phy_cck(sc, 0x10, 0x9b); 2603109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2604109998Smarkm urtw_8187_write_phy_ofdm(sc, 0x26, 0x90); 2605111147Snectar usb_pause_mtx(&sc->sc_mtx, 1); 2606109998Smarkm 2607160814Ssimon /* TX ant A, 0x0 for B */ 2608109998Smarkm error = urtw_8185_tx_antenna(sc, 0x3); 2609109998Smarkm if (error) 2610109998Smarkm goto fail; 2611109998Smarkm urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002); 2612109998Smarkm 2613111147Snectar error = urtw_8225_rf_set_chan(sc, 1); 2614109998Smarkmfail: 2615109998Smarkm return (error); 2616109998Smarkm#undef N 2617109998Smarkm} 2618109998Smarkm 2619109998Smarkmstatic usb_error_t 2620109998Smarkmurtw_8185_rf_pins_enable(struct urtw_softc *sc) 2621109998Smarkm{ 2622109998Smarkm usb_error_t error = 0; 2623109998Smarkm 2624109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1ff7); 2625109998Smarkmfail: 2626109998Smarkm return (error); 2627109998Smarkm} 2628109998Smarkm 2629109998Smarkmstatic usb_error_t 2630109998Smarkmurtw_8185_tx_antenna(struct urtw_softc *sc, uint8_t ant) 2631109998Smarkm{ 2632109998Smarkm usb_error_t error; 2633109998Smarkm 2634109998Smarkm urtw_write8_m(sc, URTW_TX_ANTENNA, ant); 2635109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2636109998Smarkmfail: 2637109998Smarkm return (error); 2638109998Smarkm} 2639109998Smarkm 2640109998Smarkmstatic usb_error_t 2641109998Smarkmurtw_8187_write_phy_ofdm_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) 2642109998Smarkm{ 2643109998Smarkm 2644109998Smarkm data = data & 0xff; 2645109998Smarkm return urtw_8187_write_phy(sc, addr, data); 2646109998Smarkm} 2647109998Smarkm 2648109998Smarkmstatic usb_error_t 2649109998Smarkmurtw_8187_write_phy_cck_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) 2650109998Smarkm{ 2651109998Smarkm 2652109998Smarkm data = data & 0xff; 2653109998Smarkm return urtw_8187_write_phy(sc, addr, data | 0x10000); 2654109998Smarkm} 2655109998Smarkm 2656109998Smarkmstatic usb_error_t 2657109998Smarkmurtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data) 2658109998Smarkm{ 2659109998Smarkm uint32_t phyw; 2660109998Smarkm usb_error_t error; 2661109998Smarkm 2662109998Smarkm phyw = ((data << 8) | (addr | 0x80)); 2663109998Smarkm urtw_write8_m(sc, URTW_PHY_MAGIC4, ((phyw & 0xff000000) >> 24)); 2664109998Smarkm urtw_write8_m(sc, URTW_PHY_MAGIC3, ((phyw & 0x00ff0000) >> 16)); 2665109998Smarkm urtw_write8_m(sc, URTW_PHY_MAGIC2, ((phyw & 0x0000ff00) >> 8)); 2666109998Smarkm urtw_write8_m(sc, URTW_PHY_MAGIC1, ((phyw & 0x000000ff))); 2667109998Smarkm usb_pause_mtx(&sc->sc_mtx, 1); 2668109998Smarkmfail: 2669109998Smarkm return (error); 2670109998Smarkm} 2671109998Smarkm 2672109998Smarkmstatic usb_error_t 2673109998Smarkmurtw_8225_setgain(struct urtw_softc *sc, int16_t gain) 2674160814Ssimon{ 2675109998Smarkm usb_error_t error; 2676109998Smarkm 2677109998Smarkm urtw_8187_write_phy_ofdm(sc, 0x0d, urtw_8225_gain[gain * 4]); 2678109998Smarkm urtw_8187_write_phy_ofdm(sc, 0x1b, urtw_8225_gain[gain * 4 + 2]); 2679109998Smarkm urtw_8187_write_phy_ofdm(sc, 0x1d, urtw_8225_gain[gain * 4 + 3]); 2680109998Smarkm urtw_8187_write_phy_ofdm(sc, 0x23, urtw_8225_gain[gain * 4 + 1]); 2681109998Smarkmfail: 2682109998Smarkm return (error); 2683109998Smarkm} 2684109998Smarkm 2685109998Smarkmstatic usb_error_t 2686109998Smarkmurtw_8225_usb_init(struct urtw_softc *sc) 2687109998Smarkm{ 2688109998Smarkm uint8_t data; 2689109998Smarkm usb_error_t error; 2690109998Smarkm 2691109998Smarkm urtw_write8_m(sc, URTW_RF_PINS_SELECT + 1, 0); 2692111147Snectar urtw_write8_m(sc, URTW_GPIO, 0); 2693109998Smarkm error = urtw_read8e(sc, 0x53, &data); 2694109998Smarkm if (error) 2695109998Smarkm goto fail; 2696109998Smarkm error = urtw_write8e(sc, 0x53, data | (1 << 7)); 2697109998Smarkm if (error) 2698109998Smarkm goto fail; 2699109998Smarkm urtw_write8_m(sc, URTW_RF_PINS_SELECT + 1, 4); 2700109998Smarkm urtw_write8_m(sc, URTW_GPIO, 0x20); 2701109998Smarkm urtw_write8_m(sc, URTW_GP_ENABLE, 0); 2702109998Smarkm 2703109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 0x80); 2704109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_SELECT, 0x80); 2705109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x80); 2706109998Smarkm 2707109998Smarkm usb_pause_mtx(&sc->sc_mtx, 500); 2708109998Smarkmfail: 2709109998Smarkm return (error); 2710109998Smarkm} 2711109998Smarkm 2712109998Smarkmstatic usb_error_t 2713109998Smarkmurtw_8225_write_c(struct urtw_softc *sc, uint8_t addr, uint16_t data) 2714109998Smarkm{ 2715109998Smarkm uint16_t d80, d82, d84; 2716111147Snectar usb_error_t error; 2717109998Smarkm 2718109998Smarkm urtw_read16_m(sc, URTW_RF_PINS_OUTPUT, &d80); 2719109998Smarkm d80 &= URTW_RF_PINS_MAGIC1; 2720109998Smarkm urtw_read16_m(sc, URTW_RF_PINS_ENABLE, &d82); 2721109998Smarkm urtw_read16_m(sc, URTW_RF_PINS_SELECT, &d84); 2722109998Smarkm d84 &= URTW_RF_PINS_MAGIC2; 2723109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_ENABLE, d82 | URTW_RF_PINS_MAGIC3); 2724109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84 | URTW_RF_PINS_MAGIC3); 2725109998Smarkm DELAY(10); 2726109998Smarkm 2727109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); 2728111147Snectar DELAY(2); 2729111147Snectar urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80); 2730109998Smarkm DELAY(10); 2731109998Smarkm 2732109998Smarkm error = urtw_8225_write_s16(sc, addr, 0x8225, &data); 2733109998Smarkm if (error != 0) 2734109998Smarkm goto fail; 2735109998Smarkm 2736109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); 2737109998Smarkm DELAY(10); 2738109998Smarkm urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); 2739238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84); 2740238405Sjkim usb_pause_mtx(&sc->sc_mtx, 2); 2741109998Smarkmfail: 2742109998Smarkm return (error); 2743111147Snectar} 2744109998Smarkm 2745109998Smarkmstatic usb_error_t 2746109998Smarkmurtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index, 2747109998Smarkm uint16_t *data) 2748109998Smarkm{ 2749109998Smarkm uint8_t buf[2]; 2750109998Smarkm uint16_t data16; 2751109998Smarkm struct usb_device_request req; 2752109998Smarkm usb_error_t error = 0; 2753109998Smarkm 2754109998Smarkm data16 = *data; 2755109998Smarkm 2756109998Smarkm req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2757109998Smarkm req.bRequest = URTW_8187_SETREGS_REQ; 2758109998Smarkm USETW(req.wValue, addr); 2759109998Smarkm USETW(req.wIndex, index); 2760109998Smarkm USETW(req.wLength, sizeof(uint16_t)); 2761111147Snectar buf[0] = (data16 & 0x00ff); 2762109998Smarkm buf[1] = (data16 & 0xff00) >> 8; 2763109998Smarkm 2764109998Smarkm error = urtw_do_request(sc, &req, buf); 2765109998Smarkm 2766109998Smarkm return (error); 2767109998Smarkm} 2768109998Smarkm 2769160814Ssimonstatic usb_error_t 2770160814Ssimonurtw_8225_rf_set_chan(struct urtw_softc *sc, int chan) 2771109998Smarkm{ 2772109998Smarkm usb_error_t error; 2773109998Smarkm 2774109998Smarkm error = urtw_8225_set_txpwrlvl(sc, chan); 2775109998Smarkm if (error) 2776109998Smarkm goto fail; 2777109998Smarkm urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); 2778109998Smarkm usb_pause_mtx(&sc->sc_mtx, 10); 2779160814Ssimonfail: 2780109998Smarkm return (error); 2781109998Smarkm} 2782109998Smarkm 2783142425Snectarstatic usb_error_t 2784142425Snectarurtw_8225_rf_set_sens(struct urtw_softc *sc, int sens) 2785109998Smarkm{ 2786142425Snectar usb_error_t error; 2787109998Smarkm 2788109998Smarkm if (sens < 0 || sens > 6) 2789109998Smarkm return -1; 2790109998Smarkm 2791109998Smarkm if (sens > 4) 2792109998Smarkm urtw_8225_write(sc, 2793109998Smarkm URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1); 2794109998Smarkm else 2795109998Smarkm urtw_8225_write(sc, 2796109998Smarkm URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2); 2797109998Smarkm 2798109998Smarkm sens = 6 - sens; 2799109998Smarkm error = urtw_8225_setgain(sc, sens); 2800111147Snectar if (error) 2801109998Smarkm goto fail; 2802109998Smarkm 2803109998Smarkm urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]); 2804109998Smarkm 2805109998Smarkmfail: 2806109998Smarkm return (error); 2807109998Smarkm} 2808120631Snectar 2809120631Snectarstatic usb_error_t 2810142425Snectarurtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan) 2811238405Sjkim{ 2812238405Sjkim int i, idx, set; 2813142425Snectar uint8_t *cck_pwltable; 2814142425Snectar uint8_t cck_pwrlvl_max, ofdm_pwrlvl_min, ofdm_pwrlvl_max; 2815238405Sjkim uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 2816238405Sjkim uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 2817142425Snectar usb_error_t error; 2818160814Ssimon 2819142425Snectar cck_pwrlvl_max = 11; 2820142425Snectar ofdm_pwrlvl_max = 25; /* 12 -> 25 */ 2821160814Ssimon ofdm_pwrlvl_min = 10; 2822238405Sjkim 2823142425Snectar /* CCK power setting */ 2824238405Sjkim cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl; 2825238405Sjkim idx = cck_pwrlvl % 6; 2826142425Snectar set = cck_pwrlvl / 6; 2827238405Sjkim cck_pwltable = (chan == 14) ? urtw_8225_txpwr_cck_ch14 : 2828160814Ssimon urtw_8225_txpwr_cck; 2829142425Snectar 2830238405Sjkim urtw_write8_m(sc, URTW_TX_GAIN_CCK, 2831160814Ssimon urtw_8225_tx_gain_cck_ofdm[set] >> 1); 2832238405Sjkim for (i = 0; i < 8; i++) { 2833142425Snectar urtw_8187_write_phy_cck(sc, 0x44 + i, 2834238405Sjkim cck_pwltable[idx * 8 + i]); 2835238405Sjkim } 2836238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 2837238405Sjkim 2838238405Sjkim /* OFDM power setting */ 2839142425Snectar ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 2840160814Ssimon ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 2841142425Snectar ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 2842142425Snectar 2843238405Sjkim idx = ofdm_pwrlvl % 6; 2844160814Ssimon set = ofdm_pwrlvl / 6; 2845238405Sjkim 2846238405Sjkim error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 2847142425Snectar if (error) 2848160814Ssimon goto fail; 2849194206Ssimon urtw_8187_write_phy_ofdm(sc, 2, 0x42); 2850194206Ssimon urtw_8187_write_phy_ofdm(sc, 6, 0); 2851194206Ssimon urtw_8187_write_phy_ofdm(sc, 8, 0); 2852194206Ssimon 2853194206Ssimon urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 2854238405Sjkim urtw_8225_tx_gain_cck_ofdm[set] >> 1); 2855194206Ssimon urtw_8187_write_phy_ofdm(sc, 0x5, urtw_8225_txpwr_ofdm[idx]); 2856238405Sjkim urtw_8187_write_phy_ofdm(sc, 0x7, urtw_8225_txpwr_ofdm[idx]); 2857194206Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 2858194206Ssimonfail: 2859194206Ssimon return (error); 2860194206Ssimon} 2861194206Ssimon 2862160814Ssimon 2863160814Ssimonstatic usb_error_t 2864160814Ssimonurtw_8225_rf_stop(struct urtw_softc *sc) 2865160814Ssimon{ 2866160814Ssimon uint8_t data; 2867160814Ssimon usb_error_t error; 2868160814Ssimon 2869160814Ssimon urtw_8225_write(sc, 0x4, 0x1f); 2870160814Ssimon 2871160814Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 2872160814Ssimon if (error) 2873160814Ssimon goto fail; 2874160814Ssimon 2875238405Sjkim urtw_read8_m(sc, URTW_CONFIG3, &data); 2876205128Ssimon urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); 2877205128Ssimon if (sc->sc_flags & URTW_RTL8187B) { 2878160814Ssimon urtw_write32_m(sc, URTW_ANAPARAM2, 2879160814Ssimon URTW_8187B_8225_ANAPARAM2_OFF); 2880238405Sjkim urtw_write32_m(sc, URTW_ANAPARAM, URTW_8187B_8225_ANAPARAM_OFF); 2881238405Sjkim urtw_write32_m(sc, URTW_ANAPARAM3, 2882160814Ssimon URTW_8187B_8225_ANAPARAM3_OFF); 2883160814Ssimon } else { 2884160814Ssimon urtw_write32_m(sc, URTW_ANAPARAM2, URTW_8225_ANAPARAM2_OFF); 2885160814Ssimon urtw_write32_m(sc, URTW_ANAPARAM, URTW_8225_ANAPARAM_OFF); 2886160814Ssimon } 2887160814Ssimon 2888160814Ssimon urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); 2889194206Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 2890160814Ssimon if (error) 2891160814Ssimon goto fail; 2892160814Ssimon 2893160814Ssimonfail: 2894160814Ssimon return (error); 2895160814Ssimon} 2896160814Ssimon 2897160814Ssimonstatic usb_error_t 2898160814Ssimonurtw_8225v2_rf_init(struct urtw_softc *sc) 2899160814Ssimon{ 2900238405Sjkim#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) 2901238405Sjkim int i; 2902160814Ssimon uint16_t data; 2903160814Ssimon uint32_t data32; 2904238405Sjkim usb_error_t error; 2905238405Sjkim 2906160814Ssimon error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 2907160814Ssimon if (error) 2908160814Ssimon goto fail; 2909238405Sjkim 2910160814Ssimon error = urtw_8225_usb_init(sc); 2911160814Ssimon if (error) 2912160814Ssimon goto fail; 2913238405Sjkim 2914238405Sjkim urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008); 2915160814Ssimon urtw_read16_m(sc, URTW_BRSR, &data); /* XXX ??? */ 2916160814Ssimon urtw_write16_m(sc, URTW_BRSR, 0xffff); 2917160814Ssimon urtw_write32_m(sc, URTW_RF_PARA, 0x100044); 2918160814Ssimon 2919160814Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 2920160814Ssimon if (error) 2921238405Sjkim goto fail; 2922238405Sjkim urtw_write8_m(sc, URTW_CONFIG3, 0x44); 2923160814Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 2924205128Ssimon if (error) 2925160814Ssimon goto fail; 2926160814Ssimon 2927238405Sjkim error = urtw_8185_rf_pins_enable(sc); 2928238405Sjkim if (error) 2929238405Sjkim goto fail; 2930238405Sjkim 2931238405Sjkim usb_pause_mtx(&sc->sc_mtx, 500); 2932160814Ssimon 2933160814Ssimon for (i = 0; i < N(urtw_8225v2_rf_part1); i++) { 2934160814Ssimon urtw_8225_write(sc, urtw_8225v2_rf_part1[i].reg, 2935238405Sjkim urtw_8225v2_rf_part1[i].val); 2936238405Sjkim } 2937160814Ssimon usb_pause_mtx(&sc->sc_mtx, 50); 2938160814Ssimon 2939160814Ssimon urtw_8225_write(sc, 2940160814Ssimon URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1); 2941160814Ssimon 2942160814Ssimon for (i = 0; i < 95; i++) { 2943160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); 2944160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 2945238405Sjkim urtw_8225v2_rxgain[i]); 2946238405Sjkim } 2947160814Ssimon 2948160814Ssimon urtw_8225_write(sc, 2949160814Ssimon URTW_8225_ADDR_3_MAGIC, URTW_8225_ADDR_3_DATA_MAGIC1); 2950238405Sjkim urtw_8225_write(sc, 2951160814Ssimon URTW_8225_ADDR_5_MAGIC, URTW_8225_ADDR_5_DATA_MAGIC1); 2952238405Sjkim urtw_8225_write(sc, 2953238405Sjkim URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC2); 2954160814Ssimon urtw_8225_write(sc, 2955160814Ssimon URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); 2956238405Sjkim usb_pause_mtx(&sc->sc_mtx, 100); 2957160814Ssimon urtw_8225_write(sc, 2958160814Ssimon URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); 2959160814Ssimon usb_pause_mtx(&sc->sc_mtx, 100); 2960160814Ssimon 2961238405Sjkim error = urtw_8225_read(sc, URTW_8225_ADDR_6_MAGIC, &data32); 2962238405Sjkim if (error != 0) 2963238405Sjkim goto fail; 2964160814Ssimon if (data32 != URTW_8225_ADDR_6_DATA_MAGIC1) 2965160814Ssimon device_printf(sc->sc_dev, "expect 0xe6!! (0x%x)\n", data32); 2966160814Ssimon if (!(data32 & URTW_8225_ADDR_6_DATA_MAGIC2)) { 2967160814Ssimon urtw_8225_write(sc, 2968238405Sjkim URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); 2969160814Ssimon usb_pause_mtx(&sc->sc_mtx, 100); 2970160814Ssimon urtw_8225_write(sc, 2971160814Ssimon URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); 2972238405Sjkim usb_pause_mtx(&sc->sc_mtx, 50); 2973160814Ssimon error = urtw_8225_read(sc, URTW_8225_ADDR_6_MAGIC, &data32); 2974160814Ssimon if (error != 0) 2975238405Sjkim goto fail; 2976160814Ssimon if (!(data32 & URTW_8225_ADDR_6_DATA_MAGIC2)) 2977160814Ssimon device_printf(sc->sc_dev, "RF calibration failed\n"); 2978238405Sjkim } 2979238405Sjkim usb_pause_mtx(&sc->sc_mtx, 100); 2980160814Ssimon 2981238405Sjkim urtw_8225_write(sc, 2982160814Ssimon URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC6); 2983160814Ssimon for (i = 0; i < 128; i++) { 2984160814Ssimon urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]); 2985160814Ssimon urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80); 2986160814Ssimon } 2987238405Sjkim 2988160814Ssimon for (i = 0; i < N(urtw_8225v2_rf_part2); i++) { 2989238405Sjkim urtw_8187_write_phy_ofdm(sc, urtw_8225v2_rf_part2[i].reg, 2990160814Ssimon urtw_8225v2_rf_part2[i].val); 2991160814Ssimon } 2992238405Sjkim 2993160814Ssimon error = urtw_8225v2_setgain(sc, 4); 2994160814Ssimon if (error) 2995238405Sjkim goto fail; 2996238405Sjkim 2997160814Ssimon for (i = 0; i < N(urtw_8225v2_rf_part3); i++) { 2998160814Ssimon urtw_8187_write_phy_cck(sc, urtw_8225v2_rf_part3[i].reg, 2999238405Sjkim urtw_8225v2_rf_part3[i].val); 3000238405Sjkim } 3001238405Sjkim 3002238405Sjkim urtw_write8_m(sc, URTW_TESTR, 0x0d); 3003238405Sjkim 3004160814Ssimon error = urtw_8225v2_set_txpwrlvl(sc, 1); 3005160814Ssimon if (error) 3006238405Sjkim goto fail; 3007160814Ssimon 3008160814Ssimon urtw_8187_write_phy_cck(sc, 0x10, 0x9b); 3009160814Ssimon urtw_8187_write_phy_ofdm(sc, 0x26, 0x90); 3010238405Sjkim 3011238405Sjkim /* TX ant A, 0x0 for B */ 3012160814Ssimon error = urtw_8185_tx_antenna(sc, 0x3); 3013160814Ssimon if (error) 3014160814Ssimon goto fail; 3015160814Ssimon urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002); 3016160814Ssimon 3017160814Ssimon error = urtw_8225_rf_set_chan(sc, 1); 3018160814Ssimonfail: 3019160814Ssimon return (error); 3020160814Ssimon#undef N 3021238405Sjkim} 3022160814Ssimon 3023160814Ssimonstatic usb_error_t 3024160814Ssimonurtw_8225v2_rf_set_chan(struct urtw_softc *sc, int chan) 3025238405Sjkim{ 3026160814Ssimon usb_error_t error; 3027238405Sjkim 3028160814Ssimon error = urtw_8225v2_set_txpwrlvl(sc, chan); 3029160814Ssimon if (error) 3030160814Ssimon goto fail; 3031160814Ssimon 3032160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); 3033238405Sjkim usb_pause_mtx(&sc->sc_mtx, 10); 3034238405Sjkimfail: 3035160814Ssimon return (error); 3036160814Ssimon} 3037238405Sjkim 3038238405Sjkimstatic usb_error_t 3039160814Ssimonurtw_8225_read(struct urtw_softc *sc, uint8_t addr, uint32_t *data) 3040160814Ssimon{ 3041160814Ssimon int i; 3042160814Ssimon int16_t bit; 3043160814Ssimon uint8_t rlen = 12, wlen = 6; 3044238405Sjkim uint16_t o1, o2, o3, tmp; 3045238405Sjkim uint32_t d2w = ((uint32_t)(addr & 0x1f)) << 27; 3046238405Sjkim uint32_t mask = 0x80000000, value = 0; 3047160814Ssimon usb_error_t error; 3048160814Ssimon 3049160814Ssimon urtw_read16_m(sc, URTW_RF_PINS_OUTPUT, &o1); 3050160814Ssimon urtw_read16_m(sc, URTW_RF_PINS_ENABLE, &o2); 3051160814Ssimon urtw_read16_m(sc, URTW_RF_PINS_SELECT, &o3); 3052238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_ENABLE, o2 | URTW_RF_PINS_MAGIC4); 3053238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_SELECT, o3 | URTW_RF_PINS_MAGIC4); 3054160814Ssimon o1 &= ~URTW_RF_PINS_MAGIC4; 3055160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_EN); 3056160814Ssimon DELAY(5); 3057160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1); 3058160814Ssimon DELAY(5); 3059238405Sjkim 3060238405Sjkim for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) { 3061238405Sjkim bit = ((d2w & mask) != 0) ? 1 : 0; 3062160814Ssimon 3063238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1); 3064238405Sjkim DELAY(2); 3065238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 3066160814Ssimon URTW_BB_HOST_BANG_CLK); 3067160814Ssimon DELAY(2); 3068238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 3069238405Sjkim URTW_BB_HOST_BANG_CLK); 3070238405Sjkim DELAY(2); 3071238405Sjkim mask = mask >> 1; 3072238405Sjkim if (i == 2) 3073160814Ssimon break; 3074160814Ssimon bit = ((d2w & mask) != 0) ? 1 : 0; 3075238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 3076238405Sjkim URTW_BB_HOST_BANG_CLK); 3077160814Ssimon DELAY(2); 3078238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | 3079238405Sjkim URTW_BB_HOST_BANG_CLK); 3080238405Sjkim DELAY(2); 3081238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1); 3082238405Sjkim DELAY(1); 3083160814Ssimon } 3084238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | URTW_BB_HOST_BANG_RW | 3085160814Ssimon URTW_BB_HOST_BANG_CLK); 3086238405Sjkim DELAY(2); 3087160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | URTW_BB_HOST_BANG_RW); 3088160814Ssimon DELAY(2); 3089160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_RW); 3090160814Ssimon DELAY(2); 3091160814Ssimon 3092160814Ssimon mask = 0x800; 3093160814Ssimon for (i = 0; i < rlen; i++, mask = mask >> 1) { 3094238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 3095238405Sjkim o1 | URTW_BB_HOST_BANG_RW); 3096160814Ssimon DELAY(2); 3097160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 3098238405Sjkim o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); 3099160814Ssimon DELAY(2); 3100238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 3101160814Ssimon o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); 3102160814Ssimon DELAY(2); 3103160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 3104160814Ssimon o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); 3105160814Ssimon DELAY(2); 3106160814Ssimon 3107238405Sjkim urtw_read16_m(sc, URTW_RF_PINS_INPUT, &tmp); 3108160814Ssimon value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0); 3109160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 3110160814Ssimon o1 | URTW_BB_HOST_BANG_RW); 3111238405Sjkim DELAY(2); 3112238405Sjkim } 3113238405Sjkim 3114238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_EN | 3115160814Ssimon URTW_BB_HOST_BANG_RW); 3116160814Ssimon DELAY(2); 3117160814Ssimon 3118238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_ENABLE, o2); 3119238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_SELECT, o3); 3120238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, URTW_RF_PINS_OUTPUT_MAGIC1); 3121238405Sjkim 3122238405Sjkim if (data != NULL) 3123238405Sjkim *data = value; 3124238405Sjkimfail: 3125160814Ssimon return (error); 3126160814Ssimon} 3127238405Sjkim 3128160814Ssimon 3129238405Sjkimstatic usb_error_t 3130160814Ssimonurtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan) 3131160814Ssimon{ 3132238405Sjkim int i; 3133160814Ssimon uint8_t *cck_pwrtable; 3134160814Ssimon uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10; 3135205128Ssimon uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 3136238405Sjkim uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 3137238405Sjkim usb_error_t error; 3138238405Sjkim 3139238405Sjkim /* CCK power setting */ 3140160814Ssimon cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl; 3141160814Ssimon cck_pwrlvl += sc->sc_txpwr_cck_base; 3142160814Ssimon cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; 3143238405Sjkim cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : 3144238405Sjkim urtw_8225v2_txpwr_cck; 3145160814Ssimon 3146160814Ssimon for (i = 0; i < 8; i++) 3147238405Sjkim urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]); 3148238405Sjkim 3149160814Ssimon urtw_write8_m(sc, URTW_TX_GAIN_CCK, 3150160814Ssimon urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]); 3151160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3152238405Sjkim 3153160814Ssimon /* OFDM power setting */ 3154160814Ssimon ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? 3155160814Ssimon ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; 3156160814Ssimon ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; 3157160814Ssimon ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 3158160814Ssimon 3159238405Sjkim error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 3160160814Ssimon if (error) 3161238405Sjkim goto fail; 3162160814Ssimon 3163238405Sjkim urtw_8187_write_phy_ofdm(sc, 2, 0x42); 3164238405Sjkim urtw_8187_write_phy_ofdm(sc, 5, 0x0); 3165160814Ssimon urtw_8187_write_phy_ofdm(sc, 6, 0x40); 3166238405Sjkim urtw_8187_write_phy_ofdm(sc, 7, 0x0); 3167160814Ssimon urtw_8187_write_phy_ofdm(sc, 8, 0x40); 3168205128Ssimon 3169238405Sjkim urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 3170238405Sjkim urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]); 3171238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3172238405Sjkimfail: 3173160814Ssimon return (error); 3174160814Ssimon} 3175160814Ssimon 3176238405Sjkimstatic usb_error_t 3177238405Sjkimurtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain) 3178160814Ssimon{ 3179238405Sjkim uint8_t *gainp; 3180238405Sjkim usb_error_t error; 3181160814Ssimon 3182238405Sjkim /* XXX for A? */ 3183238405Sjkim gainp = urtw_8225v2_gain_bg; 3184160814Ssimon urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]); 3185238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3186238405Sjkim urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]); 3187238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3188238405Sjkim urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]); 3189238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3190238405Sjkim urtw_8187_write_phy_ofdm(sc, 0x21, 0x17); 3191160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3192238405Sjkimfail: 3193238405Sjkim return (error); 3194238405Sjkim} 3195238405Sjkim 3196160814Ssimonstatic usb_error_t 3197238405Sjkimurtw_8225_isv2(struct urtw_softc *sc, int *ret) 3198160814Ssimon{ 3199160814Ssimon uint32_t data; 3200160814Ssimon usb_error_t error; 3201160814Ssimon 3202160814Ssimon *ret = 1; 3203160814Ssimon 3204160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, URTW_RF_PINS_MAGIC5); 3205238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_SELECT, URTW_RF_PINS_MAGIC5); 3206160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_ENABLE, URTW_RF_PINS_MAGIC5); 3207160814Ssimon usb_pause_mtx(&sc->sc_mtx, 500); 3208160814Ssimon 3209160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 3210160814Ssimon URTW_8225_ADDR_0_DATA_MAGIC1); 3211160814Ssimon 3212160814Ssimon error = urtw_8225_read(sc, URTW_8225_ADDR_8_MAGIC, &data); 3213238405Sjkim if (error != 0) 3214160814Ssimon goto fail; 3215160814Ssimon if (data != URTW_8225_ADDR_8_DATA_MAGIC1) 3216160814Ssimon *ret = 0; 3217160814Ssimon else { 3218238405Sjkim error = urtw_8225_read(sc, URTW_8225_ADDR_9_MAGIC, &data); 3219238405Sjkim if (error != 0) 3220160814Ssimon goto fail; 3221238405Sjkim if (data != URTW_8225_ADDR_9_DATA_MAGIC1) 3222160814Ssimon *ret = 0; 3223238405Sjkim } 3224238405Sjkim 3225160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 3226160814Ssimon URTW_8225_ADDR_0_DATA_MAGIC2); 3227205128Ssimonfail: 3228238405Sjkim return (error); 3229160814Ssimon} 3230160814Ssimon 3231160814Ssimonstatic usb_error_t 3232238405Sjkimurtw_8225v2b_rf_init(struct urtw_softc *sc) 3233160814Ssimon{ 3234238405Sjkim#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) 3235160814Ssimon int i; 3236160814Ssimon uint8_t data8; 3237160814Ssimon usb_error_t error; 3238160814Ssimon 3239238405Sjkim error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3240160814Ssimon if (error) 3241160814Ssimon goto fail; 3242238405Sjkim 3243160814Ssimon /* 3244160814Ssimon * initialize extra registers on 8187 3245238405Sjkim */ 3246160814Ssimon urtw_write16_m(sc, URTW_BRSR_8187B, 0xfff); 3247160814Ssimon 3248238405Sjkim /* retry limit */ 3249160814Ssimon urtw_read8_m(sc, URTW_CW_CONF, &data8); 3250160814Ssimon data8 |= URTW_CW_CONF_PERPACKET_RETRY; 3251160814Ssimon urtw_write8_m(sc, URTW_CW_CONF, data8); 3252160814Ssimon 3253160814Ssimon /* TX AGC */ 3254160814Ssimon urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); 3255160814Ssimon data8 |= URTW_TX_AGC_CTL_PERPACKET_GAIN; 3256238405Sjkim urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); 3257238405Sjkim 3258160814Ssimon /* Auto Rate Fallback Control */ 3259160814Ssimon#define URTW_ARFR 0x1e0 3260160814Ssimon urtw_write16_m(sc, URTW_ARFR, 0xfff); 3261160814Ssimon urtw_read8_m(sc, URTW_RATE_FALLBACK, &data8); 3262160814Ssimon urtw_write8_m(sc, URTW_RATE_FALLBACK, 3263160814Ssimon data8 | URTW_RATE_FALLBACK_ENABLE); 3264160814Ssimon 3265160814Ssimon urtw_read8_m(sc, URTW_MSR, &data8); 3266205128Ssimon urtw_write8_m(sc, URTW_MSR, data8 & 0xf3); 3267238405Sjkim urtw_read8_m(sc, URTW_MSR, &data8); 3268160814Ssimon urtw_write8_m(sc, URTW_MSR, data8 | URTW_MSR_LINK_ENEDCA); 3269160814Ssimon urtw_write8_m(sc, URTW_ACM_CONTROL, sc->sc_acmctl); 3270160814Ssimon 3271238405Sjkim urtw_write16_m(sc, URTW_ATIM_WND, 2); 3272205128Ssimon urtw_write16_m(sc, URTW_BEACON_INTERVAL, 100); 3273160814Ssimon#define URTW_FEMR_FOR_8187B 0x1d4 3274238405Sjkim urtw_write16_m(sc, URTW_FEMR_FOR_8187B, 0xffff); 3275238405Sjkim 3276160814Ssimon /* led type */ 3277238405Sjkim urtw_read8_m(sc, URTW_CONFIG1, &data8); 3278238405Sjkim data8 = (data8 & 0x3f) | 0x80; 3279238405Sjkim urtw_write8_m(sc, URTW_CONFIG1, data8); 3280160814Ssimon 3281160814Ssimon /* applying MAC address again. */ 3282160814Ssimon urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]); 3283160814Ssimon urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff); 3284160814Ssimon 3285160814Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3286160814Ssimon if (error) 3287160814Ssimon goto fail; 3288160814Ssimon 3289238405Sjkim urtw_write8_m(sc, URTW_WPA_CONFIG, 0); 3290238405Sjkim 3291160814Ssimon /* 3292160814Ssimon * MAC configuration 3293160814Ssimon */ 3294160814Ssimon for (i = 0; i < N(urtw_8225v2b_rf_part1); i++) 3295160814Ssimon urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg, 3296160814Ssimon urtw_8225v2b_rf_part1[i].val); 3297160814Ssimon urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50); 3298160814Ssimon urtw_write16_m(sc, URTW_INT_MIG, 0x0000); 3299238405Sjkim urtw_write32_m(sc, 0x1f0, 0); 3300160814Ssimon urtw_write32_m(sc, 0x1f4, 0); 3301160814Ssimon urtw_write8_m(sc, 0x1f8, 0); 3302160814Ssimon urtw_write32_m(sc, URTW_RF_TIMING, 0x4001); 3303160814Ssimon 3304160814Ssimon#define URTW_RFSW_CTRL 0x272 3305160814Ssimon urtw_write16_m(sc, URTW_RFSW_CTRL, 0x569a); 3306160814Ssimon 3307160814Ssimon /* 3308160814Ssimon * initialize PHY 3309238405Sjkim */ 3310160814Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3311160814Ssimon if (error) 3312160814Ssimon goto fail; 3313160814Ssimon urtw_read8_m(sc, URTW_CONFIG3, &data8); 3314160814Ssimon urtw_write8_m(sc, URTW_CONFIG3, 3315238405Sjkim data8 | URTW_CONFIG3_ANAPARAM_WRITE); 3316238405Sjkim 3317160814Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3318160814Ssimon if (error) 3319160814Ssimon goto fail; 3320160814Ssimon 3321160814Ssimon /* setup RFE initial timing */ 3322160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 0x0480); 3323238405Sjkim urtw_write16_m(sc, URTW_RF_PINS_SELECT, 0x2488); 3324160814Ssimon urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff); 3325160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1100); 3326160814Ssimon 3327160814Ssimon for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) { 3328238405Sjkim urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg, 3329160814Ssimon urtw_8225v2b_rf_part0[i].val); 3330160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3331160814Ssimon } 3332160814Ssimon urtw_8225_write(sc, 0x00, 0x01b7); 3333160814Ssimon 3334160814Ssimon for (i = 0; i < 95; i++) { 3335238405Sjkim urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); 3336238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3337160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 3338205128Ssimon urtw_8225v2b_rxgain[i]); 3339238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3340160814Ssimon } 3341205128Ssimon 3342160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_3_MAGIC, 0x080); 3343160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3344238405Sjkim urtw_8225_write(sc, URTW_8225_ADDR_5_MAGIC, 0x004); 3345238405Sjkim usb_pause_mtx(&sc->sc_mtx, 1); 3346160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x0b7); 3347205128Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3348160814Ssimon usb_pause_mtx(&sc->sc_mtx, 3000); 3349238405Sjkim urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0xc4d); 3350160814Ssimon usb_pause_mtx(&sc->sc_mtx, 2000); 3351160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0x44d); 3352160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3353160814Ssimon urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x2bf); 3354160814Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3355160814Ssimon 3356160814Ssimon urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03); 3357238405Sjkim urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07); 3358238405Sjkim urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03); 3359160814Ssimon 3360160814Ssimon urtw_8187_write_phy_ofdm(sc, 0x80, 0x12); 3361160814Ssimon for (i = 0; i < 128; i++) { 3362160814Ssimon uint32_t addr, data; 3363238405Sjkim 3364160814Ssimon data = (urtw_8225z2_agc[i] << 8) | 0x0000008f; 3365160814Ssimon addr = ((i + 0x80) << 8) | 0x0000008e; 3366160814Ssimon 3367160814Ssimon urtw_8187_write_phy_ofdm(sc, data & 0x7f, (data >> 8) & 0xff); 3368160814Ssimon urtw_8187_write_phy_ofdm(sc, addr & 0x7f, (addr >> 8) & 0xff); 3369160814Ssimon urtw_8187_write_phy_ofdm(sc, 0x0e, 0x00); 3370160814Ssimon } 3371238405Sjkim urtw_8187_write_phy_ofdm(sc, 0x80, 0x10); 3372160814Ssimon 3373238405Sjkim for (i = 0; i < N(urtw_8225v2b_rf_part2); i++) 3374160814Ssimon urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val); 3375160814Ssimon 3376160814Ssimon urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c); 3377160814Ssimon urtw_write32_m(sc, URTW_8187B_AC_VI, (7 << 12) | (3 << 8) | 0x1c); 3378160814Ssimon urtw_write32_m(sc, URTW_8187B_AC_BE, (7 << 12) | (3 << 8) | 0x1c); 3379160814Ssimon urtw_write32_m(sc, URTW_8187B_AC_BK, (7 << 12) | (3 << 8) | 0x1c); 3380160814Ssimon 3381160814Ssimon urtw_8187_write_phy_ofdm(sc, 0x97, 0x46); 3382160814Ssimon urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6); 3383160814Ssimon urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc); 3384160814Ssimon urtw_8187_write_phy_cck(sc, 0xc1, 0x88); 3385160814Ssimon 3386160814Ssimonfail: 3387162911Ssimon return (error); 3388162911Ssimon#undef N 3389162911Ssimon} 3390162911Ssimon 3391162911Ssimonstatic usb_error_t 3392238405Sjkimurtw_8225v2b_rf_set_chan(struct urtw_softc *sc, int chan) 3393162911Ssimon{ 3394162911Ssimon usb_error_t error; 3395162911Ssimon 3396162911Ssimon error = urtw_8225v2b_set_txpwrlvl(sc, chan); 3397162911Ssimon if (error) 3398162911Ssimon goto fail; 3399162911Ssimon 3400162911Ssimon urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); 3401162911Ssimon usb_pause_mtx(&sc->sc_mtx, 10); 3402162911Ssimonfail: 3403162911Ssimon return (error); 3404162911Ssimon} 3405162911Ssimon 3406162911Ssimonstatic usb_error_t 3407162911Ssimonurtw_8225v2b_set_txpwrlvl(struct urtw_softc *sc, int chan) 3408162911Ssimon{ 3409162911Ssimon int i; 3410162911Ssimon uint8_t *cck_pwrtable; 3411162911Ssimon uint8_t cck_pwrlvl_max = 15; 3412162911Ssimon uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; 3413162911Ssimon uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; 3414162911Ssimon usb_error_t error; 3415162911Ssimon 3416167612Ssimon /* CCK power setting */ 3417167612Ssimon cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? 3418167612Ssimon ((sc->sc_flags & URTW_RTL8187B_REV_B) ? cck_pwrlvl_max : 22) : 3419167612Ssimon (cck_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 0 : 7)); 3420167612Ssimon cck_pwrlvl += sc->sc_txpwr_cck_base; 3421167612Ssimon cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; 3422167612Ssimon cck_pwrtable = (chan == 14) ? urtw_8225v2b_txpwr_cck_ch14 : 3423167612Ssimon urtw_8225v2b_txpwr_cck; 3424167612Ssimon 3425167612Ssimon if (sc->sc_flags & URTW_RTL8187B_REV_B) 3426167612Ssimon cck_pwrtable += (cck_pwrlvl <= 6) ? 0 : 3427167612Ssimon ((cck_pwrlvl <= 11) ? 8 : 16); 3428167612Ssimon else 3429167612Ssimon cck_pwrtable += (cck_pwrlvl <= 5) ? 0 : 3430167612Ssimon ((cck_pwrlvl <= 11) ? 8 : ((cck_pwrlvl <= 17) ? 16 : 24)); 3431167612Ssimon 3432167612Ssimon for (i = 0; i < 8; i++) 3433167612Ssimon urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]); 3434167612Ssimon 3435167612Ssimon urtw_write8_m(sc, URTW_TX_GAIN_CCK, 3436167612Ssimon urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1); 3437167612Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3438167612Ssimon 3439167612Ssimon /* OFDM power setting */ 3440167612Ssimon ofdm_pwrlvl = (ofdm_pwrlvl > 15) ? 3441167612Ssimon ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 17 : 25) : 3442167612Ssimon (ofdm_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 2 : 10)); 3443167612Ssimon ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; 3444167612Ssimon ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; 3445167612Ssimon 3446167612Ssimon urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 3447167612Ssimon urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1); 3448167612Ssimon 3449167612Ssimon if (sc->sc_flags & URTW_RTL8187B_REV_B) { 3450167612Ssimon if (ofdm_pwrlvl <= 11) { 3451167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x87, 0x60); 3452167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x89, 0x60); 3453167612Ssimon } else { 3454167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c); 3455167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c); 3456167612Ssimon } 3457167612Ssimon } else { 3458167612Ssimon if (ofdm_pwrlvl <= 11) { 3459167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c); 3460167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c); 3461167612Ssimon } else if (ofdm_pwrlvl <= 17) { 3462167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x87, 0x54); 3463167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x89, 0x54); 3464167612Ssimon } else { 3465167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x87, 0x50); 3466167612Ssimon urtw_8187_write_phy_ofdm(sc, 0x89, 0x50); 3467167612Ssimon } 3468167612Ssimon } 3469167612Ssimon usb_pause_mtx(&sc->sc_mtx, 1); 3470167612Ssimonfail: 3471167612Ssimon return (error); 3472167612Ssimon} 3473167612Ssimon 3474167612Ssimonstatic usb_error_t 3475167612Ssimonurtw_read8e(struct urtw_softc *sc, int val, uint8_t *data) 3476167612Ssimon{ 3477167612Ssimon struct usb_device_request req; 3478167612Ssimon usb_error_t error; 3479167612Ssimon 3480167612Ssimon req.bmRequestType = UT_READ_VENDOR_DEVICE; 3481167612Ssimon req.bRequest = URTW_8187_GETREGS_REQ; 3482167612Ssimon USETW(req.wValue, val | 0xfe00); 3483167612Ssimon USETW(req.wIndex, 0); 3484167612Ssimon USETW(req.wLength, sizeof(uint8_t)); 3485167612Ssimon 3486167612Ssimon error = urtw_do_request(sc, &req, data); 3487167612Ssimon return (error); 3488167612Ssimon} 3489167612Ssimon 3490167612Ssimonstatic usb_error_t 3491167612Ssimonurtw_write8e(struct urtw_softc *sc, int val, uint8_t data) 3492167612Ssimon{ 3493167612Ssimon struct usb_device_request req; 3494167612Ssimon 3495167612Ssimon req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 3496167612Ssimon req.bRequest = URTW_8187_SETREGS_REQ; 3497167612Ssimon USETW(req.wValue, val | 0xfe00); 3498167612Ssimon USETW(req.wIndex, 0); 3499167612Ssimon USETW(req.wLength, sizeof(uint8_t)); 3500167612Ssimon 3501167612Ssimon return (urtw_do_request(sc, &req, &data)); 3502167612Ssimon} 3503167612Ssimon 3504167612Ssimonstatic usb_error_t 3505167612Ssimonurtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val) 3506167612Ssimon{ 3507167612Ssimon uint8_t data; 3508167612Ssimon usb_error_t error; 3509167612Ssimon 3510167612Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3511167612Ssimon if (error) 3512167612Ssimon goto fail; 3513167612Ssimon 3514167612Ssimon urtw_read8_m(sc, URTW_CONFIG3, &data); 3515167612Ssimon urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); 3516167612Ssimon urtw_write32_m(sc, URTW_ANAPARAM, val); 3517246772Sjkim urtw_read8_m(sc, URTW_CONFIG3, &data); 3518264278Sjkim urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); 3519194206Ssimon 3520194206Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3521194206Ssimon if (error) 3522194206Ssimon goto fail; 3523194206Ssimonfail: 3524194206Ssimon return (error); 3525194206Ssimon} 3526194206Ssimon 3527194206Ssimonstatic usb_error_t 3528194206Ssimonurtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val) 3529194206Ssimon{ 3530194206Ssimon uint8_t data; 3531194206Ssimon usb_error_t error; 3532194206Ssimon 3533194206Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); 3534194206Ssimon if (error) 3535194206Ssimon goto fail; 3536194206Ssimon 3537194206Ssimon urtw_read8_m(sc, URTW_CONFIG3, &data); 3538194206Ssimon urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); 3539194206Ssimon urtw_write32_m(sc, URTW_ANAPARAM2, val); 3540194206Ssimon urtw_read8_m(sc, URTW_CONFIG3, &data); 3541194206Ssimon urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); 3542194206Ssimon 3543194206Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); 3544194206Ssimon if (error) 3545194206Ssimon goto fail; 3546194206Ssimonfail: 3547194206Ssimon return (error); 3548298998Sjkim} 3549298998Sjkim 3550194206Ssimonstatic usb_error_t 3551194206Ssimonurtw_intr_enable(struct urtw_softc *sc) 3552194206Ssimon{ 3553194206Ssimon usb_error_t error; 3554194206Ssimon 3555194206Ssimon urtw_write16_m(sc, URTW_INTR_MASK, 0xffff); 3556194206Ssimonfail: 3557194206Ssimon return (error); 3558194206Ssimon} 3559194206Ssimon 3560194206Ssimonstatic usb_error_t 3561194206Ssimonurtw_intr_disable(struct urtw_softc *sc) 3562194206Ssimon{ 3563194206Ssimon usb_error_t error; 3564194206Ssimon 3565194206Ssimon urtw_write16_m(sc, URTW_INTR_MASK, 0); 3566194206Ssimonfail: 3567194206Ssimon return (error); 3568194206Ssimon} 3569194206Ssimon 3570194206Ssimonstatic usb_error_t 3571194206Ssimonurtw_reset(struct urtw_softc *sc) 3572194206Ssimon{ 3573194206Ssimon uint8_t data; 3574194206Ssimon usb_error_t error; 3575194206Ssimon 3576194206Ssimon error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 3577194206Ssimon if (error) 3578194206Ssimon goto fail; 3579194206Ssimon error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 3580194206Ssimon if (error) 3581194206Ssimon goto fail; 3582194206Ssimon 3583194206Ssimon error = urtw_intr_disable(sc); 3584194206Ssimon if (error) 3585194206Ssimon goto fail; 3586194206Ssimon usb_pause_mtx(&sc->sc_mtx, 100); 3587194206Ssimon 3588194206Ssimon error = urtw_write8e(sc, 0x18, 0x10); 3589194206Ssimon if (error != 0) 3590194206Ssimon goto fail; 3591194206Ssimon error = urtw_write8e(sc, 0x18, 0x11); 3592194206Ssimon if (error != 0) 3593194206Ssimon goto fail; 3594238405Sjkim error = urtw_write8e(sc, 0x18, 0x00); 3595194206Ssimon if (error != 0) 3596194206Ssimon goto fail; 3597194206Ssimon usb_pause_mtx(&sc->sc_mtx, 100); 3598194206Ssimon 3599194206Ssimon urtw_read8_m(sc, URTW_CMD, &data); 3600194206Ssimon data = (data & 0x2) | URTW_CMD_RST; 3601194206Ssimon urtw_write8_m(sc, URTW_CMD, data); 3602194206Ssimon usb_pause_mtx(&sc->sc_mtx, 100); 3603194206Ssimon 3604194206Ssimon urtw_read8_m(sc, URTW_CMD, &data); 3605194206Ssimon if (data & URTW_CMD_RST) { 3606194206Ssimon device_printf(sc->sc_dev, "reset timeout\n"); 3607194206Ssimon goto fail; 3608194206Ssimon } 3609194206Ssimon 3610194206Ssimon error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD); 3611194206Ssimon if (error) 3612194206Ssimon goto fail; 3613194206Ssimon usb_pause_mtx(&sc->sc_mtx, 100); 3614194206Ssimon 3615194206Ssimon error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); 3616194206Ssimon if (error) 3617194206Ssimon goto fail; 3618194206Ssimon error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); 3619194206Ssimon if (error) 3620194206Ssimon goto fail; 3621194206Ssimonfail: 3622194206Ssimon return (error); 3623194206Ssimon} 3624194206Ssimon 3625194206Ssimonstatic usb_error_t 3626194206Ssimonurtw_led_ctl(struct urtw_softc *sc, int mode) 3627194206Ssimon{ 3628194206Ssimon usb_error_t error = 0; 3629194206Ssimon 3630194206Ssimon switch (sc->sc_strategy) { 3631194206Ssimon case URTW_SW_LED_MODE0: 3632194206Ssimon error = urtw_led_mode0(sc, mode); 3633194206Ssimon break; 3634194206Ssimon case URTW_SW_LED_MODE1: 3635194206Ssimon error = urtw_led_mode1(sc, mode); 3636194206Ssimon break; 3637194206Ssimon case URTW_SW_LED_MODE2: 3638194206Ssimon error = urtw_led_mode2(sc, mode); 3639194206Ssimon break; 3640194206Ssimon case URTW_SW_LED_MODE3: 3641194206Ssimon error = urtw_led_mode3(sc, mode); 3642194206Ssimon break; 3643194206Ssimon default: 3644194206Ssimon DPRINTF(sc, URTW_DEBUG_STATE, 3645194206Ssimon "unsupported LED mode %d\n", sc->sc_strategy); 3646194206Ssimon error = USB_ERR_INVAL; 3647194206Ssimon break; 3648194206Ssimon } 3649194206Ssimon 3650194206Ssimon return (error); 3651194206Ssimon} 3652194206Ssimon 3653194206Ssimonstatic usb_error_t 3654194206Ssimonurtw_led_mode0(struct urtw_softc *sc, int mode) 3655194206Ssimon{ 3656194206Ssimon 3657194206Ssimon switch (mode) { 3658194206Ssimon case URTW_LED_CTL_POWER_ON: 3659194206Ssimon sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK; 3660194206Ssimon break; 3661194206Ssimon case URTW_LED_CTL_TX: 3662194206Ssimon if (sc->sc_gpio_ledinprogress == 1) 3663194206Ssimon return (0); 3664194206Ssimon 3665194206Ssimon sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL; 3666238405Sjkim sc->sc_gpio_blinktime = 2; 3667194206Ssimon break; 3668238405Sjkim case URTW_LED_CTL_LINK: 3669194206Ssimon sc->sc_gpio_ledstate = URTW_LED_ON; 3670238405Sjkim break; 3671238405Sjkim default: 3672238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3673238405Sjkim "unsupported LED mode 0x%x", mode); 3674238405Sjkim return (USB_ERR_INVAL); 3675238405Sjkim } 3676238405Sjkim 3677238405Sjkim switch (sc->sc_gpio_ledstate) { 3678194206Ssimon case URTW_LED_ON: 3679194206Ssimon if (sc->sc_gpio_ledinprogress != 0) 3680238405Sjkim break; 3681238405Sjkim urtw_led_on(sc, URTW_LED_GPIO); 3682238405Sjkim break; 3683238405Sjkim case URTW_LED_BLINK_NORMAL: 3684238405Sjkim if (sc->sc_gpio_ledinprogress != 0) 3685238405Sjkim break; 3686238405Sjkim sc->sc_gpio_ledinprogress = 1; 3687238405Sjkim sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ? 3688194206Ssimon URTW_LED_OFF : URTW_LED_ON; 3689238405Sjkim usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc); 3690238405Sjkim break; 3691238405Sjkim case URTW_LED_POWER_ON_BLINK: 3692238405Sjkim urtw_led_on(sc, URTW_LED_GPIO); 3693238405Sjkim usb_pause_mtx(&sc->sc_mtx, 100); 3694238405Sjkim urtw_led_off(sc, URTW_LED_GPIO); 3695238405Sjkim break; 3696246772Sjkim default: 3697238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3698238405Sjkim "unknown LED status 0x%x", sc->sc_gpio_ledstate); 3699238405Sjkim return (USB_ERR_INVAL); 3700238405Sjkim } 3701238405Sjkim return (0); 3702238405Sjkim} 3703238405Sjkim 3704194206Ssimonstatic usb_error_t 3705238405Sjkimurtw_led_mode1(struct urtw_softc *sc, int mode) 3706238405Sjkim{ 3707238405Sjkim return (USB_ERR_INVAL); 3708238405Sjkim} 3709238405Sjkim 3710194206Ssimonstatic usb_error_t 3711194206Ssimonurtw_led_mode2(struct urtw_softc *sc, int mode) 3712194206Ssimon{ 3713194206Ssimon return (USB_ERR_INVAL); 3714194206Ssimon} 3715194206Ssimon 3716194206Ssimonstatic usb_error_t 3717194206Ssimonurtw_led_mode3(struct urtw_softc *sc, int mode) 3718194206Ssimon{ 3719194206Ssimon return (USB_ERR_INVAL); 3720194206Ssimon} 3721194206Ssimon 3722194206Ssimonstatic usb_error_t 3723194206Ssimonurtw_led_on(struct urtw_softc *sc, int type) 3724194206Ssimon{ 3725194206Ssimon usb_error_t error; 3726194206Ssimon 3727194206Ssimon if (type == URTW_LED_GPIO) { 3728194206Ssimon switch (sc->sc_gpio_ledpin) { 3729194206Ssimon case URTW_LED_PIN_GPIO0: 3730194206Ssimon urtw_write8_m(sc, URTW_GPIO, 0x01); 3731194206Ssimon urtw_write8_m(sc, URTW_GP_ENABLE, 0x00); 3732194206Ssimon break; 3733205128Ssimon default: 3734238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3735238405Sjkim "unsupported LED PIN type 0x%x", 3736238405Sjkim sc->sc_gpio_ledpin); 3737238405Sjkim error = USB_ERR_INVAL; 3738238405Sjkim goto fail; 3739238405Sjkim } 3740238405Sjkim } else { 3741238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3742238405Sjkim "unsupported LED type 0x%x", type); 3743238405Sjkim error = USB_ERR_INVAL; 3744238405Sjkim goto fail; 3745238405Sjkim } 3746238405Sjkim 3747238405Sjkim sc->sc_gpio_ledon = 1; 3748238405Sjkimfail: 3749238405Sjkim return (error); 3750238405Sjkim} 3751238405Sjkim 3752238405Sjkimstatic usb_error_t 3753238405Sjkimurtw_led_off(struct urtw_softc *sc, int type) 3754238405Sjkim{ 3755238405Sjkim usb_error_t error; 3756238405Sjkim 3757238405Sjkim if (type == URTW_LED_GPIO) { 3758238405Sjkim switch (sc->sc_gpio_ledpin) { 3759238405Sjkim case URTW_LED_PIN_GPIO0: 3760238405Sjkim urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1); 3761238405Sjkim urtw_write8_m(sc, 3762238405Sjkim URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1); 3763238405Sjkim break; 3764238405Sjkim default: 3765238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3766238405Sjkim "unsupported LED PIN type 0x%x", 3767238405Sjkim sc->sc_gpio_ledpin); 3768238405Sjkim error = USB_ERR_INVAL; 3769238405Sjkim goto fail; 3770238405Sjkim } 3771238405Sjkim } else { 3772238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3773238405Sjkim "unsupported LED type 0x%x", type); 3774238405Sjkim error = USB_ERR_INVAL; 3775238405Sjkim goto fail; 3776238405Sjkim } 3777238405Sjkim 3778238405Sjkim sc->sc_gpio_ledon = 0; 3779238405Sjkim 3780238405Sjkimfail: 3781238405Sjkim return (error); 3782238405Sjkim} 3783238405Sjkim 3784238405Sjkimstatic void 3785238405Sjkimurtw_led_ch(void *arg) 3786238405Sjkim{ 3787238405Sjkim struct urtw_softc *sc = arg; 3788238405Sjkim struct ifnet *ifp = sc->sc_ifp; 3789238405Sjkim struct ieee80211com *ic = ifp->if_l2com; 3790238405Sjkim 3791238405Sjkim ieee80211_runtask(ic, &sc->sc_led_task); 3792238405Sjkim} 3793238405Sjkim 3794238405Sjkimstatic void 3795238405Sjkimurtw_ledtask(void *arg, int pending) 3796238405Sjkim{ 3797238405Sjkim struct urtw_softc *sc = arg; 3798238405Sjkim 3799238405Sjkim if (sc->sc_strategy != URTW_SW_LED_MODE0) { 3800238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3801238405Sjkim "could not process a LED strategy 0x%x", 3802238405Sjkim sc->sc_strategy); 3803238405Sjkim return; 3804238405Sjkim } 3805238405Sjkim 3806238405Sjkim URTW_LOCK(sc); 3807238405Sjkim urtw_led_blink(sc); 3808238405Sjkim URTW_UNLOCK(sc); 3809238405Sjkim} 3810238405Sjkim 3811238405Sjkimstatic usb_error_t 3812238405Sjkimurtw_led_blink(struct urtw_softc *sc) 3813238405Sjkim{ 3814238405Sjkim uint8_t ing = 0; 3815238405Sjkim usb_error_t error; 3816238405Sjkim 3817238405Sjkim if (sc->sc_gpio_blinkstate == URTW_LED_ON) 3818238405Sjkim error = urtw_led_on(sc, URTW_LED_GPIO); 3819238405Sjkim else 3820238405Sjkim error = urtw_led_off(sc, URTW_LED_GPIO); 3821238405Sjkim sc->sc_gpio_blinktime--; 3822238405Sjkim if (sc->sc_gpio_blinktime == 0) 3823238405Sjkim ing = 1; 3824238405Sjkim else { 3825238405Sjkim if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL && 3826238405Sjkim sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY && 3827238405Sjkim sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3) 3828238405Sjkim ing = 1; 3829238405Sjkim } 3830238405Sjkim if (ing == 1) { 3831238405Sjkim if (sc->sc_gpio_ledstate == URTW_LED_ON && 3832238405Sjkim sc->sc_gpio_ledon == 0) 3833238405Sjkim error = urtw_led_on(sc, URTW_LED_GPIO); 3834238405Sjkim else if (sc->sc_gpio_ledstate == URTW_LED_OFF && 3835238405Sjkim sc->sc_gpio_ledon == 1) 3836238405Sjkim error = urtw_led_off(sc, URTW_LED_GPIO); 3837238405Sjkim 3838238405Sjkim sc->sc_gpio_blinktime = 0; 3839238405Sjkim sc->sc_gpio_ledinprogress = 0; 3840238405Sjkim return (0); 3841238405Sjkim } 3842238405Sjkim 3843238405Sjkim sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ? 3844238405Sjkim URTW_LED_ON : URTW_LED_OFF; 3845238405Sjkim 3846238405Sjkim switch (sc->sc_gpio_ledstate) { 3847238405Sjkim case URTW_LED_BLINK_NORMAL: 3848238405Sjkim usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc); 3849238405Sjkim break; 3850238405Sjkim default: 3851238405Sjkim DPRINTF(sc, URTW_DEBUG_STATE, 3852238405Sjkim "unknown LED status 0x%x", 3853238405Sjkim sc->sc_gpio_ledstate); 3854238405Sjkim return (USB_ERR_INVAL); 3855238405Sjkim } 3856238405Sjkim return (0); 3857238405Sjkim} 3858238405Sjkim 3859238405Sjkimstatic usb_error_t 3860238405Sjkimurtw_rx_enable(struct urtw_softc *sc) 3861238405Sjkim{ 3862238405Sjkim uint8_t data; 3863238405Sjkim usb_error_t error; 3864238405Sjkim 3865238405Sjkim usbd_transfer_start((sc->sc_flags & URTW_RTL8187B) ? 3866238405Sjkim sc->sc_xfer[URTW_8187B_BULK_RX] : sc->sc_xfer[URTW_8187L_BULK_RX]); 3867238405Sjkim 3868238405Sjkim error = urtw_rx_setconf(sc); 3869238405Sjkim if (error != 0) 3870238405Sjkim goto fail; 3871238405Sjkim 3872238405Sjkim if ((sc->sc_flags & URTW_RTL8187B) == 0) { 3873238405Sjkim urtw_read8_m(sc, URTW_CMD, &data); 3874238405Sjkim urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE); 3875238405Sjkim } 3876238405Sjkimfail: 3877238405Sjkim return (error); 3878238405Sjkim} 3879238405Sjkim 3880238405Sjkimstatic usb_error_t 3881238405Sjkimurtw_tx_enable(struct urtw_softc *sc) 3882238405Sjkim{ 3883238405Sjkim uint8_t data8; 3884238405Sjkim uint32_t data; 3885238405Sjkim usb_error_t error; 3886238405Sjkim 3887238405Sjkim if (sc->sc_flags & URTW_RTL8187B) { 3888238405Sjkim urtw_read32_m(sc, URTW_TX_CONF, &data); 3889238405Sjkim data &= ~URTW_TX_LOOPBACK_MASK; 3890238405Sjkim data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); 3891238405Sjkim data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); 3892238405Sjkim data &= ~URTW_TX_SWPLCPLEN; 3893238405Sjkim data |= URTW_TX_HW_SEQNUM | URTW_TX_DISREQQSIZE | 3894238405Sjkim (7 << 8) | /* short retry limit */ 3895238405Sjkim (7 << 0) | /* long retry limit */ 3896238405Sjkim (7 << 21); /* MAX TX DMA */ 3897238405Sjkim urtw_write32_m(sc, URTW_TX_CONF, data); 3898238405Sjkim 3899238405Sjkim urtw_read8_m(sc, URTW_MSR, &data8); 3900238405Sjkim data8 |= URTW_MSR_LINK_ENEDCA; 3901238405Sjkim urtw_write8_m(sc, URTW_MSR, data8); 3902238405Sjkim return (error); 3903238405Sjkim } 3904238405Sjkim 3905238405Sjkim urtw_read8_m(sc, URTW_CW_CONF, &data8); 3906238405Sjkim data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY); 3907238405Sjkim urtw_write8_m(sc, URTW_CW_CONF, data8); 3908238405Sjkim 3909238405Sjkim urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); 3910238405Sjkim data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; 3911238405Sjkim data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; 3912238405Sjkim data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; 3913238405Sjkim urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); 3914238405Sjkim 3915238405Sjkim urtw_read32_m(sc, URTW_TX_CONF, &data); 3916238405Sjkim data &= ~URTW_TX_LOOPBACK_MASK; 3917238405Sjkim data |= URTW_TX_LOOPBACK_NONE; 3918238405Sjkim data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); 3919238405Sjkim data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; 3920238405Sjkim data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; 3921238405Sjkim data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); 3922238405Sjkim data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW; 3923238405Sjkim data &= ~URTW_TX_SWPLCPLEN; 3924238405Sjkim data |= URTW_TX_NOICV; 3925238405Sjkim urtw_write32_m(sc, URTW_TX_CONF, data); 3926238405Sjkim 3927238405Sjkim urtw_read8_m(sc, URTW_CMD, &data8); 3928238405Sjkim urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE); 3929238405Sjkimfail: 3930238405Sjkim return (error); 3931238405Sjkim} 3932238405Sjkim 3933238405Sjkimstatic usb_error_t 3934238405Sjkimurtw_rx_setconf(struct urtw_softc *sc) 3935238405Sjkim{ 3936238405Sjkim struct ifnet *ifp = sc->sc_ifp; 3937238405Sjkim struct ieee80211com *ic = ifp->if_l2com; 3938238405Sjkim uint32_t data; 3939238405Sjkim usb_error_t error; 3940238405Sjkim 3941238405Sjkim urtw_read32_m(sc, URTW_RX, &data); 3942238405Sjkim data = data &~ URTW_RX_FILTER_MASK; 3943238405Sjkim if (sc->sc_flags & URTW_RTL8187B) { 3944238405Sjkim data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA | 3945238405Sjkim URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST | 3946238405Sjkim URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID | 3947238405Sjkim URTW_RX_FIFO_THRESHOLD_NONE | 3948238405Sjkim URTW_MAX_RX_DMA_2048 | 3949238405Sjkim URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT; 3950238405Sjkim } else { 3951238405Sjkim data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA; 3952238405Sjkim data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST; 3953238405Sjkim 3954238405Sjkim if (ic->ic_opmode == IEEE80211_M_MONITOR) { 3955238405Sjkim data = data | URTW_RX_FILTER_ICVERR; 3956238405Sjkim data = data | URTW_RX_FILTER_PWR; 3957238405Sjkim } 3958238405Sjkim if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR) 3959238405Sjkim data = data | URTW_RX_FILTER_CRCERR; 3960238405Sjkim 3961238405Sjkim if (ic->ic_opmode == IEEE80211_M_MONITOR || 3962238405Sjkim (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { 3963238405Sjkim data = data | URTW_RX_FILTER_ALLMAC; 3964238405Sjkim } else { 3965238405Sjkim data = data | URTW_RX_FILTER_NICMAC; 3966238405Sjkim data = data | URTW_RX_CHECK_BSSID; 3967238405Sjkim } 3968238405Sjkim 3969238405Sjkim data = data &~ URTW_RX_FIFO_THRESHOLD_MASK; 3970238405Sjkim data = data | URTW_RX_FIFO_THRESHOLD_NONE | 3971238405Sjkim URTW_RX_AUTORESETPHY; 3972238405Sjkim data = data &~ URTW_MAX_RX_DMA_MASK; 3973238405Sjkim data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT; 3974238405Sjkim } 3975238405Sjkim 3976238405Sjkim urtw_write32_m(sc, URTW_RX, data); 3977238405Sjkimfail: 3978238405Sjkim return (error); 3979238405Sjkim} 3980238405Sjkim 3981238405Sjkimstatic struct mbuf * 3982238405Sjkimurtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, 3983238405Sjkim int8_t *nf_p) 3984238405Sjkim{ 3985238405Sjkim int actlen, flen, rssi; 3986238405Sjkim struct ieee80211_frame *wh; 3987238405Sjkim struct mbuf *m, *mnew; 3988238405Sjkim struct urtw_softc *sc = data->sc; 3989238405Sjkim struct ifnet *ifp = sc->sc_ifp; 3990238405Sjkim struct ieee80211com *ic = ifp->if_l2com; 3991238405Sjkim uint8_t noise = 0, rate; 3992238405Sjkim 3993238405Sjkim usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 3994238405Sjkim 3995238405Sjkim if (actlen < (int)URTW_MIN_RXBUFSZ) { 3996238405Sjkim ifp->if_ierrors++; 3997238405Sjkim return (NULL); 3998238405Sjkim } 3999238405Sjkim 4000238405Sjkim if (sc->sc_flags & URTW_RTL8187B) { 4001238405Sjkim struct urtw_8187b_rxhdr *rx; 4002238405Sjkim 4003238405Sjkim rx = (struct urtw_8187b_rxhdr *)(data->buf + 4004238405Sjkim (actlen - (sizeof(struct urtw_8187b_rxhdr)))); 4005238405Sjkim flen = le32toh(rx->flag) & 0xfff; 4006238405Sjkim if (flen > actlen) { 4007238405Sjkim ifp->if_ierrors++; 4008238405Sjkim return (NULL); 4009238405Sjkim } 4010238405Sjkim rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; 4011238405Sjkim /* XXX correct? */ 4012238405Sjkim rssi = rx->rssi & URTW_RX_RSSI_MASK; 4013238405Sjkim noise = rx->noise; 4014238405Sjkim } else { 4015238405Sjkim struct urtw_8187l_rxhdr *rx; 4016238405Sjkim 4017238405Sjkim rx = (struct urtw_8187l_rxhdr *)(data->buf + 4018238405Sjkim (actlen - (sizeof(struct urtw_8187l_rxhdr)))); 4019238405Sjkim flen = le32toh(rx->flag) & 0xfff; 4020238405Sjkim if (flen > actlen) { 4021238405Sjkim ifp->if_ierrors++; 4022238405Sjkim return (NULL); 4023238405Sjkim } 4024238405Sjkim 4025238405Sjkim rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; 4026238405Sjkim /* XXX correct? */ 4027238405Sjkim rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK; 4028238405Sjkim noise = rx->noise; 4029238405Sjkim } 4030238405Sjkim 4031238405Sjkim mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 4032238405Sjkim if (mnew == NULL) { 4033238405Sjkim ifp->if_ierrors++; 4034238405Sjkim return (NULL); 4035238405Sjkim } 4036238405Sjkim 4037238405Sjkim m = data->m; 4038238405Sjkim data->m = mnew; 4039238405Sjkim data->buf = mtod(mnew, uint8_t *); 4040238405Sjkim 4041238405Sjkim /* finalize mbuf */ 4042238405Sjkim m->m_pkthdr.rcvif = ifp; 4043238405Sjkim m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN; 4044238405Sjkim 4045238405Sjkim if (ieee80211_radiotap_active(ic)) { 4046238405Sjkim struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap; 4047238405Sjkim 4048238405Sjkim /* XXX Are variables correct? */ 4049238405Sjkim tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); 4050238405Sjkim tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); 4051238405Sjkim tap->wr_dbm_antsignal = (int8_t)rssi; 4052238405Sjkim } 4053238405Sjkim 4054238405Sjkim wh = mtod(m, struct ieee80211_frame *); 4055238405Sjkim if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) 4056238405Sjkim sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; 4057238405Sjkim 4058238405Sjkim *rssi_p = rssi; 4059238405Sjkim *nf_p = noise; /* XXX correct? */ 4060238405Sjkim 4061238405Sjkim return (m); 4062238405Sjkim} 4063238405Sjkim 4064238405Sjkimstatic void 4065238405Sjkimurtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) 4066238405Sjkim{ 4067238405Sjkim struct urtw_softc *sc = usbd_xfer_softc(xfer); 4068238405Sjkim struct ifnet *ifp = sc->sc_ifp; 4069238405Sjkim struct ieee80211com *ic = ifp->if_l2com; 4070238405Sjkim struct ieee80211_frame *wh; 4071238405Sjkim struct ieee80211_node *ni; 4072238405Sjkim struct mbuf *m = NULL; 4073238405Sjkim struct urtw_data *data; 4074238405Sjkim int8_t nf = -95; 4075238405Sjkim int rssi = 1; 4076238405Sjkim 4077238405Sjkim URTW_ASSERT_LOCKED(sc); 4078238405Sjkim 4079238405Sjkim switch (USB_GET_STATE(xfer)) { 4080238405Sjkim case USB_ST_TRANSFERRED: 4081238405Sjkim data = STAILQ_FIRST(&sc->sc_rx_active); 4082238405Sjkim if (data == NULL) 4083238405Sjkim goto setup; 4084238405Sjkim STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); 4085238405Sjkim m = urtw_rxeof(xfer, data, &rssi, &nf); 4086238405Sjkim STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); 4087238405Sjkim /* FALLTHROUGH */ 4088238405Sjkim case USB_ST_SETUP: 4089238405Sjkimsetup: 4090238405Sjkim data = STAILQ_FIRST(&sc->sc_rx_inactive); 4091238405Sjkim if (data == NULL) { 4092238405Sjkim KASSERT(m == NULL, ("mbuf isn't NULL")); 4093238405Sjkim return; 4094238405Sjkim } 4095238405Sjkim STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next); 4096238405Sjkim STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next); 4097238405Sjkim usbd_xfer_set_frame_data(xfer, 0, data->buf, 4098238405Sjkim usbd_xfer_max_len(xfer)); 4099238405Sjkim usbd_transfer_submit(xfer); 4100238405Sjkim 4101238405Sjkim /* 4102238405Sjkim * To avoid LOR we should unlock our private mutex here to call 4103238405Sjkim * ieee80211_input() because here is at the end of a USB 4104238405Sjkim * callback and safe to unlock. 4105238405Sjkim */ 4106238405Sjkim URTW_UNLOCK(sc); 4107238405Sjkim if (m != NULL) { 4108238405Sjkim wh = mtod(m, struct ieee80211_frame *); 4109238405Sjkim ni = ieee80211_find_rxnode(ic, 4110238405Sjkim (struct ieee80211_frame_min *)wh); 4111238405Sjkim if (ni != NULL) { 4112238405Sjkim (void) ieee80211_input(ni, m, rssi, nf); 4113238405Sjkim /* node is no longer needed */ 4114238405Sjkim ieee80211_free_node(ni); 4115238405Sjkim } else 4116238405Sjkim (void) ieee80211_input_all(ic, m, rssi, nf); 4117238405Sjkim m = NULL; 4118238405Sjkim } 4119238405Sjkim URTW_LOCK(sc); 4120238405Sjkim break; 4121238405Sjkim default: 4122238405Sjkim /* needs it to the inactive queue due to a error. */ 4123238405Sjkim data = STAILQ_FIRST(&sc->sc_rx_active); 4124238405Sjkim if (data != NULL) { 4125238405Sjkim STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); 4126238405Sjkim STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); 4127238405Sjkim } 4128238405Sjkim if (error != USB_ERR_CANCELLED) { 4129238405Sjkim usbd_xfer_set_stall(xfer); 4130238405Sjkim ifp->if_ierrors++; 4131238405Sjkim goto setup; 4132238405Sjkim } 4133238405Sjkim break; 4134238405Sjkim } 4135238405Sjkim} 4136238405Sjkim 4137238405Sjkim#define URTW_STATUS_TYPE_TXCLOSE 1 4138238405Sjkim#define URTW_STATUS_TYPE_BEACON_INTR 0 4139238405Sjkim 4140238405Sjkimstatic void 4141238405Sjkimurtw_txstatus_eof(struct usb_xfer *xfer) 4142238405Sjkim{ 4143238405Sjkim struct urtw_softc *sc = usbd_xfer_softc(xfer); 4144238405Sjkim struct ifnet *ifp = sc->sc_ifp; 4145238405Sjkim int actlen, type, pktretry, seq; 4146238405Sjkim uint64_t val; 4147238405Sjkim 4148238405Sjkim usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 4149238405Sjkim 4150238405Sjkim if (actlen != sizeof(uint64_t)) 4151238405Sjkim return; 4152238405Sjkim 4153238405Sjkim val = le64toh(sc->sc_txstatus); 4154238405Sjkim type = (val >> 30) & 0x3; 4155238405Sjkim if (type == URTW_STATUS_TYPE_TXCLOSE) { 4156238405Sjkim pktretry = val & 0xff; 4157238405Sjkim seq = (val >> 16) & 0xff; 4158238405Sjkim if (pktretry == URTW_TX_MAXRETRY) 4159238405Sjkim ifp->if_oerrors++; 4160238405Sjkim DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n", 4161238405Sjkim pktretry, seq); 4162238405Sjkim } 4163238405Sjkim} 4164238405Sjkim 4165238405Sjkimstatic void 4166238405Sjkimurtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error) 4167238405Sjkim{ 4168238405Sjkim struct urtw_softc *sc = usbd_xfer_softc(xfer); 4169238405Sjkim struct ifnet *ifp = sc->sc_ifp; 4170238405Sjkim void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0); 4171238405Sjkim 4172238405Sjkim URTW_ASSERT_LOCKED(sc); 4173238405Sjkim 4174238405Sjkim switch (USB_GET_STATE(xfer)) { 4175238405Sjkim case USB_ST_TRANSFERRED: 4176238405Sjkim urtw_txstatus_eof(xfer); 4177238405Sjkim /* FALLTHROUGH */ 4178238405Sjkim case USB_ST_SETUP: 4179238405Sjkimsetup: 4180238405Sjkim memcpy(dma_buf, &sc->sc_txstatus, sizeof(uint64_t)); 4181238405Sjkim usbd_xfer_set_frame_len(xfer, 0, sizeof(uint64_t)); 4182238405Sjkim usbd_transfer_submit(xfer); 4183238405Sjkim break; 4184238405Sjkim default: 4185238405Sjkim if (error != USB_ERR_CANCELLED) { 4186238405Sjkim usbd_xfer_set_stall(xfer); 4187238405Sjkim ifp->if_ierrors++; 4188238405Sjkim goto setup; 4189238405Sjkim } 4190238405Sjkim break; 4191238405Sjkim } 4192238405Sjkim} 4193238405Sjkim 4194238405Sjkimstatic void 4195238405Sjkimurtw_txeof(struct usb_xfer *xfer, struct urtw_data *data) 4196238405Sjkim{ 4197238405Sjkim struct urtw_softc *sc = usbd_xfer_softc(xfer); 4198238405Sjkim struct ifnet *ifp = sc->sc_ifp; 4199238405Sjkim struct mbuf *m; 4200238405Sjkim 4201238405Sjkim URTW_ASSERT_LOCKED(sc); 4202238405Sjkim 4203238405Sjkim /* 4204238405Sjkim * Do any tx complete callback. Note this must be done before releasing 4205238405Sjkim * the node reference. 4206238405Sjkim */ 4207238405Sjkim if (data->m) { 4208238405Sjkim m = data->m; 4209238405Sjkim if (m->m_flags & M_TXCB) { 4210238405Sjkim /* XXX status? */ 4211238405Sjkim ieee80211_process_callback(data->ni, m, 0); 4212238405Sjkim } 4213238405Sjkim m_freem(m); 4214238405Sjkim data->m = NULL; 4215238405Sjkim } 4216238405Sjkim if (data->ni) { 4217238405Sjkim ieee80211_free_node(data->ni); 4218238405Sjkim data->ni = NULL; 4219238405Sjkim } 4220238405Sjkim sc->sc_txtimer = 0; 4221238405Sjkim ifp->if_opackets++; 4222238405Sjkim ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 4223238405Sjkim} 4224238405Sjkim 4225238405Sjkimstatic void 4226238405Sjkimurtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) 4227238405Sjkim{ 4228238405Sjkim struct urtw_softc *sc = usbd_xfer_softc(xfer); 4229238405Sjkim struct ifnet *ifp = sc->sc_ifp; 4230238405Sjkim struct urtw_data *data; 4231238405Sjkim 4232238405Sjkim URTW_ASSERT_LOCKED(sc); 4233238405Sjkim 4234238405Sjkim switch (USB_GET_STATE(xfer)) { 4235238405Sjkim case USB_ST_TRANSFERRED: 4236238405Sjkim data = STAILQ_FIRST(&sc->sc_tx_active); 4237238405Sjkim if (data == NULL) 4238238405Sjkim goto setup; 4239238405Sjkim STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next); 4240238405Sjkim urtw_txeof(xfer, data); 4241238405Sjkim STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); 4242238405Sjkim /* FALLTHROUGH */ 4243238405Sjkim case USB_ST_SETUP: 4244238405Sjkimsetup: 4245238405Sjkim data = STAILQ_FIRST(&sc->sc_tx_pending); 4246238405Sjkim if (data == NULL) { 4247238405Sjkim DPRINTF(sc, URTW_DEBUG_XMIT, 4248238405Sjkim "%s: empty pending queue\n", __func__); 4249238405Sjkim return; 4250238405Sjkim } 4251238405Sjkim STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next); 4252238405Sjkim STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next); 4253238405Sjkim 4254238405Sjkim usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); 4255238405Sjkim usbd_transfer_submit(xfer); 4256238405Sjkim 4257238405Sjkim URTW_UNLOCK(sc); 4258238405Sjkim urtw_start(ifp); 4259238405Sjkim URTW_LOCK(sc); 4260238405Sjkim break; 4261238405Sjkim default: 4262238405Sjkim data = STAILQ_FIRST(&sc->sc_tx_active); 4263238405Sjkim if (data == NULL) 4264238405Sjkim goto setup; 4265238405Sjkim if (data->ni != NULL) { 4266238405Sjkim ieee80211_free_node(data->ni); 4267238405Sjkim data->ni = NULL; 4268238405Sjkim ifp->if_oerrors++; 4269238405Sjkim } 4270238405Sjkim if (error != USB_ERR_CANCELLED) { 4271238405Sjkim usbd_xfer_set_stall(xfer); 4272238405Sjkim goto setup; 4273238405Sjkim } 4274238405Sjkim break; 4275238405Sjkim } 4276238405Sjkim} 4277238405Sjkim 4278238405Sjkimstatic struct urtw_data * 4279238405Sjkim_urtw_getbuf(struct urtw_softc *sc) 4280238405Sjkim{ 4281238405Sjkim struct urtw_data *bf; 4282238405Sjkim 4283238405Sjkim bf = STAILQ_FIRST(&sc->sc_tx_inactive); 4284238405Sjkim if (bf != NULL) 4285238405Sjkim STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next); 4286238405Sjkim else 4287290207Sjkim bf = NULL; 4288238405Sjkim if (bf == NULL) 4289238405Sjkim DPRINTF(sc, URTW_DEBUG_XMIT, "%s: %s\n", __func__, 4290238405Sjkim "out of xmit buffers"); 4291238405Sjkim return (bf); 4292238405Sjkim} 4293238405Sjkim 4294238405Sjkimstatic struct urtw_data * 4295238405Sjkimurtw_getbuf(struct urtw_softc *sc) 4296238405Sjkim{ 4297238405Sjkim struct urtw_data *bf; 4298238405Sjkim 4299238405Sjkim URTW_ASSERT_LOCKED(sc); 4300238405Sjkim 4301238405Sjkim bf = _urtw_getbuf(sc); 4302238405Sjkim if (bf == NULL) { 4303238405Sjkim struct ifnet *ifp = sc->sc_ifp; 4304238405Sjkim 4305238405Sjkim DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__); 4306238405Sjkim ifp->if_drv_flags |= IFF_DRV_OACTIVE; 4307238405Sjkim } 4308238405Sjkim return (bf); 4309238405Sjkim} 4310238405Sjkim 4311238405Sjkimstatic int 4312238405Sjkimurtw_isbmode(uint16_t rate) 4313238405Sjkim{ 4314238405Sjkim 4315238405Sjkim return ((rate <= 22 && rate != 12 && rate != 18) || 4316238405Sjkim rate == 44) ? (1) : (0); 4317238405Sjkim} 4318238405Sjkim 4319290207Sjkimstatic uint16_t 4320290207Sjkimurtw_rate2dbps(uint16_t rate) 4321290207Sjkim{ 4322290207Sjkim 4323290207Sjkim switch(rate) { 4324290207Sjkim case 12: 4325290207Sjkim case 18: 4326290207Sjkim case 24: 4327290207Sjkim case 36: 4328290207Sjkim case 48: 4329290207Sjkim case 72: 4330290207Sjkim case 96: 4331290207Sjkim case 108: 4332290207Sjkim return (rate * 2); 4333290207Sjkim default: 4334290207Sjkim break; 4335290207Sjkim } 4336290207Sjkim return (24); 4337290207Sjkim} 4338290207Sjkim 4339290207Sjkimstatic int 4340290207Sjkimurtw_compute_txtime(uint16_t framelen, uint16_t rate, 4341290207Sjkim uint8_t ismgt, uint8_t isshort) 4342290207Sjkim{ 4343290207Sjkim uint16_t ceiling, frametime, n_dbps; 4344290207Sjkim 4345290207Sjkim if (urtw_isbmode(rate)) { 4346290207Sjkim if (ismgt || !isshort || rate == 2) 4347290207Sjkim frametime = (uint16_t)(144 + 48 + 4348290207Sjkim (framelen * 8 / (rate / 2))); 4349290207Sjkim else 4350290207Sjkim frametime = (uint16_t)(72 + 24 + 4351290207Sjkim (framelen * 8 / (rate / 2))); 4352290207Sjkim if ((framelen * 8 % (rate / 2)) != 0) 4353290207Sjkim frametime++; 4354290207Sjkim } else { 4355290207Sjkim n_dbps = urtw_rate2dbps(rate); 4356290207Sjkim ceiling = (16 + 8 * framelen + 6) / n_dbps 4357290207Sjkim + (((16 + 8 * framelen + 6) % n_dbps) ? 1 : 0); 4358290207Sjkim frametime = (uint16_t)(16 + 4 + 4 * ceiling + 6); 4359290207Sjkim } 4360290207Sjkim return (frametime); 4361290207Sjkim} 4362290207Sjkim 4363290207Sjkim/* 4364290207Sjkim * Callback from the 802.11 layer to update the 4365290207Sjkim * slot time based on the current setting. 4366290207Sjkim */ 4367290207Sjkimstatic void 4368290207Sjkimurtw_updateslot(struct ifnet *ifp) 4369290207Sjkim{ 4370290207Sjkim struct urtw_softc *sc = ifp->if_softc; 4371290207Sjkim struct ieee80211com *ic = ifp->if_l2com; 4372290207Sjkim 4373325337Sjkim ieee80211_runtask(ic, &sc->sc_updateslot_task); 4374290207Sjkim} 4375290207Sjkim 4376290207Sjkimstatic void 4377290207Sjkimurtw_updateslottask(void *arg, int pending) 4378290207Sjkim{ 4379290207Sjkim struct urtw_softc *sc = arg; 4380290207Sjkim struct ifnet *ifp = sc->sc_ifp; 4381290207Sjkim struct ieee80211com *ic = ifp->if_l2com; 4382290207Sjkim int error; 4383290207Sjkim 4384290207Sjkim if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 4385290207Sjkim return; 4386290207Sjkim 4387290207Sjkim URTW_LOCK(sc); 4388290207Sjkim if (sc->sc_flags & URTW_RTL8187B) { 4389290207Sjkim urtw_write8_m(sc, URTW_SIFS, 0x22); 4390290207Sjkim if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) 4391290207Sjkim urtw_write8_m(sc, URTW_SLOT, 0x9); 4392290207Sjkim else 4393290207Sjkim urtw_write8_m(sc, URTW_SLOT, 0x14); 4394290207Sjkim urtw_write8_m(sc, URTW_8187B_EIFS, 0x5b); 4395290207Sjkim urtw_write8_m(sc, URTW_CARRIER_SCOUNT, 0x5b); 4396290207Sjkim } else { 4397290207Sjkim urtw_write8_m(sc, URTW_SIFS, 0x22); 4398290207Sjkim if (sc->sc_state == IEEE80211_S_ASSOC && 4399290207Sjkim ic->ic_flags & IEEE80211_F_SHSLOT) 4400290207Sjkim urtw_write8_m(sc, URTW_SLOT, 0x9); 4401290207Sjkim else 4402290207Sjkim urtw_write8_m(sc, URTW_SLOT, 0x14); 4403290207Sjkim if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) { 4404290207Sjkim urtw_write8_m(sc, URTW_DIFS, 0x14); 4405290207Sjkim urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14); 4406290207Sjkim urtw_write8_m(sc, URTW_CW_VAL, 0x73); 4407290207Sjkim } else { 4408290207Sjkim urtw_write8_m(sc, URTW_DIFS, 0x24); 4409290207Sjkim urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24); 4410290207Sjkim urtw_write8_m(sc, URTW_CW_VAL, 0xa5); 4411290207Sjkim } 4412290207Sjkim } 4413290207Sjkimfail: 4414290207Sjkim URTW_UNLOCK(sc); 4415290207Sjkim} 4416290207Sjkim 4417290207Sjkimstatic void 4418290207Sjkimurtw_sysctl_node(struct urtw_softc *sc) 4419325337Sjkim{ 4420326663Sjkim#define URTW_SYSCTL_STAT_ADD32(c, h, n, p, d) \ 4421326663Sjkim SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) 4422325337Sjkim struct sysctl_ctx_list *ctx; 4423325337Sjkim struct sysctl_oid_list *child, *parent; 4424325337Sjkim struct sysctl_oid *tree; 4425325337Sjkim struct urtw_stats *stats = &sc->sc_stats; 4426325337Sjkim 4427325337Sjkim ctx = device_get_sysctl_ctx(sc->sc_dev); 4428325337Sjkim child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)); 4429325337Sjkim 4430325337Sjkim tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, 4431325337Sjkim NULL, "URTW statistics"); 4432325337Sjkim parent = SYSCTL_CHILDREN(tree); 4433325337Sjkim 4434340704Sjkim /* Tx statistics. */ 4435352193Sjkim tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD, 4436 NULL, "Tx MAC statistics"); 4437 child = SYSCTL_CHILDREN(tree); 4438 URTW_SYSCTL_STAT_ADD32(ctx, child, "1m", &stats->txrates[0], 4439 "1 Mbit/s"); 4440 URTW_SYSCTL_STAT_ADD32(ctx, child, "2m", &stats->txrates[1], 4441 "2 Mbit/s"); 4442 URTW_SYSCTL_STAT_ADD32(ctx, child, "5.5m", &stats->txrates[2], 4443 "5.5 Mbit/s"); 4444 URTW_SYSCTL_STAT_ADD32(ctx, child, "6m", &stats->txrates[4], 4445 "6 Mbit/s"); 4446 URTW_SYSCTL_STAT_ADD32(ctx, child, "9m", &stats->txrates[5], 4447 "9 Mbit/s"); 4448 URTW_SYSCTL_STAT_ADD32(ctx, child, "11m", &stats->txrates[3], 4449 "11 Mbit/s"); 4450 URTW_SYSCTL_STAT_ADD32(ctx, child, "12m", &stats->txrates[6], 4451 "12 Mbit/s"); 4452 URTW_SYSCTL_STAT_ADD32(ctx, child, "18m", &stats->txrates[7], 4453 "18 Mbit/s"); 4454 URTW_SYSCTL_STAT_ADD32(ctx, child, "24m", &stats->txrates[8], 4455 "24 Mbit/s"); 4456 URTW_SYSCTL_STAT_ADD32(ctx, child, "36m", &stats->txrates[9], 4457 "36 Mbit/s"); 4458 URTW_SYSCTL_STAT_ADD32(ctx, child, "48m", &stats->txrates[10], 4459 "48 Mbit/s"); 4460 URTW_SYSCTL_STAT_ADD32(ctx, child, "54m", &stats->txrates[11], 4461 "54 Mbit/s"); 4462#undef URTW_SYSCTL_STAT_ADD32 4463} 4464 4465static device_method_t urtw_methods[] = { 4466 DEVMETHOD(device_probe, urtw_match), 4467 DEVMETHOD(device_attach, urtw_attach), 4468 DEVMETHOD(device_detach, urtw_detach), 4469 DEVMETHOD_END 4470}; 4471static driver_t urtw_driver = { 4472 .name = "urtw", 4473 .methods = urtw_methods, 4474 .size = sizeof(struct urtw_softc) 4475}; 4476static devclass_t urtw_devclass; 4477 4478DRIVER_MODULE(urtw, uhub, urtw_driver, urtw_devclass, NULL, 0); 4479MODULE_DEPEND(urtw, wlan, 1, 1, 1); 4480MODULE_DEPEND(urtw, usb, 1, 1, 1); 4481MODULE_VERSION(urtw, 1); 4482