From: Sascha Wildner Date: Sat, 5 Jan 2019 13:25:45 +0000 (+0100) Subject: Clean up the USB driver directories, remove unbuilt source. X-Git-Tag: v5.7.0~634 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/5a31d9923078987ff4fc0dc060ab54ee2937fa53 Clean up the USB driver directories, remove unbuilt source. Remove old source that has not (yet) been ported. If any of these drivers would get ported in the future, it would be from current FreeBSD source anyway. Keeping the old source around just confuses when grepping in /usr/src. --- diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 46045a100d..9f101e6a8d 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -3444,6 +3444,7 @@ TO_REMOVE+=/usr/include/sys/clist.h TO_REMOVE+=/usr/share/man/man2/sigstack.2.gz TO_REMOVE+=/usr/include/sys/input.h TO_REMOVE+=/usr/include/sys/linux_types.h +TO_REMOVE+=/etc/devd/uath.conf .if !defined(WANT_INSTALLER) TO_REMOVE+=/usr/sbin/dfuibe_installer diff --git a/etc/devd.conf b/etc/devd.conf index b83ed2463d..a686aeaf66 100644 --- a/etc/devd.conf +++ b/etc/devd.conf @@ -23,8 +23,8 @@ options { ida|iir|ips|isp|mlx|mly|mpr|mps|mpt|ncr|sym|trm)\ [0-9]+"; set wifi-driver-regex - "(ath|bwi|bwn|ipw|iwi|iwn|malo|mwl|ral|rsu|rum|run|uath|upgt|\ - ural|urtw|urtwn|wi|wpi|wtap|zyd)[0-9]+"; + "(ath|bwi|bwn|ipw|iwi|iwn|malo|mwl|ral|rsu|rum|run|\ + urtw|urtwn|wi|wpi|wtap)[0-9]+"; }; # Note that the attach/detach with the highest value wins, so that one can diff --git a/etc/devd/Makefile b/etc/devd/Makefile index 3ce6aa53e9..38a51660a4 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -1,6 +1,6 @@ # $FreeBSD: head/etc/devd/Makefile 261894 2014-02-14 15:31:48Z avg $ -FILES= uath.conf usb.conf +FILES= usb.conf .if ${MACHINE_ARCH} == "x86_64" FILES+= asus.conf diff --git a/etc/devd/uath.conf b/etc/devd/uath.conf deleted file mode 100644 index b2a9afaf96..0000000000 --- a/etc/devd/uath.conf +++ /dev/null @@ -1,146 +0,0 @@ -# $FreeBSD: head/etc/devd/uath.conf 223566 2011-06-26 11:37:24Z gavin $ -# -# Atheros USB wireless network device specific devd events - -# Accton -# SMCWUSBT-G2 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x083a"; - match "product" "0x4507"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Atheros Communications -# AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x168c"; - match "product" "0x0002"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Atheros Communications -# AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x0cf3"; - match "product" "(0x0002|0x0004|0x0006)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Conceptronic -# AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x0d8e"; - match "product" "(0x7802|0x7812)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# D-Link -# DWL-AG132, DWL-G132 and DWL-AG122 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x2001"; - match "product" "(0x3a01|0x3a03|0x3a05)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# D-Link -# DWA-120 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x07d1"; - match "product" "0x3a0c"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Gigaset -# SMCWUSBT-G -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x1690"; - match "product" "(0x0711|0x0713)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Global Sun Technology -# AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x16ab"; - match "product" "(0x7802|0x7812)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# BayNETGEAR -# WG111U -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x0846"; - match "product" "0x4301"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Netgear -# WG111T and WPN111 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x1385"; - match "product" "(0x4251|0x5f01)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# U-MEDIA Communications -# TEW-444UB and AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x157e"; - match "product" "(0x3007|0x3206)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Wistron NeWeb -# AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x1435"; - match "product" "(0x0827|0x0829)"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; - -# Z-Com -# AR5523 -notify 100 { - match "system" "USB"; - match "subsystem" "DEVICE"; - match "type" "ATTACH"; - match "vendor" "0x0cde"; - match "product" "0x0013"; - action "/usr/sbin/uathload -d /dev/$cdev"; -}; diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index d6e41f3c63..e3d4afa70c 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -497,7 +497,6 @@ MLINKS+=ral.4 if_ral.4 MLINKS+=random.4 urandom.4 MLINKS+=re.4 if_re.4 MLINKS+=rl.4 if_rl.4 -#MLINKS+=rue.4 if_rue.4 MLINKS+=rum.4 if_rum.4 MLINKS+=run.4 if_run.4 MLINKS+=sbsh.4 if_sbsh.4 @@ -546,7 +545,6 @@ MLINKS+=tx.4 if_tx.4 MLINKS+=txp.4 if_txp.4 MLINKS+=udav.4 if_udav.4 MLINKS+=upmap.4 kpmap.4 -#MLINKS+=ural.4 if_ural.4 MLINKS+=urndis.4 if_urndis.4 MLINKS+=urtwn.4 if_urtwn.4 MLINKS+=vga_switcheroo.4 apple_gmux.4 diff --git a/share/man/man4/miibus.4 b/share/man/man4/miibus.4 index c7755902f3..6a59fdbf8b 100644 --- a/share/man/man4/miibus.4 +++ b/share/man/man4/miibus.4 @@ -93,8 +93,6 @@ AMD Am79C97x PCI 10/100 RealTek 8139C+/8169/8169S/8110S .It Xr rl 4 RealTek 8129/8139 -.\".It Xr rue 4 -.\"RealTek RTL8150 USB To Fast Ethernet .It Xr sf 4 Adaptec AIC-6915 .It Xr sis 4 @@ -155,7 +153,6 @@ but as a result are not well behaved newbus device drivers. .Xr pcn 4 , .Xr re 4 , .Xr rl 4 , -.\".Xr rue 4 , .Xr sf 4 , .Xr sis 4 , .Xr sk 4 , diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4 index 4c459bb997..3867ada253 100644 --- a/share/man/man4/usb.4 +++ b/share/man/man4/usb.4 @@ -112,8 +112,6 @@ USB Apple iPhone/iPad tethered Ethernet driver Kawasaki LSI KL5KUSB101B Ethernet driver .It Xr mos 4 Moschip MCS7730/MCS7830/MCS7832 USB Ethernet driver -.\".It Xr rue 4 -.\"RealTek RTL8150 Ethernet driver .It Xr udav 4 Davicom DM9601 USB Ethernet driver .El @@ -127,8 +125,6 @@ Ralink Technology RT2501USB/RT2601USB IEEE 802.11 driver Ralink Technology RT2700U/RT2800U/RT3000U IEEE 802.11 driver .\".It Xr ubt 4 .\"Bluetooth adapters -.\".It Xr ural 4 -.\"Ralink Technology RT2500USB IEEE 802.11 driver .It Xr urndis 4 RNDIS USB ethernet driver .It Xr urtwn 4 @@ -274,7 +270,6 @@ specifications can be found at: .Xr ndis 4 , .Xr ohci 4 , .Xr pci 4 , -.\".Xr rue 4 , .Xr rum 4 , .Xr run 4 , .Xr u3g 4 , diff --git a/share/man/man4/wlan.4 b/share/man/man4/wlan.4 index 37839be2f2..425af52f32 100644 --- a/share/man/man4/wlan.4 +++ b/share/man/man4/wlan.4 @@ -186,10 +186,6 @@ may not interoperate. .\".Xr rsu 4 , .Xr rum 4 , .Xr run 4 , -.\".Xr uath 4 , -.\".Xr upgt 4 , -.\".Xr ural 4 , -.\".Xr urtw 4 , .Xr urtwn 4 , .Xr wi 4 , .Xr wlan_acl 4 , @@ -198,7 +194,6 @@ may not interoperate. .Xr wlan_wep 4 , .Xr wlan_xauth 4 , .Xr wpi 4 -.\".Xr zyd 4 .Sh STANDARDS More information can be found in the IEEE 802.11 Standards. .Sh HISTORY diff --git a/share/man/man4/wlan_amrr.4 b/share/man/man4/wlan_amrr.4 index b568f560e3..f1973f7e0d 100644 --- a/share/man/man4/wlan_amrr.4 +++ b/share/man/man4/wlan_amrr.4 @@ -44,10 +44,8 @@ algorithm for use by 802.11 device drivers. .Xr iwn 4 , .Xr ral 4 , .Xr rum 4 , -.\".Xr ural 4 , .Xr wlan 4 , .Xr wpi 4 -.\".Xr zyd 4 .Sh STANDARDS More information can be found in the paper describing the .Em AMRR diff --git a/sys/boot/dloader/loader-bootp.conf b/sys/boot/dloader/loader-bootp.conf index 09839484c4..e1f1d6aeb4 100644 --- a/sys/boot/dloader/loader-bootp.conf +++ b/sys/boot/dloader/loader-bootp.conf @@ -273,9 +273,7 @@ if_aue_load="NO" # ADMtek USB ethernet if_axe_load="NO" # ASIX Electronics AX88172 USB ethernet if_cue_load="NO" # CATC USB ethernet if_kue_load="NO" # Kawasaki LSI USB ethernet -if_rue_load="NO" # RealTek RTL8150 USB fast ethernet if_rum_load="NO" # Ralink RT2501USB/RT2601USB 802.11 wireless NICs -if_ural_load="NO" # Ralink RT2500USB 802.11 wireless NICs snd_uaudio_load="NO" # USB audio diff --git a/sys/boot/dloader/loader.conf b/sys/boot/dloader/loader.conf index ec556b72e6..a2e58274bb 100644 --- a/sys/boot/dloader/loader.conf +++ b/sys/boot/dloader/loader.conf @@ -277,9 +277,7 @@ if_aue_load="NO" # ADMtek USB ethernet if_axe_load="NO" # ASIX Electronics AX88172 USB ethernet if_cue_load="NO" # CATC USB ethernet if_kue_load="NO" # Kawasaki LSI USB ethernet -if_rue_load="NO" # RealTek RTL8150 USB fast ethernet if_rum_load="NO" # Ralink RT2501USB/RT2601USB 802.11 wireless NICs -if_ural_load="NO" # Ralink RT2500USB 802.11 wireless NICs snd_uaudio_load="NO" # USB audio diff --git a/sys/bus/u4b/input/atp.c b/sys/bus/u4b/input/atp.c deleted file mode 100644 index de02b38151..0000000000 --- a/sys/bus/u4b/input/atp.c +++ /dev/null @@ -1,2233 +0,0 @@ -/*- - * Copyright (c) 2009 Rohit Grover - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "usbdevs.h" - -#define USB_DEBUG_VAR atp_debug -#include - -#include - -#define ATP_DRIVER_NAME "atp" - -/* - * Driver specific options: the following options may be set by - * `options' statements in the kernel configuration file. - */ - -/* The multiplier used to translate sensor reported positions to mickeys. */ -#ifndef ATP_SCALE_FACTOR -#define ATP_SCALE_FACTOR 48 -#endif - -/* - * This is the age (in microseconds) beyond which a touch is - * considered to be a slide; and therefore a tap event isn't registered. - */ -#ifndef ATP_TOUCH_TIMEOUT -#define ATP_TOUCH_TIMEOUT 125000 -#endif - -/* - * A double-tap followed by a single-finger slide is treated as a - * special gesture. The driver responds to this gesture by assuming a - * virtual button-press for the lifetime of the slide. The following - * threshold is the maximum time gap (in microseconds) between the two - * tap events preceding the slide for such a gesture. - */ -#ifndef ATP_DOUBLE_TAP_N_DRAG_THRESHOLD -#define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD 200000 -#endif - -/* - * The device provides us only with pressure readings from an array of - * X and Y sensors; for our algorithms, we need to interpret groups - * (typically pairs) of X and Y readings as being related to a single - * finger stroke. We can relate X and Y readings based on their times - * of incidence. The coincidence window should be at least 10000us - * since it is used against values from getmicrotime(), which has a - * precision of around 10ms. - */ -#ifndef ATP_COINCIDENCE_THRESHOLD -#define ATP_COINCIDENCE_THRESHOLD 40000 /* unit: microseconds */ -#if ATP_COINCIDENCE_THRESHOLD > 100000 -#error "ATP_COINCIDENCE_THRESHOLD too large" -#endif -#endif /* #ifndef ATP_COINCIDENCE_THRESHOLD */ - -/* - * The wait duration (in microseconds) after losing a touch contact - * before zombied strokes are reaped and turned into button events. - */ -#define ATP_ZOMBIE_STROKE_REAP_WINDOW 50000 -#if ATP_ZOMBIE_STROKE_REAP_WINDOW > 100000 -#error "ATP_ZOMBIE_STROKE_REAP_WINDOW too large" -#endif - -/* end of driver specific options */ - - -/* Tunables */ -static SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW, 0, "USB atp"); - -#ifdef USB_DEBUG -enum atp_log_level { - ATP_LLEVEL_DISABLED = 0, - ATP_LLEVEL_ERROR, - ATP_LLEVEL_DEBUG, /* for troubleshooting */ - ATP_LLEVEL_INFO, /* for diagnostics */ -}; -static int atp_debug = ATP_LLEVEL_ERROR; /* the default is to only log errors */ -SYSCTL_INT(_hw_usb_atp, OID_AUTO, debug, CTLFLAG_RW, - &atp_debug, ATP_LLEVEL_ERROR, "ATP debug level"); -TUNABLE_INT("hw.usb.atp.debug", &atp_debug); -#endif /* USB_DEBUG */ - -static u_int atp_touch_timeout = ATP_TOUCH_TIMEOUT; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, touch_timeout, CTLFLAG_RW, - &atp_touch_timeout, 125000, "age threshold (in micros) for a touch"); -TUNABLE_INT("hw.usb.atp.touch_timeout", &atp_touch_timeout); - -static u_int atp_double_tap_threshold = ATP_DOUBLE_TAP_N_DRAG_THRESHOLD; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, double_tap_threshold, CTLFLAG_RW, - &atp_double_tap_threshold, ATP_DOUBLE_TAP_N_DRAG_THRESHOLD, - "maximum time (in micros) between a double-tap"); -TUNABLE_INT("hw.usb.atp.double_tap_threshold", &atp_double_tap_threshold); - -static u_int atp_mickeys_scale_factor = ATP_SCALE_FACTOR; -static int atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS); -SYSCTL_PROC(_hw_usb_atp, OID_AUTO, scale_factor, CTLTYPE_UINT | CTLFLAG_RW, - &atp_mickeys_scale_factor, sizeof(atp_mickeys_scale_factor), - atp_sysctl_scale_factor_handler, "IU", "movement scale factor"); -TUNABLE_INT("hw.usb.atp.scale_factor", &atp_mickeys_scale_factor); - -static u_int atp_small_movement_threshold = ATP_SCALE_FACTOR >> 3; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, small_movement, CTLFLAG_RW, - &atp_small_movement_threshold, ATP_SCALE_FACTOR >> 3, - "the small movement black-hole for filtering noise"); -TUNABLE_INT("hw.usb.atp.small_movement", &atp_small_movement_threshold); - -/* - * The movement threshold for a stroke; this is the maximum difference - * in position which will be resolved as a continuation of a stroke - * component. - */ -static u_int atp_max_delta_mickeys = ((3 * ATP_SCALE_FACTOR) >> 1); -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, max_delta_mickeys, CTLFLAG_RW, - &atp_max_delta_mickeys, ((3 * ATP_SCALE_FACTOR) >> 1), - "max. mickeys-delta which will match against an existing stroke"); -/* - * Strokes which accumulate at least this amount of absolute movement - * from the aggregate of their components are considered as - * slides. Unit: mickeys. - */ -static u_int atp_slide_min_movement = (ATP_SCALE_FACTOR >> 3); -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, slide_min_movement, CTLFLAG_RW, - &atp_slide_min_movement, (ATP_SCALE_FACTOR >> 3), - "strokes with at least this amt. of movement are considered slides"); -TUNABLE_INT("hw.usb.atp.slide_min_movement", &atp_slide_min_movement); - -/* - * The minimum age of a stroke for it to be considered mature; this - * helps filter movements (noise) from immature strokes. Units: interrupts. - */ -static u_int atp_stroke_maturity_threshold = 2; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, stroke_maturity_threshold, CTLFLAG_RW, - &atp_stroke_maturity_threshold, 2, - "the minimum age of a stroke for it to be considered mature"); -TUNABLE_INT("hw.usb.atp.stroke_maturity_threshold", - &atp_stroke_maturity_threshold); - -/* Accept pressure readings from sensors only if above this value. */ -static u_int atp_sensor_noise_threshold = 2; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, sensor_noise_threshold, CTLFLAG_RW, - &atp_sensor_noise_threshold, 2, - "accept pressure readings from sensors only if above this value"); - -/* Ignore pressure spans with cumulative press. below this value. */ -static u_int atp_pspan_min_cum_pressure = 10; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, pspan_min_cum_pressure, CTLFLAG_RW, - &atp_pspan_min_cum_pressure, 10, - "ignore pressure spans with cumulative press. below this value"); - -/* Maximum allowed width for pressure-spans.*/ -static u_int atp_pspan_max_width = 4; -SYSCTL_UINT(_hw_usb_atp, OID_AUTO, pspan_max_width, CTLFLAG_RW, - &atp_pspan_max_width, 4, - "maximum allowed width (in sensors) for pressure-spans"); - -/* We support three payload protocols */ -typedef enum { - ATP_PROT_GEYSER1, - ATP_PROT_GEYSER2, - ATP_PROT_GEYSER3, -} atp_protocol; - -/* Define the various flavours of devices supported by this driver. */ -enum { - ATP_DEV_PARAMS_0, - ATP_DEV_PARAMS_PBOOK, - ATP_DEV_PARAMS_PBOOK_15A, - ATP_DEV_PARAMS_PBOOK_17, - ATP_N_DEV_PARAMS -}; -struct atp_dev_params { - u_int data_len; /* for sensor data */ - u_int n_xsensors; - u_int n_ysensors; - atp_protocol prot; -} atp_dev_params[ATP_N_DEV_PARAMS] = { - [ATP_DEV_PARAMS_0] = { - .data_len = 64, - .n_xsensors = 20, - .n_ysensors = 10, - .prot = ATP_PROT_GEYSER3 - }, - [ATP_DEV_PARAMS_PBOOK] = { - .data_len = 81, - .n_xsensors = 16, - .n_ysensors = 16, - .prot = ATP_PROT_GEYSER1 - }, - [ATP_DEV_PARAMS_PBOOK_15A] = { - .data_len = 64, - .n_xsensors = 15, - .n_ysensors = 9, - .prot = ATP_PROT_GEYSER2 - }, - [ATP_DEV_PARAMS_PBOOK_17] = { - .data_len = 81, - .n_xsensors = 26, - .n_ysensors = 16, - .prot = ATP_PROT_GEYSER1 - }, -}; - -static const STRUCT_USB_HOST_ID atp_devs[] = { - /* Core Duo MacBook & MacBook Pro */ - { USB_VPI(USB_VENDOR_APPLE, 0x0217, ATP_DEV_PARAMS_0) }, - { USB_VPI(USB_VENDOR_APPLE, 0x0218, ATP_DEV_PARAMS_0) }, - { USB_VPI(USB_VENDOR_APPLE, 0x0219, ATP_DEV_PARAMS_0) }, - - /* Core2 Duo MacBook & MacBook Pro */ - { USB_VPI(USB_VENDOR_APPLE, 0x021a, ATP_DEV_PARAMS_0) }, - { USB_VPI(USB_VENDOR_APPLE, 0x021b, ATP_DEV_PARAMS_0) }, - { USB_VPI(USB_VENDOR_APPLE, 0x021c, ATP_DEV_PARAMS_0) }, - - /* Core2 Duo MacBook3,1 */ - { USB_VPI(USB_VENDOR_APPLE, 0x0229, ATP_DEV_PARAMS_0) }, - { USB_VPI(USB_VENDOR_APPLE, 0x022a, ATP_DEV_PARAMS_0) }, - { USB_VPI(USB_VENDOR_APPLE, 0x022b, ATP_DEV_PARAMS_0) }, - - /* 12 inch PowerBook and iBook */ - { USB_VPI(USB_VENDOR_APPLE, 0x030a, ATP_DEV_PARAMS_PBOOK) }, - { USB_VPI(USB_VENDOR_APPLE, 0x030b, ATP_DEV_PARAMS_PBOOK) }, - - /* 15 inch PowerBook */ - { USB_VPI(USB_VENDOR_APPLE, 0x020e, ATP_DEV_PARAMS_PBOOK) }, - { USB_VPI(USB_VENDOR_APPLE, 0x020f, ATP_DEV_PARAMS_PBOOK) }, - { USB_VPI(USB_VENDOR_APPLE, 0x0215, ATP_DEV_PARAMS_PBOOK_15A) }, - - /* 17 inch PowerBook */ - { USB_VPI(USB_VENDOR_APPLE, 0x020d, ATP_DEV_PARAMS_PBOOK_17) }, - -}; - -/* - * The following structure captures the state of a pressure span along - * an axis. Each contact with the touchpad results in separate - * pressure spans along the two axes. - */ -typedef struct atp_pspan { - u_int width; /* in units of sensors */ - u_int cum; /* cumulative compression (from all sensors) */ - u_int cog; /* center of gravity */ - u_int loc; /* location (scaled using the mickeys factor) */ - boolean_t matched; /* to track pspans as they match against strokes. */ -} atp_pspan; - -typedef enum atp_stroke_type { - ATP_STROKE_TOUCH, - ATP_STROKE_SLIDE, -} atp_stroke_type; - -#define ATP_MAX_PSPANS_PER_AXIS 3 - -typedef struct atp_stroke_component { - /* Fields encapsulating the pressure-span. */ - u_int loc; /* location (scaled) */ - u_int cum_pressure; /* cumulative compression */ - u_int max_cum_pressure; /* max cumulative compression */ - boolean_t matched; /*to track components as they match against pspans.*/ - - /* Fields containing information about movement. */ - int delta_mickeys; /* change in location (un-smoothened movement)*/ - int pending; /* cum. of pending short movements */ - int movement; /* current smoothened movement */ -} atp_stroke_component; - -typedef enum atp_axis { - X = 0, - Y = 1 -} atp_axis; - -#define ATP_MAX_STROKES (2 * ATP_MAX_PSPANS_PER_AXIS) - -/* - * The following structure captures a finger contact with the - * touchpad. A stroke comprises two p-span components and some state. - */ -typedef struct atp_stroke { - atp_stroke_type type; - struct timeval ctime; /* create time; for coincident siblings. */ - u_int age; /* - * Unit: interrupts; we maintain - * this value in addition to - * 'ctime' in order to avoid the - * expensive call to microtime() - * at every interrupt. - */ - - atp_stroke_component components[2]; - u_int velocity_squared; /* - * Average magnitude (squared) - * of recent velocity. - */ - u_int cum_movement; /* cum. absolute movement so far */ - - uint32_t flags; /* the state of this stroke */ -#define ATSF_ZOMBIE 0x1 -} atp_stroke; - -#define ATP_FIFO_BUF_SIZE 8 /* bytes */ -#define ATP_FIFO_QUEUE_MAXLEN 50 /* units */ - -enum { - ATP_INTR_DT, - ATP_RESET, - ATP_N_TRANSFER, -}; - -struct atp_softc { - device_t sc_dev; - struct usb_device *sc_usb_device; -#define MODE_LENGTH 8 - char sc_mode_bytes[MODE_LENGTH]; /* device mode */ - struct mtx sc_mutex; /* for synchronization */ - struct usb_xfer *sc_xfer[ATP_N_TRANSFER]; - struct usb_fifo_sc sc_fifo; - - struct atp_dev_params *sc_params; - - mousehw_t sc_hw; - mousemode_t sc_mode; - u_int sc_pollrate; - mousestatus_t sc_status; - u_int sc_state; -#define ATP_ENABLED 0x01 -#define ATP_ZOMBIES_EXIST 0x02 -#define ATP_DOUBLE_TAP_DRAG 0x04 -#define ATP_VALID 0x08 - - u_int sc_left_margin; - u_int sc_right_margin; - - atp_stroke sc_strokes[ATP_MAX_STROKES]; - u_int sc_n_strokes; - - int8_t *sensor_data; /* from interrupt packet */ - int *base_x; /* base sensor readings */ - int *base_y; - int *cur_x; /* current sensor readings */ - int *cur_y; - int *pressure_x; /* computed pressures */ - int *pressure_y; - - u_int sc_idlecount; /* preceding idle interrupts */ -#define ATP_IDLENESS_THRESHOLD 10 - - struct timeval sc_reap_time; - struct timeval sc_reap_ctime; /*ctime of siblings to be reaped*/ -}; - -/* - * The last byte of the sensor data contains status bits; the - * following values define the meanings of these bits. - */ -enum atp_status_bits { - ATP_STATUS_BUTTON = (uint8_t)0x01, /* The button was pressed */ - ATP_STATUS_BASE_UPDATE = (uint8_t)0x04, /* Data from an untouched pad.*/ -}; - -typedef enum interface_mode { - RAW_SENSOR_MODE = (uint8_t)0x04, - HID_MODE = (uint8_t)0x08 -} interface_mode; - -/* - * function prototypes - */ -static usb_fifo_cmd_t atp_start_read; -static usb_fifo_cmd_t atp_stop_read; -static usb_fifo_open_t atp_open; -static usb_fifo_close_t atp_close; -static usb_fifo_ioctl_t atp_ioctl; - -static struct usb_fifo_methods atp_fifo_methods = { - .f_open = &atp_open, - .f_close = &atp_close, - .f_ioctl = &atp_ioctl, - .f_start_read = &atp_start_read, - .f_stop_read = &atp_stop_read, - .basename[0] = ATP_DRIVER_NAME, -}; - -/* device initialization and shutdown */ -static usb_error_t atp_req_get_report(struct usb_device *udev, void *data); -static int atp_set_device_mode(device_t dev, interface_mode mode); -static void atp_reset_callback(struct usb_xfer *, usb_error_t); -static int atp_enable(struct atp_softc *sc); -static void atp_disable(struct atp_softc *sc); -static int atp_softc_populate(struct atp_softc *); -static void atp_softc_unpopulate(struct atp_softc *); - -/* sensor interpretation */ -static __inline void atp_interpret_sensor_data(const int8_t *, u_int, atp_axis, - int *, atp_protocol); -static __inline void atp_get_pressures(int *, const int *, const int *, int); -static void atp_detect_pspans(int *, u_int, u_int, atp_pspan *, - u_int *); - -/* movement detection */ -static boolean_t atp_match_stroke_component(atp_stroke_component *, - const atp_pspan *, atp_stroke_type); -static void atp_match_strokes_against_pspans(struct atp_softc *, - atp_axis, atp_pspan *, u_int, u_int); -static boolean_t atp_update_strokes(struct atp_softc *, - atp_pspan *, u_int, atp_pspan *, u_int); -static __inline void atp_add_stroke(struct atp_softc *, const atp_pspan *, - const atp_pspan *); -static void atp_add_new_strokes(struct atp_softc *, atp_pspan *, - u_int, atp_pspan *, u_int); -static void atp_advance_stroke_state(struct atp_softc *, - atp_stroke *, boolean_t *); -static void atp_terminate_stroke(struct atp_softc *, u_int); -static __inline boolean_t atp_stroke_has_small_movement(const atp_stroke *); -static __inline void atp_update_pending_mickeys(atp_stroke_component *); -static void atp_compute_smoothening_scale_ratio(atp_stroke *, int *, - int *); -static boolean_t atp_compute_stroke_movement(atp_stroke *); - -/* tap detection */ -static __inline void atp_setup_reap_time(struct atp_softc *, struct timeval *); -static void atp_reap_zombies(struct atp_softc *, u_int *, u_int *); -static void atp_convert_to_slide(struct atp_softc *, atp_stroke *); - -/* updating fifo */ -static void atp_reset_buf(struct atp_softc *sc); -static void atp_add_to_queue(struct atp_softc *, int, int, uint32_t); - - -usb_error_t -atp_req_get_report(struct usb_device *udev, void *data) -{ - struct usb_device_request req; - - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UR_GET_REPORT; - USETW2(req.wValue, (uint8_t)0x03 /* type */, (uint8_t)0x00 /* id */); - USETW(req.wIndex, 0); - USETW(req.wLength, MODE_LENGTH); - - return (usbd_do_request(udev, NULL /* mutex */, &req, data)); -} - -static int -atp_set_device_mode(device_t dev, interface_mode mode) -{ - struct atp_softc *sc; - usb_device_request_t req; - usb_error_t err; - - if ((mode != RAW_SENSOR_MODE) && (mode != HID_MODE)) - return (ENXIO); - - sc = device_get_softc(dev); - - sc->sc_mode_bytes[0] = mode; - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, (uint8_t)0x03 /* type */, (uint8_t)0x00 /* id */); - USETW(req.wIndex, 0); - USETW(req.wLength, MODE_LENGTH); - err = usbd_do_request(sc->sc_usb_device, NULL, &req, sc->sc_mode_bytes); - if (err != USB_ERR_NORMAL_COMPLETION) - return (ENXIO); - - return (0); -} - -void -atp_reset_callback(struct usb_xfer *xfer, usb_error_t error) -{ - usb_device_request_t req; - struct usb_page_cache *pc; - struct atp_softc *sc = usbd_xfer_softc(xfer); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_SETUP: - sc->sc_mode_bytes[0] = RAW_SENSOR_MODE; - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UR_SET_REPORT; - USETW2(req.wValue, - (uint8_t)0x03 /* type */, (uint8_t)0x00 /* id */); - USETW(req.wIndex, 0); - USETW(req.wLength, MODE_LENGTH); - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &req, sizeof(req)); - pc = usbd_xfer_get_frame(xfer, 1); - usbd_copy_in(pc, 0, sc->sc_mode_bytes, MODE_LENGTH); - - usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); - usbd_xfer_set_frame_len(xfer, 1, MODE_LENGTH); - usbd_xfer_set_frames(xfer, 2); - usbd_transfer_submit(xfer); - break; - - case USB_ST_TRANSFERRED: - default: - break; - } -} - -static int -atp_enable(struct atp_softc *sc) -{ - /* Allocate the dynamic buffers */ - if (atp_softc_populate(sc) != 0) { - atp_softc_unpopulate(sc); - return (ENOMEM); - } - - /* reset status */ - memset(sc->sc_strokes, 0, sizeof(sc->sc_strokes)); - sc->sc_n_strokes = 0; - memset(&sc->sc_status, 0, sizeof(sc->sc_status)); - sc->sc_idlecount = 0; - sc->sc_state |= ATP_ENABLED; - - DPRINTFN(ATP_LLEVEL_INFO, "enabled atp\n"); - return (0); -} - -static void -atp_disable(struct atp_softc *sc) -{ - atp_softc_unpopulate(sc); - - sc->sc_state &= ~(ATP_ENABLED | ATP_VALID); - DPRINTFN(ATP_LLEVEL_INFO, "disabled atp\n"); -} - -/* Allocate dynamic memory for some fields in softc. */ -static int -atp_softc_populate(struct atp_softc *sc) -{ - const struct atp_dev_params *params = sc->sc_params; - - if (params == NULL) { - DPRINTF("params uninitialized!\n"); - return (ENXIO); - } - if (params->data_len) { - sc->sensor_data = malloc(params->data_len * sizeof(int8_t), - M_USB, M_WAITOK); - if (sc->sensor_data == NULL) { - DPRINTF("mem for sensor_data\n"); - return (ENXIO); - } - } - - if (params->n_xsensors != 0) { - sc->base_x = malloc(params->n_xsensors * sizeof(*(sc->base_x)), - M_USB, M_WAITOK); - if (sc->base_x == NULL) { - DPRINTF("mem for sc->base_x\n"); - return (ENXIO); - } - - sc->cur_x = malloc(params->n_xsensors * sizeof(*(sc->cur_x)), - M_USB, M_WAITOK); - if (sc->cur_x == NULL) { - DPRINTF("mem for sc->cur_x\n"); - return (ENXIO); - } - - sc->pressure_x = - malloc(params->n_xsensors * sizeof(*(sc->pressure_x)), - M_USB, M_WAITOK); - if (sc->pressure_x == NULL) { - DPRINTF("mem. for pressure_x\n"); - return (ENXIO); - } - } - - if (params->n_ysensors != 0) { - sc->base_y = malloc(params->n_ysensors * sizeof(*(sc->base_y)), - M_USB, M_WAITOK); - if (sc->base_y == NULL) { - DPRINTF("mem for base_y\n"); - return (ENXIO); - } - - sc->cur_y = malloc(params->n_ysensors * sizeof(*(sc->cur_y)), - M_USB, M_WAITOK); - if (sc->cur_y == NULL) { - DPRINTF("mem for cur_y\n"); - return (ENXIO); - } - - sc->pressure_y = - malloc(params->n_ysensors * sizeof(*(sc->pressure_y)), - M_USB, M_WAITOK); - if (sc->pressure_y == NULL) { - DPRINTF("mem. for pressure_y\n"); - return (ENXIO); - } - } - - return (0); -} - -/* Free dynamic memory allocated for some fields in softc. */ -static void -atp_softc_unpopulate(struct atp_softc *sc) -{ - const struct atp_dev_params *params = sc->sc_params; - - if (params == NULL) { - return; - } - if (params->n_xsensors != 0) { - if (sc->base_x != NULL) { - free(sc->base_x, M_USB); - sc->base_x = NULL; - } - - if (sc->cur_x != NULL) { - free(sc->cur_x, M_USB); - sc->cur_x = NULL; - } - - if (sc->pressure_x != NULL) { - free(sc->pressure_x, M_USB); - sc->pressure_x = NULL; - } - } - if (params->n_ysensors != 0) { - if (sc->base_y != NULL) { - free(sc->base_y, M_USB); - sc->base_y = NULL; - } - - if (sc->cur_y != NULL) { - free(sc->cur_y, M_USB); - sc->cur_y = NULL; - } - - if (sc->pressure_y != NULL) { - free(sc->pressure_y, M_USB); - sc->pressure_y = NULL; - } - } - if (sc->sensor_data != NULL) { - free(sc->sensor_data, M_USB); - sc->sensor_data = NULL; - } -} - -/* - * Interpret the data from the X and Y pressure sensors. This function - * is called separately for the X and Y sensor arrays. The data in the - * USB packet is laid out in the following manner: - * - * sensor_data: - * --,--,Y1,Y2,--,Y3,Y4,--,Y5,...,Y10, ... X1,X2,--,X3,X4 - * indices: 0 1 2 3 4 5 6 7 8 ... 15 ... 20 21 22 23 24 - * - * '--' (in the above) indicates that the value is unimportant. - * - * Information about the above layout was obtained from the - * implementation of the AppleTouch driver in Linux. - * - * parameters: - * sensor_data - * raw sensor data from the USB packet. - * num - * The number of elements in the array 'arr'. - * axis - * Axis of data to fetch - * arr - * The array to be initialized with the readings. - * prot - * The protocol to use to interpret the data - */ -static __inline void -atp_interpret_sensor_data(const int8_t *sensor_data, u_int num, atp_axis axis, - int *arr, atp_protocol prot) -{ - u_int i; - u_int di; /* index into sensor data */ - - switch (prot) { - case ATP_PROT_GEYSER1: - /* - * For Geyser 1, the sensors are laid out in pairs - * every 5 bytes. - */ - for (i = 0, di = (axis == Y) ? 1 : 2; i < 8; di += 5, i++) { - arr[i] = sensor_data[di]; - arr[i+8] = sensor_data[di+2]; - if (axis == X && num > 16) - arr[i+16] = sensor_data[di+40]; - } - - break; - case ATP_PROT_GEYSER2: - case ATP_PROT_GEYSER3: - for (i = 0, di = (axis == Y) ? 2 : 20; i < num; /* empty */ ) { - arr[i++] = sensor_data[di++]; - arr[i++] = sensor_data[di++]; - di++; - } - break; - } -} - -static __inline void -atp_get_pressures(int *p, const int *cur, const int *base, int n) -{ - int i; - - for (i = 0; i < n; i++) { - p[i] = cur[i] - base[i]; - if (p[i] > 127) - p[i] -= 256; - if (p[i] < -127) - p[i] += 256; - if (p[i] < 0) - p[i] = 0; - - /* - * Shave off pressures below the noise-pressure - * threshold; this will reduce the contribution from - * lower pressure readings. - */ - if (p[i] <= atp_sensor_noise_threshold) - p[i] = 0; /* filter away noise */ - else - p[i] -= atp_sensor_noise_threshold; - } -} - -static void -atp_detect_pspans(int *p, u_int num_sensors, - u_int max_spans, /* max # of pspans permitted */ - atp_pspan *spans, /* finger spans */ - u_int *nspans_p) /* num spans detected */ -{ - u_int i; - int maxp; /* max pressure seen within a span */ - u_int num_spans = 0; - - enum atp_pspan_state { - ATP_PSPAN_INACTIVE, - ATP_PSPAN_INCREASING, - ATP_PSPAN_DECREASING, - } state; /* state of the pressure span */ - - /* - * The following is a simple state machine to track - * the phase of the pressure span. - */ - memset(spans, 0, max_spans * sizeof(atp_pspan)); - maxp = 0; - state = ATP_PSPAN_INACTIVE; - for (i = 0; i < num_sensors; i++) { - if (num_spans >= max_spans) - break; - - if (p[i] == 0) { - if (state == ATP_PSPAN_INACTIVE) { - /* - * There is no pressure information for this - * sensor, and we aren't tracking a finger. - */ - continue; - } else { - state = ATP_PSPAN_INACTIVE; - maxp = 0; - num_spans++; - } - } else { - switch (state) { - case ATP_PSPAN_INACTIVE: - state = ATP_PSPAN_INCREASING; - maxp = p[i]; - break; - - case ATP_PSPAN_INCREASING: - if (p[i] > maxp) - maxp = p[i]; - else if (p[i] <= (maxp >> 1)) - state = ATP_PSPAN_DECREASING; - break; - - case ATP_PSPAN_DECREASING: - if (p[i] > p[i - 1]) { - /* - * This is the beginning of - * another span; change state - * to give the appearance that - * we're starting from an - * inactive span, and then - * re-process this reading in - * the next iteration. - */ - num_spans++; - state = ATP_PSPAN_INACTIVE; - maxp = 0; - i--; - continue; - } - break; - } - - /* Update the finger span with this reading. */ - spans[num_spans].width++; - spans[num_spans].cum += p[i]; - spans[num_spans].cog += p[i] * (i + 1); - } - } - if (state != ATP_PSPAN_INACTIVE) - num_spans++; /* close the last finger span */ - - /* post-process the spans */ - for (i = 0; i < num_spans; i++) { - /* filter away unwanted pressure spans */ - if ((spans[i].cum < atp_pspan_min_cum_pressure) || - (spans[i].width > atp_pspan_max_width)) { - if ((i + 1) < num_spans) { - memcpy(&spans[i], &spans[i + 1], - (num_spans - i - 1) * sizeof(atp_pspan)); - i--; - } - num_spans--; - continue; - } - - /* compute this span's representative location */ - spans[i].loc = spans[i].cog * atp_mickeys_scale_factor / - spans[i].cum; - - spans[i].matched = FALSE; /* not yet matched against a stroke */ - } - - *nspans_p = num_spans; -} - -/* - * Match a pressure-span against a stroke-component. If there is a - * match, update the component's state and return TRUE. - */ -static boolean_t -atp_match_stroke_component(atp_stroke_component *component, - const atp_pspan *pspan, atp_stroke_type stroke_type) -{ - int delta_mickeys; - u_int min_pressure; - - delta_mickeys = pspan->loc - component->loc; - - if (abs(delta_mickeys) > atp_max_delta_mickeys) - return (FALSE); /* the finger span is too far out; no match */ - - component->loc = pspan->loc; - - /* - * A sudden and significant increase in a pspan's cumulative - * pressure indicates the incidence of a new finger - * contact. This usually revises the pspan's - * centre-of-gravity, and hence the location of any/all - * matching stroke component(s). But such a change should - * *not* be interpreted as a movement. - */ - if (pspan->cum > ((3 * component->cum_pressure) >> 1)) - delta_mickeys = 0; - - component->cum_pressure = pspan->cum; - if (pspan->cum > component->max_cum_pressure) - component->max_cum_pressure = pspan->cum; - - /* - * Disregard the component's movement if its cumulative - * pressure drops below a fraction of the maximum; this - * fraction is determined based on the stroke's type. - */ - if (stroke_type == ATP_STROKE_TOUCH) - min_pressure = (3 * component->max_cum_pressure) >> 2; - else - min_pressure = component->max_cum_pressure >> 2; - if (component->cum_pressure < min_pressure) - delta_mickeys = 0; - - component->delta_mickeys = delta_mickeys; - return (TRUE); -} - -static void -atp_match_strokes_against_pspans(struct atp_softc *sc, atp_axis axis, - atp_pspan *pspans, u_int n_pspans, u_int repeat_count) -{ - u_int i, j; - u_int repeat_index = 0; - - /* Determine the index of the multi-span. */ - if (repeat_count) { - u_int cum = 0; - for (i = 0; i < n_pspans; i++) { - if (pspans[i].cum > cum) { - repeat_index = i; - cum = pspans[i].cum; - } - } - } - - for (i = 0; i < sc->sc_n_strokes; i++) { - atp_stroke *stroke = &sc->sc_strokes[i]; - if (stroke->components[axis].matched) - continue; /* skip matched components */ - - for (j = 0; j < n_pspans; j++) { - if (pspans[j].matched) - continue; /* skip matched pspans */ - - if (atp_match_stroke_component( - &stroke->components[axis], &pspans[j], - stroke->type)) { - /* There is a match. */ - stroke->components[axis].matched = TRUE; - - /* Take care to repeat at the multi-span. */ - if ((repeat_count > 0) && (j == repeat_index)) - repeat_count--; - else - pspans[j].matched = TRUE; - - break; /* skip to the next stroke */ - } - } /* loop over pspans */ - } /* loop over strokes */ -} - -/* - * Update strokes by matching against current pressure-spans. - * Return TRUE if any movement is detected. - */ -static boolean_t -atp_update_strokes(struct atp_softc *sc, atp_pspan *pspans_x, - u_int n_xpspans, atp_pspan *pspans_y, u_int n_ypspans) -{ - u_int i, j; - atp_stroke *stroke; - boolean_t movement = FALSE; - u_int repeat_count = 0; - - /* Reset X and Y components of all strokes as unmatched. */ - for (i = 0; i < sc->sc_n_strokes; i++) { - stroke = &sc->sc_strokes[i]; - stroke->components[X].matched = FALSE; - stroke->components[Y].matched = FALSE; - } - - /* - * Usually, the X and Y pspans come in pairs (the common case - * being a single pair). It is possible, however, that - * multiple contacts resolve to a single pspan along an - * axis, as illustrated in the following: - * - * F = finger-contact - * - * pspan pspan - * +-----------------------+ - * | . . | - * | . . | - * | . . | - * | . . | - * pspan |.........F......F | - * | | - * | | - * | | - * +-----------------------+ - * - * - * The above case can be detected by a difference in the - * number of X and Y pspans. When this happens, X and Y pspans - * aren't easy to pair or match against strokes. - * - * When X and Y pspans differ in number, the axis with the - * smaller number of pspans is regarded as having a repeating - * pspan (or a multi-pspan)--in the above illustration, the - * Y-axis has a repeating pspan. Our approach is to try to - * match the multi-pspan repeatedly against strokes. The - * difference between the number of X and Y pspans gives us a - * crude repeat_count for matching multi-pspans--i.e. the - * multi-pspan along the Y axis (above) has a repeat_count of 1. - */ - repeat_count = abs(n_xpspans - n_ypspans); - - atp_match_strokes_against_pspans(sc, X, pspans_x, n_xpspans, - (((repeat_count != 0) && ((n_xpspans < n_ypspans))) ? - repeat_count : 0)); - atp_match_strokes_against_pspans(sc, Y, pspans_y, n_ypspans, - (((repeat_count != 0) && (n_ypspans < n_xpspans)) ? - repeat_count : 0)); - - /* Update the state of strokes based on the above pspan matches. */ - for (i = 0; i < sc->sc_n_strokes; i++) { - stroke = &sc->sc_strokes[i]; - if (stroke->components[X].matched && - stroke->components[Y].matched) { - atp_advance_stroke_state(sc, stroke, &movement); - } else { - /* - * At least one component of this stroke - * didn't match against current pspans; - * terminate it. - */ - atp_terminate_stroke(sc, i); - } - } - - /* Add new strokes for pairs of unmatched pspans */ - for (i = 0; i < n_xpspans; i++) { - if (pspans_x[i].matched == FALSE) break; - } - for (j = 0; j < n_ypspans; j++) { - if (pspans_y[j].matched == FALSE) break; - } - if ((i < n_xpspans) && (j < n_ypspans)) { -#ifdef USB_DEBUG - if (atp_debug >= ATP_LLEVEL_INFO) { - printf("unmatched pspans:"); - for (; i < n_xpspans; i++) { - if (pspans_x[i].matched) - continue; - printf(" X:[loc:%u,cum:%u]", - pspans_x[i].loc, pspans_x[i].cum); - } - for (; j < n_ypspans; j++) { - if (pspans_y[j].matched) - continue; - printf(" Y:[loc:%u,cum:%u]", - pspans_y[j].loc, pspans_y[j].cum); - } - printf("\n"); - } -#endif /* USB_DEBUG */ - if ((n_xpspans == 1) && (n_ypspans == 1)) - /* The common case of a single pair of new pspans. */ - atp_add_stroke(sc, &pspans_x[0], &pspans_y[0]); - else - atp_add_new_strokes(sc, - pspans_x, n_xpspans, - pspans_y, n_ypspans); - } - -#ifdef USB_DEBUG - if (atp_debug >= ATP_LLEVEL_INFO) { - for (i = 0; i < sc->sc_n_strokes; i++) { - atp_stroke *stroke = &sc->sc_strokes[i]; - - printf(" %s%clc:%u,dm:%d,pnd:%d,cum:%d,max:%d,mv:%d%c" - ",%clc:%u,dm:%d,pnd:%d,cum:%d,max:%d,mv:%d%c", - (stroke->flags & ATSF_ZOMBIE) ? "zomb:" : "", - (stroke->type == ATP_STROKE_TOUCH) ? '[' : '<', - stroke->components[X].loc, - stroke->components[X].delta_mickeys, - stroke->components[X].pending, - stroke->components[X].cum_pressure, - stroke->components[X].max_cum_pressure, - stroke->components[X].movement, - (stroke->type == ATP_STROKE_TOUCH) ? ']' : '>', - (stroke->type == ATP_STROKE_TOUCH) ? '[' : '<', - stroke->components[Y].loc, - stroke->components[Y].delta_mickeys, - stroke->components[Y].pending, - stroke->components[Y].cum_pressure, - stroke->components[Y].max_cum_pressure, - stroke->components[Y].movement, - (stroke->type == ATP_STROKE_TOUCH) ? ']' : '>'); - } - if (sc->sc_n_strokes) - printf("\n"); - } -#endif /* USB_DEBUG */ - - return (movement); -} - -/* Initialize a stroke using a pressure-span. */ -static __inline void -atp_add_stroke(struct atp_softc *sc, const atp_pspan *pspan_x, - const atp_pspan *pspan_y) -{ - atp_stroke *stroke; - - if (sc->sc_n_strokes >= ATP_MAX_STROKES) - return; - stroke = &sc->sc_strokes[sc->sc_n_strokes]; - - memset(stroke, 0, sizeof(atp_stroke)); - - /* - * Strokes begin as potential touches. If a stroke survives - * longer than a threshold, or if it records significant - * cumulative movement, then it is considered a 'slide'. - */ - stroke->type = ATP_STROKE_TOUCH; - microtime(&stroke->ctime); - stroke->age = 1; /* Unit: interrupts */ - - stroke->components[X].loc = pspan_x->loc; - stroke->components[X].cum_pressure = pspan_x->cum; - stroke->components[X].max_cum_pressure = pspan_x->cum; - stroke->components[X].matched = TRUE; - - stroke->components[Y].loc = pspan_y->loc; - stroke->components[Y].cum_pressure = pspan_y->cum; - stroke->components[Y].max_cum_pressure = pspan_y->cum; - stroke->components[Y].matched = TRUE; - - sc->sc_n_strokes++; - if (sc->sc_n_strokes > 1) { - /* Reset double-tap-n-drag if we have more than one strokes. */ - sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; - } - - DPRINTFN(ATP_LLEVEL_INFO, "[%u,%u], time: %u,%ld\n", - stroke->components[X].loc, - stroke->components[Y].loc, - (unsigned int)stroke->ctime.tv_sec, - (unsigned long int)stroke->ctime.tv_usec); -} - -static void -atp_add_new_strokes(struct atp_softc *sc, atp_pspan *pspans_x, - u_int n_xpspans, atp_pspan *pspans_y, u_int n_ypspans) -{ - int i, j; - atp_pspan spans[2][ATP_MAX_PSPANS_PER_AXIS]; - u_int nspans[2]; - - /* Copy unmatched pspans into the local arrays. */ - for (i = 0, nspans[X] = 0; i < n_xpspans; i++) { - if (pspans_x[i].matched == FALSE) { - spans[X][nspans[X]] = pspans_x[i]; - nspans[X]++; - } - } - for (j = 0, nspans[Y] = 0; j < n_ypspans; j++) { - if (pspans_y[j].matched == FALSE) { - spans[Y][nspans[Y]] = pspans_y[j]; - nspans[Y]++; - } - } - - if (nspans[X] == nspans[Y]) { - /* Create new strokes from pairs of unmatched pspans */ - for (i = 0, j = 0; (i < nspans[X]) && (j < nspans[Y]); i++, j++) - atp_add_stroke(sc, &spans[X][i], &spans[Y][j]); - } else { - u_int cum = 0; - atp_axis repeat_axis; /* axis with multi-pspans */ - u_int repeat_count; /* repeat count for the multi-pspan*/ - u_int repeat_index = 0; /* index of the multi-span */ - - repeat_axis = (nspans[X] > nspans[Y]) ? Y : X; - repeat_count = abs(nspans[X] - nspans[Y]); - for (i = 0; i < nspans[repeat_axis]; i++) { - if (spans[repeat_axis][i].cum > cum) { - repeat_index = i; - cum = spans[repeat_axis][i].cum; - } - } - - /* Create new strokes from pairs of unmatched pspans */ - i = 0, j = 0; - for (; (i < nspans[X]) && (j < nspans[Y]); i++, j++) { - atp_add_stroke(sc, &spans[X][i], &spans[Y][j]); - - /* Take care to repeat at the multi-pspan. */ - if (repeat_count > 0) { - if ((repeat_axis == X) && - (repeat_index == i)) { - i--; /* counter loop increment */ - repeat_count--; - } else if ((repeat_axis == Y) && - (repeat_index == j)) { - j--; /* counter loop increment */ - repeat_count--; - } - } - } - } -} - -/* - * Advance the state of this stroke--and update the out-parameter - * 'movement' as a side-effect. - */ -void -atp_advance_stroke_state(struct atp_softc *sc, atp_stroke *stroke, - boolean_t *movement) -{ - stroke->age++; - if (stroke->age <= atp_stroke_maturity_threshold) { - /* Avoid noise from immature strokes. */ - stroke->components[X].delta_mickeys = 0; - stroke->components[Y].delta_mickeys = 0; - } - - /* Revitalize stroke if it had previously been marked as a zombie. */ - if (stroke->flags & ATSF_ZOMBIE) - stroke->flags &= ~ATSF_ZOMBIE; - - if (atp_compute_stroke_movement(stroke)) - *movement = TRUE; - - if (stroke->type != ATP_STROKE_TOUCH) - return; - - /* Convert touch strokes to slides upon detecting movement or age. */ - if (stroke->cum_movement >= atp_slide_min_movement) { - atp_convert_to_slide(sc, stroke); - } else { - /* If a touch stroke is found to be older than the - * touch-timeout threshold, it should be converted to - * a slide; except if there is a co-incident sibling - * with a later creation time. - * - * When multiple fingers make contact with the - * touchpad, they are likely to be separated in their - * times of incidence. During a multi-finger tap, - * therefore, the last finger to make - * contact--i.e. the one with the latest - * 'ctime'--should be used to determine how the - * touch-siblings get treated; otherwise older - * siblings may lapse the touch-timeout and get - * converted into slides prematurely. The following - * loop determines if there exists another touch - * stroke with a larger 'ctime' than the current - * stroke (NOTE: zombies with a larger 'ctime' are - * also considered) . - */ - - u_int i; - for (i = 0; i < sc->sc_n_strokes; i++) { - if ((&sc->sc_strokes[i] == stroke) || - (sc->sc_strokes[i].type != ATP_STROKE_TOUCH)) - continue; - - if (timevalcmp(&sc->sc_strokes[i].ctime, - &stroke->ctime, >)) - break; - } - if (i == sc->sc_n_strokes) { - /* Found no other touch stroke with a larger 'ctime'. */ - struct timeval tdiff; - - /* Compute the stroke's age. */ - getmicrotime(&tdiff); - if (timevalcmp(&tdiff, &stroke->ctime, >)) - timevalsub(&tdiff, &stroke->ctime); - else { - /* - * If we are here, it is because getmicrotime - * reported the current time as being behind - * the stroke's start time; getmicrotime can - * be imprecise. - */ - tdiff.tv_sec = 0; - tdiff.tv_usec = 0; - } - - if ((tdiff.tv_sec > (atp_touch_timeout / 1000000)) || - ((tdiff.tv_sec == (atp_touch_timeout / 1000000)) && - (tdiff.tv_usec >= - (atp_touch_timeout % 1000000)))) - atp_convert_to_slide(sc, stroke); - } - } -} - -/* Switch a given touch stroke to being a slide. */ -void -atp_convert_to_slide(struct atp_softc *sc, atp_stroke *stroke) -{ - stroke->type = ATP_STROKE_SLIDE; - - /* Are we at the beginning of a double-click-n-drag? */ - if ((sc->sc_n_strokes == 1) && - ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) && - timevalcmp(&stroke->ctime, &sc->sc_reap_time, >)) { - struct timeval delta; - struct timeval window = { - atp_double_tap_threshold / 1000000, - atp_double_tap_threshold % 1000000 - }; - - delta = stroke->ctime; - timevalsub(&delta, &sc->sc_reap_time); - if (timevalcmp(&delta, &window, <=)) - sc->sc_state |= ATP_DOUBLE_TAP_DRAG; - } -} - -/* - * Terminate a stroke. While SLIDE strokes are dropped, TOUCH strokes - * are retained as zombies so as to reap all their siblings together; - * this helps establish the number of fingers involved in the tap. - */ -static void -atp_terminate_stroke(struct atp_softc *sc, - u_int index) /* index of the stroke to be terminated */ -{ - atp_stroke *s = &sc->sc_strokes[index]; - - if (s->flags & ATSF_ZOMBIE) { - return; - } - - if ((s->type == ATP_STROKE_TOUCH) && - (s->age > atp_stroke_maturity_threshold)) { - s->flags |= ATSF_ZOMBIE; - - /* If no zombies exist, then prepare to reap zombies later. */ - if ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) { - atp_setup_reap_time(sc, &s->ctime); - sc->sc_state |= ATP_ZOMBIES_EXIST; - } - } else { - /* Drop this stroke. */ - memcpy(&sc->sc_strokes[index], &sc->sc_strokes[index + 1], - (sc->sc_n_strokes - index - 1) * sizeof(atp_stroke)); - sc->sc_n_strokes--; - - /* - * Reset the double-click-n-drag at the termination of - * any slide stroke. - */ - sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; - } -} - -static __inline boolean_t -atp_stroke_has_small_movement(const atp_stroke *stroke) -{ - return ((abs(stroke->components[X].delta_mickeys) <= - atp_small_movement_threshold) && - (abs(stroke->components[Y].delta_mickeys) <= - atp_small_movement_threshold)); -} - -/* - * Accumulate delta_mickeys into the component's 'pending' bucket; if - * the aggregate exceeds the small_movement_threshold, then retain - * delta_mickeys for later. - */ -static __inline void -atp_update_pending_mickeys(atp_stroke_component *component) -{ - component->pending += component->delta_mickeys; - if (abs(component->pending) <= atp_small_movement_threshold) - component->delta_mickeys = 0; - else { - /* - * Penalise pending mickeys for having accumulated - * over short deltas. This operation has the effect of - * scaling down the cumulative contribution of short - * movements. - */ - component->pending -= (component->delta_mickeys << 1); - } -} - - -static void -atp_compute_smoothening_scale_ratio(atp_stroke *stroke, int *numerator, - int *denominator) -{ - int dxdt; - int dydt; - u_int vel_squared; /* Square of the velocity vector's magnitude. */ - u_int vel_squared_smooth; - - /* Table holding (10 * sqrt(x)) for x between 1 and 256. */ - static uint8_t sqrt_table[256] = { - 10, 14, 17, 20, 22, 24, 26, 28, - 30, 31, 33, 34, 36, 37, 38, 40, - 41, 42, 43, 44, 45, 46, 47, 48, - 50, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 60, 61, 62, 63, - 64, 64, 65, 66, 67, 67, 68, 69, - 70, 70, 71, 72, 72, 73, 74, 74, - 75, 76, 76, 77, 78, 78, 79, 80, - 80, 81, 81, 82, 83, 83, 84, 84, - 85, 86, 86, 87, 87, 88, 88, 89, - 90, 90, 91, 91, 92, 92, 93, 93, - 94, 94, 95, 95, 96, 96, 97, 97, - 98, 98, 99, 100, 100, 100, 101, 101, - 102, 102, 103, 103, 104, 104, 105, 105, - 106, 106, 107, 107, 108, 108, 109, 109, - 110, 110, 110, 111, 111, 112, 112, 113, - 113, 114, 114, 114, 115, 115, 116, 116, - 117, 117, 117, 118, 118, 119, 119, 120, - 120, 120, 121, 121, 122, 122, 122, 123, - 123, 124, 124, 124, 125, 125, 126, 126, - 126, 127, 127, 128, 128, 128, 129, 129, - 130, 130, 130, 131, 131, 131, 132, 132, - 133, 133, 133, 134, 134, 134, 135, 135, - 136, 136, 136, 137, 137, 137, 138, 138, - 138, 139, 139, 140, 140, 140, 141, 141, - 141, 142, 142, 142, 143, 143, 143, 144, - 144, 144, 145, 145, 145, 146, 146, 146, - 147, 147, 147, 148, 148, 148, 149, 149, - 150, 150, 150, 150, 151, 151, 151, 152, - 152, 152, 153, 153, 153, 154, 154, 154, - 155, 155, 155, 156, 156, 156, 157, 157, - 157, 158, 158, 158, 159, 159, 159, 160 - }; - const u_int N = NELEM(sqrt_table); - - dxdt = stroke->components[X].delta_mickeys; - dydt = stroke->components[Y].delta_mickeys; - - *numerator = 0, *denominator = 0; /* default values. */ - - /* Compute a smoothened magnitude_squared of the stroke's velocity. */ - vel_squared = dxdt * dxdt + dydt * dydt; - vel_squared_smooth = (3 * stroke->velocity_squared + vel_squared) >> 2; - stroke->velocity_squared = vel_squared_smooth; /* retained as history */ - if ((vel_squared == 0) || (vel_squared_smooth == 0)) - return; /* returning (numerator == 0) will imply zero movement*/ - - /* - * In order to determine the overall movement scale factor, - * we're actually interested in the effect of smoothening upon - * the *magnitude* of velocity; i.e. we need to compute the - * square-root of (vel_squared_smooth / vel_squared) in the - * form of a numerator and denominator. - */ - - /* Keep within the bounds of the square-root table. */ - while ((vel_squared > N) || (vel_squared_smooth > N)) { - /* Dividing uniformly by 2 won't disturb the final ratio. */ - vel_squared >>= 1; - vel_squared_smooth >>= 1; - } - - *numerator = sqrt_table[vel_squared_smooth - 1]; - *denominator = sqrt_table[vel_squared - 1]; -} - -/* - * Compute a smoothened value for the stroke's movement from - * delta_mickeys in the X and Y components. - */ -static boolean_t -atp_compute_stroke_movement(atp_stroke *stroke) -{ - int num; /* numerator of scale ratio */ - int denom; /* denominator of scale ratio */ - - /* - * Short movements are added first to the 'pending' bucket, - * and then acted upon only when their aggregate exceeds a - * threshold. This has the effect of filtering away movement - * noise. - */ - if (atp_stroke_has_small_movement(stroke)) { - atp_update_pending_mickeys(&stroke->components[X]); - atp_update_pending_mickeys(&stroke->components[Y]); - } else { /* large movement */ - /* clear away any pending mickeys if there are large movements*/ - stroke->components[X].pending = 0; - stroke->components[Y].pending = 0; - } - - /* Get the scale ratio and smoothen movement. */ - atp_compute_smoothening_scale_ratio(stroke, &num, &denom); - if ((num == 0) || (denom == 0)) { - stroke->components[X].movement = 0; - stroke->components[Y].movement = 0; - stroke->velocity_squared >>= 1; /* Erode velocity_squared. */ - } else { - stroke->components[X].movement = - (stroke->components[X].delta_mickeys * num) / denom; - stroke->components[Y].movement = - (stroke->components[Y].delta_mickeys * num) / denom; - - stroke->cum_movement += - abs(stroke->components[X].movement) + - abs(stroke->components[Y].movement); - } - - return ((stroke->components[X].movement != 0) || - (stroke->components[Y].movement != 0)); -} - -static __inline void -atp_setup_reap_time(struct atp_softc *sc, struct timeval *tvp) -{ - struct timeval reap_window = { - ATP_ZOMBIE_STROKE_REAP_WINDOW / 1000000, - ATP_ZOMBIE_STROKE_REAP_WINDOW % 1000000 - }; - - microtime(&sc->sc_reap_time); - timevaladd(&sc->sc_reap_time, &reap_window); - - sc->sc_reap_ctime = *tvp; /* ctime to reap */ -} - -static void -atp_reap_zombies(struct atp_softc *sc, u_int *n_reaped, u_int *reaped_xlocs) -{ - u_int i; - atp_stroke *stroke; - - *n_reaped = 0; - for (i = 0; i < sc->sc_n_strokes; i++) { - struct timeval tdiff; - - stroke = &sc->sc_strokes[i]; - - if ((stroke->flags & ATSF_ZOMBIE) == 0) - continue; - - /* Compare this stroke's ctime with the ctime being reaped. */ - if (timevalcmp(&stroke->ctime, &sc->sc_reap_ctime, >=)) { - tdiff = stroke->ctime; - timevalsub(&tdiff, &sc->sc_reap_ctime); - } else { - tdiff = sc->sc_reap_ctime; - timevalsub(&tdiff, &stroke->ctime); - } - - if ((tdiff.tv_sec > (ATP_COINCIDENCE_THRESHOLD / 1000000)) || - ((tdiff.tv_sec == (ATP_COINCIDENCE_THRESHOLD / 1000000)) && - (tdiff.tv_usec > (ATP_COINCIDENCE_THRESHOLD % 1000000)))) { - continue; /* Skip non-siblings. */ - } - - /* - * Reap this sibling zombie stroke. - */ - - if (reaped_xlocs != NULL) - reaped_xlocs[*n_reaped] = stroke->components[X].loc; - - /* Erase the stroke from the sc. */ - memcpy(&stroke[i], &stroke[i + 1], - (sc->sc_n_strokes - i - 1) * sizeof(atp_stroke)); - sc->sc_n_strokes--; - - *n_reaped += 1; - --i; /* Decr. i to keep it unchanged for the next iteration */ - } - - DPRINTFN(ATP_LLEVEL_INFO, "reaped %u zombies\n", *n_reaped); - - /* There could still be zombies remaining in the system. */ - for (i = 0; i < sc->sc_n_strokes; i++) { - stroke = &sc->sc_strokes[i]; - if (stroke->flags & ATSF_ZOMBIE) { - DPRINTFN(ATP_LLEVEL_INFO, "zombies remain!\n"); - atp_setup_reap_time(sc, &stroke->ctime); - return; - } - } - - /* If we reach here, then no more zombies remain. */ - sc->sc_state &= ~ATP_ZOMBIES_EXIST; -} - - -/* Device methods. */ -static device_probe_t atp_probe; -static device_attach_t atp_attach; -static device_detach_t atp_detach; -static usb_callback_t atp_intr; - -static const struct usb_config atp_config[ATP_N_TRANSFER] = { - [ATP_INTR_DT] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .flags = { - .pipe_bof = 1, - .short_xfer_ok = 1, - }, - .bufsize = 0, /* use wMaxPacketSize */ - .callback = &atp_intr, - }, - [ATP_RESET] = { - .type = UE_CONTROL, - .endpoint = 0, /* Control pipe */ - .direction = UE_DIR_ANY, - .bufsize = sizeof(struct usb_device_request) + MODE_LENGTH, - .callback = &atp_reset_callback, - .interval = 0, /* no pre-delay */ - }, -}; - -static int -atp_probe(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - - if ((uaa->info.bInterfaceClass != UICLASS_HID) || - (uaa->info.bInterfaceProtocol != UIPROTO_MOUSE)) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(atp_devs, sizeof(atp_devs), uaa)); -} - -static int -atp_attach(device_t dev) -{ - struct atp_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - usb_error_t err; - - DPRINTFN(ATP_LLEVEL_INFO, "sc=%p\n", sc); - - sc->sc_dev = dev; - sc->sc_usb_device = uaa->device; - - /* - * By default the touchpad behaves like an HID device, sending - * packets with reportID = 2. Such reports contain only - * limited information--they encode movement deltas and button - * events,--but do not include data from the pressure - * sensors. The device input mode can be switched from HID - * reports to raw sensor data using vendor-specific USB - * control commands; but first the mode must be read. - */ - err = atp_req_get_report(sc->sc_usb_device, sc->sc_mode_bytes); - if (err != USB_ERR_NORMAL_COMPLETION) { - DPRINTF("failed to read device mode (%d)\n", err); - return (ENXIO); - } - - if (atp_set_device_mode(dev, RAW_SENSOR_MODE) != 0) { - DPRINTF("failed to set mode to 'RAW_SENSOR' (%d)\n", err); - return (ENXIO); - } - - mtx_init(&sc->sc_mutex, "atpmtx", NULL, MTX_DEF | MTX_RECURSE); - - err = usbd_transfer_setup(uaa->device, - &uaa->info.bIfaceIndex, sc->sc_xfer, atp_config, - ATP_N_TRANSFER, sc, &sc->sc_mutex); - - if (err) { - DPRINTF("error=%s\n", usbd_errstr(err)); - goto detach; - } - - if (usb_fifo_attach(sc->sc_usb_device, sc, &sc->sc_mutex, - &atp_fifo_methods, &sc->sc_fifo, - device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex, - UID_ROOT, GID_OPERATOR, 0644)) { - goto detach; - } - - device_set_usb_desc(dev); - - sc->sc_params = &atp_dev_params[uaa->driver_info]; - - sc->sc_hw.buttons = 3; - sc->sc_hw.iftype = MOUSE_IF_USB; - sc->sc_hw.type = MOUSE_PAD; - sc->sc_hw.model = MOUSE_MODEL_GENERIC; - sc->sc_hw.hwid = 0; - sc->sc_mode.protocol = MOUSE_PROTO_MSC; - sc->sc_mode.rate = -1; - sc->sc_mode.resolution = MOUSE_RES_UNKNOWN; - sc->sc_mode.accelfactor = 0; - sc->sc_mode.level = 0; - sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; - - sc->sc_state = 0; - - sc->sc_left_margin = atp_mickeys_scale_factor; - sc->sc_right_margin = (sc->sc_params->n_xsensors - 1) * - atp_mickeys_scale_factor; - - return (0); - -detach: - atp_detach(dev); - return (ENOMEM); -} - -static int -atp_detach(device_t dev) -{ - struct atp_softc *sc; - - sc = device_get_softc(dev); - if (sc->sc_state & ATP_ENABLED) { - mtx_lock(&sc->sc_mutex); - atp_disable(sc); - mtx_unlock(&sc->sc_mutex); - } - - usb_fifo_detach(&sc->sc_fifo); - - usbd_transfer_unsetup(sc->sc_xfer, ATP_N_TRANSFER); - - mtx_destroy(&sc->sc_mutex); - - return (0); -} - -static void -atp_intr(struct usb_xfer *xfer, usb_error_t error) -{ - struct atp_softc *sc = usbd_xfer_softc(xfer); - int len; - struct usb_page_cache *pc; - uint8_t status_bits; - atp_pspan pspans_x[ATP_MAX_PSPANS_PER_AXIS]; - atp_pspan pspans_y[ATP_MAX_PSPANS_PER_AXIS]; - u_int n_xpspans = 0, n_ypspans = 0; - u_int reaped_xlocs[ATP_MAX_STROKES]; - u_int tap_fingers = 0; - - usbd_xfer_status(xfer, &len, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - if (len > sc->sc_params->data_len) { - DPRINTFN(ATP_LLEVEL_ERROR, - "truncating large packet from %u to %u bytes\n", - len, sc->sc_params->data_len); - len = sc->sc_params->data_len; - } - if (len < sc->sc_params->data_len) - goto tr_setup; - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, sc->sensor_data, sc->sc_params->data_len); - - /* Interpret sensor data */ - atp_interpret_sensor_data(sc->sensor_data, - sc->sc_params->n_xsensors, X, sc->cur_x, - sc->sc_params->prot); - atp_interpret_sensor_data(sc->sensor_data, - sc->sc_params->n_ysensors, Y, sc->cur_y, - sc->sc_params->prot); - - /* - * If this is the initial update (from an untouched - * pad), we should set the base values for the sensor - * data; deltas with respect to these base values can - * be used as pressure readings subsequently. - */ - status_bits = sc->sensor_data[sc->sc_params->data_len - 1]; - if ((sc->sc_params->prot == ATP_PROT_GEYSER3 && - (status_bits & ATP_STATUS_BASE_UPDATE)) || - !(sc->sc_state & ATP_VALID)) { - memcpy(sc->base_x, sc->cur_x, - sc->sc_params->n_xsensors * sizeof(*(sc->base_x))); - memcpy(sc->base_y, sc->cur_y, - sc->sc_params->n_ysensors * sizeof(*(sc->base_y))); - sc->sc_state |= ATP_VALID; - goto tr_setup; - } - - /* Get pressure readings and detect p-spans for both axes. */ - atp_get_pressures(sc->pressure_x, sc->cur_x, sc->base_x, - sc->sc_params->n_xsensors); - atp_detect_pspans(sc->pressure_x, sc->sc_params->n_xsensors, - ATP_MAX_PSPANS_PER_AXIS, - pspans_x, &n_xpspans); - atp_get_pressures(sc->pressure_y, sc->cur_y, sc->base_y, - sc->sc_params->n_ysensors); - atp_detect_pspans(sc->pressure_y, sc->sc_params->n_ysensors, - ATP_MAX_PSPANS_PER_AXIS, - pspans_y, &n_ypspans); - - /* Update strokes with new pspans to detect movements. */ - sc->sc_status.flags &= ~MOUSE_POSCHANGED; - if (atp_update_strokes(sc, - pspans_x, n_xpspans, - pspans_y, n_ypspans)) - sc->sc_status.flags |= MOUSE_POSCHANGED; - - /* Reap zombies if it is time. */ - if (sc->sc_state & ATP_ZOMBIES_EXIST) { - struct timeval now; - - getmicrotime(&now); - if (timevalcmp(&now, &sc->sc_reap_time, >=)) - atp_reap_zombies(sc, &tap_fingers, - reaped_xlocs); - } - - sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED; - sc->sc_status.obutton = sc->sc_status.button; - - /* Get the state of the physical buttton. */ - sc->sc_status.button = (status_bits & ATP_STATUS_BUTTON) ? - MOUSE_BUTTON1DOWN : 0; - if (sc->sc_status.button != 0) { - /* Reset DOUBLE_TAP_N_DRAG if the button is pressed. */ - sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; - } else if (sc->sc_state & ATP_DOUBLE_TAP_DRAG) { - /* Assume a button-press with DOUBLE_TAP_N_DRAG. */ - sc->sc_status.button = MOUSE_BUTTON1DOWN; - } - - sc->sc_status.flags |= - sc->sc_status.button ^ sc->sc_status.obutton; - if (sc->sc_status.flags & MOUSE_STDBUTTONSCHANGED) { - DPRINTFN(ATP_LLEVEL_INFO, "button %s\n", - ((sc->sc_status.button & MOUSE_BUTTON1DOWN) ? - "pressed" : "released")); - } else if ((sc->sc_status.obutton == 0) && - (sc->sc_status.button == 0) && - (tap_fingers != 0)) { - /* Ignore single-finger taps at the edges. */ - if ((tap_fingers == 1) && - ((reaped_xlocs[0] <= sc->sc_left_margin) || - (reaped_xlocs[0] > sc->sc_right_margin))) { - tap_fingers = 0; - } - DPRINTFN(ATP_LLEVEL_INFO, - "tap_fingers: %u\n", tap_fingers); - } - - if (sc->sc_status.flags & - (MOUSE_POSCHANGED | MOUSE_STDBUTTONSCHANGED)) { - int dx, dy; - u_int n_movements; - - dx = 0, dy = 0, n_movements = 0; - for (u_int i = 0; i < sc->sc_n_strokes; i++) { - atp_stroke *stroke = &sc->sc_strokes[i]; - - if ((stroke->components[X].movement) || - (stroke->components[Y].movement)) { - dx += stroke->components[X].movement; - dy += stroke->components[Y].movement; - n_movements++; - } - } - /* - * Disregard movement if multiple - * strokes record motion. - */ - if (n_movements != 1) - dx = 0, dy = 0; - - sc->sc_status.dx += dx; - sc->sc_status.dy += dy; - atp_add_to_queue(sc, dx, -dy, sc->sc_status.button); - } - - if (tap_fingers != 0) { - /* Add a pair of events (button-down and button-up). */ - switch (tap_fingers) { - case 1: atp_add_to_queue(sc, 0, 0, MOUSE_BUTTON1DOWN); - break; - case 2: atp_add_to_queue(sc, 0, 0, MOUSE_BUTTON2DOWN); - break; - case 3: atp_add_to_queue(sc, 0, 0, MOUSE_BUTTON3DOWN); - break; - default: break;/* handle taps of only up to 3 fingers */ - } - atp_add_to_queue(sc, 0, 0, 0); /* button release */ - } - - /* - * The device continues to trigger interrupts at a - * fast rate even after touchpad activity has - * stopped. Upon detecting that the device has - * remained idle beyond a threshold, we reinitialize - * it to silence the interrupts. - */ - if ((sc->sc_status.flags == 0) && - (sc->sc_n_strokes == 0) && - (sc->sc_status.button == 0)) { - sc->sc_idlecount++; - if (sc->sc_idlecount >= ATP_IDLENESS_THRESHOLD) { - DPRINTFN(ATP_LLEVEL_INFO, "idle\n"); - - /* - * Use the last frame before we go idle for - * calibration on pads which do not send - * calibration frames. - */ - if (sc->sc_params->prot < ATP_PROT_GEYSER3) { - memcpy(sc->base_x, sc->cur_x, - sc->sc_params->n_xsensors * - sizeof(*(sc->base_x))); - memcpy(sc->base_y, sc->cur_y, - sc->sc_params->n_ysensors * - sizeof(*(sc->base_y))); - } - - sc->sc_idlecount = 0; - usbd_transfer_start(sc->sc_xfer[ATP_RESET]); - } - } else { - sc->sc_idlecount = 0; - } - - case USB_ST_SETUP: - tr_setup: - /* check if we can put more data into the FIFO */ - if (usb_fifo_put_bytes_max( - sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { - usbd_xfer_set_frame_len(xfer, 0, - sc->sc_params->data_len); - usbd_transfer_submit(xfer); - } - break; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - /* try clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } - - return; -} - -static void -atp_add_to_queue(struct atp_softc *sc, int dx, int dy, uint32_t buttons_in) -{ - uint32_t buttons_out; - uint8_t buf[8]; - - dx = imin(dx, 254); dx = imax(dx, -256); - dy = imin(dy, 254); dy = imax(dy, -256); - - buttons_out = MOUSE_MSC_BUTTONS; - if (buttons_in & MOUSE_BUTTON1DOWN) - buttons_out &= ~MOUSE_MSC_BUTTON1UP; - else if (buttons_in & MOUSE_BUTTON2DOWN) - buttons_out &= ~MOUSE_MSC_BUTTON2UP; - else if (buttons_in & MOUSE_BUTTON3DOWN) - buttons_out &= ~MOUSE_MSC_BUTTON3UP; - - DPRINTFN(ATP_LLEVEL_INFO, "dx=%d, dy=%d, buttons=%x\n", - dx, dy, buttons_out); - - /* Encode the mouse data in standard format; refer to mouse(4) */ - buf[0] = sc->sc_mode.syncmask[1]; - buf[0] |= buttons_out; - buf[1] = dx >> 1; - buf[2] = dy >> 1; - buf[3] = dx - (dx >> 1); - buf[4] = dy - (dy >> 1); - /* Encode extra bytes for level 1 */ - if (sc->sc_mode.level == 1) { - buf[5] = 0; /* dz */ - buf[6] = 0; /* dz - (dz / 2) */ - buf[7] = MOUSE_SYS_EXTBUTTONS; /* Extra buttons all up. */ - } - - usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf, - sc->sc_mode.packetsize, 1); -} - -static void -atp_reset_buf(struct atp_softc *sc) -{ - /* reset read queue */ - usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]); -} - -static void -atp_start_read(struct usb_fifo *fifo) -{ - struct atp_softc *sc = usb_fifo_softc(fifo); - int rate; - - /* Check if we should override the default polling interval */ - rate = sc->sc_pollrate; - /* Range check rate */ - if (rate > 1000) - rate = 1000; - /* Check for set rate */ - if ((rate > 0) && (sc->sc_xfer[ATP_INTR_DT] != NULL)) { - /* Stop current transfer, if any */ - usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]); - /* Set new interval */ - usbd_xfer_set_interval(sc->sc_xfer[ATP_INTR_DT], 1000 / rate); - /* Only set pollrate once */ - sc->sc_pollrate = 0; - } - - usbd_transfer_start(sc->sc_xfer[ATP_INTR_DT]); -} - -static void -atp_stop_read(struct usb_fifo *fifo) -{ - struct atp_softc *sc = usb_fifo_softc(fifo); - - usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]); -} - -static int -atp_open(struct usb_fifo *fifo, int fflags) -{ - DPRINTFN(ATP_LLEVEL_INFO, "\n"); - - if (fflags & FREAD) { - struct atp_softc *sc = usb_fifo_softc(fifo); - int rc; - - if (sc->sc_state & ATP_ENABLED) - return (EBUSY); - - if (usb_fifo_alloc_buffer(fifo, - ATP_FIFO_BUF_SIZE, ATP_FIFO_QUEUE_MAXLEN)) { - return (ENOMEM); - } - - rc = atp_enable(sc); - if (rc != 0) { - usb_fifo_free_buffer(fifo); - return (rc); - } - } - - return (0); -} - -static void -atp_close(struct usb_fifo *fifo, int fflags) -{ - if (fflags & FREAD) { - struct atp_softc *sc = usb_fifo_softc(fifo); - - atp_disable(sc); - usb_fifo_free_buffer(fifo); - } -} - -int -atp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags) -{ - struct atp_softc *sc = usb_fifo_softc(fifo); - mousemode_t mode; - int error = 0; - - mtx_lock(&sc->sc_mutex); - - switch(cmd) { - case MOUSE_GETHWINFO: - *(mousehw_t *)addr = sc->sc_hw; - break; - case MOUSE_GETMODE: - *(mousemode_t *)addr = sc->sc_mode; - break; - case MOUSE_SETMODE: - mode = *(mousemode_t *)addr; - - if (mode.level == -1) - /* Don't change the current setting */ - ; - else if ((mode.level < 0) || (mode.level > 1)) { - error = EINVAL; - goto done; - } - sc->sc_mode.level = mode.level; - sc->sc_pollrate = mode.rate; - sc->sc_hw.buttons = 3; - - if (sc->sc_mode.level == 0) { - sc->sc_mode.protocol = MOUSE_PROTO_MSC; - sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; - } else if (sc->sc_mode.level == 1) { - sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE; - sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE; - sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK; - sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC; - } - atp_reset_buf(sc); - break; - case MOUSE_GETLEVEL: - *(int *)addr = sc->sc_mode.level; - break; - case MOUSE_SETLEVEL: - if (*(int *)addr < 0 || *(int *)addr > 1) { - error = EINVAL; - goto done; - } - sc->sc_mode.level = *(int *)addr; - sc->sc_hw.buttons = 3; - - if (sc->sc_mode.level == 0) { - sc->sc_mode.protocol = MOUSE_PROTO_MSC; - sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; - sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; - sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; - } else if (sc->sc_mode.level == 1) { - sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE; - sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE; - sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK; - sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC; - } - atp_reset_buf(sc); - break; - case MOUSE_GETSTATUS: { - mousestatus_t *status = (mousestatus_t *)addr; - - *status = sc->sc_status; - sc->sc_status.obutton = sc->sc_status.button; - sc->sc_status.button = 0; - sc->sc_status.dx = 0; - sc->sc_status.dy = 0; - sc->sc_status.dz = 0; - - if (status->dx || status->dy || status->dz) - status->flags |= MOUSE_POSCHANGED; - if (status->button != status->obutton) - status->flags |= MOUSE_BUTTONSCHANGED; - break; - } - default: - error = ENOTTY; - } - -done: - mtx_unlock(&sc->sc_mutex); - return (error); -} - -static int -atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS) -{ - int error; - u_int tmp; - u_int prev_mickeys_scale_factor; - - prev_mickeys_scale_factor = atp_mickeys_scale_factor; - - tmp = atp_mickeys_scale_factor; - error = sysctl_handle_int(oidp, &tmp, 0, req); - if (error != 0 || req->newptr == NULL) - return (error); - - if (tmp == prev_mickeys_scale_factor) - return (0); /* no change */ - - atp_mickeys_scale_factor = tmp; - DPRINTFN(ATP_LLEVEL_INFO, "%s: resetting mickeys_scale_factor to %u\n", - ATP_DRIVER_NAME, tmp); - - /* Update dependent thresholds. */ - if (atp_small_movement_threshold == (prev_mickeys_scale_factor >> 3)) - atp_small_movement_threshold = atp_mickeys_scale_factor >> 3; - if (atp_max_delta_mickeys == ((3 * prev_mickeys_scale_factor) >> 1)) - atp_max_delta_mickeys = ((3 * atp_mickeys_scale_factor) >>1); - if (atp_slide_min_movement == (prev_mickeys_scale_factor >> 3)) - atp_slide_min_movement = atp_mickeys_scale_factor >> 3; - - return (0); -} - -static device_method_t atp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, atp_probe), - DEVMETHOD(device_attach, atp_attach), - DEVMETHOD(device_detach, atp_detach), - DEVMETHOD_END -}; - -static driver_t atp_driver = { - ATP_DRIVER_NAME, - atp_methods, - sizeof(struct atp_softc) -}; - -static devclass_t atp_devclass; - -DRIVER_MODULE(atp, uhub, atp_driver, atp_devclass, NULL, NULL); -MODULE_DEPEND(atp, usb, 1, 1, 1); -MODULE_VERSION(atp, 1); diff --git a/sys/bus/u4b/misc/udbp.c b/sys/bus/u4b/misc/udbp.c deleted file mode 100644 index b0c1734f43..0000000000 --- a/sys/bus/u4b/misc/udbp.c +++ /dev/null @@ -1,857 +0,0 @@ -/*- - * Copyright (c) 1996-2000 Whistle Communications, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of author nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY NICK HIBMA AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -/* Driver for arbitrary double bulk pipe devices. - * The driver assumes that there will be the same driver on the other side. - * - * XXX Some more information on what the framing of the IP packets looks like. - * - * To take full advantage of bulk transmission, packets should be chosen - * between 1k and 5k in size (1k to make sure the sending side starts - * streaming, and <5k to avoid overflowing the system with small TDs). - */ - - -/* probe/attach/detach: - * Connect the driver to the hardware and netgraph - * - * The reason we submit a bulk in transfer is that USB does not know about - * interrupts. The bulk transfer continuously polls the device for data. - * While the device has no data available, the device NAKs the TDs. As soon - * as there is data, the transfer happens and the data comes flowing in. - * - * In case you were wondering, interrupt transfers happen exactly that way. - * It therefore doesn't make sense to use the interrupt pipe to signal - * 'data ready' and then schedule a bulk transfer to fetch it. That would - * incur a 2ms delay at least, without reducing bandwidth requirements. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "usbdevs.h" - -#define USB_DEBUG_VAR udbp_debug -#include - -#include - -#include -#include -#include -#include - -#include - -#ifdef USB_DEBUG -static int udbp_debug = 0; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp"); -SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RWTUN, - &udbp_debug, 0, "udbp debug level"); -#endif - -#define UDBP_TIMEOUT 2000 /* timeout on outbound transfers, in - * msecs */ -#define UDBP_BUFFERSIZE MCLBYTES /* maximum number of bytes in one - * transfer */ -#define UDBP_T_WR 0 -#define UDBP_T_RD 1 -#define UDBP_T_WR_CS 2 -#define UDBP_T_RD_CS 3 -#define UDBP_T_MAX 4 -#define UDBP_Q_MAXLEN 50 - -struct udbp_softc { - - struct mtx sc_mtx; - struct ng_bt_mbufq sc_xmitq_hipri; /* hi-priority transmit queue */ - struct ng_bt_mbufq sc_xmitq; /* low-priority transmit queue */ - - struct usb_xfer *sc_xfer[UDBP_T_MAX]; - node_p sc_node; /* back pointer to node */ - hook_p sc_hook; /* pointer to the hook */ - struct mbuf *sc_bulk_in_buffer; - - uint32_t sc_packets_in; /* packets in from downstream */ - uint32_t sc_packets_out; /* packets out towards downstream */ - - uint8_t sc_flags; -#define UDBP_FLAG_READ_STALL 0x01 /* read transfer stalled */ -#define UDBP_FLAG_WRITE_STALL 0x02 /* write transfer stalled */ - - uint8_t sc_name[16]; -}; - -/* prototypes */ - -static int udbp_modload(module_t mod, int event, void *data); - -static device_probe_t udbp_probe; -static device_attach_t udbp_attach; -static device_detach_t udbp_detach; - -static usb_callback_t udbp_bulk_read_callback; -static usb_callback_t udbp_bulk_read_clear_stall_callback; -static usb_callback_t udbp_bulk_write_callback; -static usb_callback_t udbp_bulk_write_clear_stall_callback; - -static void udbp_bulk_read_complete(node_p, hook_p, void *, int); - -static ng_constructor_t ng_udbp_constructor; -static ng_rcvmsg_t ng_udbp_rcvmsg; -static ng_shutdown_t ng_udbp_rmnode; -static ng_newhook_t ng_udbp_newhook; -static ng_connect_t ng_udbp_connect; -static ng_rcvdata_t ng_udbp_rcvdata; -static ng_disconnect_t ng_udbp_disconnect; - -/* Parse type for struct ngudbpstat */ -static const struct ng_parse_struct_field - ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO; - -static const struct ng_parse_type ng_udbp_stat_type = { - &ng_parse_struct_type, - &ng_udbp_stat_type_fields -}; - -/* List of commands and how to convert arguments to/from ASCII */ -static const struct ng_cmdlist ng_udbp_cmdlist[] = { - { - NGM_UDBP_COOKIE, - NGM_UDBP_GET_STATUS, - "getstatus", - NULL, - &ng_udbp_stat_type, - }, - { - NGM_UDBP_COOKIE, - NGM_UDBP_SET_FLAG, - "setflag", - &ng_parse_int32_type, - NULL - }, - {0} -}; - -/* Netgraph node type descriptor */ -static struct ng_type ng_udbp_typestruct = { - .version = NG_ABI_VERSION, - .name = NG_UDBP_NODE_TYPE, - .constructor = ng_udbp_constructor, - .rcvmsg = ng_udbp_rcvmsg, - .shutdown = ng_udbp_rmnode, - .newhook = ng_udbp_newhook, - .connect = ng_udbp_connect, - .rcvdata = ng_udbp_rcvdata, - .disconnect = ng_udbp_disconnect, - .cmdlist = ng_udbp_cmdlist, -}; - -/* USB config */ -static const struct usb_config udbp_config[UDBP_T_MAX] = { - - [UDBP_T_WR] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = UDBP_BUFFERSIZE, - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = &udbp_bulk_write_callback, - .timeout = UDBP_TIMEOUT, - }, - - [UDBP_T_RD] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = UDBP_BUFFERSIZE, - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = &udbp_bulk_read_callback, - }, - - [UDBP_T_WR_CS] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* Control pipe */ - .direction = UE_DIR_ANY, - .bufsize = sizeof(struct usb_device_request), - .callback = &udbp_bulk_write_clear_stall_callback, - .timeout = 1000, /* 1 second */ - .interval = 50, /* 50ms */ - }, - - [UDBP_T_RD_CS] = { - .type = UE_CONTROL, - .endpoint = 0x00, /* Control pipe */ - .direction = UE_DIR_ANY, - .bufsize = sizeof(struct usb_device_request), - .callback = &udbp_bulk_read_clear_stall_callback, - .timeout = 1000, /* 1 second */ - .interval = 50, /* 50ms */ - }, -}; - -static devclass_t udbp_devclass; - -static device_method_t udbp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, udbp_probe), - DEVMETHOD(device_attach, udbp_attach), - DEVMETHOD(device_detach, udbp_detach), - DEVMETHOD_END -}; - -static driver_t udbp_driver = { - .name = "udbp", - .methods = udbp_methods, - .size = sizeof(struct udbp_softc), -}; - -DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, udbp_modload, NULL); -MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION); -MODULE_DEPEND(udbp, usb, 1, 1, 1); -MODULE_VERSION(udbp, 1); - -static int -udbp_modload(module_t mod, int event, void *data) -{ - int error; - - switch (event) { - case MOD_LOAD: - error = ng_newtype(&ng_udbp_typestruct); - if (error != 0) { - printf("%s: Could not register " - "Netgraph node type, error=%d\n", - NG_UDBP_NODE_TYPE, error); - } - break; - - case MOD_UNLOAD: - error = ng_rmtype(&ng_udbp_typestruct); - break; - - default: - error = EOPNOTSUPP; - break; - } - return (error); -} - -static const STRUCT_USB_HOST_ID udbp_devs[] = { - {USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_TURBOCONNECT, 0)}, - {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301, 0)}, - {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302, 0)}, - {USB_VPI(USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_EZLINK, 0)}, - {USB_VPI(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL620USB, 0)}, -}; - -static int -udbp_probe(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != 0) - return (ENXIO); - if (uaa->info.bIfaceIndex != 0) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(udbp_devs, sizeof(udbp_devs), uaa)); -} - -static int -udbp_attach(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct udbp_softc *sc = device_get_softc(dev); - int error; - - device_set_usb_desc(dev); - - snprintf(sc->sc_name, sizeof(sc->sc_name), - "%s", device_get_nameunit(dev)); - - mtx_init(&sc->sc_mtx, "udbp lock", NULL, MTX_DEF | MTX_RECURSE); - - error = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, - sc->sc_xfer, udbp_config, UDBP_T_MAX, sc, &sc->sc_mtx); - if (error) { - DPRINTF("error=%s\n", usbd_errstr(error)); - goto detach; - } - NG_BT_MBUFQ_INIT(&sc->sc_xmitq, UDBP_Q_MAXLEN); - - NG_BT_MBUFQ_INIT(&sc->sc_xmitq_hipri, UDBP_Q_MAXLEN); - - /* create Netgraph node */ - - if (ng_make_node_common(&ng_udbp_typestruct, &sc->sc_node) != 0) { - printf("%s: Could not create Netgraph node\n", - sc->sc_name); - sc->sc_node = NULL; - goto detach; - } - /* name node */ - - if (ng_name_node(sc->sc_node, sc->sc_name) != 0) { - printf("%s: Could not name node\n", - sc->sc_name); - NG_NODE_UNREF(sc->sc_node); - sc->sc_node = NULL; - goto detach; - } - NG_NODE_SET_PRIVATE(sc->sc_node, sc); - - /* the device is now operational */ - - return (0); /* success */ - -detach: - udbp_detach(dev); - return (ENOMEM); /* failure */ -} - -static int -udbp_detach(device_t dev) -{ - struct udbp_softc *sc = device_get_softc(dev); - - /* destroy Netgraph node */ - - if (sc->sc_node != NULL) { - NG_NODE_SET_PRIVATE(sc->sc_node, NULL); - ng_rmnode_self(sc->sc_node); - sc->sc_node = NULL; - } - /* free USB transfers, if any */ - - usbd_transfer_unsetup(sc->sc_xfer, UDBP_T_MAX); - - mtx_destroy(&sc->sc_mtx); - - /* destroy queues */ - - NG_BT_MBUFQ_DESTROY(&sc->sc_xmitq); - NG_BT_MBUFQ_DESTROY(&sc->sc_xmitq_hipri); - - /* extra check */ - - if (sc->sc_bulk_in_buffer) { - m_freem(sc->sc_bulk_in_buffer); - sc->sc_bulk_in_buffer = NULL; - } - return (0); /* success */ -} - -static void -udbp_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct udbp_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - struct mbuf *m; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - /* allocate new mbuf */ - - MGETHDR(m, M_DONTWAIT, MT_DATA); - - if (m == NULL) { - goto tr_setup; - } - MCLGET(m, M_DONTWAIT); - - if (!(m->m_flags & M_EXT)) { - m_freem(m); - goto tr_setup; - } - m->m_pkthdr.len = m->m_len = actlen; - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, m->m_data, actlen); - - sc->sc_bulk_in_buffer = m; - - DPRINTF("received package %d bytes\n", actlen); - - case USB_ST_SETUP: -tr_setup: - if (sc->sc_bulk_in_buffer) { - ng_send_fn(sc->sc_node, NULL, &udbp_bulk_read_complete, NULL, 0); - return; - } - if (sc->sc_flags & UDBP_FLAG_READ_STALL) { - usbd_transfer_start(sc->sc_xfer[UDBP_T_RD_CS]); - return; - } - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - return; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - sc->sc_flags |= UDBP_FLAG_READ_STALL; - usbd_transfer_start(sc->sc_xfer[UDBP_T_RD_CS]); - } - return; - - } -} - -static void -udbp_bulk_read_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct udbp_softc *sc = usbd_xfer_softc(xfer); - struct usb_xfer *xfer_other = sc->sc_xfer[UDBP_T_RD]; - - if (usbd_clear_stall_callback(xfer, xfer_other)) { - DPRINTF("stall cleared\n"); - sc->sc_flags &= ~UDBP_FLAG_READ_STALL; - usbd_transfer_start(xfer_other); - } -} - -static void -udbp_bulk_read_complete(node_p node, hook_p hook, void *arg1, int arg2) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(node); - struct mbuf *m; - int error; - - if (sc == NULL) { - return; - } - mtx_lock(&sc->sc_mtx); - - m = sc->sc_bulk_in_buffer; - - if (m) { - - sc->sc_bulk_in_buffer = NULL; - - if ((sc->sc_hook == NULL) || - NG_HOOK_NOT_VALID(sc->sc_hook)) { - DPRINTF("No upstream hook\n"); - goto done; - } - sc->sc_packets_in++; - - NG_SEND_DATA_ONLY(error, sc->sc_hook, m); - - m = NULL; - } -done: - if (m) { - m_freem(m); - } - /* start USB bulk-in transfer, if not already started */ - - usbd_transfer_start(sc->sc_xfer[UDBP_T_RD]); - - mtx_unlock(&sc->sc_mtx); -} - -static void -udbp_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct udbp_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - struct mbuf *m; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - sc->sc_packets_out++; - - case USB_ST_SETUP: - if (sc->sc_flags & UDBP_FLAG_WRITE_STALL) { - usbd_transfer_start(sc->sc_xfer[UDBP_T_WR_CS]); - return; - } - /* get next mbuf, if any */ - - NG_BT_MBUFQ_DEQUEUE(&sc->sc_xmitq_hipri, m); - if (m == NULL) { - NG_BT_MBUFQ_DEQUEUE(&sc->sc_xmitq, m); - if (m == NULL) { - DPRINTF("Data queue is empty\n"); - return; - } - } - if (m->m_pkthdr.len > MCLBYTES) { - DPRINTF("truncating large packet " - "from %d to %d bytes\n", m->m_pkthdr.len, - MCLBYTES); - m->m_pkthdr.len = MCLBYTES; - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); - - usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len); - - DPRINTF("packet out: %d bytes\n", m->m_pkthdr.len); - - m_freem(m); - - usbd_transfer_submit(xfer); - return; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - sc->sc_flags |= UDBP_FLAG_WRITE_STALL; - usbd_transfer_start(sc->sc_xfer[UDBP_T_WR_CS]); - } - return; - - } -} - -static void -udbp_bulk_write_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct udbp_softc *sc = usbd_xfer_softc(xfer); - struct usb_xfer *xfer_other = sc->sc_xfer[UDBP_T_WR]; - - if (usbd_clear_stall_callback(xfer, xfer_other)) { - DPRINTF("stall cleared\n"); - sc->sc_flags &= ~UDBP_FLAG_WRITE_STALL; - usbd_transfer_start(xfer_other); - } -} - -/*********************************************************************** - * Start of Netgraph methods - **********************************************************************/ - -/* - * If this is a device node so this work is done in the attach() - * routine and the constructor will return EINVAL as you should not be able - * to create nodes that depend on hardware (unless you can add the hardware :) - */ -static int -ng_udbp_constructor(node_p node) -{ - return (EINVAL); -} - -/* - * Give our ok for a hook to be added... - * If we are not running this might kick a device into life. - * Possibly decode information out of the hook name. - * Add the hook's private info to the hook structure. - * (if we had some). In this example, we assume that there is a - * an array of structs, called 'channel' in the private info, - * one for each active channel. The private - * pointer of each hook points to the appropriate UDBP_hookinfo struct - * so that the source of an input packet is easily identified. - */ -static int -ng_udbp_newhook(node_p node, hook_p hook, const char *name) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(node); - int32_t error = 0; - - if (strcmp(name, NG_UDBP_HOOK_NAME)) { - return (EINVAL); - } - mtx_lock(&sc->sc_mtx); - - if (sc->sc_hook != NULL) { - error = EISCONN; - } else { - sc->sc_hook = hook; - NG_HOOK_SET_PRIVATE(hook, NULL); - } - - mtx_unlock(&sc->sc_mtx); - - return (error); -} - -/* - * Get a netgraph control message. - * Check it is one we understand. If needed, send a response. - * We could save the address for an async action later, but don't here. - * Always free the message. - * The response should be in a malloc'd region that the caller can 'free'. - * A response is not required. - * Theoretically you could respond defferently to old message types if - * the cookie in the header didn't match what we consider to be current - * (so that old userland programs could continue to work). - */ -static int -ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(node); - struct ng_mesg *resp = NULL; - int error = 0; - struct ng_mesg *msg; - - NGI_GET_MSG(item, msg); - /* Deal with message according to cookie and command */ - switch (msg->header.typecookie) { - case NGM_UDBP_COOKIE: - switch (msg->header.cmd) { - case NGM_UDBP_GET_STATUS: - { - struct ngudbpstat *stats; - - NG_MKRESPONSE(resp, msg, sizeof(*stats), M_WAITOK); - if (!resp) { - error = ENOMEM; - break; - } - stats = (struct ngudbpstat *)resp->data; - mtx_lock(&sc->sc_mtx); - stats->packets_in = sc->sc_packets_in; - stats->packets_out = sc->sc_packets_out; - mtx_unlock(&sc->sc_mtx); - break; - } - case NGM_UDBP_SET_FLAG: - if (msg->header.arglen != sizeof(uint32_t)) { - error = EINVAL; - break; - } - DPRINTF("flags = 0x%08x\n", - *((uint32_t *)msg->data)); - break; - default: - error = EINVAL; /* unknown command */ - break; - } - break; - default: - error = EINVAL; /* unknown cookie type */ - break; - } - - /* Take care of synchronous response, if any */ - NG_RESPOND_MSG(error, node, item, resp); - NG_FREE_MSG(msg); - return (error); -} - -/* - * Accept data from the hook and queue it for output. - */ -static int -ng_udbp_rcvdata(hook_p hook, item_p item) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - struct ng_bt_mbufq *queue_ptr; - struct mbuf *m; - struct ng_tag_prio *ptag; - int error; - - if (sc == NULL) { - NG_FREE_ITEM(item); - return (EHOSTDOWN); - } - NGI_GET_M(item, m); - NG_FREE_ITEM(item); - - /* - * Now queue the data for when it can be sent - */ - ptag = (void *)m_tag_locate(m, NGM_GENERIC_COOKIE, - NG_TAG_PRIO, NULL); - - if (ptag && (ptag->priority > NG_PRIO_CUTOFF)) - queue_ptr = &sc->sc_xmitq_hipri; - else - queue_ptr = &sc->sc_xmitq; - - mtx_lock(&sc->sc_mtx); - - if (NG_BT_MBUFQ_FULL(queue_ptr)) { - NG_BT_MBUFQ_DROP(queue_ptr); - NG_FREE_M(m); - error = ENOBUFS; - } else { - NG_BT_MBUFQ_ENQUEUE(queue_ptr, m); - /* - * start bulk-out transfer, if not already started: - */ - usbd_transfer_start(sc->sc_xfer[UDBP_T_WR]); - error = 0; - } - - mtx_unlock(&sc->sc_mtx); - - return (error); -} - -/* - * Do local shutdown processing.. - * We are a persistant device, we refuse to go away, and - * only remove our links and reset ourself. - */ -static int -ng_udbp_rmnode(node_p node) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(node); - - /* Let old node go */ - NG_NODE_SET_PRIVATE(node, NULL); - NG_NODE_UNREF(node); /* forget it ever existed */ - - if (sc == NULL) { - goto done; - } - /* Create Netgraph node */ - if (ng_make_node_common(&ng_udbp_typestruct, &sc->sc_node) != 0) { - printf("%s: Could not create Netgraph node\n", - sc->sc_name); - sc->sc_node = NULL; - goto done; - } - /* Name node */ - if (ng_name_node(sc->sc_node, sc->sc_name) != 0) { - printf("%s: Could not name Netgraph node\n", - sc->sc_name); - NG_NODE_UNREF(sc->sc_node); - sc->sc_node = NULL; - goto done; - } - NG_NODE_SET_PRIVATE(sc->sc_node, sc); - -done: - if (sc) { - mtx_unlock(&sc->sc_mtx); - } - return (0); -} - -/* - * This is called once we've already connected a new hook to the other node. - * It gives us a chance to balk at the last minute. - */ -static int -ng_udbp_connect(hook_p hook) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - - /* probably not at splnet, force outward queueing */ - NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); - - mtx_lock(&sc->sc_mtx); - - sc->sc_flags |= (UDBP_FLAG_READ_STALL | - UDBP_FLAG_WRITE_STALL); - - /* start bulk-in transfer */ - usbd_transfer_start(sc->sc_xfer[UDBP_T_RD]); - - /* start bulk-out transfer */ - usbd_transfer_start(sc->sc_xfer[UDBP_T_WR]); - - mtx_unlock(&sc->sc_mtx); - - return (0); -} - -/* - * Dook disconnection - * - * For this type, removal of the last link destroys the node - */ -static int -ng_udbp_disconnect(hook_p hook) -{ - struct udbp_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - int error = 0; - - if (sc != NULL) { - - mtx_lock(&sc->sc_mtx); - - if (hook != sc->sc_hook) { - error = EINVAL; - } else { - - /* stop bulk-in transfer */ - usbd_transfer_stop(sc->sc_xfer[UDBP_T_RD_CS]); - usbd_transfer_stop(sc->sc_xfer[UDBP_T_RD]); - - /* stop bulk-out transfer */ - usbd_transfer_stop(sc->sc_xfer[UDBP_T_WR_CS]); - usbd_transfer_stop(sc->sc_xfer[UDBP_T_WR]); - - /* cleanup queues */ - NG_BT_MBUFQ_DRAIN(&sc->sc_xmitq); - NG_BT_MBUFQ_DRAIN(&sc->sc_xmitq_hipri); - - if (sc->sc_bulk_in_buffer) { - m_freem(sc->sc_bulk_in_buffer); - sc->sc_bulk_in_buffer = NULL; - } - sc->sc_hook = NULL; - } - - mtx_unlock(&sc->sc_mtx); - } - if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) - && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) - ng_rmnode_self(NG_HOOK_NODE(hook)); - - return (error); -} diff --git a/sys/bus/u4b/misc/udbp.h b/sys/bus/u4b/misc/udbp.h deleted file mode 100644 index e6fd853261..0000000000 --- a/sys/bus/u4b/misc/udbp.h +++ /dev/null @@ -1,80 +0,0 @@ -/*- - * Copyright (c) 1996-2000 Whistle Communications, Inc. - * All rights reserved. - * - * Subject to the following obligations and disclaimer of warranty, use and - * redistribution of this software, in source or object code forms, with or - * without modifications are expressly permitted by Whistle Communications; - * provided, however, that: - * 1. Any and all reproductions of the source or object code must include the - * copyright notice above and the following disclaimer of warranties; and - * 2. No rights are granted, in any manner or form, to use Whistle - * Communications, Inc. trademarks, including the mark "WHISTLE - * COMMUNICATIONS" on advertising, endorsements, or otherwise except as - * such appears in the above copyright notice or in the software. - * - * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO - * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, - * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. - * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY - * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS - * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. - * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES - * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING - * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file was derived from src/sys/netgraph/ng_sample.h, revision 1.1 - * written by Julian Elischer, Whistle Communications. - * - * $FreeBSD$ - */ - -#ifndef _NETGRAPH_UDBP_H_ -#define _NETGRAPH_UDBP_H_ - -/* Node type name. This should be unique among all netgraph node types */ -#define NG_UDBP_NODE_TYPE "udbp" - -/* Node type cookie. Should also be unique. This value MUST change whenever - an incompatible change is made to this header file, to insure consistency. - The de facto method for generating cookies is to take the output of the - date command: date -u +'%s' */ -#define NGM_UDBP_COOKIE 944609300 - - -#define NG_UDBP_HOOK_NAME "data" - -/* Netgraph commands understood by this node type */ -enum { - NGM_UDBP_SET_FLAG = 1, - NGM_UDBP_GET_STATUS, -}; - -/* This structure is returned by the NGM_UDBP_GET_STATUS command */ -struct ngudbpstat { - uint32_t packets_in; /* packets in from downstream */ - uint32_t packets_out; /* packets out towards downstream */ -}; - -/* - * This is used to define the 'parse type' for a struct ngudbpstat, which - * is bascially a description of how to convert a binary struct ngudbpstat - * to an ASCII string and back. See ng_parse.h for more info. - * - * This needs to be kept in sync with the above structure definition - */ -#define NG_UDBP_STATS_TYPE_INFO { \ - { "packets_in", &ng_parse_int32_type }, \ - { "packets_out", &ng_parse_int32_type }, \ - { NULL }, \ -} - -#endif /* _NETGRAPH_UDBP_H_ */ diff --git a/sys/bus/u4b/net/Makefile b/sys/bus/u4b/net/Makefile index d7c6a9de3a..8c1d2635bc 100644 --- a/sys/bus/u4b/net/Makefile +++ b/sys/bus/u4b/net/Makefile @@ -1,5 +1,5 @@ # -# XXX MISSING: rue smsc uhso usie +# XXX MISSING: smsc SUBDIR= aue axe axge cdce cue ipheth kue mos udav uether urndis diff --git a/sys/bus/u4b/net/if_rue.c b/sys/bus/u4b/net/if_rue.c deleted file mode 100644 index ebbe08744d..0000000000 --- a/sys/bus/u4b/net/if_rue.c +++ /dev/null @@ -1,915 +0,0 @@ -/*- - * Copyright (c) 2001-2003, Shunsuke Akiyama . - * Copyright (c) 1997, 1998, 1999, 2000 Bill Paul . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/*- - * Copyright (c) 1997, 1998, 1999, 2000 - * Bill Paul . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bill Paul. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * RealTek RTL8150 USB to fast ethernet controller driver. - * Datasheet is available from - * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "usbdevs.h" - -#define USB_DEBUG_VAR rue_debug -#include -#include - -#include -#include - -#ifdef USB_DEBUG -static int rue_debug = 0; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, rue, CTLFLAG_RW, 0, "USB rue"); -SYSCTL_INT(_hw_usb_rue, OID_AUTO, debug, CTLFLAG_RWTUN, - &rue_debug, 0, "Debug level"); -#endif - -/* - * Various supported device vendors/products. - */ - -static const STRUCT_USB_HOST_ID rue_devs[] = { - {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX, 0)}, - {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USBKR100, 0)}, - {USB_VPI(USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01, 0)}, -}; - -/* prototypes */ - -static device_probe_t rue_probe; -static device_attach_t rue_attach; -static device_detach_t rue_detach; - -static miibus_readreg_t rue_miibus_readreg; -static miibus_writereg_t rue_miibus_writereg; -static miibus_statchg_t rue_miibus_statchg; - -static usb_callback_t rue_intr_callback; -static usb_callback_t rue_bulk_read_callback; -static usb_callback_t rue_bulk_write_callback; - -static uether_fn_t rue_attach_post; -static uether_fn_t rue_init; -static uether_fn_t rue_stop; -static uether_fn_t rue_start; -static uether_fn_t rue_tick; -static uether_fn_t rue_setmulti; -static uether_fn_t rue_setpromisc; - -static int rue_read_mem(struct rue_softc *, uint16_t, void *, int); -static int rue_write_mem(struct rue_softc *, uint16_t, void *, int); -static uint8_t rue_csr_read_1(struct rue_softc *, uint16_t); -static uint16_t rue_csr_read_2(struct rue_softc *, uint16_t); -static int rue_csr_write_1(struct rue_softc *, uint16_t, uint8_t); -static int rue_csr_write_2(struct rue_softc *, uint16_t, uint16_t); -static int rue_csr_write_4(struct rue_softc *, int, uint32_t); - -static void rue_reset(struct rue_softc *); -static int rue_ifmedia_upd(struct ifnet *); -static void rue_ifmedia_sts(struct ifnet *, struct ifmediareq *); - -static const struct usb_config rue_config[RUE_N_TRANSFER] = { - - [RUE_BULK_DT_WR] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = MCLBYTES, - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = rue_bulk_write_callback, - .timeout = 10000, /* 10 seconds */ - }, - - [RUE_BULK_DT_RD] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = (MCLBYTES + 4), - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = rue_bulk_read_callback, - .timeout = 0, /* no timeout */ - }, - - [RUE_INTR_DT_RD] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .bufsize = 0, /* use wMaxPacketSize */ - .callback = rue_intr_callback, - }, -}; - -static device_method_t rue_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rue_probe), - DEVMETHOD(device_attach, rue_attach), - DEVMETHOD(device_detach, rue_detach), - - /* MII interface */ - DEVMETHOD(miibus_readreg, rue_miibus_readreg), - DEVMETHOD(miibus_writereg, rue_miibus_writereg), - DEVMETHOD(miibus_statchg, rue_miibus_statchg), - - DEVMETHOD_END -}; - -static driver_t rue_driver = { - .name = "rue", - .methods = rue_methods, - .size = sizeof(struct rue_softc), -}; - -static devclass_t rue_devclass; - -DRIVER_MODULE(rue, uhub, rue_driver, rue_devclass, NULL, NULL); -DRIVER_MODULE(miibus, rue, miibus_driver, miibus_devclass, NULL, NULL); -MODULE_DEPEND(rue, uether, 1, 1, 1); -MODULE_DEPEND(rue, usb, 1, 1, 1); -MODULE_DEPEND(rue, ether, 1, 1, 1); -MODULE_DEPEND(rue, miibus, 1, 1, 1); -MODULE_VERSION(rue, 1); - -static const struct usb_ether_methods rue_ue_methods = { - .ue_attach_post = rue_attach_post, - .ue_start = rue_start, - .ue_init = rue_init, - .ue_stop = rue_stop, - .ue_tick = rue_tick, - .ue_setmulti = rue_setmulti, - .ue_setpromisc = rue_setpromisc, - .ue_mii_upd = rue_ifmedia_upd, - .ue_mii_sts = rue_ifmedia_sts, -}; - -#define RUE_SETBIT(sc, reg, x) \ - rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) | (x)) - -#define RUE_CLRBIT(sc, reg, x) \ - rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) & ~(x)) - -static int -rue_read_mem(struct rue_softc *sc, uint16_t addr, void *buf, int len) -{ - struct usb_device_request req; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); -} - -static int -rue_write_mem(struct rue_softc *sc, uint16_t addr, void *buf, int len) -{ - struct usb_device_request req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = UR_SET_ADDRESS; - USETW(req.wValue, addr); - USETW(req.wIndex, 0); - USETW(req.wLength, len); - - return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); -} - -static uint8_t -rue_csr_read_1(struct rue_softc *sc, uint16_t reg) -{ - uint8_t val; - - rue_read_mem(sc, reg, &val, 1); - return (val); -} - -static uint16_t -rue_csr_read_2(struct rue_softc *sc, uint16_t reg) -{ - uint8_t val[2]; - - rue_read_mem(sc, reg, &val, 2); - return (UGETW(val)); -} - -static int -rue_csr_write_1(struct rue_softc *sc, uint16_t reg, uint8_t val) -{ - return (rue_write_mem(sc, reg, &val, 1)); -} - -static int -rue_csr_write_2(struct rue_softc *sc, uint16_t reg, uint16_t val) -{ - uint8_t temp[2]; - - USETW(temp, val); - return (rue_write_mem(sc, reg, &temp, 2)); -} - -static int -rue_csr_write_4(struct rue_softc *sc, int reg, uint32_t val) -{ - uint8_t temp[4]; - - USETDW(temp, val); - return (rue_write_mem(sc, reg, &temp, 4)); -} - -static int -rue_miibus_readreg(device_t dev, int phy, int reg) -{ - struct rue_softc *sc = device_get_softc(dev); - uint16_t rval; - uint16_t ruereg; - int locked; - - if (phy != 0) /* RTL8150 supports PHY == 0, only */ - return (0); - - locked = mtx_owned(&sc->sc_mtx); - if (!locked) - RUE_LOCK(sc); - - switch (reg) { - case MII_BMCR: - ruereg = RUE_BMCR; - break; - case MII_BMSR: - ruereg = RUE_BMSR; - break; - case MII_ANAR: - ruereg = RUE_ANAR; - break; - case MII_ANER: - ruereg = RUE_AER; - break; - case MII_ANLPAR: - ruereg = RUE_ANLP; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - rval = 0; - goto done; - default: - if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { - rval = rue_csr_read_1(sc, reg); - goto done; - } - device_printf(sc->sc_ue.ue_dev, "bad phy register\n"); - rval = 0; - goto done; - } - - rval = rue_csr_read_2(sc, ruereg); -done: - if (!locked) - RUE_UNLOCK(sc); - return (rval); -} - -static int -rue_miibus_writereg(device_t dev, int phy, int reg, int data) -{ - struct rue_softc *sc = device_get_softc(dev); - uint16_t ruereg; - int locked; - - if (phy != 0) /* RTL8150 supports PHY == 0, only */ - return (0); - - locked = mtx_owned(&sc->sc_mtx); - if (!locked) - RUE_LOCK(sc); - - switch (reg) { - case MII_BMCR: - ruereg = RUE_BMCR; - break; - case MII_BMSR: - ruereg = RUE_BMSR; - break; - case MII_ANAR: - ruereg = RUE_ANAR; - break; - case MII_ANER: - ruereg = RUE_AER; - break; - case MII_ANLPAR: - ruereg = RUE_ANLP; - break; - case MII_PHYIDR1: - case MII_PHYIDR2: - goto done; - default: - if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { - rue_csr_write_1(sc, reg, data); - goto done; - } - device_printf(sc->sc_ue.ue_dev, " bad phy register\n"); - goto done; - } - rue_csr_write_2(sc, ruereg, data); -done: - if (!locked) - RUE_UNLOCK(sc); - return (0); -} - -static void -rue_miibus_statchg(device_t dev) -{ - /* - * When the code below is enabled the card starts doing weird - * things after link going from UP to DOWN and back UP. - * - * Looks like some of register writes below messes up PHY - * interface. - * - * No visible regressions were found after commenting this code - * out, so that disable it for good. - */ -#if 0 - struct rue_softc *sc = device_get_softc(dev); - struct mii_data *mii = GET_MII(sc); - uint16_t bmcr; - int locked; - - locked = mtx_owned(&sc->sc_mtx); - if (!locked) - RUE_LOCK(sc); - - RUE_CLRBIT(sc, RUE_CR, (RUE_CR_RE | RUE_CR_TE)); - - bmcr = rue_csr_read_2(sc, RUE_BMCR); - - if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) - bmcr |= RUE_BMCR_SPD_SET; - else - bmcr &= ~RUE_BMCR_SPD_SET; - - if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) - bmcr |= RUE_BMCR_DUPLEX; - else - bmcr &= ~RUE_BMCR_DUPLEX; - - rue_csr_write_2(sc, RUE_BMCR, bmcr); - - RUE_SETBIT(sc, RUE_CR, (RUE_CR_RE | RUE_CR_TE)); - - if (!locked) - RUE_UNLOCK(sc); -#endif -} - -static void -rue_setpromisc(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); - - RUE_LOCK_ASSERT(sc, MA_OWNED); - - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - RUE_SETBIT(sc, RUE_RCR, RUE_RCR_AAP); - else - RUE_CLRBIT(sc, RUE_RCR, RUE_RCR_AAP); -} - -/* - * Program the 64-bit multicast hash filter. - */ -static void -rue_setmulti(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); - uint16_t rxcfg; - int h = 0; - uint32_t hashes[2] = { 0, 0 }; - struct ifmultiaddr *ifma; - int mcnt = 0; - - RUE_LOCK_ASSERT(sc, MA_OWNED); - - rxcfg = rue_csr_read_2(sc, RUE_RCR); - - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { - rxcfg |= (RUE_RCR_AAM | RUE_RCR_AAP); - rxcfg &= ~RUE_RCR_AM; - rue_csr_write_2(sc, RUE_RCR, rxcfg); - rue_csr_write_4(sc, RUE_MAR0, 0xFFFFFFFF); - rue_csr_write_4(sc, RUE_MAR4, 0xFFFFFFFF); - return; - } - - /* first, zot all the existing hash bits */ - rue_csr_write_4(sc, RUE_MAR0, 0); - rue_csr_write_4(sc, RUE_MAR4, 0); - - /* now program new ones */ - if_maddr_rlock(ifp); - TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) - { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - mcnt++; - } - if_maddr_runlock(ifp); - - if (mcnt) - rxcfg |= RUE_RCR_AM; - else - rxcfg &= ~RUE_RCR_AM; - - rxcfg &= ~(RUE_RCR_AAM | RUE_RCR_AAP); - - rue_csr_write_2(sc, RUE_RCR, rxcfg); - rue_csr_write_4(sc, RUE_MAR0, hashes[0]); - rue_csr_write_4(sc, RUE_MAR4, hashes[1]); -} - -static void -rue_reset(struct rue_softc *sc) -{ - int i; - - rue_csr_write_1(sc, RUE_CR, RUE_CR_SOFT_RST); - - for (i = 0; i != RUE_TIMEOUT; i++) { - if (uether_pause(&sc->sc_ue, hz / 1000)) - break; - if (!(rue_csr_read_1(sc, RUE_CR) & RUE_CR_SOFT_RST)) - break; - } - if (i == RUE_TIMEOUT) - device_printf(sc->sc_ue.ue_dev, "reset never completed\n"); - - uether_pause(&sc->sc_ue, hz / 100); -} - -static void -rue_attach_post(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - - /* reset the adapter */ - rue_reset(sc); - - /* get station address from the EEPROM */ - rue_read_mem(sc, RUE_EEPROM_IDR0, ue->ue_eaddr, ETHER_ADDR_LEN); -} - -/* - * Probe for a RTL8150 chip. - */ -static int -rue_probe(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != RUE_CONFIG_IDX) - return (ENXIO); - if (uaa->info.bIfaceIndex != RUE_IFACE_IDX) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(rue_devs, sizeof(rue_devs), uaa)); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static int -rue_attach(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct rue_softc *sc = device_get_softc(dev); - struct usb_ether *ue = &sc->sc_ue; - uint8_t iface_index; - int error; - - device_set_usb_desc(dev); - mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); - - iface_index = RUE_IFACE_IDX; - error = usbd_transfer_setup(uaa->device, &iface_index, - sc->sc_xfer, rue_config, RUE_N_TRANSFER, - sc, &sc->sc_mtx); - if (error) { - device_printf(dev, "allocating USB transfers failed\n"); - goto detach; - } - - ue->ue_sc = sc; - ue->ue_dev = dev; - ue->ue_udev = uaa->device; - ue->ue_mtx = &sc->sc_mtx; - ue->ue_methods = &rue_ue_methods; - - error = uether_ifattach(ue); - if (error) { - device_printf(dev, "could not attach interface\n"); - goto detach; - } - return (0); /* success */ - -detach: - rue_detach(dev); - return (ENXIO); /* failure */ -} - -static int -rue_detach(device_t dev) -{ - struct rue_softc *sc = device_get_softc(dev); - struct usb_ether *ue = &sc->sc_ue; - - usbd_transfer_unsetup(sc->sc_xfer, RUE_N_TRANSFER); - uether_ifdetach(ue); - mtx_destroy(&sc->sc_mtx); - - return (0); -} - -static void -rue_intr_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct rue_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = uether_getifp(&sc->sc_ue); - struct rue_intrpkt pkt; - struct usb_page_cache *pc; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - if (ifp && (ifp->if_drv_flags & IFF_DRV_RUNNING) && - actlen >= sizeof(pkt)) { - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); - - ifp->if_ierrors += pkt.rue_rxlost_cnt; - ifp->if_ierrors += pkt.rue_crcerr_cnt; - ifp->if_collisions += pkt.rue_col_cnt; - } - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - return; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - return; - } -} - -static void -rue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct rue_softc *sc = usbd_xfer_softc(xfer); - struct usb_ether *ue = &sc->sc_ue; - struct ifnet *ifp = uether_getifp(ue); - struct usb_page_cache *pc; - uint16_t status; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - if (actlen < 4) { - ifp->if_ierrors++; - goto tr_setup; - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, actlen - 4, &status, sizeof(status)); - actlen -= 4; - - /* check recieve packet was valid or not */ - status = le16toh(status); - if ((status & RUE_RXSTAT_VALID) == 0) { - ifp->if_ierrors++; - goto tr_setup; - } - uether_rxbuf(ue, pc, 0, actlen); - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - uether_rxflush(ue); - return; - - default: /* Error */ - DPRINTF("bulk read error, %s\n", - usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - return; - } -} - -static void -rue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct rue_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = uether_getifp(&sc->sc_ue); - struct usb_page_cache *pc; - struct mbuf *m; - int temp_len; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTFN(11, "transfer complete\n"); - ifp->if_opackets++; - - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - if ((sc->sc_flags & RUE_FLAG_LINK) == 0) { - /* - * don't send anything if there is no link ! - */ - return; - } - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - - if (m == NULL) - return; - if (m->m_pkthdr.len > MCLBYTES) - m->m_pkthdr.len = MCLBYTES; - temp_len = m->m_pkthdr.len; - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); - - /* - * This is an undocumented behavior. - * RTL8150 chip doesn't send frame length smaller than - * RUE_MIN_FRAMELEN (60) byte packet. - */ - if (temp_len < RUE_MIN_FRAMELEN) { - usbd_frame_zero(pc, temp_len, - RUE_MIN_FRAMELEN - temp_len); - temp_len = RUE_MIN_FRAMELEN; - } - usbd_xfer_set_frame_len(xfer, 0, temp_len); - - /* - * if there's a BPF listener, bounce a copy - * of this frame to him: - */ - BPF_MTAP(ifp, m); - - m_freem(m); - - usbd_transfer_submit(xfer); - - return; - - default: /* Error */ - DPRINTFN(11, "transfer error, %s\n", - usbd_errstr(error)); - - ifp->if_oerrors++; - - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - return; - } -} - -static void -rue_tick(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - struct mii_data *mii = GET_MII(sc); - - RUE_LOCK_ASSERT(sc, MA_OWNED); - - mii_tick(mii); - if ((sc->sc_flags & RUE_FLAG_LINK) == 0 - && mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - sc->sc_flags |= RUE_FLAG_LINK; - rue_start(ue); - } -} - -static void -rue_start(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - - /* - * start the USB transfers, if not already started: - */ - usbd_transfer_start(sc->sc_xfer[RUE_INTR_DT_RD]); - usbd_transfer_start(sc->sc_xfer[RUE_BULK_DT_RD]); - usbd_transfer_start(sc->sc_xfer[RUE_BULK_DT_WR]); -} - -static void -rue_init(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); - - RUE_LOCK_ASSERT(sc, MA_OWNED); - - /* - * Cancel pending I/O - */ - rue_reset(sc); - - /* Set MAC address */ - rue_write_mem(sc, RUE_IDR0, IF_LLADDR(ifp), ETHER_ADDR_LEN); - - rue_stop(ue); - - /* - * Set the initial TX and RX configuration. - */ - rue_csr_write_1(sc, RUE_TCR, RUE_TCR_CONFIG); - rue_csr_write_2(sc, RUE_RCR, RUE_RCR_CONFIG|RUE_RCR_AB); - - /* Load the multicast filter */ - rue_setpromisc(ue); - /* Load the multicast filter. */ - rue_setmulti(ue); - - /* Enable RX and TX */ - rue_csr_write_1(sc, RUE_CR, (RUE_CR_TE | RUE_CR_RE | RUE_CR_EP3CLREN)); - - usbd_xfer_set_stall(sc->sc_xfer[RUE_BULK_DT_WR]); - - ifp->if_drv_flags |= IFF_DRV_RUNNING; - rue_start(ue); -} - -/* - * Set media options. - */ -static int -rue_ifmedia_upd(struct ifnet *ifp) -{ - struct rue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - struct mii_softc *miisc; - - RUE_LOCK_ASSERT(sc, MA_OWNED); - - sc->sc_flags &= ~RUE_FLAG_LINK; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - PHY_RESET(miisc); - mii_mediachg(mii); - return (0); -} - -/* - * Report current media status. - */ -static void -rue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) -{ - struct rue_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); - - RUE_LOCK(sc); - mii_pollstat(mii); - ifmr->ifm_active = mii->mii_media_active; - ifmr->ifm_status = mii->mii_media_status; - RUE_UNLOCK(sc); -} - -static void -rue_stop(struct usb_ether *ue) -{ - struct rue_softc *sc = uether_getsc(ue); - struct ifnet *ifp = uether_getifp(ue); - - RUE_LOCK_ASSERT(sc, MA_OWNED); - - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - sc->sc_flags &= ~RUE_FLAG_LINK; - - /* - * stop all the transfers, if not already stopped: - */ - usbd_transfer_stop(sc->sc_xfer[RUE_BULK_DT_WR]); - usbd_transfer_stop(sc->sc_xfer[RUE_BULK_DT_RD]); - usbd_transfer_stop(sc->sc_xfer[RUE_INTR_DT_RD]); - - rue_csr_write_1(sc, RUE_CR, 0x00); - - rue_reset(sc); -} diff --git a/sys/bus/u4b/net/if_ruereg.h b/sys/bus/u4b/net/if_ruereg.h deleted file mode 100644 index c90a969215..0000000000 --- a/sys/bus/u4b/net/if_ruereg.h +++ /dev/null @@ -1,178 +0,0 @@ -/*- - * Copyright (c) 2001-2003, Shunsuke Akiyama . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define RUE_CONFIG_IDX 0 /* config number 1 */ -#define RUE_IFACE_IDX 0 - -#define RUE_INTR_PKTLEN 0x8 - -#define RUE_TIMEOUT 50 -#define RUE_MIN_FRAMELEN 60 - -/* Registers. */ -#define RUE_IDR0 0x0120 -#define RUE_IDR1 0x0121 -#define RUE_IDR2 0x0122 -#define RUE_IDR3 0x0123 -#define RUE_IDR4 0x0124 -#define RUE_IDR5 0x0125 - -#define RUE_MAR0 0x0126 -#define RUE_MAR1 0x0127 -#define RUE_MAR2 0x0128 -#define RUE_MAR3 0x0129 -#define RUE_MAR4 0x012A -#define RUE_MAR5 0x012B -#define RUE_MAR6 0x012C -#define RUE_MAR7 0x012D - -#define RUE_CR 0x012E /* B, R/W */ -#define RUE_CR_SOFT_RST 0x10 -#define RUE_CR_RE 0x08 -#define RUE_CR_TE 0x04 -#define RUE_CR_EP3CLREN 0x02 - -#define RUE_TCR 0x012F /* B, R/W */ -#define RUE_TCR_TXRR1 0x80 -#define RUE_TCR_TXRR0 0x40 -#define RUE_TCR_IFG1 0x10 -#define RUE_TCR_IFG0 0x08 -#define RUE_TCR_NOCRC 0x01 -#define RUE_TCR_CONFIG (RUE_TCR_TXRR1 | RUE_TCR_TXRR0 | \ - RUE_TCR_IFG1 | RUE_TCR_IFG0) - -#define RUE_RCR 0x0130 /* W, R/W */ -#define RUE_RCR_TAIL 0x80 -#define RUE_RCR_AER 0x40 -#define RUE_RCR_AR 0x20 -#define RUE_RCR_AM 0x10 -#define RUE_RCR_AB 0x08 -#define RUE_RCR_AD 0x04 -#define RUE_RCR_AAM 0x02 -#define RUE_RCR_AAP 0x01 -#define RUE_RCR_CONFIG (RUE_RCR_TAIL | RUE_RCR_AD) - -#define RUE_TSR 0x0132 -#define RUE_RSR 0x0133 -#define RUE_CON0 0x0135 -#define RUE_CON1 0x0136 -#define RUE_MSR 0x0137 -#define RUE_PHYADD 0x0138 -#define RUE_PHYDAT 0x0139 - -#define RUE_PHYCNT 0x013B /* B, R/W */ -#define RUE_PHYCNT_PHYOWN 0x40 -#define RUE_PHYCNT_RWCR 0x20 - -#define RUE_GPPC 0x013D -#define RUE_WAKECNT 0x013E - -#define RUE_BMCR 0x0140 -#define RUE_BMCR_SPD_SET 0x2000 -#define RUE_BMCR_DUPLEX 0x0100 - -#define RUE_BMSR 0x0142 - -#define RUE_ANAR 0x0144 /* W, R/W */ -#define RUE_ANAR_PAUSE 0x0400 - -#define RUE_ANLP 0x0146 /* W, R/O */ -#define RUE_ANLP_PAUSE 0x0400 - -#define RUE_AER 0x0148 - -#define RUE_NWAYT 0x014A -#define RUE_CSCR 0x014C - -#define RUE_CRC0 0x014E -#define RUE_CRC1 0x0150 -#define RUE_CRC2 0x0152 -#define RUE_CRC3 0x0154 -#define RUE_CRC4 0x0156 - -#define RUE_BYTEMASK0 0x0158 -#define RUE_BYTEMASK1 0x0160 -#define RUE_BYTEMASK2 0x0168 -#define RUE_BYTEMASK3 0x0170 -#define RUE_BYTEMASK4 0x0178 - -#define RUE_PHY1 0x0180 -#define RUE_PHY2 0x0184 - -#define RUE_TW1 0x0186 - -#define RUE_REG_MIN 0x0120 -#define RUE_REG_MAX 0x0189 - -/* EEPROM address declarations. */ -#define RUE_EEPROM_BASE 0x1200 -#define RUE_EEPROM_IDR0 (RUE_EEPROM_BASE + 0x02) -#define RUE_EEPROM_IDR1 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR2 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR3 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR4 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_IDR5 (RUE_EEPROM_BASE + 0x03) -#define RUE_EEPROM_INTERVAL (RUE_EEPROM_BASE + 0x17) - -#define RUE_RXSTAT_VALID (0x01 << 12) -#define RUE_RXSTAT_RUNT (0x02 << 12) -#define RUE_RXSTAT_PMATCH (0x04 << 12) -#define RUE_RXSTAT_MCAST (0x08 << 12) - -#define GET_MII(sc) uether_getmii(&(sc)->sc_ue) - -struct rue_intrpkt { - uint8_t rue_tsr; - uint8_t rue_rsr; - uint8_t rue_gep_msr; - uint8_t rue_waksr; - uint8_t rue_txok_cnt; - uint8_t rue_rxlost_cnt; - uint8_t rue_crcerr_cnt; - uint8_t rue_col_cnt; -} __packed; - -enum { - RUE_BULK_DT_WR, - RUE_BULK_DT_RD, - RUE_INTR_DT_RD, - RUE_N_TRANSFER, -}; - -struct rue_softc { - struct usb_ether sc_ue; - struct mtx sc_mtx; - struct usb_xfer *sc_xfer[RUE_N_TRANSFER]; - - int sc_flags; -#define RUE_FLAG_LINK 0x0001 -}; - -#define RUE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define RUE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define RUE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t) diff --git a/sys/bus/u4b/net/if_usie.c b/sys/bus/u4b/net/if_usie.c deleted file mode 100644 index e476daefe3..0000000000 --- a/sys/bus/u4b/net/if_usie.c +++ /dev/null @@ -1,1588 +0,0 @@ -/*- - * Copyright (c) 2011 Anybots Inc - * written by Akinori Furukoshi - * - ucom part is based on u3g.c - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include "usbdevs.h" - -#define USB_DEBUG_VAR usie_debug -#include -#include -#include - -#include - -#include - -#ifdef USB_DEBUG -static int usie_debug = 0; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, usie, CTLFLAG_RW, 0, "sierra USB modem"); -SYSCTL_INT(_hw_usb_usie, OID_AUTO, debug, CTLFLAG_RWTUN, &usie_debug, 0, - "usie debug level"); -#endif - -/* Sierra Wireless Direct IP modems */ -static const STRUCT_USB_HOST_ID usie_devs[] = { -#define USIE_DEV(v, d) { \ - USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##d) } - USIE_DEV(SIERRA, MC8700), - USIE_DEV(SIERRA, TRUINSTALL), - USIE_DEV(AIRPRIME, USB308), -#undef USIE_DEV -}; - -static device_probe_t usie_probe; -static device_attach_t usie_attach; -static device_detach_t usie_detach; - -static void usie_uc_update_line_state(struct ucom_softc *, uint8_t); -static void usie_uc_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); -static void usie_uc_cfg_set_dtr(struct ucom_softc *, uint8_t); -static void usie_uc_cfg_set_rts(struct ucom_softc *, uint8_t); -static void usie_uc_cfg_open(struct ucom_softc *); -static void usie_uc_cfg_close(struct ucom_softc *); -static void usie_uc_start_read(struct ucom_softc *); -static void usie_uc_stop_read(struct ucom_softc *); -static void usie_uc_start_write(struct ucom_softc *); -static void usie_uc_stop_write(struct ucom_softc *); - -static usb_callback_t usie_uc_tx_callback; -static usb_callback_t usie_uc_rx_callback; -static usb_callback_t usie_uc_status_callback; -static usb_callback_t usie_if_tx_callback; -static usb_callback_t usie_if_rx_callback; -static usb_callback_t usie_if_status_callback; - -static void usie_if_sync_to(void *); -static void usie_if_sync_cb(void *, int); -static void usie_if_status_cb(void *, int); - -static void usie_if_start(struct ifnet *, struct ifaltq_subque *); -static int usie_if_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct route *); -static void usie_if_init(void *); -static void usie_if_stop(struct usie_softc *); -static int usie_if_ioctl(struct ifnet *, u_long, caddr_t); - -static int usie_do_request(struct usie_softc *, struct usb_device_request *, void *); -static int usie_if_cmd(struct usie_softc *, uint8_t); -static void usie_cns_req(struct usie_softc *, uint32_t, uint16_t); -static void usie_cns_rsp(struct usie_softc *, struct usie_cns *); -static void usie_hip_rsp(struct usie_softc *, uint8_t *, uint32_t); -static int usie_driver_loaded(struct module *, int, void *); - -static const struct usb_config usie_uc_config[USIE_UC_N_XFER] = { - [USIE_UC_STATUS] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = 0, /* use wMaxPacketSize */ - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = &usie_uc_status_callback, - }, - [USIE_UC_RX] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = USIE_BUFSIZE, - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, - .callback = &usie_uc_rx_callback, - }, - [USIE_UC_TX] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = USIE_BUFSIZE, - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = &usie_uc_tx_callback, - } -}; - -static const struct usb_config usie_if_config[USIE_IF_N_XFER] = { - [USIE_IF_STATUS] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = 0, /* use wMaxPacketSize */ - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = &usie_if_status_callback, - }, - [USIE_IF_RX] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = USIE_BUFSIZE, - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = &usie_if_rx_callback, - }, - [USIE_IF_TX] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = MAX(USIE_BUFSIZE, MCLBYTES), - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = &usie_if_tx_callback, - } -}; - -static device_method_t usie_methods[] = { - DEVMETHOD(device_probe, usie_probe), - DEVMETHOD(device_attach, usie_attach), - DEVMETHOD(device_detach, usie_detach), - DEVMETHOD_END -}; - -static driver_t usie_driver = { - .name = "usie", - .methods = usie_methods, - .size = sizeof(struct usie_softc), -}; - -static devclass_t usie_devclass; -static eventhandler_tag usie_etag; - -DRIVER_MODULE(usie, uhub, usie_driver, usie_devclass, usie_driver_loaded, NULL); -MODULE_DEPEND(usie, ucom, 1, 1, 1); -MODULE_DEPEND(usie, usb, 1, 1, 1); -MODULE_VERSION(usie, 1); - -static const struct ucom_callback usie_uc_callback = { - .ucom_cfg_get_status = &usie_uc_cfg_get_status, - .ucom_cfg_set_dtr = &usie_uc_cfg_set_dtr, - .ucom_cfg_set_rts = &usie_uc_cfg_set_rts, - .ucom_cfg_open = &usie_uc_cfg_open, - .ucom_cfg_close = &usie_uc_cfg_close, - .ucom_start_read = &usie_uc_start_read, - .ucom_stop_read = &usie_uc_stop_read, - .ucom_start_write = &usie_uc_start_write, - .ucom_stop_write = &usie_uc_stop_write, -}; - -static void -usie_autoinst(void *arg, struct usb_device *udev, - struct usb_attach_arg *uaa) -{ - struct usb_interface *iface; - struct usb_interface_descriptor *id; - struct usb_device_request req; - int err; - - if (uaa->dev_state != UAA_DEV_READY) - return; - - iface = usbd_get_iface(udev, 0); - if (iface == NULL) - return; - - id = iface->idesc; - if (id == NULL || id->bInterfaceClass != UICLASS_MASS) - return; - - if (usbd_lookup_id_by_uaa(usie_devs, sizeof(usie_devs), uaa) != 0) - return; /* no device match */ - - if (bootverbose) { - DPRINTF("Ejecting %s %s\n", - usb_get_manufacturer(udev), - usb_get_product(udev)); - } - req.bmRequestType = UT_VENDOR; - req.bRequest = UR_SET_INTERFACE; - USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP); - USETW(req.wIndex, UHF_PORT_CONNECTION); - USETW(req.wLength, 0); - - /* at this moment there is no mutex */ - err = usbd_do_request_flags(udev, NULL, &req, - NULL, 0, NULL, 250 /* ms */ ); - - /* success, mark the udev as disappearing */ - if (err == 0) - uaa->dev_state = UAA_DEV_EJECTING; -} - -static int -usie_probe(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != USIE_CNFG_INDEX) - return (ENXIO); - if (uaa->info.bIfaceIndex != USIE_IFACE_INDEX) - return (ENXIO); - if (uaa->info.bInterfaceClass != UICLASS_VENDOR) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(usie_devs, sizeof(usie_devs), uaa)); -} - -static int -usie_attach(device_t self) -{ - struct usie_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ifnet *ifp; - struct usb_interface *iface; - struct usb_interface_descriptor *id; - struct usb_device_request req; - int err; - uint16_t fwattr; - uint8_t iface_index; - uint8_t ifidx; - uint8_t start; - - device_set_usb_desc(self); - sc->sc_udev = uaa->device; - sc->sc_dev = self; - - mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF); - - TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc); - TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc); - - usb_callout_init_mtx(&sc->sc_if_sync_ch, &sc->sc_mtx, 0); - - mtx_lock(&sc->sc_mtx); - - /* set power mode to D0 */ - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = USIE_POWER; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - if (usie_do_request(sc, &req, NULL)) { - mtx_unlock(&sc->sc_mtx); - goto detach; - } - /* read fw attr */ - fwattr = 0; - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = USIE_FW_ATTR; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(fwattr)); - if (usie_do_request(sc, &req, &fwattr)) { - mtx_unlock(&sc->sc_mtx); - goto detach; - } - mtx_unlock(&sc->sc_mtx); - - /* check DHCP supports */ - DPRINTF("fwattr=%x\n", fwattr); - if (!(fwattr & USIE_FW_DHCP)) { - device_printf(self, "DHCP is not supported. A firmware upgrade might be needed.\n"); - } - - /* find available interfaces */ - sc->sc_nucom = 0; - for (ifidx = 0; ifidx < USIE_IFACE_MAX; ifidx++) { - iface = usbd_get_iface(uaa->device, ifidx); - if (iface == NULL) - break; - - id = usbd_get_interface_descriptor(iface); - if ((id == NULL) || (id->bInterfaceClass != UICLASS_VENDOR)) - continue; - - /* setup Direct IP transfer */ - if (id->bInterfaceNumber >= 7 && id->bNumEndpoints == 3) { - sc->sc_if_ifnum = id->bInterfaceNumber; - iface_index = ifidx; - - DPRINTF("ifnum=%d, ifidx=%d\n", - sc->sc_if_ifnum, ifidx); - - err = usbd_transfer_setup(uaa->device, - &iface_index, sc->sc_if_xfer, usie_if_config, - USIE_IF_N_XFER, sc, &sc->sc_mtx); - - if (err == 0) - continue; - - device_printf(self, - "could not allocate USB transfers on " - "iface_index=%d, err=%s\n", - iface_index, usbd_errstr(err)); - goto detach; - } - - /* setup ucom */ - if (sc->sc_nucom >= USIE_UCOM_MAX) - continue; - - usbd_set_parent_iface(uaa->device, ifidx, - uaa->info.bIfaceIndex); - - DPRINTF("NumEndpoints=%d bInterfaceNumber=%d\n", - id->bNumEndpoints, id->bInterfaceNumber); - - if (id->bNumEndpoints == 2) { - sc->sc_uc_xfer[sc->sc_nucom][0] = NULL; - start = 1; - } else - start = 0; - - err = usbd_transfer_setup(uaa->device, &ifidx, - sc->sc_uc_xfer[sc->sc_nucom] + start, - usie_uc_config + start, USIE_UC_N_XFER - start, - &sc->sc_ucom[sc->sc_nucom], &sc->sc_mtx); - - if (err != 0) { - DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(err)); - continue; - } - - mtx_lock(&sc->sc_mtx); - for (; start < USIE_UC_N_XFER; start++) - usbd_xfer_set_stall(sc->sc_uc_xfer[sc->sc_nucom][start]); - mtx_unlock(&sc->sc_mtx); - - sc->sc_uc_ifnum[sc->sc_nucom] = id->bInterfaceNumber; - - sc->sc_nucom++; /* found a port */ - } - - if (sc->sc_nucom == 0) { - device_printf(self, "no comports found\n"); - goto detach; - } - - err = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, - sc->sc_nucom, sc, &usie_uc_callback, &sc->sc_mtx); - - if (err != 0) { - DPRINTF("ucom_attach failed\n"); - goto detach; - } - DPRINTF("Found %d interfaces.\n", sc->sc_nucom); - - /* setup ifnet (Direct IP) */ - sc->sc_ifp = ifp = if_alloc(IFT_OTHER); - - if (ifp == NULL) { - device_printf(self, "Could not allocate a network interface\n"); - goto detach; - } - if_initname(ifp, "usie", device_get_unit(self)); - - ifp->if_softc = sc; - ifp->if_mtu = USIE_MTU_MAX; - ifp->if_flags |= IFF_NOARP; - ifp->if_init = usie_if_init; - ifp->if_ioctl = usie_if_ioctl; - ifp->if_start = usie_if_start; - ifp->if_output = usie_if_output; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - if_attach(ifp); - bpfattach(ifp, DLT_RAW, 0); - - if (fwattr & USIE_PM_AUTO) { - usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE); - DPRINTF("enabling automatic suspend and resume\n"); - } else { - usbd_set_power_mode(uaa->device, USB_POWER_MODE_ON); - DPRINTF("USB power is always ON\n"); - } - - DPRINTF("device attached\n"); - return (0); - -detach: - usie_detach(self); - return (ENOMEM); -} - -static int -usie_detach(device_t self) -{ - struct usie_softc *sc = device_get_softc(self); - uint8_t x; - - /* detach ifnet */ - if (sc->sc_ifp != NULL) { - usie_if_stop(sc); - usbd_transfer_unsetup(sc->sc_if_xfer, USIE_IF_N_XFER); - bpfdetach(sc->sc_ifp); - if_detach(sc->sc_ifp); - if_free(sc->sc_ifp); - sc->sc_ifp = NULL; - } - /* detach ucom */ - if (sc->sc_nucom > 0) - ucom_detach(&sc->sc_super_ucom, sc->sc_ucom); - - /* stop all USB transfers */ - usbd_transfer_unsetup(sc->sc_if_xfer, USIE_IF_N_XFER); - - for (x = 0; x != USIE_UCOM_MAX; x++) - usbd_transfer_unsetup(sc->sc_uc_xfer[x], USIE_UC_N_XFER); - - mtx_destroy(&sc->sc_mtx); - - return (0); -} - -static void -usie_uc_update_line_state(struct ucom_softc *ucom, uint8_t ls) -{ - struct usie_softc *sc = ucom->sc_parent; - struct usb_device_request req; - - if (sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_STATUS] == NULL) - return; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = USIE_LINK_STATE; - USETW(req.wValue, ls); - USETW(req.wIndex, sc->sc_uc_ifnum[ucom->sc_subunit]); - USETW(req.wLength, 0); - - DPRINTF("sc_uc_ifnum=%d\n", sc->sc_uc_ifnum[ucom->sc_subunit]); - - usie_do_request(sc, &req, NULL); -} - -static void -usie_uc_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) -{ - struct usie_softc *sc = ucom->sc_parent; - - *msr = sc->sc_msr; - *lsr = sc->sc_lsr; -} - -static void -usie_uc_cfg_set_dtr(struct ucom_softc *ucom, uint8_t flag) -{ - uint8_t dtr; - - dtr = flag ? USIE_LS_DTR : 0; - usie_uc_update_line_state(ucom, dtr); -} - -static void -usie_uc_cfg_set_rts(struct ucom_softc *ucom, uint8_t flag) -{ - uint8_t rts; - - rts = flag ? USIE_LS_RTS : 0; - usie_uc_update_line_state(ucom, rts); -} - -static void -usie_uc_cfg_open(struct ucom_softc *ucom) -{ - struct usie_softc *sc = ucom->sc_parent; - - /* usbd_transfer_start() is NULL safe */ - - usbd_transfer_start(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_STATUS]); -} - -static void -usie_uc_cfg_close(struct ucom_softc *ucom) -{ - struct usie_softc *sc = ucom->sc_parent; - - usbd_transfer_stop(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_STATUS]); -} - -static void -usie_uc_start_read(struct ucom_softc *ucom) -{ - struct usie_softc *sc = ucom->sc_parent; - - usbd_transfer_start(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_RX]); -} - -static void -usie_uc_stop_read(struct ucom_softc *ucom) -{ - struct usie_softc *sc = ucom->sc_parent; - - usbd_transfer_stop(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_RX]); -} - -static void -usie_uc_start_write(struct ucom_softc *ucom) -{ - struct usie_softc *sc = ucom->sc_parent; - - usbd_transfer_start(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_TX]); -} - -static void -usie_uc_stop_write(struct ucom_softc *ucom) -{ - struct usie_softc *sc = ucom->sc_parent; - - usbd_transfer_stop(sc->sc_uc_xfer[ucom->sc_subunit][USIE_UC_TX]); -} - -static void -usie_uc_rx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct ucom_softc *ucom = usbd_xfer_softc(xfer); - struct usie_softc *sc = ucom->sc_parent; - struct usb_page_cache *pc; - uint32_t actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - pc = usbd_xfer_get_frame(xfer, 0); - - /* handle CnS response */ - if (ucom == sc->sc_ucom && actlen >= USIE_HIPCNS_MIN) { - - DPRINTF("transferred=%u\n", actlen); - - /* check if it is really CnS reply */ - usbd_copy_out(pc, 0, sc->sc_resp_temp, 1); - - if (sc->sc_resp_temp[0] == USIE_HIP_FRM_CHR) { - - /* verify actlen */ - if (actlen > USIE_BUFSIZE) - actlen = USIE_BUFSIZE; - - /* get complete message */ - usbd_copy_out(pc, 0, sc->sc_resp_temp, actlen); - usie_hip_rsp(sc, sc->sc_resp_temp, actlen); - - /* need to fall though */ - goto tr_setup; - } - /* else call ucom_put_data() */ - } - /* standard ucom transfer */ - ucom_put_data(ucom, pc, 0, actlen); - - /* fall though */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static void -usie_uc_tx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct ucom_softc *ucom = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - uint32_t actlen; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - case USB_ST_SETUP: -tr_setup: - pc = usbd_xfer_get_frame(xfer, 0); - - /* handle CnS request */ - struct mbuf *m = usbd_xfer_get_priv(xfer); - - if (m != NULL) { - usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); - usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len); - usbd_xfer_set_priv(xfer, NULL); - usbd_transfer_submit(xfer); - m_freem(m); - break; - } - /* standard ucom transfer */ - if (ucom_get_data(ucom, pc, 0, USIE_BUFSIZE, &actlen)) { - usbd_xfer_set_frame_len(xfer, 0, actlen); - usbd_transfer_submit(xfer); - } - break; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static void -usie_uc_status_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct usb_page_cache *pc; - struct { - struct usb_device_request req; - uint16_t param; - } st; - uint32_t actlen; - uint16_t param; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTFN(4, "info received, actlen=%u\n", actlen); - - if (actlen < sizeof(st)) { - DPRINTF("data too short actlen=%u\n", actlen); - goto tr_setup; - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, &st, sizeof(st)); - - if (st.req.bmRequestType == 0xa1 && st.req.bRequest == 0x20) { - struct ucom_softc *ucom = usbd_xfer_softc(xfer); - struct usie_softc *sc = ucom->sc_parent; - - param = le16toh(st.param); - DPRINTF("param=%x\n", param); - sc->sc_msr = sc->sc_lsr = 0; - sc->sc_msr |= (param & USIE_DCD) ? SER_DCD : 0; - sc->sc_msr |= (param & USIE_DSR) ? SER_DSR : 0; - sc->sc_msr |= (param & USIE_RI) ? SER_RI : 0; - sc->sc_msr |= (param & USIE_CTS) ? 0 : SER_CTS; - sc->sc_msr |= (param & USIE_RTS) ? SER_RTS : 0; - sc->sc_msr |= (param & USIE_DTR) ? SER_DTR : 0; - } - /* fall though */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - - default: /* Error */ - DPRINTF("USB transfer error, %s\n", - usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static void -usie_if_rx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct usie_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m0; - struct mbuf *m = NULL; - struct usie_desc *rxd; - uint32_t actlen; - uint16_t err; - uint16_t pkt; - uint16_t ipl; - uint16_t len; - uint16_t diff; - uint8_t pad; - uint8_t ipv; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTFN(15, "rx done, actlen=%u\n", actlen); - - if (actlen < sizeof(struct usie_hip)) { - DPRINTF("data too short %u\n", actlen); - goto tr_setup; - } - m = sc->sc_rxm; - sc->sc_rxm = NULL; - - /* fall though */ - case USB_ST_SETUP: -tr_setup: - - if (sc->sc_rxm == NULL) { - sc->sc_rxm = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, - MJUMPAGESIZE /* could be bigger than MCLBYTES */ ); - } - if (sc->sc_rxm == NULL) { - DPRINTF("could not allocate Rx mbuf\n"); - ifp->if_ierrors++; - usbd_xfer_set_stall(xfer); - usbd_xfer_set_frames(xfer, 0); - } else { - /* - * Directly loading a mbuf cluster into DMA to - * save some data copying. This works because - * there is only one cluster. - */ - usbd_xfer_set_frame_data(xfer, 0, - mtod(sc->sc_rxm, caddr_t), MIN(MJUMPAGESIZE, USIE_RXSZ_MAX)); - usbd_xfer_set_frames(xfer, 1); - } - usbd_transfer_submit(xfer); - break; - - default: /* Error */ - DPRINTF("USB transfer error, %s\n", usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - ifp->if_ierrors++; - goto tr_setup; - } - if (sc->sc_rxm != NULL) { - m_freem(sc->sc_rxm); - sc->sc_rxm = NULL; - } - break; - } - - if (m == NULL) - return; - - mtx_unlock(&sc->sc_mtx); - - m->m_pkthdr.len = m->m_len = actlen; - - err = pkt = 0; - - /* HW can aggregate multiple frames in a single USB xfer */ - for (;;) { - rxd = mtod(m, struct usie_desc *); - - len = be16toh(rxd->hip.len) & USIE_HIP_IP_LEN_MASK; - pad = (rxd->hip.id & USIE_HIP_PAD) ? 1 : 0; - ipl = (len - pad - ETHER_HDR_LEN); - if (ipl >= len) { - DPRINTF("Corrupt frame\n"); - m_freem(m); - break; - } - diff = sizeof(struct usie_desc) + ipl + pad; - - if (((rxd->hip.id & USIE_HIP_MASK) != USIE_HIP_IP) || - (be16toh(rxd->desc_type) & USIE_TYPE_MASK) != USIE_IP_RX) { - DPRINTF("received wrong type of packet\n"); - m->m_data += diff; - m->m_pkthdr.len = (m->m_len -= diff); - err++; - if (m->m_pkthdr.len > 0) - continue; - m_freem(m); - break; - } - switch (be16toh(rxd->ethhdr.ether_type)) { - case ETHERTYPE_IP: - ipv = NETISR_IP; - break; -#ifdef INET6 - case ETHERTYPE_IPV6: - ipv = NETISR_IPV6; - break; -#endif - default: - DPRINTF("unsupported ether type\n"); - err++; - break; - } - - /* the last packet */ - if (m->m_pkthdr.len <= diff) { - m->m_data += (sizeof(struct usie_desc) + pad); - m->m_pkthdr.len = m->m_len = ipl; - m->m_pkthdr.rcvif = ifp; - BPF_MTAP(sc->sc_ifp, m); - netisr_dispatch(ipv, m); - break; - } - /* copy aggregated frames to another mbuf */ - m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (__predict_false(m0 == NULL)) { - DPRINTF("could not allocate mbuf\n"); - err++; - m_freem(m); - break; - } - m_copydata(m, sizeof(struct usie_desc) + pad, ipl, mtod(m0, caddr_t)); - m0->m_pkthdr.rcvif = ifp; - m0->m_pkthdr.len = m0->m_len = ipl; - - BPF_MTAP(sc->sc_ifp, m0); - netisr_dispatch(ipv, m0); - - m->m_data += diff; - m->m_pkthdr.len = (m->m_len -= diff); - } - - mtx_lock(&sc->sc_mtx); - - ifp->if_ierrors += err; - ifp->if_ipackets += pkt; -} - -static void -usie_if_tx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct usie_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - uint16_t size; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTFN(11, "transfer complete\n"); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_opackets++; - - /* fall though */ - case USB_ST_SETUP: -tr_setup: - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - break; - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - if (m->m_pkthdr.len > (MCLBYTES - ETHER_HDR_LEN + - ETHER_CRC_LEN - sizeof(sc->sc_txd))) { - DPRINTF("packet len is too big: %d\n", - m->m_pkthdr.len); - break; - } - pc = usbd_xfer_get_frame(xfer, 0); - - sc->sc_txd.hip.len = htobe16(m->m_pkthdr.len + - ETHER_HDR_LEN + ETHER_CRC_LEN); - size = sizeof(sc->sc_txd); - - usbd_copy_in(pc, 0, &sc->sc_txd, size); - usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len); - usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len + - size + ETHER_CRC_LEN); - - BPF_MTAP(ifp, m); - - m_freem(m); - - usbd_transfer_submit(xfer); - break; - - default: /* Error */ - DPRINTF("USB transfer error, %s\n", - usbd_errstr(error)); - ifp->if_oerrors++; - - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - ifp->if_ierrors++; - goto tr_setup; - } - break; - } -} - -static void -usie_if_status_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct usie_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - struct usb_cdc_notification cdc; - uint32_t actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTFN(4, "info received, actlen=%d\n", actlen); - - /* usb_cdc_notification - .data[16] */ - if (actlen < (sizeof(cdc) - 16)) { - DPRINTF("data too short %d\n", actlen); - goto tr_setup; - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, &cdc, (sizeof(cdc) - 16)); - - DPRINTFN(4, "bNotification=%x\n", cdc.bNotification); - - if (cdc.bNotification & UCDC_N_RESPONSE_AVAILABLE) { - taskqueue_enqueue(taskqueue_thread, - &sc->sc_if_status_task); - } - /* fall though */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - - default: /* Error */ - DPRINTF("USB transfer error, %s\n", - usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static void -usie_if_sync_to(void *arg) -{ - struct usie_softc *sc = arg; - - taskqueue_enqueue(taskqueue_thread, &sc->sc_if_sync_task); -} - -static void -usie_if_sync_cb(void *arg, int pending) -{ - struct usie_softc *sc = arg; - - mtx_lock(&sc->sc_mtx); - - /* call twice */ - usie_if_cmd(sc, USIE_HIP_SYNC2M); - usie_if_cmd(sc, USIE_HIP_SYNC2M); - - usb_callout_reset(&sc->sc_if_sync_ch, 2 * hz, usie_if_sync_to, sc); - - mtx_unlock(&sc->sc_mtx); -} - -static void -usie_if_status_cb(void *arg, int pending) -{ - struct usie_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct usb_device_request req; - struct usie_hip *hip; - struct usie_lsi *lsi; - uint16_t actlen; - uint8_t ntries; - uint8_t pad; - - mtx_lock(&sc->sc_mtx); - - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_if_ifnum); - USETW(req.wLength, sizeof(sc->sc_status_temp)); - - for (ntries = 0; ntries != 10; ntries++) { - int err; - - err = usbd_do_request_flags(sc->sc_udev, - &sc->sc_mtx, &req, sc->sc_status_temp, USB_SHORT_XFER_OK, - &actlen, USB_DEFAULT_TIMEOUT); - - if (err == 0) - break; - - DPRINTF("Control request failed: %s %d/10\n", - usbd_errstr(err), ntries); - - usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(10)); - } - - if (ntries == 10) { - mtx_unlock(&sc->sc_mtx); - DPRINTF("Timeout\n"); - return; - } - - hip = (struct usie_hip *)sc->sc_status_temp; - - pad = (hip->id & USIE_HIP_PAD) ? 1 : 0; - - DPRINTF("hip.id=%x hip.len=%d actlen=%u pad=%d\n", - hip->id, be16toh(hip->len), actlen, pad); - - switch (hip->id & USIE_HIP_MASK) { - case USIE_HIP_SYNC2H: - usie_if_cmd(sc, USIE_HIP_SYNC2M); - break; - case USIE_HIP_RESTR: - usb_callout_stop(&sc->sc_if_sync_ch); - break; - case USIE_HIP_UMTS: - lsi = (struct usie_lsi *)( - sc->sc_status_temp + sizeof(struct usie_hip) + pad); - - DPRINTF("lsi.proto=%x lsi.len=%d\n", lsi->proto, - be16toh(lsi->len)); - - if (lsi->proto != USIE_LSI_UMTS) - break; - - if (lsi->area == USIE_LSI_AREA_NO || - lsi->area == USIE_LSI_AREA_NODATA) { - device_printf(sc->sc_dev, "no service available\n"); - break; - } - if (lsi->state == USIE_LSI_STATE_IDLE) { - DPRINTF("lsi.state=%x\n", lsi->state); - break; - } - DPRINTF("ctx=%x\n", hip->param); - sc->sc_txd.hip.param = hip->param; - - sc->sc_net.addr_len = lsi->pdp_addr_len; - memcpy(&sc->sc_net.dns1_addr, &lsi->dns1_addr, 16); - memcpy(&sc->sc_net.dns2_addr, &lsi->dns2_addr, 16); - memcpy(sc->sc_net.pdp_addr, lsi->pdp_addr, 16); - memcpy(sc->sc_net.gw_addr, lsi->gw_addr, 16); - ifp->if_flags |= IFF_UP; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - - device_printf(sc->sc_dev, "IP Addr=%d.%d.%d.%d\n", - *lsi->pdp_addr, *(lsi->pdp_addr + 1), - *(lsi->pdp_addr + 2), *(lsi->pdp_addr + 3)); - device_printf(sc->sc_dev, "Gateway Addr=%d.%d.%d.%d\n", - *lsi->gw_addr, *(lsi->gw_addr + 1), - *(lsi->gw_addr + 2), *(lsi->gw_addr + 3)); - device_printf(sc->sc_dev, "Prim NS Addr=%d.%d.%d.%d\n", - *lsi->dns1_addr, *(lsi->dns1_addr + 1), - *(lsi->dns1_addr + 2), *(lsi->dns1_addr + 3)); - device_printf(sc->sc_dev, "Scnd NS Addr=%d.%d.%d.%d\n", - *lsi->dns2_addr, *(lsi->dns2_addr + 1), - *(lsi->dns2_addr + 2), *(lsi->dns2_addr + 3)); - - usie_cns_req(sc, USIE_CNS_ID_RSSI, USIE_CNS_OB_RSSI); - break; - - case USIE_HIP_RCGI: - /* ignore, workaround for sloppy windows */ - break; - default: - DPRINTF("undefined msgid: %x\n", hip->id); - break; - } - - mtx_unlock(&sc->sc_mtx); -} - -static void -usie_if_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct usie_softc *sc = ifp->if_softc; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - DPRINTF("Not running\n"); - return; - } - mtx_lock(&sc->sc_mtx); - usbd_transfer_start(sc->sc_if_xfer[USIE_IF_TX]); - mtx_unlock(&sc->sc_mtx); - - DPRINTFN(3, "interface started\n"); -} - -static int -usie_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, - struct route *ro) -{ - int err; - - DPRINTF("proto=%x\n", dst->sa_family); - - switch (dst->sa_family) { -#ifdef INET6 - case AF_INET6; - /* fall though */ -#endif - case AF_INET: - break; - - /* silently drop dhclient packets */ - case AF_UNSPEC: - m_freem(m); - return (0); - - /* drop other packet types */ - default: - m_freem(m); - return (EAFNOSUPPORT); - } - - err = (ifp->if_transmit)(ifp, m); - if (err) { - ifp->if_oerrors++; - return (ENOBUFS); - } - ifp->if_opackets++; - - return (0); -} - -static void -usie_if_init(void *arg) -{ - struct usie_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - uint8_t i; - - mtx_lock(&sc->sc_mtx); - - /* write tx descriptor */ - sc->sc_txd.hip.id = USIE_HIP_CTX; - sc->sc_txd.hip.param = 0; /* init value */ - sc->sc_txd.desc_type = htobe16(USIE_IP_TX); - - for (i = 0; i != USIE_IF_N_XFER; i++) - usbd_xfer_set_stall(sc->sc_if_xfer[i]); - - usbd_transfer_start(sc->sc_uc_xfer[USIE_HIP_IF][USIE_UC_RX]); - usbd_transfer_start(sc->sc_if_xfer[USIE_IF_STATUS]); - usbd_transfer_start(sc->sc_if_xfer[USIE_IF_RX]); - - /* if not running, initiate the modem */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - usie_cns_req(sc, USIE_CNS_ID_INIT, USIE_CNS_OB_LINK_UPDATE); - - mtx_unlock(&sc->sc_mtx); - - DPRINTF("ifnet initialized\n"); -} - -static void -usie_if_stop(struct usie_softc *sc) -{ - usb_callout_drain(&sc->sc_if_sync_ch); - - mtx_lock(&sc->sc_mtx); - - /* usie_cns_req() clears IFF_* flags */ - usie_cns_req(sc, USIE_CNS_ID_STOP, USIE_CNS_OB_LINK_UPDATE); - - usbd_transfer_stop(sc->sc_if_xfer[USIE_IF_TX]); - usbd_transfer_stop(sc->sc_if_xfer[USIE_IF_RX]); - usbd_transfer_stop(sc->sc_if_xfer[USIE_IF_STATUS]); - - /* shutdown device */ - usie_if_cmd(sc, USIE_HIP_DOWN); - - mtx_unlock(&sc->sc_mtx); -} - -static int -usie_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct usie_softc *sc = ifp->if_softc; - struct ieee80211req *ireq; - struct ieee80211req_sta_info si; - struct ifmediareq *ifmr; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - usie_if_init(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - usie_if_stop(sc); - } - break; - - case SIOCSIFCAP: - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - device_printf(sc->sc_dev, - "Connect to the network first.\n"); - break; - } - mtx_lock(&sc->sc_mtx); - usie_cns_req(sc, USIE_CNS_ID_RSSI, USIE_CNS_OB_RSSI); - mtx_unlock(&sc->sc_mtx); - break; - - case SIOCG80211: - ireq = (struct ieee80211req *)data; - - if (ireq->i_type != IEEE80211_IOC_STA_INFO) - break; - - memset(&si, 0, sizeof(si)); - si.isi_len = sizeof(si); - /* - * ifconfig expects RSSI in 0.5dBm units - * relative to the noise floor. - */ - si.isi_rssi = 2 * sc->sc_rssi; - if (copyout(&si, (uint8_t *)ireq->i_data + 8, - sizeof(struct ieee80211req_sta_info))) - DPRINTF("copyout failed\n"); - DPRINTF("80211\n"); - break; - - case SIOCGIFMEDIA: /* to fool ifconfig */ - ifmr = (struct ifmediareq *)data; - ifmr->ifm_count = 1; - DPRINTF("media\n"); - break; - - case SIOCSIFADDR: - case SIOCSIFDSTADDR: - break; - - default: - return (EINVAL); - } - return (0); -} - -static int -usie_do_request(struct usie_softc *sc, struct usb_device_request *req, - void *data) -{ - int err = 0; - int ntries; - - mtx_assert(&sc->sc_mtx, MA_OWNED); - - for (ntries = 0; ntries != 10; ntries++) { - err = usbd_do_request(sc->sc_udev, - &sc->sc_mtx, req, data); - if (err == 0) - break; - - DPRINTF("Control request failed: %s %d/10\n", - usbd_errstr(err), ntries); - - usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(10)); - } - return (err); -} - -static int -usie_if_cmd(struct usie_softc *sc, uint8_t cmd) -{ - struct usb_device_request req; - struct usie_hip msg; - - msg.len = 0; - msg.id = cmd; - msg.param = 0; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND; - USETW(req.wValue, 0); - USETW(req.wIndex, sc->sc_if_ifnum); - USETW(req.wLength, sizeof(msg)); - - DPRINTF("cmd=%x\n", cmd); - - return (usie_do_request(sc, &req, &msg)); -} - -static void -usie_cns_req(struct usie_softc *sc, uint32_t id, uint16_t obj) -{ - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - struct usb_xfer *xfer; - struct usie_hip *hip; - struct usie_cns *cns; - uint8_t *param; - uint8_t *tmp; - uint8_t cns_len; - - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (__predict_false(m == NULL)) { - DPRINTF("could not allocate mbuf\n"); - ifp->if_ierrors++; - return; - } - /* to align usie_hip{} on 32 bit */ - m->m_data += 3; - param = mtod(m, uint8_t *); - *param++ = USIE_HIP_FRM_CHR; - hip = (struct usie_hip *)param; - cns = (struct usie_cns *)(hip + 1); - - tmp = param + USIE_HIPCNS_MIN - 2; - - switch (obj) { - case USIE_CNS_OB_LINK_UPDATE: - cns_len = 2; - cns->op = USIE_CNS_OP_SET; - *tmp++ = 1; /* profile ID, always use 1 for now */ - *tmp++ = id == USIE_CNS_ID_INIT ? 1 : 0; - break; - - case USIE_CNS_OB_PROF_WRITE: - cns_len = 245; - cns->op = USIE_CNS_OP_SET; - *tmp++ = 1; /* profile ID, always use 1 for now */ - *tmp++ = 2; - memcpy(tmp, &sc->sc_net, 34); - memset(tmp + 35, 0, 245 - 36); - tmp += 243; - break; - - case USIE_CNS_OB_RSSI: - cns_len = 0; - cns->op = USIE_CNS_OP_REQ; - break; - - default: - DPRINTF("unsupported CnS object type\n"); - return; - } - *tmp = USIE_HIP_FRM_CHR; - - hip->len = htobe16(sizeof(struct usie_cns) + cns_len); - hip->id = USIE_HIP_CNS2M; - hip->param = 0; /* none for CnS */ - - cns->obj = htobe16(obj); - cns->id = htobe32(id); - cns->len = cns_len; - cns->rsv0 = cns->rsv1 = 0; /* always '0' */ - - param = (uint8_t *)(cns + 1); - - DPRINTF("param: %16D\n", param, ":"); - - m->m_pkthdr.len = m->m_len = USIE_HIPCNS_MIN + cns_len + 2; - - xfer = sc->sc_uc_xfer[USIE_HIP_IF][USIE_UC_TX]; - - if (usbd_xfer_get_priv(xfer) == NULL) { - usbd_xfer_set_priv(xfer, m); - usbd_transfer_start(xfer); - } else { - DPRINTF("Dropped CNS event\n"); - m_freem(m); - } -} - -static void -usie_cns_rsp(struct usie_softc *sc, struct usie_cns *cns) -{ - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF("received CnS\n"); - - switch (be16toh(cns->obj)) { - case USIE_CNS_OB_LINK_UPDATE: - if (be32toh(cns->id) & USIE_CNS_ID_INIT) - usie_if_sync_to(sc); - else if (be32toh(cns->id) & USIE_CNS_ID_STOP) { - ifp->if_flags &= ~IFF_UP; - ifp->if_drv_flags &= - ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - } else - DPRINTF("undefined link update\n"); - break; - - case USIE_CNS_OB_RSSI: - sc->sc_rssi = be16toh(*(int16_t *)(cns + 1)); - if (sc->sc_rssi <= 0) - device_printf(sc->sc_dev, "No signal\n"); - else { - device_printf(sc->sc_dev, "RSSI=%ddBm\n", - sc->sc_rssi - 110); - } - break; - - case USIE_CNS_OB_PROF_WRITE: - break; - - case USIE_CNS_OB_PDP_READ: - break; - - default: - DPRINTF("undefined CnS\n"); - break; - } -} - -static void -usie_hip_rsp(struct usie_softc *sc, uint8_t *rsp, uint32_t len) -{ - struct usie_hip *hip; - struct usie_cns *cns; - uint32_t i; - uint32_t j; - uint32_t off; - uint8_t tmp[USIE_HIPCNS_MAX] __aligned(4); - - for (off = 0; (off + USIE_HIPCNS_MIN) <= len; off++) { - - uint8_t pad; - - while ((off < len) && (rsp[off] == USIE_HIP_FRM_CHR)) - off++; - - /* Unstuff the bytes */ - for (i = j = 0; ((i + off) < len) && - (j < USIE_HIPCNS_MAX); i++) { - - if (rsp[i + off] == USIE_HIP_FRM_CHR) - break; - - if (rsp[i + off] == USIE_HIP_ESC_CHR) { - if ((i + off + 1) >= len) - break; - tmp[j++] = rsp[i++ + off + 1] ^ 0x20; - } else { - tmp[j++] = rsp[i + off]; - } - } - - off += i; - - DPRINTF("frame len=%d\n", j); - - if (j < sizeof(struct usie_hip)) { - DPRINTF("too little data\n"); - break; - } - /* - * Make sure we are not reading the stack if something - * is wrong. - */ - memset(tmp + j, 0, sizeof(tmp) - j); - - hip = (struct usie_hip *)tmp; - - DPRINTF("hip: len=%d msgID=%02x, param=%02x\n", - be16toh(hip->len), hip->id, hip->param); - - pad = (hip->id & USIE_HIP_PAD) ? 1 : 0; - - if ((hip->id & USIE_HIP_MASK) == USIE_HIP_CNS2H) { - cns = (struct usie_cns *)(((uint8_t *)(hip + 1)) + pad); - - if (j < (sizeof(struct usie_cns) + - sizeof(struct usie_hip) + pad)) { - DPRINTF("too little data\n"); - break; - } - DPRINTF("cns: obj=%04x, op=%02x, rsv0=%02x, " - "app=%08x, rsv1=%02x, len=%d\n", - be16toh(cns->obj), cns->op, cns->rsv0, - be32toh(cns->id), cns->rsv1, cns->len); - - if (cns->op & USIE_CNS_OP_ERR) - DPRINTF("CnS error response\n"); - else - usie_cns_rsp(sc, cns); - - i = sizeof(struct usie_hip) + pad + sizeof(struct usie_cns); - j = cns->len; - } else { - i = sizeof(struct usie_hip) + pad; - j = be16toh(hip->len); - } -#ifdef USB_DEBUG - if (usie_debug == 0) - continue; - - while (i < USIE_HIPCNS_MAX && j > 0) { - DPRINTF("param[0x%02x] = 0x%02x\n", i, tmp[i]); - i++; - j--; - } -#endif - } -} - -static int -usie_driver_loaded(struct module *mod, int what, void *arg) -{ - switch (what) { - case MOD_LOAD: - /* register autoinstall handler */ - usie_etag = EVENTHANDLER_REGISTER(usb_dev_configured, - usie_autoinst, NULL, EVENTHANDLER_PRI_ANY); - break; - case MOD_UNLOAD: - EVENTHANDLER_DEREGISTER(usb_dev_configured, usie_etag); - break; - default: - return (EOPNOTSUPP); - } - return (0); -} - diff --git a/sys/bus/u4b/net/if_usievar.h b/sys/bus/u4b/net/if_usievar.h deleted file mode 100644 index 9ba0dc8b12..0000000000 --- a/sys/bus/u4b/net/if_usievar.h +++ /dev/null @@ -1,256 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2011 Anybots Inc - * written by Akinori Furukoshi - * - ucom part is based on u3g.c - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _IF_USEVAR_H_ -#define _IF_USEVAR_H_ - -#define USIE_DCD 0x0001 -#define USIE_DSR 0x0002 -#define USIE_DTR 0x0004 -#define USIE_RI 0x0008 -#define USIE_CTS 0x0100 -#define USIE_RTS 0x0200 - -#define USIE_HIP_FRM_CHR 0x7e -#define USIE_HIP_ESC_CHR 0x7d -#define USIE_HIP_IF 0 - -#define USIE_HIPCNS_MIN 16 /* HIP + CnS + 2 framing char */ -#define USIE_HIPCNS_MAX 261 /* HIP + max CnS 255 + 2 framing char */ - -#define USIE_CNFG_INDEX 0 -#define USIE_IFACE_INDEX 0 -#define USIE_IFACE_MAX 12 -#define USIE_BUFSIZE 2048 -#define USIE_MTU_MAX 1500 -#define USIE_RXSZ_MAX 4096 - -/* USB control pipe request */ -#define USIE_POWER 0x00 -#define USIE_FW_ATTR 0x06 -#define USIE_NMEA 0x07 -#define USIE_LINK_STATE 0x22 - -/* firmware attr flags */ -#define USIE_PM_AUTO (1 << 1) -#define USIE_FW_DHCP (1 << 3) /* DHCP capable */ - -/* line state flags */ -#define USIE_LS_DTR (1 << 0) -#define USIE_LS_RTS (1 << 1) - -/* Host Interface Porotocol Header */ -struct usie_hip { - uint16_t len; -#define USIE_HIP_LEN_MASK 0x3fff -#define USIE_HIP_IP_LEN_MASK 0x07ff - - uint8_t id; -#define USIE_HIP_PAD (1 << 7) -#define USIE_HIP_MASK 0x7f -#define USIE_HIP_SYNC2M 0x20 /* host -> modem */ -#define USIE_HIP_DOWN 0x26 -#define USIE_HIP_CNS2M 0x2b /* h -> m */ -#define USIE_HIP_CTX 0x3f -#define USIE_HIP_SYNC2H 0x60 /* h <- m */ -#define USIE_HIP_RESTR 0x62 -#define USIE_HIP_RCGI 0x64 -#define USIE_HIP_CNS2H 0x6b /* h <- m */ -#define USIE_HIP_UMTS 0x78 -#define USIE_HIP_IP 0x7f - - uint8_t param; -} __packed __aligned(4); - -/* Control and Status Header */ -struct usie_cns { - uint16_t obj; /* object type */ -#define USIE_CNS_OB_RSSI 0x1001 /* read RSSI */ -#define USIE_CNS_OB_HW_DISABLE 0x1011 /* disable h/w */ -#define USIE_CNS_OB_PW_SW 0x1071 /* power on/off */ -#define USIE_CNS_OB_PROF_WRITE 0x7003 /* write profile */ -#define USIE_CNS_OB_LINK_UPDATE 0x7004 /* dis/connect */ -#define USIE_CNS_OB_PDP_READ 0x7006 /* read out IP addr */ - - uint8_t op; /* operation type */ -#define USIE_CNS_OP_ERR (1 << 7)/* | == error */ -#define USIE_CNS_OP_REQ 0x01 /* host -> modem */ -#define USIE_CNS_OP_RSP 0x02 /* h <- m */ -#define USIE_CNS_OP_SET 0x03 /* h -> m */ -#define USIE_CNS_OP_ACK 0x04 /* h <- m */ -#define USIE_CNS_OP_NOTIF_ON 0x05 /* h -> m */ -#define USIE_CNS_OP_RSP_ON 0x06 /* h <- m */ -#define USIE_CNS_OP_NOTIF 0x07 /* h <- m */ -#define USIE_CNS_OP_NOTIF_OFF 0x08 /* h -> m */ -#define USIE_CNS_OP_RSP_OFF 0x09 /* h <- m */ -#define USIE_CNS_OP_REQ_CHG 0x0a /* h -> m */ -#define USIE_CNS_OP_RSP_CHG 0x0b /* h <- m */ - - uint8_t rsv0; /* reserved, always '0' */ - uint32_t id; /* caller ID */ -/* - * .id is to identify calling functions - * h/w responses with the same .id used in request. Only '0' is reserved - * for notification (asynchronous message generated by h/w without any - * request). All other values are user defineable. - */ -#define USIE_CNS_ID_NOTIF 0x00000000 /* reserved */ -#define USIE_CNS_ID_INIT 0x00000001 -#define USIE_CNS_ID_STOP 0x00000002 -#define USIE_CNS_ID_DNS 0x00000003 -#define USIE_CNS_ID_RSSI 0x00000004 - - uint8_t rsv1; /* reserved, always '0' */ - uint8_t len; /* length of param */ -} __packed; - -/* - * CnS param attached to struct usie_cns - * usie_cns.len is total size of this param - * max 255 - */ -#define USIE_CNS_PM_UP 0x01 -#define USIE_CNS_PM_DOWN 0x00 - -/* Link Sense Indication data structure */ -struct usie_lsi { - uint8_t proto; -#define USIE_LSI_UMTS 0x01 - - uint8_t pad0; - uint16_t len; - uint8_t area; -#define USIE_LSI_AREA_NO 0x00 -#define USIE_LSI_AREA_NODATA 0x01 - - uint8_t pad1[41]; - uint8_t state; -#define USIE_LSI_STATE_IDLE 0x00 - - uint8_t pad2[33]; - uint8_t type; -#define USIE_LSI_IP4 0x00 - - uint8_t pdp_addr_len; /* PDP addr */ - uint8_t pdp_addr[16]; - uint8_t pad3[23]; - uint8_t dns1_addr_len; /* DNS addr */ - uint8_t dns1_addr[16]; - uint8_t dns2_addr_len; - uint8_t dns2_addr[16]; - uint8_t wins1_addr_len; /* Wins addr */ - uint8_t wins1_addr[16]; - uint8_t wins2_addr_len; - uint8_t wins2_addr[16]; - uint8_t pad4[4]; - uint8_t gw_addr_len; /* GW addr */ - uint8_t gw_addr[16]; - uint8_t rsv[8]; -} __packed; - -struct usie_net_info { - uint8_t addr_len; - uint8_t pdp_addr[16]; - uint8_t dns1_addr[16]; - uint8_t dns2_addr[16]; - uint8_t gw_addr[16]; -} __packed; - -/* Tx/Rx IP packet descriptor */ -struct usie_desc { - struct usie_hip hip; - uint16_t desc_type; -#define USIE_TYPE_MASK 0x03ff -#define USIE_IP_TX 0x0002 -#define USIE_IP_RX 0x0202 - - struct ether_header ethhdr; -} __packed; - -enum { - USIE_UC_STATUS, - USIE_UC_RX, - USIE_UC_TX, - USIE_UC_N_XFER -}; - -enum { - USIE_IF_STATUS, - USIE_IF_RX, - USIE_IF_TX, - USIE_IF_N_XFER -}; - -struct usie_softc { - struct ucom_super_softc sc_super_ucom; - -#define USIE_UCOM_MAX 6 - struct ucom_softc sc_ucom[USIE_UCOM_MAX]; - uint8_t sc_uc_ifnum[USIE_UCOM_MAX]; - - struct mtx sc_mtx; - - struct task sc_if_status_task; - struct task sc_if_sync_task; - struct usb_callout sc_if_sync_ch; - - struct usie_net_info sc_net; - - struct usie_desc sc_txd; - - struct usb_xfer *sc_uc_xfer[USIE_UCOM_MAX][USIE_UC_N_XFER]; - struct usb_xfer *sc_if_xfer[USIE_IF_N_XFER]; - - struct ifnet *sc_ifp; - struct usb_device *sc_udev; - device_t sc_dev; - - struct mbuf *sc_rxm; - - uint16_t sc_if_ifnum; - - int16_t sc_rssi; - - uint8_t sc_msr; - uint8_t sc_lsr; - uint8_t sc_nucom; - - uint8_t sc_resp_temp[USIE_BUFSIZE] __aligned(4); - uint8_t sc_status_temp[USIE_BUFSIZE] __aligned(4); -}; - -/* Some code assumptions */ - -extern uint8_t usie_assert[((sizeof(struct usie_hip) + - sizeof(struct usie_lsi) + 1) <= USIE_BUFSIZE) ? 1 : -1]; - -extern uint8_t ucdc_assert[(sizeof(struct usb_cdc_notification) - >= 16) ? 1 : -1]; - -#endif /* _IF_USEVAR_H_ */ diff --git a/sys/bus/u4b/net/uhso.c b/sys/bus/u4b/net/uhso.c deleted file mode 100644 index 7057a8612a..0000000000 --- a/sys/bus/u4b/net/uhso.c +++ /dev/null @@ -1,1910 +0,0 @@ -/*- - * Copyright (c) 2010 Fredrik Lindberg - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "usbdevs.h" -#define USB_DEBUG_VAR uhso_debug -#include -#include -#include -#include - -#include - -struct uhso_tty { - struct uhso_softc *ht_sc; - struct usb_xfer *ht_xfer[3]; - int ht_muxport; /* Mux. port no */ - int ht_open; - char ht_name[32]; -}; - -struct uhso_softc { - device_t sc_dev; - struct usb_device *sc_udev; - struct mtx sc_mtx; - uint32_t sc_type; /* Interface definition */ - int sc_radio; - - struct usb_xfer *sc_xfer[3]; - uint8_t sc_iface_no; - uint8_t sc_iface_index; - - /* Control pipe */ - struct usb_xfer * sc_ctrl_xfer[2]; - uint8_t sc_ctrl_iface_no; - - /* Network */ - struct usb_xfer *sc_if_xfer[2]; - struct ifnet *sc_ifp; - struct mbuf *sc_mwait; /* Partial packet */ - size_t sc_waitlen; /* No. of outstanding bytes */ - struct ifqueue sc_rxq; - struct callout sc_c; - - /* TTY related structures */ - struct ucom_super_softc sc_super_ucom; - int sc_ttys; - struct uhso_tty *sc_tty; - struct ucom_softc *sc_ucom; - int sc_msr; - int sc_lsr; - int sc_line; -}; - -#define UHSO_MAX_MTU 2048 - -/* - * There are mainly two type of cards floating around. - * The first one has 2,3 or 4 interfaces with a multiplexed serial port - * and packet interface on the first interface and bulk serial ports - * on the others. - * The second type of card has several other interfaces, their purpose - * can be detected during run-time. - */ -#define UHSO_IFACE_SPEC(usb_type, port, port_type) \ - (((usb_type) << 24) | ((port) << 16) | (port_type)) - -#define UHSO_IFACE_USB_TYPE(x) ((x >> 24) & 0xff) -#define UHSO_IFACE_PORT(x) ((x >> 16) & 0xff) -#define UHSO_IFACE_PORT_TYPE(x) (x & 0xff) - -/* - * USB interface types - */ -#define UHSO_IF_NET 0x01 /* Network packet interface */ -#define UHSO_IF_MUX 0x02 /* Multiplexed serial port */ -#define UHSO_IF_BULK 0x04 /* Bulk interface */ - -/* - * Port types - */ -#define UHSO_PORT_UNKNOWN 0x00 -#define UHSO_PORT_SERIAL 0x01 /* Serial port */ -#define UHSO_PORT_NETWORK 0x02 /* Network packet interface */ - -/* - * Multiplexed serial port destination sub-port names - */ -#define UHSO_MPORT_TYPE_CTL 0x00 /* Control port */ -#define UHSO_MPORT_TYPE_APP 0x01 /* Application */ -#define UHSO_MPORT_TYPE_PCSC 0x02 -#define UHSO_MPORT_TYPE_GPS 0x03 -#define UHSO_MPORT_TYPE_APP2 0x04 /* Secondary application */ -#define UHSO_MPORT_TYPE_MAX UHSO_MPORT_TYPE_APP2 -#define UHSO_MPORT_TYPE_NOMAX 8 /* Max number of mux ports */ - -/* - * Port definitions - * Note that these definitions are arbitrary and do not match the values - * returned by the auto config descriptor. - */ -#define UHSO_PORT_TYPE_UNKNOWN 0x00 -#define UHSO_PORT_TYPE_CTL 0x01 -#define UHSO_PORT_TYPE_APP 0x02 -#define UHSO_PORT_TYPE_APP2 0x03 -#define UHSO_PORT_TYPE_MODEM 0x04 -#define UHSO_PORT_TYPE_NETWORK 0x05 -#define UHSO_PORT_TYPE_DIAG 0x06 -#define UHSO_PORT_TYPE_DIAG2 0x07 -#define UHSO_PORT_TYPE_GPS 0x08 -#define UHSO_PORT_TYPE_GPSCTL 0x09 -#define UHSO_PORT_TYPE_PCSC 0x0a -#define UHSO_PORT_TYPE_MSD 0x0b -#define UHSO_PORT_TYPE_VOICE 0x0c -#define UHSO_PORT_TYPE_MAX 0x0c - -static eventhandler_tag uhso_etag; - -/* Overall port type */ -static char *uhso_port[] = { - "Unknown", - "Serial", - "Network", - "Network/Serial" -}; - -/* - * Map between interface port type read from device and description type. - * The position in this array is a direct map to the auto config - * descriptor values. - */ -static unsigned char uhso_port_map[] = { - UHSO_PORT_TYPE_UNKNOWN, - UHSO_PORT_TYPE_DIAG, - UHSO_PORT_TYPE_GPS, - UHSO_PORT_TYPE_GPSCTL, - UHSO_PORT_TYPE_APP, - UHSO_PORT_TYPE_APP2, - UHSO_PORT_TYPE_CTL, - UHSO_PORT_TYPE_NETWORK, - UHSO_PORT_TYPE_MODEM, - UHSO_PORT_TYPE_MSD, - UHSO_PORT_TYPE_PCSC, - UHSO_PORT_TYPE_VOICE -}; -static char uhso_port_map_max = sizeof(uhso_port_map) / sizeof(char); - -static unsigned char uhso_mux_port_map[] = { - UHSO_PORT_TYPE_CTL, - UHSO_PORT_TYPE_APP, - UHSO_PORT_TYPE_PCSC, - UHSO_PORT_TYPE_GPS, - UHSO_PORT_TYPE_APP2 -}; - -static char *uhso_port_type[] = { - "Unknown", /* Not a valid port */ - "Control", - "Application", - "Application (Secondary)", - "Modem", - "Network", - "Diagnostic", - "Diagnostic (Secondary)", - "GPS", - "GPS Control", - "PC Smartcard", - "MSD", - "Voice", -}; - -static char *uhso_port_type_sysctl[] = { - "unknown", - "control", - "application", - "application", - "modem", - "network", - "diagnostic", - "diagnostic", - "gps", - "gps_control", - "pcsc", - "msd", - "voice", -}; - -#define UHSO_STATIC_IFACE 0x01 -#define UHSO_AUTO_IFACE 0x02 - -/* ifnet device unit allocations */ -static struct unrhdr *uhso_ifnet_unit = NULL; - -static const STRUCT_USB_HOST_ID uhso_devs[] = { -#define UHSO_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } - /* Option GlobeTrotter MAX 7.2 with upgraded firmware */ - UHSO_DEV(OPTION, GTMAX72, UHSO_STATIC_IFACE), - /* Option GlobeSurfer iCON 7.2 */ - UHSO_DEV(OPTION, GSICON72, UHSO_STATIC_IFACE), - /* Option iCON 225 */ - UHSO_DEV(OPTION, GTHSDPA, UHSO_STATIC_IFACE), - /* Option GlobeSurfer iCON HSUPA */ - UHSO_DEV(OPTION, GSICONHSUPA, UHSO_STATIC_IFACE), - /* Option GlobeTrotter HSUPA */ - UHSO_DEV(OPTION, GTHSUPA, UHSO_STATIC_IFACE), - /* GE40x */ - UHSO_DEV(OPTION, GE40X, UHSO_AUTO_IFACE), - UHSO_DEV(OPTION, GE40X_1, UHSO_AUTO_IFACE), - UHSO_DEV(OPTION, GE40X_2, UHSO_AUTO_IFACE), - UHSO_DEV(OPTION, GE40X_3, UHSO_AUTO_IFACE), - /* Option GlobeSurfer iCON 401 */ - UHSO_DEV(OPTION, ICON401, UHSO_AUTO_IFACE), - /* Option GlobeTrotter Module 382 */ - UHSO_DEV(OPTION, GMT382, UHSO_AUTO_IFACE), - /* Option iCON EDGE */ - UHSO_DEV(OPTION, ICONEDGE, UHSO_STATIC_IFACE), - /* Option Module HSxPA */ - UHSO_DEV(OPTION, MODHSXPA, UHSO_STATIC_IFACE), - /* Option iCON 321 */ - UHSO_DEV(OPTION, ICON321, UHSO_STATIC_IFACE), - /* Option iCON 322 */ - UHSO_DEV(OPTION, GTICON322, UHSO_STATIC_IFACE), - /* Option iCON 505 */ - UHSO_DEV(OPTION, ICON505, UHSO_AUTO_IFACE), - /* Option iCON 452 */ - UHSO_DEV(OPTION, ICON505, UHSO_AUTO_IFACE), -#undef UHSO_DEV -}; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, uhso, CTLFLAG_RW, 0, "USB uhso"); -static int uhso_autoswitch = 1; -SYSCTL_INT(_hw_usb_uhso, OID_AUTO, auto_switch, CTLFLAG_RWTUN, - &uhso_autoswitch, 0, "Automatically switch to modem mode"); - -#ifdef USB_DEBUG -#ifdef UHSO_DEBUG -static int uhso_debug = UHSO_DEBUG; -#else -static int uhso_debug = -1; -#endif - -SYSCTL_INT(_hw_usb_uhso, OID_AUTO, debug, CTLFLAG_RWTUN, - &uhso_debug, 0, "Debug level"); - -#define UHSO_DPRINTF(n, x, ...) {\ - if (uhso_debug >= n) {\ - printf("%s: " x, __func__, ##__VA_ARGS__);\ - }\ -} -#else -#define UHSO_DPRINTF(n, x, ...) -#endif - -#ifdef UHSO_DEBUG_HEXDUMP -# define UHSO_HEXDUMP(_buf, _len) do { \ - { \ - size_t __tmp; \ - const char *__buf = (const char *)_buf; \ - for (__tmp = 0; __tmp < _len; __tmp++) \ - printf("%02hhx ", *__buf++); \ - printf("\n"); \ - } \ -} while(0) -#else -# define UHSO_HEXDUMP(_buf, _len) -#endif - -enum { - UHSO_MUX_ENDPT_INTR = 0, - UHSO_MUX_ENDPT_MAX -}; - -enum { - UHSO_CTRL_READ = 0, - UHSO_CTRL_WRITE, - UHSO_CTRL_MAX -}; - -enum { - UHSO_IFNET_READ = 0, - UHSO_IFNET_WRITE, - UHSO_IFNET_MAX -}; - -enum { - UHSO_BULK_ENDPT_READ = 0, - UHSO_BULK_ENDPT_WRITE, - UHSO_BULK_ENDPT_INTR, - UHSO_BULK_ENDPT_MAX -}; - -static usb_callback_t uhso_mux_intr_callback; -static usb_callback_t uhso_mux_read_callback; -static usb_callback_t uhso_mux_write_callback; -static usb_callback_t uhso_bs_read_callback; -static usb_callback_t uhso_bs_write_callback; -static usb_callback_t uhso_bs_intr_callback; -static usb_callback_t uhso_ifnet_read_callback; -static usb_callback_t uhso_ifnet_write_callback; - -/* Config used for the default control pipes */ -static const struct usb_config uhso_ctrl_config[UHSO_CTRL_MAX] = { - [UHSO_CTRL_READ] = { - .type = UE_CONTROL, - .endpoint = 0x00, - .direction = UE_DIR_ANY, - .flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, - .bufsize = sizeof(struct usb_device_request) + 1024, - .callback = &uhso_mux_read_callback - }, - - [UHSO_CTRL_WRITE] = { - .type = UE_CONTROL, - .endpoint = 0x00, - .direction = UE_DIR_ANY, - .flags = { .pipe_bof = 1, .force_short_xfer = 1 }, - .bufsize = sizeof(struct usb_device_request) + 1024, - .timeout = 1000, - .callback = &uhso_mux_write_callback - } -}; - -/* Config for the multiplexed serial ports */ -static const struct usb_config uhso_mux_config[UHSO_MUX_ENDPT_MAX] = { - [UHSO_MUX_ENDPT_INTR] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .flags = { .short_xfer_ok = 1 }, - .bufsize = 0, - .callback = &uhso_mux_intr_callback, - } -}; - -/* Config for the raw IP-packet interface */ -static const struct usb_config uhso_ifnet_config[UHSO_IFNET_MAX] = { - [UHSO_IFNET_READ] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, - .bufsize = MCLBYTES, - .callback = &uhso_ifnet_read_callback - }, - [UHSO_IFNET_WRITE] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .flags = { .pipe_bof = 1, .force_short_xfer = 1 }, - .bufsize = MCLBYTES, - .timeout = 5 * USB_MS_HZ, - .callback = &uhso_ifnet_write_callback - } -}; - -/* Config for interfaces with normal bulk serial ports */ -static const struct usb_config uhso_bs_config[UHSO_BULK_ENDPT_MAX] = { - [UHSO_BULK_ENDPT_READ] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .flags = { .pipe_bof = 1, .short_xfer_ok = 1 }, - .bufsize = 4096, - .callback = &uhso_bs_read_callback - }, - - [UHSO_BULK_ENDPT_WRITE] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .flags = { .pipe_bof = 1, .force_short_xfer = 1 }, - .bufsize = 8192, - .callback = &uhso_bs_write_callback - }, - - [UHSO_BULK_ENDPT_INTR] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .flags = { .short_xfer_ok = 1 }, - .bufsize = 0, - .callback = &uhso_bs_intr_callback, - } -}; - -static int uhso_probe_iface(struct uhso_softc *, int, - int (*probe)(struct usb_device *, int)); -static int uhso_probe_iface_auto(struct usb_device *, int); -static int uhso_probe_iface_static(struct usb_device *, int); -static int uhso_attach_muxserial(struct uhso_softc *, struct usb_interface *, - int type); -static int uhso_attach_bulkserial(struct uhso_softc *, struct usb_interface *, - int type); -static int uhso_attach_ifnet(struct uhso_softc *, struct usb_interface *, - int type); -static void uhso_test_autoinst(void *, struct usb_device *, - struct usb_attach_arg *); -static int uhso_driver_loaded(struct module *, int, void *); -static int uhso_radio_sysctl(SYSCTL_HANDLER_ARGS); -static int uhso_radio_ctrl(struct uhso_softc *, int); - -static void uhso_ucom_start_read(struct ucom_softc *); -static void uhso_ucom_stop_read(struct ucom_softc *); -static void uhso_ucom_start_write(struct ucom_softc *); -static void uhso_ucom_stop_write(struct ucom_softc *); -static void uhso_ucom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); -static void uhso_ucom_cfg_set_dtr(struct ucom_softc *, uint8_t); -static void uhso_ucom_cfg_set_rts(struct ucom_softc *, uint8_t); -static void uhso_if_init(void *); -static void uhso_if_start(struct ifnet *, struct ifaltq_subque *); -static void uhso_if_stop(struct uhso_softc *); -static int uhso_if_ioctl(struct ifnet *, u_long, caddr_t); -static int uhso_if_output(struct ifnet *, struct mbuf *, struct sockaddr *, - struct route *); -static void uhso_if_rxflush(void *); - -static device_probe_t uhso_probe; -static device_attach_t uhso_attach; -static device_detach_t uhso_detach; - -static device_method_t uhso_methods[] = { - DEVMETHOD(device_probe, uhso_probe), - DEVMETHOD(device_attach, uhso_attach), - DEVMETHOD(device_detach, uhso_detach), - DEVMETHOD_END -}; - -static driver_t uhso_driver = { - "uhso", - uhso_methods, - sizeof(struct uhso_softc) -}; - -static devclass_t uhso_devclass; -DRIVER_MODULE(uhso, uhub, uhso_driver, uhso_devclass, uhso_driver_loaded, NULL); -MODULE_DEPEND(uhso, ucom, 1, 1, 1); -MODULE_DEPEND(uhso, usb, 1, 1, 1); -MODULE_VERSION(uhso, 1); - -static struct ucom_callback uhso_ucom_callback = { - .ucom_cfg_get_status = &uhso_ucom_cfg_get_status, - .ucom_cfg_set_dtr = &uhso_ucom_cfg_set_dtr, - .ucom_cfg_set_rts = &uhso_ucom_cfg_set_rts, - .ucom_start_read = uhso_ucom_start_read, - .ucom_stop_read = uhso_ucom_stop_read, - .ucom_start_write = uhso_ucom_start_write, - .ucom_stop_write = uhso_ucom_stop_write -}; - -static int -uhso_probe(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - int error; - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != 0) - return (ENXIO); - if (uaa->info.bDeviceClass != 0xff) - return (ENXIO); - - error = usbd_lookup_id_by_uaa(uhso_devs, sizeof(uhso_devs), uaa); - if (error != 0) - return (error); - - /* - * Probe device to see if we are able to attach - * to this interface or not. - */ - if (USB_GET_DRIVER_INFO(uaa) == UHSO_AUTO_IFACE) { - if (uhso_probe_iface_auto(uaa->device, - uaa->info.bIfaceNum) == 0) - return (ENXIO); - } - return (error); -} - -static int -uhso_attach(device_t self) -{ - struct uhso_softc *sc = device_get_softc(self); - struct usb_attach_arg *uaa = device_get_ivars(self); - struct usb_config_descriptor *cd; - struct usb_interface_descriptor *id; - struct sysctl_ctx_list *sctx; - struct sysctl_oid *soid; - struct sysctl_oid *tree = NULL, *tty_node; - struct ucom_softc *ucom; - struct uhso_tty *ht; - int i, error, port; - void *probe_f; - usb_error_t uerr; - char *desc; - - sc->sc_dev = self; - sc->sc_udev = uaa->device; - mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF); - - sc->sc_ucom = NULL; - sc->sc_ttys = 0; - sc->sc_radio = 1; - - cd = usbd_get_config_descriptor(uaa->device); - id = usbd_get_interface_descriptor(uaa->iface); - sc->sc_ctrl_iface_no = id->bInterfaceNumber; - - sc->sc_iface_no = uaa->info.bIfaceNum; - sc->sc_iface_index = uaa->info.bIfaceIndex; - - /* Setup control pipe */ - uerr = usbd_transfer_setup(uaa->device, - &sc->sc_iface_index, sc->sc_ctrl_xfer, - uhso_ctrl_config, UHSO_CTRL_MAX, sc, &sc->sc_mtx); - if (uerr) { - device_printf(self, "Failed to setup control pipe: %s\n", - usbd_errstr(uerr)); - goto out; - } - - if (USB_GET_DRIVER_INFO(uaa) == UHSO_STATIC_IFACE) - probe_f = uhso_probe_iface_static; - else if (USB_GET_DRIVER_INFO(uaa) == UHSO_AUTO_IFACE) - probe_f = uhso_probe_iface_auto; - else - goto out; - - error = uhso_probe_iface(sc, uaa->info.bIfaceNum, probe_f); - if (error != 0) - goto out; - - sctx = device_get_sysctl_ctx(sc->sc_dev); - soid = device_get_sysctl_tree(sc->sc_dev); - - SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "type", - CTLFLAG_RD, uhso_port[UHSO_IFACE_PORT(sc->sc_type)], 0, - "Port available at this interface"); - SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "radio", - CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uhso_radio_sysctl, "I", "Enable radio"); - - /* - * The default interface description on most Option devices isn't - * very helpful. So we skip device_set_usb_desc and set the - * device description manually. - */ - device_set_desc_copy(self, uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)]); - /* Announce device */ - device_printf(self, "<%s port> at <%s %s> on %s\n", - uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)], - usb_get_manufacturer(uaa->device), - usb_get_product(uaa->device), - device_get_nameunit(device_get_parent(self))); - - if (sc->sc_ttys > 0) { - SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "ports", - CTLFLAG_RD, &sc->sc_ttys, 0, "Number of attached serial ports"); - - tree = SYSCTL_ADD_NODE(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, - "port", CTLFLAG_RD, NULL, "Serial ports"); - } - - /* - * Loop through the number of found TTYs and create sysctl - * nodes for them. - */ - for (i = 0; i < sc->sc_ttys; i++) { - ht = &sc->sc_tty[i]; - ucom = &sc->sc_ucom[i]; - - if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) - port = uhso_mux_port_map[ht->ht_muxport]; - else - port = UHSO_IFACE_PORT_TYPE(sc->sc_type); - - desc = uhso_port_type_sysctl[port]; - - tty_node = SYSCTL_ADD_NODE(sctx, SYSCTL_CHILDREN(tree), OID_AUTO, - desc, CTLFLAG_RD, NULL, ""); - - ht->ht_name[0] = 0; - if (sc->sc_ttys == 1) - snprintf(ht->ht_name, 32, "cuaU%d", ucom->sc_super->sc_unit); - else { - snprintf(ht->ht_name, 32, "cuaU%d.%d", - ucom->sc_super->sc_unit, ucom->sc_subunit); - } - - desc = uhso_port_type[port]; - SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(tty_node), OID_AUTO, - "tty", CTLFLAG_RD, ht->ht_name, 0, ""); - SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(tty_node), OID_AUTO, - "desc", CTLFLAG_RD, desc, 0, ""); - - if (bootverbose) - device_printf(sc->sc_dev, - "\"%s\" port at %s\n", desc, ht->ht_name); - } - - return (0); -out: - uhso_detach(sc->sc_dev); - return (ENXIO); -} - -static int -uhso_detach(device_t self) -{ - struct uhso_softc *sc = device_get_softc(self); - int i; - - usbd_transfer_unsetup(sc->sc_xfer, 3); - usbd_transfer_unsetup(sc->sc_ctrl_xfer, UHSO_CTRL_MAX); - if (sc->sc_ttys > 0) { - ucom_detach(&sc->sc_super_ucom, sc->sc_ucom); - - for (i = 0; i < sc->sc_ttys; i++) { - if (sc->sc_tty[i].ht_muxport != -1) { - usbd_transfer_unsetup(sc->sc_tty[i].ht_xfer, - UHSO_CTRL_MAX); - } - } - - free(sc->sc_tty, M_USBDEV); - free(sc->sc_ucom, M_USBDEV); - } - - if (sc->sc_ifp != NULL) { - callout_drain(&sc->sc_c); - free_unr(uhso_ifnet_unit, sc->sc_ifp->if_dunit); - mtx_lock(&sc->sc_mtx); - uhso_if_stop(sc); - bpfdetach(sc->sc_ifp); - if_detach(sc->sc_ifp); - if_free(sc->sc_ifp); - mtx_unlock(&sc->sc_mtx); - usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX); - } - - mtx_destroy(&sc->sc_mtx); - return (0); -} - -static void -uhso_test_autoinst(void *arg, struct usb_device *udev, - struct usb_attach_arg *uaa) -{ - struct usb_interface *iface; - struct usb_interface_descriptor *id; - - if (uaa->dev_state != UAA_DEV_READY || !uhso_autoswitch) - return; - - iface = usbd_get_iface(udev, 0); - if (iface == NULL) - return; - id = iface->idesc; - if (id == NULL || id->bInterfaceClass != UICLASS_MASS) - return; - if (usbd_lookup_id_by_uaa(uhso_devs, sizeof(uhso_devs), uaa)) - return; /* no device match */ - - if (usb_msc_eject(udev, 0, MSC_EJECT_REZERO) == 0) { - /* success, mark the udev as disappearing */ - uaa->dev_state = UAA_DEV_EJECTING; - } -} - -static int -uhso_driver_loaded(struct module *mod, int what, void *arg) -{ - switch (what) { - case MOD_LOAD: - /* register our autoinstall handler */ - uhso_etag = EVENTHANDLER_REGISTER(usb_dev_configured, - uhso_test_autoinst, NULL, EVENTHANDLER_PRI_ANY); - /* create our unit allocator for inet devs */ - uhso_ifnet_unit = new_unrhdr(0, INT_MAX, NULL); - break; - case MOD_UNLOAD: - EVENTHANDLER_DEREGISTER(usb_dev_configured, uhso_etag); - delete_unrhdr(uhso_ifnet_unit); - break; - default: - return (EOPNOTSUPP); - } - return (0); -} - -/* - * Probe the interface type by querying the device. The elements - * of an array indicates the capabilities of a particular interface. - * Returns a bit mask with the interface capabilities. - */ -static int -uhso_probe_iface_auto(struct usb_device *udev, int index) -{ - struct usb_device_request req; - usb_error_t uerr; - uint16_t actlen = 0; - char port; - char buf[17] = {0}; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = 0x86; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 17); - - uerr = usbd_do_request_flags(udev, NULL, &req, buf, - 0, &actlen, USB_MS_HZ); - if (uerr != 0) { - printf("%s: usbd_do_request_flags failed, %s\n", - __func__, usbd_errstr(uerr)); - return (0); - } - - UHSO_DPRINTF(1, "actlen=%d\n", actlen); - UHSO_HEXDUMP(buf, 17); - - if (index < 0 || index > 16) { - UHSO_DPRINTF(0, "Index %d out of range\n", index); - return (0); - } - - UHSO_DPRINTF(1, "index=%d, type=%x[%s]\n", index, buf[index], - uhso_port_type[(int)uhso_port_map[(int)buf[index]]]); - - if (buf[index] >= uhso_port_map_max) - port = 0; - else - port = uhso_port_map[(int)buf[index]]; - - switch (port) { - case UHSO_PORT_TYPE_NETWORK: - return (UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX, - UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, port)); - case UHSO_PORT_TYPE_DIAG: - case UHSO_PORT_TYPE_DIAG2: - case UHSO_PORT_TYPE_CTL: - case UHSO_PORT_TYPE_APP: - case UHSO_PORT_TYPE_APP2: - case UHSO_PORT_TYPE_MODEM: - return (UHSO_IFACE_SPEC(UHSO_IF_BULK, - UHSO_PORT_SERIAL, port)); - case UHSO_PORT_TYPE_MSD: - return (0); - case UHSO_PORT_TYPE_UNKNOWN: - default: - return (0); - } - - return (0); -} - -/* - * Returns the capabilities of interfaces for devices that don't - * support the automatic query. - * Returns a bit mask with the interface capabilities. - */ -static int -uhso_probe_iface_static(struct usb_device *udev, int index) -{ - struct usb_config_descriptor *cd; - - cd = usbd_get_config_descriptor(udev); - if (cd->bNumInterface <= 3) { - /* Cards with 3 or less interfaces */ - switch (index) { - case 0: - return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX, - UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, - UHSO_PORT_TYPE_NETWORK); - case 1: - return UHSO_IFACE_SPEC(UHSO_IF_BULK, - UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG); - case 2: - return UHSO_IFACE_SPEC(UHSO_IF_BULK, - UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM); - } - } else { - /* Cards with 4 interfaces */ - switch (index) { - case 0: - return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX, - UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, - UHSO_PORT_TYPE_NETWORK); - case 1: - return UHSO_IFACE_SPEC(UHSO_IF_BULK, - UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG2); - case 2: - return UHSO_IFACE_SPEC(UHSO_IF_BULK, - UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM); - case 3: - return UHSO_IFACE_SPEC(UHSO_IF_BULK, - UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG); - } - } - return (0); -} - -/* - * Probes an interface for its particular capabilities and attaches if - * it's a supported interface. - */ -static int -uhso_probe_iface(struct uhso_softc *sc, int index, - int (*probe)(struct usb_device *, int)) -{ - struct usb_interface *iface; - int type, error; - - UHSO_DPRINTF(1, "Probing for interface %d, probe_func=%p\n", index, probe); - - type = probe(sc->sc_udev, index); - UHSO_DPRINTF(1, "Probe result %x\n", type); - if (type <= 0) - return (ENXIO); - - sc->sc_type = type; - iface = usbd_get_iface(sc->sc_udev, index); - - if (UHSO_IFACE_PORT_TYPE(type) == UHSO_PORT_TYPE_NETWORK) { - error = uhso_attach_ifnet(sc, iface, type); - if (error) { - UHSO_DPRINTF(1, "uhso_attach_ifnet failed"); - return (ENXIO); - } - - /* - * If there is an additional interrupt endpoint on this - * interface then we most likely have a multiplexed serial port - * available. - */ - if (iface->idesc->bNumEndpoints < 3) { - sc->sc_type = UHSO_IFACE_SPEC( - UHSO_IFACE_USB_TYPE(type) & ~UHSO_IF_MUX, - UHSO_IFACE_PORT(type) & ~UHSO_PORT_SERIAL, - UHSO_IFACE_PORT_TYPE(type)); - return (0); - } - - UHSO_DPRINTF(1, "Trying to attach mux. serial\n"); - error = uhso_attach_muxserial(sc, iface, type); - if (error == 0 && sc->sc_ttys > 0) { - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, - sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx); - if (error) { - device_printf(sc->sc_dev, "ucom_attach failed\n"); - return (ENXIO); - } - ucom_set_pnpinfo_usb(&sc->sc_super_ucom, sc->sc_dev); - - mtx_lock(&sc->sc_mtx); - usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]); - mtx_unlock(&sc->sc_mtx); - } - } else if ((UHSO_IFACE_USB_TYPE(type) & UHSO_IF_BULK) && - UHSO_IFACE_PORT(type) & UHSO_PORT_SERIAL) { - - error = uhso_attach_bulkserial(sc, iface, type); - if (error) - return (ENXIO); - - error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, - sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx); - if (error) { - device_printf(sc->sc_dev, "ucom_attach failed\n"); - return (ENXIO); - } - ucom_set_pnpinfo_usb(&sc->sc_super_ucom, sc->sc_dev); - } - else { - UHSO_DPRINTF(0, "Unknown type %x\n", type); - return (ENXIO); - } - - return (0); -} - -static int -uhso_radio_ctrl(struct uhso_softc *sc, int onoff) -{ - struct usb_device_request req; - usb_error_t uerr; - - req.bmRequestType = UT_VENDOR; - req.bRequest = onoff ? 0x82 : 0x81; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, 0); - - uerr = usbd_do_request(sc->sc_udev, NULL, &req, NULL); - if (uerr != 0) { - device_printf(sc->sc_dev, "usbd_do_request_flags failed: %s\n", - usbd_errstr(uerr)); - return (-1); - } - return (onoff); -} - -static int -uhso_radio_sysctl(SYSCTL_HANDLER_ARGS) -{ - struct uhso_softc *sc = arg1; - int error, radio; - - radio = sc->sc_radio; - error = sysctl_handle_int(oidp, &radio, 0, req); - if (error) - return (error); - if (radio != sc->sc_radio) { - radio = radio != 0 ? 1 : 0; - error = uhso_radio_ctrl(sc, radio); - if (error != -1) - sc->sc_radio = radio; - } - return (0); -} - -/* - * Expands allocated memory to fit an additional TTY. - * Two arrays are kept with matching indexes, one for ucom and one - * for our private data. - */ -static int -uhso_alloc_tty(struct uhso_softc *sc) -{ - - sc->sc_ttys++; - sc->sc_tty = reallocf(sc->sc_tty, sizeof(struct uhso_tty) * sc->sc_ttys, - M_USBDEV, M_WAITOK | M_ZERO); - if (sc->sc_tty == NULL) - return (-1); - - sc->sc_ucom = reallocf(sc->sc_ucom, - sizeof(struct ucom_softc) * sc->sc_ttys, M_USBDEV, M_WAITOK | M_ZERO); - if (sc->sc_ucom == NULL) - return (-1); - - sc->sc_tty[sc->sc_ttys - 1].ht_sc = sc; - - UHSO_DPRINTF(1, "Allocated TTY %d\n", sc->sc_ttys - 1); - return (sc->sc_ttys - 1); -} - -/* - * Attach a multiplexed serial port - * Data is read/written with requests on the default control pipe. An interrupt - * endpoint returns when there is new data to be read. - */ -static int -uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface, - int type) -{ - struct usb_descriptor *desc; - int i, port, tty; - usb_error_t uerr; - - /* - * The class specific interface (type 0x24) descriptor subtype field - * contains a bitmask that specifies which (and how many) ports that - * are available through this multiplexed serial port. - */ - desc = usbd_find_descriptor(sc->sc_udev, NULL, - iface->idesc->bInterfaceNumber, UDESC_CS_INTERFACE, 0xff, 0, 0); - if (desc == NULL) { - UHSO_DPRINTF(0, "Failed to find UDESC_CS_INTERFACE\n"); - return (ENXIO); - } - - UHSO_DPRINTF(1, "Mux port mask %x\n", desc->bDescriptorSubtype); - if (desc->bDescriptorSubtype == 0) - return (ENXIO); - - /* - * The bitmask is one octet, loop through the number of - * bits that are set and create a TTY for each. - */ - for (i = 0; i < 8; i++) { - port = (1 << i); - if ((port & desc->bDescriptorSubtype) == port) { - UHSO_DPRINTF(2, "Found mux port %x (%d)\n", port, i); - tty = uhso_alloc_tty(sc); - if (tty < 0) - return (ENOMEM); - sc->sc_tty[tty].ht_muxport = i; - uerr = usbd_transfer_setup(sc->sc_udev, - &sc->sc_iface_index, sc->sc_tty[tty].ht_xfer, - uhso_ctrl_config, UHSO_CTRL_MAX, sc, &sc->sc_mtx); - if (uerr) { - device_printf(sc->sc_dev, - "Failed to setup control pipe: %s\n", - usbd_errstr(uerr)); - return (ENXIO); - } - } - } - - /* Setup the intr. endpoint */ - uerr = usbd_transfer_setup(sc->sc_udev, - &iface->idesc->bInterfaceNumber, sc->sc_xfer, - uhso_mux_config, 1, sc, &sc->sc_mtx); - if (uerr) - return (ENXIO); - - return (0); -} - -/* - * Interrupt callback for the multiplexed serial port. Indicates - * which serial port has data waiting. - */ -static void -uhso_mux_intr_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct usb_page_cache *pc; - struct usb_page_search res; - struct uhso_softc *sc = usbd_xfer_softc(xfer); - unsigned int i, mux; - - UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer)); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - /* - * The multiplexed port number can be found at the first byte. - * It contains a bit mask, we transform this in to an integer. - */ - pc = usbd_xfer_get_frame(xfer, 0); - usbd_get_page(pc, 0, &res); - - i = *((unsigned char *)res.buffer); - mux = 0; - while (i >>= 1) { - mux++; - } - - UHSO_DPRINTF(3, "mux port %d (%d)\n", mux, i); - if (mux > UHSO_MPORT_TYPE_NOMAX) - break; - - /* Issue a read for this serial port */ - usbd_xfer_set_priv( - sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ], - &sc->sc_tty[mux]); - usbd_transfer_start(sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ]); - - break; - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -static void -uhso_mux_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - struct usb_device_request req; - struct uhso_tty *ht; - int actlen, len; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer)); - - ht = usbd_xfer_get_priv(xfer); - UHSO_DPRINTF(3, "ht=%p open=%d\n", ht, ht->ht_open); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - /* Got data, send to ucom */ - pc = usbd_xfer_get_frame(xfer, 1); - len = usbd_xfer_frame_len(xfer, 1); - - UHSO_DPRINTF(3, "got %d bytes on mux port %d\n", len, - ht->ht_muxport); - if (len <= 0) { - usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]); - break; - } - - /* Deliver data if the TTY is open, discard otherwise */ - if (ht->ht_open) - ucom_put_data(&sc->sc_ucom[ht->ht_muxport], pc, 0, len); - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - memset(&req, 0, sizeof(struct usb_device_request)); - req.bmRequestType = UT_READ_CLASS_INTERFACE; - req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE; - USETW(req.wValue, 0); - USETW(req.wIndex, ht->ht_muxport); - USETW(req.wLength, 1024); - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &req, sizeof(req)); - - usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); - usbd_xfer_set_frame_len(xfer, 1, 1024); - usbd_xfer_set_frames(xfer, 2); - usbd_transfer_submit(xfer); - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -static void -uhso_mux_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct uhso_tty *ht; - struct usb_page_cache *pc; - struct usb_device_request req; - int actlen; - struct usb_page_search res; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - ht = usbd_xfer_get_priv(xfer); - UHSO_DPRINTF(3, "status=%d, using mux port %d\n", - USB_GET_STATE(xfer), ht->ht_muxport); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - UHSO_DPRINTF(3, "wrote %zd data bytes to muxport %d\n", - actlen - sizeof(struct usb_device_request) , - ht->ht_muxport); - /* FALLTHROUGH */ - case USB_ST_SETUP: - pc = usbd_xfer_get_frame(xfer, 1); - if (ucom_get_data(&sc->sc_ucom[ht->ht_muxport], pc, - 0, 32, &actlen)) { - - usbd_get_page(pc, 0, &res); - - memset(&req, 0, sizeof(struct usb_device_request)); - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND; - USETW(req.wValue, 0); - USETW(req.wIndex, ht->ht_muxport); - USETW(req.wLength, actlen); - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &req, sizeof(req)); - - usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); - usbd_xfer_set_frame_len(xfer, 1, actlen); - usbd_xfer_set_frames(xfer, 2); - - UHSO_DPRINTF(3, "Prepared %d bytes for transmit " - "on muxport %d\n", actlen, ht->ht_muxport); - - usbd_transfer_submit(xfer); - } - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - break; - } -} - -static int -uhso_attach_bulkserial(struct uhso_softc *sc, struct usb_interface *iface, - int type) -{ - usb_error_t uerr; - int tty; - - /* Try attaching RD/WR/INTR first */ - uerr = usbd_transfer_setup(sc->sc_udev, - &iface->idesc->bInterfaceNumber, sc->sc_xfer, - uhso_bs_config, UHSO_BULK_ENDPT_MAX, sc, &sc->sc_mtx); - if (uerr) { - /* Try only RD/WR */ - uerr = usbd_transfer_setup(sc->sc_udev, - &iface->idesc->bInterfaceNumber, sc->sc_xfer, - uhso_bs_config, UHSO_BULK_ENDPT_MAX - 1, sc, &sc->sc_mtx); - } - if (uerr) { - UHSO_DPRINTF(0, "usbd_transfer_setup failed"); - return (-1); - } - - tty = uhso_alloc_tty(sc); - if (tty < 0) { - usbd_transfer_unsetup(sc->sc_xfer, UHSO_BULK_ENDPT_MAX); - return (ENOMEM); - } - - sc->sc_tty[tty].ht_muxport = -1; - return (0); -} - -static void -uhso_bs_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - pc = usbd_xfer_get_frame(xfer, 0); - ucom_put_data(&sc->sc_ucom[0], pc, 0, actlen); - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -static void -uhso_bs_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - case USB_ST_SETUP: -tr_setup: - pc = usbd_xfer_get_frame(xfer, 0); - if (ucom_get_data(&sc->sc_ucom[0], pc, 0, 8192, &actlen)) { - usbd_xfer_set_frame_len(xfer, 0, actlen); - usbd_transfer_submit(xfer); - } - break; - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -static void -uhso_bs_cfg(struct uhso_softc *sc) -{ - struct usb_device_request req; - usb_error_t uerr; - - if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK)) - return; - - req.bmRequestType = UT_WRITE_CLASS_INTERFACE; - req.bRequest = UCDC_SET_CONTROL_LINE_STATE; - USETW(req.wValue, sc->sc_line); - USETW(req.wIndex, sc->sc_iface_no); - USETW(req.wLength, 0); - - uerr = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom[0], &req, NULL, 0, 1000); - if (uerr != 0) { - device_printf(sc->sc_dev, "failed to set ctrl line state to " - "0x%02x: %s\n", sc->sc_line, usbd_errstr(uerr)); - } -} - -static void -uhso_bs_intr_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct usb_page_cache *pc; - int actlen; - struct usb_cdc_notification cdc; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - if (actlen < UCDC_NOTIFICATION_LENGTH) { - UHSO_DPRINTF(0, "UCDC notification too short: %d\n", actlen); - goto tr_setup; - } - else if (actlen > sizeof(struct usb_cdc_notification)) { - UHSO_DPRINTF(0, "UCDC notification too large: %d\n", actlen); - actlen = sizeof(struct usb_cdc_notification); - } - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, &cdc, actlen); - - if (UGETW(cdc.wIndex) != sc->sc_iface_no) { - UHSO_DPRINTF(0, "Interface mismatch, got %d expected %d\n", - UGETW(cdc.wIndex), sc->sc_iface_no); - goto tr_setup; - } - - if (cdc.bmRequestType == UCDC_NOTIFICATION && - cdc.bNotification == UCDC_N_SERIAL_STATE) { - UHSO_DPRINTF(2, "notify = 0x%02x\n", cdc.data[0]); - - sc->sc_msr = 0; - sc->sc_lsr = 0; - if (cdc.data[0] & UCDC_N_SERIAL_RI) - sc->sc_msr |= SER_RI; - if (cdc.data[0] & UCDC_N_SERIAL_DSR) - sc->sc_msr |= SER_DSR; - if (cdc.data[0] & UCDC_N_SERIAL_DCD) - sc->sc_msr |= SER_DCD; - - ucom_status_change(&sc->sc_ucom[0]); - } - case USB_ST_SETUP: -tr_setup: - default: - if (error == USB_ERR_CANCELLED) - break; - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -static void -uhso_ucom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr) -{ - struct uhso_softc *sc = ucom->sc_parent; - - *lsr = sc->sc_lsr; - *msr = sc->sc_msr; -} - -static void -uhso_ucom_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff) -{ - struct uhso_softc *sc = ucom->sc_parent; - - if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK)) - return; - - if (onoff) - sc->sc_line |= UCDC_LINE_DTR; - else - sc->sc_line &= ~UCDC_LINE_DTR; - - uhso_bs_cfg(sc); -} - -static void -uhso_ucom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff) -{ - struct uhso_softc *sc = ucom->sc_parent; - - if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK)) - return; - - if (onoff) - sc->sc_line |= UCDC_LINE_RTS; - else - sc->sc_line &= ~UCDC_LINE_RTS; - - uhso_bs_cfg(sc); -} - -static void -uhso_ucom_start_read(struct ucom_softc *ucom) -{ - struct uhso_softc *sc = ucom->sc_parent; - - UHSO_DPRINTF(3, "unit=%d, subunit=%d\n", - ucom->sc_super->sc_unit, ucom->sc_subunit); - - if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) { - sc->sc_tty[ucom->sc_subunit].ht_open = 1; - usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]); - } - else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) { - sc->sc_tty[0].ht_open = 1; - usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]); - if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL) - usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]); - } -} - -static void -uhso_ucom_stop_read(struct ucom_softc *ucom) -{ - - struct uhso_softc *sc = ucom->sc_parent; - - if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) { - sc->sc_tty[ucom->sc_subunit].ht_open = 0; - usbd_transfer_stop( - sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_READ]); - } - else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) { - sc->sc_tty[0].ht_open = 0; - usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]); - if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL) - usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]); - } -} - -static void -uhso_ucom_start_write(struct ucom_softc *ucom) -{ - struct uhso_softc *sc = ucom->sc_parent; - - if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) { - UHSO_DPRINTF(3, "local unit %d\n", ucom->sc_subunit); - - usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]); - - usbd_xfer_set_priv( - sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE], - &sc->sc_tty[ucom->sc_subunit]); - usbd_transfer_start( - sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE]); - - } - else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) { - usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]); - } -} - -static void -uhso_ucom_stop_write(struct ucom_softc *ucom) -{ - struct uhso_softc *sc = ucom->sc_parent; - - if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) { - usbd_transfer_stop( - sc->sc_tty[ucom->sc_subunit].ht_xfer[UHSO_CTRL_WRITE]); - } - else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) { - usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]); - } -} - -static int -uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface, int type) -{ - struct ifnet *ifp; - usb_error_t uerr; - struct sysctl_ctx_list *sctx; - struct sysctl_oid *soid; - unsigned int devunit; - - uerr = usbd_transfer_setup(sc->sc_udev, - &iface->idesc->bInterfaceNumber, sc->sc_if_xfer, - uhso_ifnet_config, UHSO_IFNET_MAX, sc, &sc->sc_mtx); - if (uerr) { - UHSO_DPRINTF(0, "usbd_transfer_setup failed: %s\n", - usbd_errstr(uerr)); - return (-1); - } - - sc->sc_ifp = ifp = if_alloc(IFT_OTHER); - if (sc->sc_ifp == NULL) { - device_printf(sc->sc_dev, "if_alloc() failed\n"); - return (-1); - } - - callout_init_mtx(&sc->sc_c, &sc->sc_mtx, 0); - mtx_lock(&sc->sc_mtx); - callout_reset(&sc->sc_c, 1, uhso_if_rxflush, sc); - mtx_unlock(&sc->sc_mtx); - - /* - * We create our own unit numbers for ifnet devices because the - * USB interface unit numbers can be at arbitrary positions yielding - * odd looking device names. - */ - devunit = alloc_unr(uhso_ifnet_unit); - - if_initname(ifp, device_get_name(sc->sc_dev), devunit); - ifp->if_mtu = UHSO_MAX_MTU; - ifp->if_ioctl = uhso_if_ioctl; - ifp->if_init = uhso_if_init; - ifp->if_start = uhso_if_start; - ifp->if_output = uhso_if_output; - ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_NOARP; - ifp->if_softc = sc; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - if_attach(ifp); - bpfattach(ifp, DLT_RAW, 0); - - sctx = device_get_sysctl_ctx(sc->sc_dev); - soid = device_get_sysctl_tree(sc->sc_dev); - /* Unlocked read... */ - SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "netif", - CTLFLAG_RD, ifp->if_xname, 0, "Attached network interface"); - - return (0); -} - -static void -uhso_ifnet_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct mbuf *m; - struct usb_page_cache *pc; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - UHSO_DPRINTF(3, "status=%d, actlen=%d\n", USB_GET_STATE(xfer), actlen); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - if (actlen > 0 && (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) { - pc = usbd_xfer_get_frame(xfer, 0); - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - usbd_copy_out(pc, 0, mtod(m, uint8_t *), actlen); - m->m_pkthdr.len = m->m_len = actlen; - /* Enqueue frame for further processing */ - _IF_ENQUEUE(&sc->sc_rxq, m); - if (!callout_pending(&sc->sc_c) || - !callout_active(&sc->sc_c)) { - callout_schedule(&sc->sc_c, 1); - } - } - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -/* - * Deferred RX processing, called with mutex locked. - * - * Each frame we receive might contain several small ip-packets as well - * as partial ip-packets. We need to separate/assemble them into individual - * packets before sending them to the ip-layer. - */ -static void -uhso_if_rxflush(void *arg) -{ - struct uhso_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - uint8_t *cp; - struct mbuf *m, *m0, *mwait; - struct ip *ip; -#ifdef INET6 - struct ip6_hdr *ip6; -#endif - uint16_t iplen; - int len, isr; - - m = NULL; - mwait = sc->sc_mwait; - for (;;) { - if (m == NULL) { - _IF_DEQUEUE(&sc->sc_rxq, m); - if (m == NULL) - break; - UHSO_DPRINTF(3, "dequeue m=%p, len=%d\n", m, m->m_len); - } - mtx_unlock(&sc->sc_mtx); - - /* Do we have a partial packet waiting? */ - if (mwait != NULL) { - m0 = mwait; - mwait = NULL; - - UHSO_DPRINTF(3, "partial m0=%p(%d), concat w/ m=%p(%d)\n", - m0, m0->m_len, m, m->m_len); - len = m->m_len + m0->m_len; - - /* Concat mbufs and fix headers */ - m_cat(m0, m); - m0->m_pkthdr.len = len; - m->m_flags &= ~M_PKTHDR; - - m = m_pullup(m0, sizeof(struct ip)); - if (m == NULL) { - ifp->if_ierrors++; - UHSO_DPRINTF(0, "m_pullup failed\n"); - mtx_lock(&sc->sc_mtx); - continue; - } - UHSO_DPRINTF(3, "Constructed mbuf=%p, len=%d\n", - m, m->m_pkthdr.len); - } - - cp = mtod(m, uint8_t *); - ip = (struct ip *)cp; -#ifdef INET6 - ip6 = (struct ip6_hdr *)cp; -#endif - - /* Check for IPv4 */ - if (ip->ip_v == IPVERSION) { - iplen = htons(ip->ip_len); - isr = NETISR_IP; - } -#ifdef INET6 - /* Check for IPv6 */ - else if ((ip6->ip6_vfc & IPV6_VERSION_MASK) == IPV6_VERSION) { - iplen = htons(ip6->ip6_plen); - isr = NETISR_IPV6; - } -#endif - else { - UHSO_DPRINTF(0, "got unexpected ip version %d, " - "m=%p, len=%d\n", (*cp & 0xf0) >> 4, m, m->m_len); - ifp->if_ierrors++; - UHSO_HEXDUMP(cp, 4); - m_freem(m); - m = NULL; - mtx_lock(&sc->sc_mtx); - continue; - } - - if (iplen == 0) { - UHSO_DPRINTF(0, "Zero IP length\n"); - ifp->if_ierrors++; - m_freem(m); - m = NULL; - mtx_lock(&sc->sc_mtx); - continue; - } - - UHSO_DPRINTF(3, "m=%p, len=%d, cp=%p, iplen=%d\n", - m, m->m_pkthdr.len, cp, iplen); - - m0 = NULL; - - /* More IP packets in this mbuf */ - if (iplen < m->m_pkthdr.len) { - m0 = m; - - /* - * Allocate a new mbuf for this IP packet and - * copy the IP-packet into it. - */ - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - memcpy(mtod(m, uint8_t *), mtod(m0, uint8_t *), iplen); - m->m_pkthdr.len = m->m_len = iplen; - - /* Adjust the size of the original mbuf */ - m_adj(m0, iplen); - m0 = m_defrag(m0, M_WAIT); - - UHSO_DPRINTF(3, "New mbuf=%p, len=%d/%d, m0=%p, " - "m0_len=%d/%d\n", m, m->m_pkthdr.len, m->m_len, - m0, m0->m_pkthdr.len, m0->m_len); - } - else if (iplen > m->m_pkthdr.len) { - UHSO_DPRINTF(3, "Deferred mbuf=%p, len=%d\n", - m, m->m_pkthdr.len); - mwait = m; - m = NULL; - mtx_lock(&sc->sc_mtx); - continue; - } - - ifp->if_ipackets++; - m->m_pkthdr.rcvif = ifp; - - /* Dispatch to IP layer */ - BPF_MTAP(sc->sc_ifp, m); - M_SETFIB(m, ifp->if_fib); - netisr_dispatch(isr, m); - m = m0 != NULL ? m0 : NULL; - mtx_lock(&sc->sc_mtx); - } - sc->sc_mwait = mwait; -} - -static void -uhso_ifnet_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uhso_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct usb_page_cache *pc; - struct mbuf *m; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - ifp->if_opackets++; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - case USB_ST_SETUP: -tr_setup: - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - - if (m->m_pkthdr.len > MCLBYTES) - m->m_pkthdr.len = MCLBYTES; - - usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len); - pc = usbd_xfer_get_frame(xfer, 0); - usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); - usbd_transfer_submit(xfer); - - BPF_MTAP(ifp, m); - m_freem(m); - break; - default: - UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error)); - if (error == USB_ERR_CANCELLED) - break; - usbd_xfer_set_stall(xfer); - goto tr_setup; - } -} - -static int -uhso_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct uhso_softc *sc; - - sc = ifp->if_softc; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - uhso_if_init(sc); - } - } - else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - mtx_lock(&sc->sc_mtx); - uhso_if_stop(sc); - mtx_unlock(&sc->sc_mtx); - } - } - break; - case SIOCSIFADDR: - case SIOCSIFDSTADDR: - case SIOCADDMULTI: - case SIOCDELMULTI: - break; - default: - return (EINVAL); - } - return (0); -} - -static void -uhso_if_init(void *priv) -{ - struct uhso_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - - mtx_lock(&sc->sc_mtx); - uhso_if_stop(sc); - ifp = sc->sc_ifp; - ifp->if_flags |= IFF_UP; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - mtx_unlock(&sc->sc_mtx); - - UHSO_DPRINTF(2, "ifnet initialized\n"); -} - -static int -uhso_if_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, - struct route *ro) -{ - int error; - - /* Only IPv4/6 support */ - if (dst->sa_family != AF_INET -#ifdef INET6 - && dst->sa_family != AF_INET6 -#endif - ) { - return (EAFNOSUPPORT); - } - - error = (ifp->if_transmit)(ifp, m0); - if (error) { - ifp->if_oerrors++; - return (ENOBUFS); - } - ifp->if_opackets++; - return (0); -} - -static void -uhso_if_start(struct ifnet *ifp, struct ifaltq_subque *ifsq) -{ - struct uhso_softc *sc = ifp->if_softc; - - ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - UHSO_DPRINTF(1, "Not running\n"); - return; - } - - mtx_lock(&sc->sc_mtx); - usbd_transfer_start(sc->sc_if_xfer[UHSO_IFNET_READ]); - usbd_transfer_start(sc->sc_if_xfer[UHSO_IFNET_WRITE]); - mtx_unlock(&sc->sc_mtx); - UHSO_DPRINTF(3, "interface started\n"); -} - -static void -uhso_if_stop(struct uhso_softc *sc) -{ - - usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_READ]); - usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_WRITE]); - sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); -} diff --git a/sys/bus/u4b/usb/Makefile b/sys/bus/u4b/usb/Makefile index ccf8a32d62..63c4b68620 100644 --- a/sys/bus/u4b/usb/Makefile +++ b/sys/bus/u4b/usb/Makefile @@ -2,8 +2,6 @@ KMOD= usb -# XXX usb_compat_linux.c - SRCS= bus_if.h device_if.h usb_if.h usb_if.c \ opt_usb.h opt_ddb.h \ usbdevs.h usbdevs_data.h \ diff --git a/sys/bus/u4b/usb_compat_linux.c b/sys/bus/u4b/usb_compat_linux.c deleted file mode 100644 index 80bbac9514..0000000000 --- a/sys/bus/u4b/usb_compat_linux.c +++ /dev/null @@ -1,1730 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved. - * Copyright (c) 2007 Hans Petter Selasky. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define USB_DEBUG_VAR usb_debug - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct usb_linux_softc { - LIST_ENTRY(usb_linux_softc) sc_attached_list; - - device_t sc_fbsd_dev; - struct usb_device *sc_fbsd_udev; - struct usb_interface *sc_ui; - struct usb_driver *sc_udrv; -}; - -/* prototypes */ -static device_probe_t usb_linux_probe; -static device_attach_t usb_linux_attach; -static device_detach_t usb_linux_detach; -static device_suspend_t usb_linux_suspend; -static device_resume_t usb_linux_resume; - -static usb_callback_t usb_linux_isoc_callback; -static usb_callback_t usb_linux_non_isoc_callback; - -static usb_complete_t usb_linux_wait_complete; - -static uint16_t usb_max_isoc_frames(struct usb_device *); -static int usb_start_wait_urb(struct urb *, usb_timeout_t, uint16_t *); -static const struct usb_device_id *usb_linux_lookup_id( - const struct usb_device_id *, struct usb_attach_arg *); -static struct usb_driver *usb_linux_get_usb_driver(struct usb_linux_softc *); -static int usb_linux_create_usb_device(struct usb_device *, device_t); -static void usb_linux_cleanup_interface(struct usb_device *, - struct usb_interface *); -static void usb_linux_complete(struct usb_xfer *); -static int usb_unlink_urb_sub(struct urb *, uint8_t); - -/*------------------------------------------------------------------------* - * FreeBSD USB interface - *------------------------------------------------------------------------*/ - -static LIST_HEAD(, usb_linux_softc) usb_linux_attached_list; -static LIST_HEAD(, usb_driver) usb_linux_driver_list; - -static device_method_t usb_linux_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, usb_linux_probe), - DEVMETHOD(device_attach, usb_linux_attach), - DEVMETHOD(device_detach, usb_linux_detach), - DEVMETHOD(device_suspend, usb_linux_suspend), - DEVMETHOD(device_resume, usb_linux_resume), - - DEVMETHOD_END -}; - -static driver_t usb_linux_driver = { - .name = "usb_linux", - .methods = usb_linux_methods, - .size = sizeof(struct usb_linux_softc), -}; - -static devclass_t usb_linux_devclass; - -DRIVER_MODULE(usb_linux, uhub, usb_linux_driver, usb_linux_devclass, NULL, NULL); -MODULE_VERSION(usb_linux, 1); - -/*------------------------------------------------------------------------* - * usb_linux_lookup_id - * - * This functions takes an array of "struct usb_device_id" and tries - * to match the entries with the information in "struct usb_attach_arg". - * If it finds a match the matching entry will be returned. - * Else "NULL" will be returned. - *------------------------------------------------------------------------*/ -static const struct usb_device_id * -usb_linux_lookup_id(const struct usb_device_id *id, struct usb_attach_arg *uaa) -{ - if (id == NULL) { - goto done; - } - /* - * Keep on matching array entries until we find one with - * "match_flags" equal to zero, which indicates the end of the - * array: - */ - for (; id->match_flags; id++) { - - if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - (id->idVendor != uaa->info.idVendor)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - (id->idProduct != uaa->info.idProduct)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && - (id->bcdDevice_lo > uaa->info.bcdDevice)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && - (id->bcdDevice_hi < uaa->info.bcdDevice)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && - (id->bDeviceClass != uaa->info.bDeviceClass)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && - (id->bDeviceSubClass != uaa->info.bDeviceSubClass)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && - (id->bDeviceProtocol != uaa->info.bDeviceProtocol)) { - continue; - } - if ((uaa->info.bDeviceClass == 0xFF) && - !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS | - USB_DEVICE_ID_MATCH_INT_PROTOCOL))) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && - (id->bInterfaceClass != uaa->info.bInterfaceClass)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && - (id->bInterfaceSubClass != uaa->info.bInterfaceSubClass)) { - continue; - } - if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && - (id->bInterfaceProtocol != uaa->info.bInterfaceProtocol)) { - continue; - } - /* we found a match! */ - return (id); - } - -done: - return (NULL); -} - -/*------------------------------------------------------------------------* - * usb_linux_probe - * - * This function is the FreeBSD probe callback. It is called from the - * FreeBSD USB stack through the "device_probe_and_attach()" function. - *------------------------------------------------------------------------*/ -static int -usb_linux_probe(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct usb_driver *udrv; - int err = ENXIO; - - if (uaa->usb_mode != USB_MODE_HOST) { - return (ENXIO); - } - mtx_lock(&Giant); - LIST_FOREACH(udrv, &usb_linux_driver_list, linux_driver_list) { - if (usb_linux_lookup_id(udrv->id_table, uaa)) { - err = 0; - break; - } - } - mtx_unlock(&Giant); - - return (err); -} - -/*------------------------------------------------------------------------* - * usb_linux_get_usb_driver - * - * This function returns the pointer to the "struct usb_driver" where - * the Linux USB device driver "struct usb_device_id" match was found. - * We apply a lock before reading out the pointer to avoid races. - *------------------------------------------------------------------------*/ -static struct usb_driver * -usb_linux_get_usb_driver(struct usb_linux_softc *sc) -{ - struct usb_driver *udrv; - - mtx_lock(&Giant); - udrv = sc->sc_udrv; - mtx_unlock(&Giant); - return (udrv); -} - -/*------------------------------------------------------------------------* - * usb_linux_attach - * - * This function is the FreeBSD attach callback. It is called from the - * FreeBSD USB stack through the "device_probe_and_attach()" function. - * This function is called when "usb_linux_probe()" returns zero. - *------------------------------------------------------------------------*/ -static int -usb_linux_attach(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct usb_linux_softc *sc = device_get_softc(dev); - struct usb_driver *udrv; - const struct usb_device_id *id = NULL; - - mtx_lock(&Giant); - LIST_FOREACH(udrv, &usb_linux_driver_list, linux_driver_list) { - id = usb_linux_lookup_id(udrv->id_table, uaa); - if (id) - break; - } - mtx_unlock(&Giant); - - if (id == NULL) { - return (ENXIO); - } - if (usb_linux_create_usb_device(uaa->device, dev) != 0) - return (ENOMEM); - device_set_usb_desc(dev); - - sc->sc_fbsd_udev = uaa->device; - sc->sc_fbsd_dev = dev; - sc->sc_udrv = udrv; - sc->sc_ui = usb_ifnum_to_if(uaa->device, uaa->info.bIfaceNum); - if (sc->sc_ui == NULL) { - return (EINVAL); - } - if (udrv->probe) { - if ((udrv->probe) (sc->sc_ui, id)) { - return (ENXIO); - } - } - mtx_lock(&Giant); - LIST_INSERT_HEAD(&usb_linux_attached_list, sc, sc_attached_list); - mtx_unlock(&Giant); - - /* success */ - return (0); -} - -/*------------------------------------------------------------------------* - * usb_linux_detach - * - * This function is the FreeBSD detach callback. It is called from the - * FreeBSD USB stack through the "device_detach()" function. - *------------------------------------------------------------------------*/ -static int -usb_linux_detach(device_t dev) -{ - struct usb_linux_softc *sc = device_get_softc(dev); - struct usb_driver *udrv = NULL; - - mtx_lock(&Giant); - if (sc->sc_attached_list.le_prev) { - LIST_REMOVE(sc, sc_attached_list); - sc->sc_attached_list.le_prev = NULL; - udrv = sc->sc_udrv; - sc->sc_udrv = NULL; - } - mtx_unlock(&Giant); - - if (udrv && udrv->disconnect) { - (udrv->disconnect) (sc->sc_ui); - } - /* - * Make sure that we free all FreeBSD USB transfers belonging to - * this Linux "usb_interface", hence they will most likely not be - * needed any more. - */ - usb_linux_cleanup_interface(sc->sc_fbsd_udev, sc->sc_ui); - return (0); -} - -/*------------------------------------------------------------------------* - * usb_linux_suspend - * - * This function is the FreeBSD suspend callback. Usually it does nothing. - *------------------------------------------------------------------------*/ -static int -usb_linux_suspend(device_t dev) -{ - struct usb_linux_softc *sc = device_get_softc(dev); - struct usb_driver *udrv = usb_linux_get_usb_driver(sc); - int err; - - if (udrv && udrv->suspend) { - err = (udrv->suspend) (sc->sc_ui, 0); - } - return (0); -} - -/*------------------------------------------------------------------------* - * usb_linux_resume - * - * This function is the FreeBSD resume callback. Usually it does nothing. - *------------------------------------------------------------------------*/ -static int -usb_linux_resume(device_t dev) -{ - struct usb_linux_softc *sc = device_get_softc(dev); - struct usb_driver *udrv = usb_linux_get_usb_driver(sc); - int err; - - if (udrv && udrv->resume) { - err = (udrv->resume) (sc->sc_ui); - } - return (0); -} - -/*------------------------------------------------------------------------* - * Linux emulation layer - *------------------------------------------------------------------------*/ - -/*------------------------------------------------------------------------* - * usb_max_isoc_frames - * - * The following function returns the maximum number of isochronous - * frames that we support per URB. It is not part of the Linux USB API. - *------------------------------------------------------------------------*/ -static uint16_t -usb_max_isoc_frames(struct usb_device *dev) -{ - ; /* indent fix */ - switch (usbd_get_speed(dev)) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - return (USB_MAX_FULL_SPEED_ISOC_FRAMES); - default: - return (USB_MAX_HIGH_SPEED_ISOC_FRAMES); - } -} - -/*------------------------------------------------------------------------* - * usb_submit_urb - * - * This function is used to queue an URB after that it has been - * initialized. If it returns non-zero, it means that the URB was not - * queued. - *------------------------------------------------------------------------*/ -int -usb_submit_urb(struct urb *urb, uint16_t mem_flags) -{ - struct usb_host_endpoint *uhe; - uint8_t do_unlock; - int err; - - if (urb == NULL) - return (-EINVAL); - - do_unlock = mtx_owned(&Giant) ? 0 : 1; - if (do_unlock) - mtx_lock(&Giant); - - if (urb->endpoint == NULL) { - err = -EINVAL; - goto done; - } - - /* - * Check to see if the urb is in the process of being killed - * and stop a urb that is in the process of being killed from - * being re-submitted (e.g. from its completion callback - * function). - */ - if (urb->kill_count != 0) { - err = -EPERM; - goto done; - } - - uhe = urb->endpoint; - - /* - * Check that we have got a FreeBSD USB transfer that will dequeue - * the URB structure and do the real transfer. If there are no USB - * transfers, then we return an error. - */ - if (uhe->bsd_xfer[0] || - uhe->bsd_xfer[1]) { - /* we are ready! */ - - TAILQ_INSERT_TAIL(&uhe->bsd_urb_list, urb, bsd_urb_list); - - urb->status = -EINPROGRESS; - - usbd_transfer_start(uhe->bsd_xfer[0]); - usbd_transfer_start(uhe->bsd_xfer[1]); - err = 0; - } else { - /* no pipes have been setup yet! */ - urb->status = -EINVAL; - err = -EINVAL; - } -done: - if (do_unlock) - mtx_unlock(&Giant); - return (err); -} - -/*------------------------------------------------------------------------* - * usb_unlink_urb - * - * This function is used to stop an URB after that it is been - * submitted, but before the "complete" callback has been called. On - *------------------------------------------------------------------------*/ -int -usb_unlink_urb(struct urb *urb) -{ - return (usb_unlink_urb_sub(urb, 0)); -} - -static void -usb_unlink_bsd(struct usb_xfer *xfer, - struct urb *urb, uint8_t drain) -{ - if (xfer == NULL) - return; - if (!usbd_transfer_pending(xfer)) - return; - if (xfer->priv_fifo == (void *)urb) { - if (drain) { - mtx_unlock(&Giant); - usbd_transfer_drain(xfer); - mtx_lock(&Giant); - } else { - usbd_transfer_stop(xfer); - } - usbd_transfer_start(xfer); - } -} - -static int -usb_unlink_urb_sub(struct urb *urb, uint8_t drain) -{ - struct usb_host_endpoint *uhe; - uint16_t x; - uint8_t do_unlock; - int err; - - if (urb == NULL) - return (-EINVAL); - - do_unlock = mtx_owned(&Giant) ? 0 : 1; - if (do_unlock) - mtx_lock(&Giant); - if (drain) - urb->kill_count++; - - if (urb->endpoint == NULL) { - err = -EINVAL; - goto done; - } - uhe = urb->endpoint; - - if (urb->bsd_urb_list.tqe_prev) { - - /* not started yet, just remove it from the queue */ - TAILQ_REMOVE(&uhe->bsd_urb_list, urb, bsd_urb_list); - urb->bsd_urb_list.tqe_prev = NULL; - urb->status = -ECONNRESET; - urb->actual_length = 0; - - for (x = 0; x < urb->number_of_packets; x++) { - urb->iso_frame_desc[x].actual_length = 0; - } - - if (urb->complete) { - (urb->complete) (urb); - } - } else { - - /* - * If the URB is not on the URB list, then check if one of - * the FreeBSD USB transfer are processing the current URB. - * If so, re-start that transfer, which will lead to the - * termination of that URB: - */ - usb_unlink_bsd(uhe->bsd_xfer[0], urb, drain); - usb_unlink_bsd(uhe->bsd_xfer[1], urb, drain); - } - err = 0; -done: - if (drain) - urb->kill_count--; - if (do_unlock) - mtx_unlock(&Giant); - return (err); -} - -/*------------------------------------------------------------------------* - * usb_clear_halt - * - * This function must always be used to clear the stall. Stall is when - * an USB endpoint returns a stall message to the USB host controller. - * Until the stall is cleared, no data can be transferred. - *------------------------------------------------------------------------*/ -int -usb_clear_halt(struct usb_device *dev, struct usb_host_endpoint *uhe) -{ - struct usb_config cfg[1]; - struct usb_endpoint *ep; - uint8_t type; - uint8_t addr; - - if (uhe == NULL) - return (-EINVAL); - - type = uhe->desc.bmAttributes & UE_XFERTYPE; - addr = uhe->desc.bEndpointAddress; - - memset(cfg, 0, sizeof(cfg)); - - cfg[0].type = type; - cfg[0].endpoint = addr & UE_ADDR; - cfg[0].direction = addr & (UE_DIR_OUT | UE_DIR_IN); - - ep = usbd_get_endpoint(dev, uhe->bsd_iface_index, cfg); - if (ep == NULL) - return (-EINVAL); - - usbd_clear_data_toggle(dev, ep); - - return (usb_control_msg(dev, &dev->ep0, - UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT, - UF_ENDPOINT_HALT, addr, NULL, 0, 1000)); -} - -/*------------------------------------------------------------------------* - * usb_start_wait_urb - * - * This is an internal function that is used to perform synchronous - * Linux USB transfers. - *------------------------------------------------------------------------*/ -static int -usb_start_wait_urb(struct urb *urb, usb_timeout_t timeout, uint16_t *p_actlen) -{ - int err; - uint8_t do_unlock; - - /* you must have a timeout! */ - if (timeout == 0) { - timeout = 1; - } - urb->complete = &usb_linux_wait_complete; - urb->timeout = timeout; - urb->transfer_flags |= URB_WAIT_WAKEUP; - urb->transfer_flags &= ~URB_IS_SLEEPING; - - do_unlock = mtx_owned(&Giant) ? 0 : 1; - if (do_unlock) - mtx_lock(&Giant); - err = usb_submit_urb(urb, 0); - if (err) - goto done; - - /* - * the URB might have completed before we get here, so check that by - * using some flags! - */ - while (urb->transfer_flags & URB_WAIT_WAKEUP) { - urb->transfer_flags |= URB_IS_SLEEPING; - cv_wait(&urb->cv_wait, &Giant); - urb->transfer_flags &= ~URB_IS_SLEEPING; - } - - err = urb->status; - -done: - if (do_unlock) - mtx_unlock(&Giant); - if (p_actlen != NULL) { - if (err) - *p_actlen = 0; - else - *p_actlen = urb->actual_length; - } - return (err); -} - -/*------------------------------------------------------------------------* - * usb_control_msg - * - * The following function performs a control transfer sequence one any - * control, bulk or interrupt endpoint, specified by "uhe". A control - * transfer means that you transfer an 8-byte header first followed by - * a data-phase as indicated by the 8-byte header. The "timeout" is - * given in milliseconds. - * - * Return values: - * 0: Success - * < 0: Failure - * > 0: Acutal length - *------------------------------------------------------------------------*/ -int -usb_control_msg(struct usb_device *dev, struct usb_host_endpoint *uhe, - uint8_t request, uint8_t requesttype, - uint16_t value, uint16_t index, void *data, - uint16_t size, usb_timeout_t timeout) -{ - struct usb_device_request req; - struct urb *urb; - int err; - uint16_t actlen; - uint8_t type; - uint8_t addr; - - req.bmRequestType = requesttype; - req.bRequest = request; - USETW(req.wValue, value); - USETW(req.wIndex, index); - USETW(req.wLength, size); - - if (uhe == NULL) { - return (-EINVAL); - } - type = (uhe->desc.bmAttributes & UE_XFERTYPE); - addr = (uhe->desc.bEndpointAddress & UE_ADDR); - - if (type != UE_CONTROL) { - return (-EINVAL); - } - if (addr == 0) { - /* - * The FreeBSD USB stack supports standard control - * transfers on control endpoint zero: - */ - err = usbd_do_request_flags(dev, - NULL, &req, data, USB_SHORT_XFER_OK, - &actlen, timeout); - if (err) { - err = -EPIPE; - } else { - err = actlen; - } - return (err); - } - if (dev->flags.usb_mode != USB_MODE_HOST) { - /* not supported */ - return (-EINVAL); - } - err = usb_setup_endpoint(dev, uhe, 1 /* dummy */ ); - - /* - * NOTE: we need to allocate real memory here so that we don't - * transfer data to/from the stack! - * - * 0xFFFF is a FreeBSD specific magic value. - */ - urb = usb_alloc_urb(0xFFFF, size); - if (urb == NULL) - return (-ENOMEM); - - urb->dev = dev; - urb->endpoint = uhe; - - memcpy(urb->setup_packet, &req, sizeof(req)); - - if (size && (!(req.bmRequestType & UT_READ))) { - /* move the data to a real buffer */ - memcpy(USB_ADD_BYTES(urb->setup_packet, sizeof(req)), - data, size); - } - err = usb_start_wait_urb(urb, timeout, &actlen); - - if (req.bmRequestType & UT_READ) { - if (actlen) { - bcopy(USB_ADD_BYTES(urb->setup_packet, - sizeof(req)), data, actlen); - } - } - usb_free_urb(urb); - - if (err == 0) { - err = actlen; - } - return (err); -} - -/*------------------------------------------------------------------------* - * usb_set_interface - * - * The following function will select which alternate setting of an - * USB interface you plan to use. By default alternate setting with - * index zero is selected. Note that "iface_no" is not the interface - * index, but rather the value of "bInterfaceNumber". - *------------------------------------------------------------------------*/ -int -usb_set_interface(struct usb_device *dev, uint8_t iface_no, uint8_t alt_index) -{ - struct usb_interface *p_ui = usb_ifnum_to_if(dev, iface_no); - int err; - - if (p_ui == NULL) - return (-EINVAL); - if (alt_index >= p_ui->num_altsetting) - return (-EINVAL); - usb_linux_cleanup_interface(dev, p_ui); - err = -usbd_set_alt_interface_index(dev, - p_ui->bsd_iface_index, alt_index); - if (err == 0) { - p_ui->cur_altsetting = p_ui->altsetting + alt_index; - } - return (err); -} - -/*------------------------------------------------------------------------* - * usb_setup_endpoint - * - * The following function is an extension to the Linux USB API that - * allows you to set a maximum buffer size for a given USB endpoint. - * The maximum buffer size is per URB. If you don't call this function - * to set a maximum buffer size, the endpoint will not be functional. - * Note that for isochronous endpoints the maximum buffer size must be - * a non-zero dummy, hence this function will base the maximum buffer - * size on "wMaxPacketSize". - *------------------------------------------------------------------------*/ -int -usb_setup_endpoint(struct usb_device *dev, - struct usb_host_endpoint *uhe, usb_size_t bufsize) -{ - struct usb_config cfg[2]; - uint8_t type = uhe->desc.bmAttributes & UE_XFERTYPE; - uint8_t addr = uhe->desc.bEndpointAddress; - - if (uhe->fbsd_buf_size == bufsize) { - /* optimize */ - return (0); - } - usbd_transfer_unsetup(uhe->bsd_xfer, 2); - - uhe->fbsd_buf_size = bufsize; - - if (bufsize == 0) { - return (0); - } - memset(cfg, 0, sizeof(cfg)); - - if (type == UE_ISOCHRONOUS) { - - /* - * Isochronous transfers are special in that they don't fit - * into the BULK/INTR/CONTROL transfer model. - */ - - cfg[0].type = type; - cfg[0].endpoint = addr & UE_ADDR; - cfg[0].direction = addr & (UE_DIR_OUT | UE_DIR_IN); - cfg[0].callback = &usb_linux_isoc_callback; - cfg[0].bufsize = 0; /* use wMaxPacketSize */ - cfg[0].frames = usb_max_isoc_frames(dev); - cfg[0].flags.proxy_buffer = 1; -#if 0 - /* - * The Linux USB API allows non back-to-back - * isochronous frames which we do not support. If the - * isochronous frames are not back-to-back we need to - * do a copy, and then we need a buffer for - * that. Enable this at your own risk. - */ - cfg[0].flags.ext_buffer = 1; -#endif - cfg[0].flags.short_xfer_ok = 1; - - bcopy(cfg, cfg + 1, sizeof(*cfg)); - - /* Allocate and setup two generic FreeBSD USB transfers */ - - if (usbd_transfer_setup(dev, &uhe->bsd_iface_index, - uhe->bsd_xfer, cfg, 2, uhe, &Giant)) { - return (-EINVAL); - } - } else { - if (bufsize > (1 << 22)) { - /* limit buffer size */ - bufsize = (1 << 22); - } - /* Allocate and setup one generic FreeBSD USB transfer */ - - cfg[0].type = type; - cfg[0].endpoint = addr & UE_ADDR; - cfg[0].direction = addr & (UE_DIR_OUT | UE_DIR_IN); - cfg[0].callback = &usb_linux_non_isoc_callback; - cfg[0].bufsize = bufsize; - cfg[0].flags.ext_buffer = 1; /* enable zero-copy */ - cfg[0].flags.proxy_buffer = 1; - cfg[0].flags.short_xfer_ok = 1; - - if (usbd_transfer_setup(dev, &uhe->bsd_iface_index, - uhe->bsd_xfer, cfg, 1, uhe, &Giant)) { - return (-EINVAL); - } - } - return (0); -} - -/*------------------------------------------------------------------------* - * usb_linux_create_usb_device - * - * The following function is used to build up a per USB device - * structure tree, that mimics the Linux one. The root structure - * is returned by this function. - *------------------------------------------------------------------------*/ -static int -usb_linux_create_usb_device(struct usb_device *udev, device_t dev) -{ - struct usb_config_descriptor *cd = usbd_get_config_descriptor(udev); - struct usb_descriptor *desc; - struct usb_interface_descriptor *id; - struct usb_endpoint_descriptor *ed; - struct usb_interface *p_ui = NULL; - struct usb_host_interface *p_uhi = NULL; - struct usb_host_endpoint *p_uhe = NULL; - usb_size_t size; - uint16_t niface_total; - uint16_t nedesc; - uint16_t iface_no_curr; - uint16_t iface_index; - uint8_t pass; - uint8_t iface_no; - - /* - * We do two passes. One pass for computing necessary memory size - * and one pass to initialize all the allocated memory structures. - */ - for (pass = 0; pass < 2; pass++) { - - iface_no_curr = 0 - 1; - niface_total = 0; - iface_index = 0; - nedesc = 0; - desc = NULL; - - /* - * Iterate over all the USB descriptors. Use the USB config - * descriptor pointer provided by the FreeBSD USB stack. - */ - while ((desc = usb_desc_foreach(cd, desc))) { - - /* - * Build up a tree according to the descriptors we - * find: - */ - switch (desc->bDescriptorType) { - case UDESC_DEVICE: - break; - - case UDESC_ENDPOINT: - ed = (void *)desc; - if ((ed->bLength < sizeof(*ed)) || - (iface_index == 0)) - break; - if (p_uhe) { - bcopy(ed, &p_uhe->desc, sizeof(p_uhe->desc)); - p_uhe->bsd_iface_index = iface_index - 1; - TAILQ_INIT(&p_uhe->bsd_urb_list); - p_uhe++; - } - if (p_uhi) { - (p_uhi - 1)->desc.bNumEndpoints++; - } - nedesc++; - break; - - case UDESC_INTERFACE: - id = (void *)desc; - if (id->bLength < sizeof(*id)) - break; - if (p_uhi) { - bcopy(id, &p_uhi->desc, sizeof(p_uhi->desc)); - p_uhi->desc.bNumEndpoints = 0; - p_uhi->endpoint = p_uhe; - p_uhi->string = ""; - p_uhi->bsd_iface_index = iface_index; - p_uhi++; - } - iface_no = id->bInterfaceNumber; - niface_total++; - if (iface_no_curr != iface_no) { - if (p_ui) { - p_ui->altsetting = p_uhi - 1; - p_ui->cur_altsetting = p_uhi - 1; - p_ui->num_altsetting = 1; - p_ui->bsd_iface_index = iface_index; - p_ui->linux_udev = udev; - p_ui++; - } - iface_no_curr = iface_no; - iface_index++; - } else { - if (p_ui) { - (p_ui - 1)->num_altsetting++; - } - } - break; - - default: - break; - } - } - - if (pass == 0) { - - size = (sizeof(*p_uhe) * nedesc) + - (sizeof(*p_ui) * iface_index) + - (sizeof(*p_uhi) * niface_total); - - p_uhe = malloc(size, M_USBDEV, M_WAITOK | M_ZERO); - p_ui = (void *)(p_uhe + nedesc); - p_uhi = (void *)(p_ui + iface_index); - - udev->linux_iface_start = p_ui; - udev->linux_iface_end = p_ui + iface_index; - udev->linux_endpoint_start = p_uhe; - udev->linux_endpoint_end = p_uhe + nedesc; - udev->devnum = device_get_unit(dev); - bcopy(&udev->ddesc, &udev->descriptor, - sizeof(udev->descriptor)); - bcopy(udev->ctrl_ep.edesc, &udev->ep0.desc, - sizeof(udev->ep0.desc)); - } - } - return (0); -} - -/*------------------------------------------------------------------------* - * usb_alloc_urb - * - * This function should always be used when you allocate an URB for - * use with the USB Linux stack. In case of an isochronous transfer - * you must specifiy the maximum number of "iso_packets" which you - * plan to transfer per URB. This function is always blocking, and - * "mem_flags" are not regarded like on Linux. - *------------------------------------------------------------------------*/ -struct urb * -usb_alloc_urb(uint16_t iso_packets, uint16_t mem_flags) -{ - struct urb *urb; - usb_size_t size; - - if (iso_packets == 0xFFFF) { - /* - * FreeBSD specific magic value to ask for control transfer - * memory allocation: - */ - size = sizeof(*urb) + sizeof(struct usb_device_request) + mem_flags; - } else { - size = sizeof(*urb) + (iso_packets * sizeof(urb->iso_frame_desc[0])); - } - - urb = malloc(size, M_USBDEV, M_WAITOK | M_ZERO); - if (urb) { - - cv_init(&urb->cv_wait, "URBWAIT"); - if (iso_packets == 0xFFFF) { - urb->setup_packet = (void *)(urb + 1); - urb->transfer_buffer = (void *)(urb->setup_packet + - sizeof(struct usb_device_request)); - } else { - urb->number_of_packets = iso_packets; - } - } - return (urb); -} - -/*------------------------------------------------------------------------* - * usb_find_host_endpoint - * - * The following function will return the Linux USB host endpoint - * structure that matches the given endpoint type and endpoint - * value. If no match is found, NULL is returned. This function is not - * part of the Linux USB API and is only used internally. - *------------------------------------------------------------------------*/ -struct usb_host_endpoint * -usb_find_host_endpoint(struct usb_device *dev, uint8_t type, uint8_t ep) -{ - struct usb_host_endpoint *uhe; - struct usb_host_endpoint *uhe_end; - struct usb_host_interface *uhi; - struct usb_interface *ui; - uint8_t ea; - uint8_t at; - uint8_t mask; - - if (dev == NULL) { - return (NULL); - } - if (type == UE_CONTROL) { - mask = UE_ADDR; - } else { - mask = (UE_DIR_IN | UE_DIR_OUT | UE_ADDR); - } - - ep &= mask; - - /* - * Iterate over all the interfaces searching the selected alternate - * setting only, and all belonging endpoints. - */ - for (ui = dev->linux_iface_start; - ui != dev->linux_iface_end; - ui++) { - uhi = ui->cur_altsetting; - if (uhi) { - uhe_end = uhi->endpoint + uhi->desc.bNumEndpoints; - for (uhe = uhi->endpoint; - uhe != uhe_end; - uhe++) { - ea = uhe->desc.bEndpointAddress; - at = uhe->desc.bmAttributes; - - if (((ea & mask) == ep) && - ((at & UE_XFERTYPE) == type)) { - return (uhe); - } - } - } - } - - if ((type == UE_CONTROL) && ((ep & UE_ADDR) == 0)) { - return (&dev->ep0); - } - return (NULL); -} - -/*------------------------------------------------------------------------* - * usb_altnum_to_altsetting - * - * The following function returns a pointer to an alternate setting by - * index given a "usb_interface" pointer. If the alternate setting by - * index does not exist, NULL is returned. And alternate setting is a - * variant of an interface, but usually with slightly different - * characteristics. - *------------------------------------------------------------------------*/ -struct usb_host_interface * -usb_altnum_to_altsetting(const struct usb_interface *intf, uint8_t alt_index) -{ - if (alt_index >= intf->num_altsetting) { - return (NULL); - } - return (intf->altsetting + alt_index); -} - -/*------------------------------------------------------------------------* - * usb_ifnum_to_if - * - * The following function searches up an USB interface by - * "bInterfaceNumber". If no match is found, NULL is returned. - *------------------------------------------------------------------------*/ -struct usb_interface * -usb_ifnum_to_if(struct usb_device *dev, uint8_t iface_no) -{ - struct usb_interface *p_ui; - - for (p_ui = dev->linux_iface_start; - p_ui != dev->linux_iface_end; - p_ui++) { - if ((p_ui->num_altsetting > 0) && - (p_ui->altsetting->desc.bInterfaceNumber == iface_no)) { - return (p_ui); - } - } - return (NULL); -} - -/*------------------------------------------------------------------------* - * usb_buffer_alloc - *------------------------------------------------------------------------*/ -void * -usb_buffer_alloc(struct usb_device *dev, usb_size_t size, uint16_t mem_flags, uint8_t *dma_addr) -{ - return (malloc(size, M_USBDEV, M_WAITOK | M_ZERO)); -} - -/*------------------------------------------------------------------------* - * usbd_get_intfdata - *------------------------------------------------------------------------*/ -void * -usbd_get_intfdata(struct usb_interface *intf) -{ - return (intf->bsd_priv_sc); -} - -/*------------------------------------------------------------------------* - * usb_linux_register - * - * The following function is used by the "USB_DRIVER_EXPORT()" macro, - * and is used to register a Linux USB driver, so that its - * "usb_device_id" structures gets searched a probe time. This - * function is not part of the Linux USB API, and is for internal use - * only. - *------------------------------------------------------------------------*/ -void -usb_linux_register(void *arg) -{ - struct usb_driver *drv = arg; - - mtx_lock(&Giant); - LIST_INSERT_HEAD(&usb_linux_driver_list, drv, linux_driver_list); - mtx_unlock(&Giant); - - usb_needs_explore_all(); -} - -/*------------------------------------------------------------------------* - * usb_linux_deregister - * - * The following function is used by the "USB_DRIVER_EXPORT()" macro, - * and is used to deregister a Linux USB driver. This function will - * ensure that all driver instances belonging to the Linux USB device - * driver in question, gets detached before the driver is - * unloaded. This function is not part of the Linux USB API, and is - * for internal use only. - *------------------------------------------------------------------------*/ -void -usb_linux_deregister(void *arg) -{ - struct usb_driver *drv = arg; - struct usb_linux_softc *sc; - -repeat: - mtx_lock(&Giant); - LIST_FOREACH(sc, &usb_linux_attached_list, sc_attached_list) { - if (sc->sc_udrv == drv) { - mtx_unlock(&Giant); - device_detach(sc->sc_fbsd_dev); - goto repeat; - } - } - LIST_REMOVE(drv, linux_driver_list); - mtx_unlock(&Giant); -} - -/*------------------------------------------------------------------------* - * usb_linux_free_device - * - * The following function is only used by the FreeBSD USB stack, to - * cleanup and free memory after that a Linux USB device was attached. - *------------------------------------------------------------------------*/ -void -usb_linux_free_device(struct usb_device *dev) -{ - struct usb_host_endpoint *uhe; - struct usb_host_endpoint *uhe_end; - int err; - - uhe = dev->linux_endpoint_start; - uhe_end = dev->linux_endpoint_end; - while (uhe != uhe_end) { - err = usb_setup_endpoint(dev, uhe, 0); - uhe++; - } - err = usb_setup_endpoint(dev, &dev->ep0, 0); - free(dev->linux_endpoint_start, M_USBDEV); -} - -/*------------------------------------------------------------------------* - * usb_buffer_free - *------------------------------------------------------------------------*/ -void -usb_buffer_free(struct usb_device *dev, usb_size_t size, - void *addr, uint8_t dma_addr) -{ - free(addr, M_USBDEV); -} - -/*------------------------------------------------------------------------* - * usb_free_urb - *------------------------------------------------------------------------*/ -void -usb_free_urb(struct urb *urb) -{ - if (urb == NULL) { - return; - } - /* make sure that the current URB is not active */ - usb_kill_urb(urb); - - /* destroy condition variable */ - cv_destroy(&urb->cv_wait); - - /* just free it */ - free(urb, M_USBDEV); -} - -/*------------------------------------------------------------------------* - * usb_init_urb - * - * The following function can be used to initialize a custom URB. It - * is not recommended to use this function. Use "usb_alloc_urb()" - * instead. - *------------------------------------------------------------------------*/ -void -usb_init_urb(struct urb *urb) -{ - if (urb == NULL) { - return; - } - memset(urb, 0, sizeof(*urb)); -} - -/*------------------------------------------------------------------------* - * usb_kill_urb - *------------------------------------------------------------------------*/ -void -usb_kill_urb(struct urb *urb) -{ - usb_unlink_urb_sub(urb, 1); -} - -/*------------------------------------------------------------------------* - * usb_set_intfdata - * - * The following function sets the per Linux USB interface private - * data pointer. It is used by most Linux USB device drivers. - *------------------------------------------------------------------------*/ -void -usb_set_intfdata(struct usb_interface *intf, void *data) -{ - intf->bsd_priv_sc = data; -} - -/*------------------------------------------------------------------------* - * usb_linux_cleanup_interface - * - * The following function will release all FreeBSD USB transfers - * associated with a Linux USB interface. It is for internal use only. - *------------------------------------------------------------------------*/ -static void -usb_linux_cleanup_interface(struct usb_device *dev, struct usb_interface *iface) -{ - struct usb_host_interface *uhi; - struct usb_host_interface *uhi_end; - struct usb_host_endpoint *uhe; - struct usb_host_endpoint *uhe_end; - int err; - - uhi = iface->altsetting; - uhi_end = iface->altsetting + iface->num_altsetting; - while (uhi != uhi_end) { - uhe = uhi->endpoint; - uhe_end = uhi->endpoint + uhi->desc.bNumEndpoints; - while (uhe != uhe_end) { - err = usb_setup_endpoint(dev, uhe, 0); - uhe++; - } - uhi++; - } -} - -/*------------------------------------------------------------------------* - * usb_linux_wait_complete - * - * The following function is used by "usb_start_wait_urb()" to wake it - * up, when an USB transfer has finished. - *------------------------------------------------------------------------*/ -static void -usb_linux_wait_complete(struct urb *urb) -{ - if (urb->transfer_flags & URB_IS_SLEEPING) { - cv_signal(&urb->cv_wait); - } - urb->transfer_flags &= ~URB_WAIT_WAKEUP; -} - -/*------------------------------------------------------------------------* - * usb_linux_complete - *------------------------------------------------------------------------*/ -static void -usb_linux_complete(struct usb_xfer *xfer) -{ - struct urb *urb; - - urb = usbd_xfer_get_priv(xfer); - usbd_xfer_set_priv(xfer, NULL); - if (urb->complete) { - (urb->complete) (urb); - } -} - -/*------------------------------------------------------------------------* - * usb_linux_isoc_callback - * - * The following is the FreeBSD isochronous USB callback. Isochronous - * frames are USB packets transferred 1000 or 8000 times per second, - * depending on whether a full- or high- speed USB transfer is - * used. - *------------------------------------------------------------------------*/ -static void -usb_linux_isoc_callback(struct usb_xfer *xfer, usb_error_t error) -{ - usb_frlength_t max_frame = xfer->max_frame_size; - usb_frlength_t offset; - usb_frcount_t x; - struct urb *urb = usbd_xfer_get_priv(xfer); - struct usb_host_endpoint *uhe = usbd_xfer_softc(xfer); - struct usb_iso_packet_descriptor *uipd; - - DPRINTF("\n"); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - if (urb->bsd_isread) { - - /* copy in data with regard to the URB */ - - offset = 0; - - for (x = 0; x < urb->number_of_packets; x++) { - uipd = urb->iso_frame_desc + x; - if (uipd->length > xfer->frlengths[x]) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - /* XXX should be EREMOTEIO */ - uipd->status = -EPIPE; - } else { - uipd->status = 0; - } - } else { - uipd->status = 0; - } - uipd->actual_length = xfer->frlengths[x]; - if (!xfer->flags.ext_buffer) { - usbd_copy_out(xfer->frbuffers, offset, - USB_ADD_BYTES(urb->transfer_buffer, - uipd->offset), uipd->actual_length); - } - offset += max_frame; - } - } else { - for (x = 0; x < urb->number_of_packets; x++) { - uipd = urb->iso_frame_desc + x; - uipd->actual_length = xfer->frlengths[x]; - uipd->status = 0; - } - } - - urb->actual_length = xfer->actlen; - - /* check for short transfer */ - if (xfer->actlen < xfer->sumlen) { - /* short transfer */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - /* XXX should be EREMOTEIO */ - urb->status = -EPIPE; - } else { - urb->status = 0; - } - } else { - /* success */ - urb->status = 0; - } - - /* call callback */ - usb_linux_complete(xfer); - - case USB_ST_SETUP: -tr_setup: - - if (xfer->priv_fifo == NULL) { - - /* get next transfer */ - urb = TAILQ_FIRST(&uhe->bsd_urb_list); - if (urb == NULL) { - /* nothing to do */ - return; - } - TAILQ_REMOVE(&uhe->bsd_urb_list, urb, bsd_urb_list); - urb->bsd_urb_list.tqe_prev = NULL; - - x = xfer->max_frame_count; - if (urb->number_of_packets > x) { - /* XXX simply truncate the transfer */ - urb->number_of_packets = x; - } - } else { - DPRINTF("Already got a transfer\n"); - - /* already got a transfer (should not happen) */ - urb = usbd_xfer_get_priv(xfer); - } - - urb->bsd_isread = (uhe->desc.bEndpointAddress & UE_DIR_IN) ? 1 : 0; - - if (xfer->flags.ext_buffer) { - /* set virtual address to load */ - usbd_xfer_set_frame_data(xfer, 0, urb->transfer_buffer, 0); - } - if (!(urb->bsd_isread)) { - - /* copy out data with regard to the URB */ - - offset = 0; - - for (x = 0; x < urb->number_of_packets; x++) { - uipd = urb->iso_frame_desc + x; - usbd_xfer_set_frame_len(xfer, x, uipd->length); - if (!xfer->flags.ext_buffer) { - usbd_copy_in(xfer->frbuffers, offset, - USB_ADD_BYTES(urb->transfer_buffer, - uipd->offset), uipd->length); - } - offset += uipd->length; - } - } else { - - /* - * compute the transfer length into the "offset" - * variable - */ - - offset = urb->number_of_packets * max_frame; - - /* setup "frlengths" array */ - - for (x = 0; x < urb->number_of_packets; x++) { - uipd = urb->iso_frame_desc + x; - usbd_xfer_set_frame_len(xfer, x, max_frame); - } - } - usbd_xfer_set_priv(xfer, urb); - xfer->flags.force_short_xfer = 0; - xfer->timeout = urb->timeout; - xfer->nframes = urb->number_of_packets; - usbd_transfer_submit(xfer); - return; - - default: /* Error */ - if (xfer->error == USB_ERR_CANCELLED) { - urb->status = -ECONNRESET; - } else { - urb->status = -EPIPE; /* stalled */ - } - - /* Set zero for "actual_length" */ - urb->actual_length = 0; - - /* Set zero for "actual_length" */ - for (x = 0; x < urb->number_of_packets; x++) { - urb->iso_frame_desc[x].actual_length = 0; - urb->iso_frame_desc[x].status = urb->status; - } - - /* call callback */ - usb_linux_complete(xfer); - - if (xfer->error == USB_ERR_CANCELLED) { - /* we need to return in this case */ - return; - } - goto tr_setup; - - } -} - -/*------------------------------------------------------------------------* - * usb_linux_non_isoc_callback - * - * The following is the FreeBSD BULK/INTERRUPT and CONTROL USB - * callback. It dequeues Linux USB stack compatible URB's, transforms - * the URB fields into a FreeBSD USB transfer, and defragments the USB - * transfer as required. When the transfer is complete the "complete" - * callback is called. - *------------------------------------------------------------------------*/ -static void -usb_linux_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error) -{ - enum { - REQ_SIZE = sizeof(struct usb_device_request) - }; - struct urb *urb = usbd_xfer_get_priv(xfer); - struct usb_host_endpoint *uhe = usbd_xfer_softc(xfer); - uint8_t *ptr; - usb_frlength_t max_bulk = usbd_xfer_max_len(xfer); - uint8_t data_frame = xfer->flags_int.control_xfr ? 1 : 0; - - DPRINTF("\n"); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - if (xfer->flags_int.control_xfr) { - - /* don't transfer the setup packet again: */ - - usbd_xfer_set_frame_len(xfer, 0, 0); - } - if (urb->bsd_isread && (!xfer->flags.ext_buffer)) { - /* copy in data with regard to the URB */ - usbd_copy_out(xfer->frbuffers + data_frame, 0, - urb->bsd_data_ptr, xfer->frlengths[data_frame]); - } - urb->bsd_length_rem -= xfer->frlengths[data_frame]; - urb->bsd_data_ptr += xfer->frlengths[data_frame]; - urb->actual_length += xfer->frlengths[data_frame]; - - /* check for short transfer */ - if (xfer->actlen < xfer->sumlen) { - urb->bsd_length_rem = 0; - - /* short transfer */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - urb->status = -EPIPE; - } else { - urb->status = 0; - } - } else { - /* check remainder */ - if (urb->bsd_length_rem > 0) { - goto setup_bulk; - } - /* success */ - urb->status = 0; - } - - /* call callback */ - usb_linux_complete(xfer); - - case USB_ST_SETUP: -tr_setup: - /* get next transfer */ - urb = TAILQ_FIRST(&uhe->bsd_urb_list); - if (urb == NULL) { - /* nothing to do */ - return; - } - TAILQ_REMOVE(&uhe->bsd_urb_list, urb, bsd_urb_list); - urb->bsd_urb_list.tqe_prev = NULL; - - usbd_xfer_set_priv(xfer, urb); - xfer->flags.force_short_xfer = 0; - xfer->timeout = urb->timeout; - - if (xfer->flags_int.control_xfr) { - - /* - * USB control transfers need special handling. - * First copy in the header, then copy in data! - */ - if (!xfer->flags.ext_buffer) { - usbd_copy_in(xfer->frbuffers, 0, - urb->setup_packet, REQ_SIZE); - usbd_xfer_set_frame_len(xfer, 0, REQ_SIZE); - } else { - /* set virtual address to load */ - usbd_xfer_set_frame_data(xfer, 0, - urb->setup_packet, REQ_SIZE); - } - - ptr = urb->setup_packet; - - /* setup data transfer direction and length */ - urb->bsd_isread = (ptr[0] & UT_READ) ? 1 : 0; - urb->bsd_length_rem = ptr[6] | (ptr[7] << 8); - - } else { - - /* setup data transfer direction */ - - urb->bsd_length_rem = urb->transfer_buffer_length; - urb->bsd_isread = (uhe->desc.bEndpointAddress & - UE_DIR_IN) ? 1 : 0; - } - - urb->bsd_data_ptr = urb->transfer_buffer; - urb->actual_length = 0; - -setup_bulk: - if (max_bulk > urb->bsd_length_rem) { - max_bulk = urb->bsd_length_rem; - } - /* check if we need to force a short transfer */ - - if ((max_bulk == urb->bsd_length_rem) && - (urb->transfer_flags & URB_ZERO_PACKET) && - (!xfer->flags_int.control_xfr)) { - xfer->flags.force_short_xfer = 1; - } - /* check if we need to copy in data */ - - if (xfer->flags.ext_buffer) { - /* set virtual address to load */ - usbd_xfer_set_frame_data(xfer, data_frame, - urb->bsd_data_ptr, max_bulk); - } else if (!urb->bsd_isread) { - /* copy out data with regard to the URB */ - usbd_copy_in(xfer->frbuffers + data_frame, 0, - urb->bsd_data_ptr, max_bulk); - usbd_xfer_set_frame_len(xfer, data_frame, max_bulk); - } - if (xfer->flags_int.control_xfr) { - if (max_bulk > 0) { - xfer->nframes = 2; - } else { - xfer->nframes = 1; - } - } else { - xfer->nframes = 1; - } - usbd_transfer_submit(xfer); - return; - - default: - if (xfer->error == USB_ERR_CANCELLED) { - urb->status = -ECONNRESET; - } else { - urb->status = -EPIPE; - } - - /* Set zero for "actual_length" */ - urb->actual_length = 0; - - /* call callback */ - usb_linux_complete(xfer); - - if (xfer->error == USB_ERR_CANCELLED) { - /* we need to return in this case */ - return; - } - goto tr_setup; - } -} - -/*------------------------------------------------------------------------* - * usb_fill_bulk_urb - *------------------------------------------------------------------------*/ -void -usb_fill_bulk_urb(struct urb *urb, struct usb_device *udev, - struct usb_host_endpoint *uhe, void *buf, - int length, usb_complete_t callback, void *arg) -{ - urb->dev = udev; - urb->endpoint = uhe; - urb->transfer_buffer = buf; - urb->transfer_buffer_length = length; - urb->complete = callback; - urb->context = arg; -} - -/*------------------------------------------------------------------------* - * usb_bulk_msg - * - * NOTE: This function can also be used for interrupt endpoints! - * - * Return values: - * 0: Success - * Else: Failure - *------------------------------------------------------------------------*/ -int -usb_bulk_msg(struct usb_device *udev, struct usb_host_endpoint *uhe, - void *data, int len, uint16_t *pactlen, usb_timeout_t timeout) -{ - struct urb *urb; - int err; - - if (uhe == NULL) - return (-EINVAL); - if (len < 0) - return (-EINVAL); - - err = usb_setup_endpoint(udev, uhe, 4096 /* bytes */); - if (err) - return (err); - - urb = usb_alloc_urb(0, 0); - if (urb == NULL) - return (-ENOMEM); - - usb_fill_bulk_urb(urb, udev, uhe, data, len, - usb_linux_wait_complete, NULL); - - err = usb_start_wait_urb(urb, timeout, pactlen); - - usb_free_urb(urb); - - return (err); -} diff --git a/sys/bus/u4b/usb_compat_linux.h b/sys/bus/u4b/usb_compat_linux.h deleted file mode 100644 index 1f00d4b4ad..0000000000 --- a/sys/bus/u4b/usb_compat_linux.h +++ /dev/null @@ -1,310 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved. - * Copyright (c) 2007 Hans Petter Selasky. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _USB_COMPAT_LINUX_H -#define _USB_COMPAT_LINUX_H - -struct usb_device; -struct usb_interface; -struct usb_driver; -struct urb; - -typedef void *pm_message_t; -typedef void (usb_complete_t)(struct urb *); - -#define USB_MAX_FULL_SPEED_ISOC_FRAMES (60 * 1) -#define USB_MAX_HIGH_SPEED_ISOC_FRAMES (60 * 8) - -#define USB_DEVICE_ID_MATCH_DEVICE \ - (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) - -#define USB_DEVICE(vend,prod) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = (vend), \ - .idProduct = (prod) - -/* The "usb_driver" structure holds the Linux USB device driver - * callbacks, and a pointer to device ID's which this entry should - * match against. Usually this entry is exposed to the USB emulation - * layer using the "USB_DRIVER_EXPORT()" macro, which is defined - * below. - */ -struct usb_driver { - const char *name; - - int (*probe) (struct usb_interface *intf, - const struct usb_device_id *id); - - void (*disconnect) (struct usb_interface *intf); - - int (*ioctl) (struct usb_interface *intf, unsigned int code, - void *buf); - - int (*suspend) (struct usb_interface *intf, pm_message_t message); - int (*resume) (struct usb_interface *intf); - - const struct usb_device_id *id_table; - - void (*shutdown) (struct usb_interface *intf); - - LIST_ENTRY(usb_driver) linux_driver_list; -}; - -#define USB_DRIVER_EXPORT(id,p_usb_drv) \ - SYSINIT(id,SI_SUB_KLD,SI_ORDER_FIRST,usb_linux_register,p_usb_drv); \ - SYSUNINIT(id,SI_SUB_KLD,SI_ORDER_ANY,usb_linux_deregister,p_usb_drv) - -#define USB_DT_ENDPOINT_SIZE 7 -#define USB_DT_ENDPOINT_AUDIO_SIZE 9 - -/* - * Endpoints - */ -#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ -#define USB_ENDPOINT_DIR_MASK 0x80 - -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 -#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 - -/* CONTROL REQUEST SUPPORT */ - -/* - * Definition of direction mask for - * "bEndpointAddress" and "bmRequestType": - */ -#define USB_DIR_MASK 0x80 -#define USB_DIR_OUT 0x00 /* write to USB device */ -#define USB_DIR_IN 0x80 /* read from USB device */ - -/* - * Definition of type mask for - * "bmRequestType": - */ -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -/* - * Definition of receiver mask for - * "bmRequestType": - */ -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 - -/* - * Definition of standard request values for - * "bRequest": - */ -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ -#define USB_REQ_GET_ENCRYPTION 0x0E -#define USB_REQ_SET_HANDSHAKE 0x0F -#define USB_REQ_GET_HANDSHAKE 0x10 -#define USB_REQ_SET_CONNECTION 0x11 -#define USB_REQ_SET_SECURITY_DATA 0x12 -#define USB_REQ_GET_SECURITY_DATA 0x13 -#define USB_REQ_SET_WUSB_DATA 0x14 -#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 -#define USB_REQ_LOOPBACK_DATA_READ 0x16 -#define USB_REQ_SET_INTERFACE_DS 0x17 - -/* - * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and - * are read as a bit array returned by USB_REQ_GET_STATUS. (So there - * are at most sixteen features of each type.) - */ -#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ -#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ -#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ -#define USB_DEVICE_BATTERY 2 /* (wireless) */ -#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ -#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless) */ -#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ -#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ -#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ - -#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ - -#define PIPE_ISOCHRONOUS 0x01 /* UE_ISOCHRONOUS */ -#define PIPE_INTERRUPT 0x03 /* UE_INTERRUPT */ -#define PIPE_CONTROL 0x00 /* UE_CONTROL */ -#define PIPE_BULK 0x02 /* UE_BULK */ - -/* Whenever Linux references an USB endpoint: - * a) to initialize "urb->endpoint" - * b) second argument passed to "usb_control_msg()" - * - * Then it uses one of the following macros. The "endpoint" argument - * is the physical endpoint value masked by 0xF. The "dev" argument - * is a pointer to "struct usb_device". - */ -#define usb_sndctrlpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_CONTROL, (endpoint) | USB_DIR_OUT) - -#define usb_rcvctrlpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_CONTROL, (endpoint) | USB_DIR_IN) - -#define usb_sndisocpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_ISOCHRONOUS, (endpoint) | USB_DIR_OUT) - -#define usb_rcvisocpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_ISOCHRONOUS, (endpoint) | USB_DIR_IN) - -#define usb_sndbulkpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_BULK, (endpoint) | USB_DIR_OUT) - -#define usb_rcvbulkpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_BULK, (endpoint) | USB_DIR_IN) - -#define usb_sndintpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_INTERRUPT, (endpoint) | USB_DIR_OUT) - -#define usb_rcvintpipe(dev,endpoint) \ - usb_find_host_endpoint(dev, PIPE_INTERRUPT, (endpoint) | USB_DIR_IN) - -/* - * The following structure is used to extend "struct urb" when we are - * dealing with an isochronous endpoint. It contains information about - * the data offset and data length of an isochronous packet. - * The "actual_length" field is updated before the "complete" - * callback in the "urb" structure is called. - */ -struct usb_iso_packet_descriptor { - uint32_t offset; /* depreciated buffer offset (the - * packets are usually back to back) */ - uint16_t length; /* expected length */ - uint16_t actual_length; - int16_t status; /* transfer status */ -}; - -/* - * The following structure holds various information about an USB - * transfer. This structure is used for all kinds of USB transfers. - * - * URB is short for USB Request Block. - */ -struct urb { - TAILQ_ENTRY(urb) bsd_urb_list; - struct cv cv_wait; - - struct usb_device *dev; /* (in) pointer to associated device */ - struct usb_host_endpoint *endpoint; /* (in) pipe pointer */ - uint8_t *setup_packet; /* (in) setup packet (control only) */ - uint8_t *bsd_data_ptr; - void *transfer_buffer; /* (in) associated data buffer */ - void *context; /* (in) context for completion */ - usb_complete_t *complete; /* (in) completion routine */ - - usb_size_t transfer_buffer_length;/* (in) data buffer length */ - usb_size_t bsd_length_rem; - usb_size_t actual_length; /* (return) actual transfer length */ - usb_timeout_t timeout; /* FreeBSD specific */ - - uint16_t transfer_flags; /* (in) */ -#define URB_SHORT_NOT_OK 0x0001 /* report short transfers like errors */ -#define URB_ISO_ASAP 0x0002 /* ignore "start_frame" field */ -#define URB_ZERO_PACKET 0x0004 /* the USB transfer ends with a short - * packet */ -#define URB_NO_TRANSFER_DMA_MAP 0x0008 /* "transfer_dma" is valid on submit */ -#define URB_WAIT_WAKEUP 0x0010 /* custom flags */ -#define URB_IS_SLEEPING 0x0020 /* custom flags */ - - usb_frcount_t start_frame; /* (modify) start frame (ISO) */ - usb_frcount_t number_of_packets; /* (in) number of ISO packets */ - uint16_t interval; /* (modify) transfer interval - * (INT/ISO) */ - uint16_t error_count; /* (return) number of ISO errors */ - int16_t status; /* (return) status */ - - uint8_t setup_dma; /* (in) not used on FreeBSD */ - uint8_t transfer_dma; /* (in) not used on FreeBSD */ - uint8_t bsd_isread; - uint8_t kill_count; /* FreeBSD specific */ - - struct usb_iso_packet_descriptor iso_frame_desc[]; /* (in) ISO ONLY */ -}; - -/* various prototypes */ - -int usb_submit_urb(struct urb *urb, uint16_t mem_flags); -int usb_unlink_urb(struct urb *urb); -int usb_clear_halt(struct usb_device *dev, struct usb_host_endpoint *uhe); -int usb_control_msg(struct usb_device *dev, struct usb_host_endpoint *ep, - uint8_t request, uint8_t requesttype, uint16_t value, - uint16_t index, void *data, uint16_t size, usb_timeout_t timeout); -int usb_set_interface(struct usb_device *dev, uint8_t ifnum, - uint8_t alternate); -int usb_setup_endpoint(struct usb_device *dev, - struct usb_host_endpoint *uhe, usb_frlength_t bufsize); - -struct usb_host_endpoint *usb_find_host_endpoint(struct usb_device *dev, - uint8_t type, uint8_t ep); -struct urb *usb_alloc_urb(uint16_t iso_packets, uint16_t mem_flags); -struct usb_host_interface *usb_altnum_to_altsetting( - const struct usb_interface *intf, uint8_t alt_index); -struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, uint8_t iface_no); - -void *usb_buffer_alloc(struct usb_device *dev, usb_size_t size, - uint16_t mem_flags, uint8_t *dma_addr); -void *usbd_get_intfdata(struct usb_interface *intf); - -void usb_buffer_free(struct usb_device *dev, usb_size_t size, void *addr, uint8_t dma_addr); -void usb_free_urb(struct urb *urb); -void usb_init_urb(struct urb *urb); -void usb_kill_urb(struct urb *urb); -void usb_set_intfdata(struct usb_interface *intf, void *data); -void usb_linux_register(void *arg); -void usb_linux_deregister(void *arg); - -void usb_fill_bulk_urb(struct urb *, struct usb_device *, - struct usb_host_endpoint *, void *, int, usb_complete_t, void *); -int usb_bulk_msg(struct usb_device *, struct usb_host_endpoint *, - void *, int, uint16_t *, usb_timeout_t); - -#define interface_to_usbdev(intf) (intf)->linux_udev -#define interface_to_bsddev(intf) (intf)->linux_udev - -#endif /* _USB_COMPAT_LINUX_H */ diff --git a/sys/bus/u4b/video/udl.c b/sys/bus/u4b/video/udl.c deleted file mode 100644 index 2ef703de69..0000000000 --- a/sys/bus/u4b/video/udl.c +++ /dev/null @@ -1,1097 +0,0 @@ -/* $OpenBSD: udl.c,v 1.81 2014/12/09 07:05:06 doug Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2015 Hans Petter Selasky - * Copyright (c) 2009 Marcus Glocker - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Driver for the "DisplayLink DL-120 / DL-160" graphic chips based on - * the reversed engineered specifications of Florian Echtler - * : - * - * http://floe.butterbrot.org/displaylink/doku.php - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include "usbdevs.h" - -#include - -#include "fb_if.h" - -#undef DPRINTF -#undef DPRINTFN -#define USB_DEBUG_VAR udl_debug -#include - -static SYSCTL_NODE(_hw_usb, OID_AUTO, udl, CTLFLAG_RW, 0, "USB UDL"); - -#ifdef USB_DEBUG -static int udl_debug = 0; - -SYSCTL_INT(_hw_usb_udl, OID_AUTO, debug, CTLFLAG_RWTUN, - &udl_debug, 0, "Debug level"); -#endif - -#define UDL_FPS_MAX 60 -#define UDL_FPS_MIN 1 - -static int udl_fps = 25; -SYSCTL_INT(_hw_usb_udl, OID_AUTO, fps, CTLFLAG_RWTUN, - &udl_fps, 0, "Frames Per Second, 1-60"); - -/* - * Prototypes. - */ -static usb_callback_t udl_bulk_write_callback; - -static device_probe_t udl_probe; -static device_attach_t udl_attach; -static device_detach_t udl_detach; -static fb_getinfo_t udl_fb_getinfo; -static fb_setblankmode_t udl_fb_setblankmode; - -static void udl_select_chip(struct udl_softc *, struct usb_attach_arg *); -static int udl_init_chip(struct udl_softc *); -static void udl_select_mode(struct udl_softc *); -static int udl_init_resolution(struct udl_softc *); -static void udl_fbmem_alloc(struct udl_softc *); -static int udl_cmd_write_buf_le16(struct udl_softc *, const uint8_t *, uint32_t, uint8_t, int); -static int udl_cmd_buf_copy_le16(struct udl_softc *, uint32_t, uint32_t, uint8_t, int); -static void udl_cmd_insert_int_1(struct udl_cmd_buf *, uint8_t); -static void udl_cmd_insert_int_3(struct udl_cmd_buf *, uint32_t); -static void udl_cmd_insert_buf_le16(struct udl_cmd_buf *, const uint8_t *, uint32_t); -static void udl_cmd_write_reg_1(struct udl_cmd_buf *, uint8_t, uint8_t); -static void udl_cmd_write_reg_3(struct udl_cmd_buf *, uint8_t, uint32_t); -static int udl_power_save(struct udl_softc *, int, int); - -static const struct usb_config udl_config[UDL_N_TRANSFER] = { - [UDL_BULK_WRITE_0] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_TX, - .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, - .bufsize = UDL_CMD_MAX_DATA_SIZE * UDL_CMD_MAX_FRAMES, - .callback = &udl_bulk_write_callback, - .frames = UDL_CMD_MAX_FRAMES, - .timeout = 5000, /* 5 seconds */ - }, - [UDL_BULK_WRITE_1] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_TX, - .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, - .bufsize = UDL_CMD_MAX_DATA_SIZE * UDL_CMD_MAX_FRAMES, - .callback = &udl_bulk_write_callback, - .frames = UDL_CMD_MAX_FRAMES, - .timeout = 5000, /* 5 seconds */ - }, -}; - -/* - * Driver glue. - */ -static devclass_t udl_devclass; - -static device_method_t udl_methods[] = { - DEVMETHOD(device_probe, udl_probe), - DEVMETHOD(device_attach, udl_attach), - DEVMETHOD(device_detach, udl_detach), - DEVMETHOD(fb_getinfo, udl_fb_getinfo), - DEVMETHOD_END -}; - -static driver_t udl_driver = { - .name = "udl", - .methods = udl_methods, - .size = sizeof(struct udl_softc), -}; - -DRIVER_MODULE(udl, uhub, udl_driver, udl_devclass, NULL, NULL); -MODULE_DEPEND(udl, usb, 1, 1, 1); -MODULE_DEPEND(udl, fbd, 1, 1, 1); -MODULE_DEPEND(udl, videomode, 1, 1, 1); -MODULE_VERSION(udl, 1); - -/* - * Matching devices. - */ -static const STRUCT_USB_HOST_ID udl_devs[] = { - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LCD4300U, DL120)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LCD8000U, DL120)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_GUC2020, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LD220, DL165)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_VCUD60, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_DLDVI, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_VGA10, DL120)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_WSDVI, DLUNK)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_EC008, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_HPDOCK, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_NL571, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_M01061, DL195)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_NBDOCK, DL165)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_SWDVI, DLUNK)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_UM7X0, DL120)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_CONV, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_PLUGABLE, DL160)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LUM70, DL125)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_POLARIS2, DLUNK)}, - {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LT1421, DLUNK)} -}; - -static uint32_t -udl_get_fb_size(struct udl_softc *sc) -{ - unsigned i = sc->sc_cur_mode; - - return ((uint32_t)udl_modes[i].hdisplay * - (uint32_t)udl_modes[i].vdisplay * 2); -} - -static uint32_t -udl_get_fb_width(struct udl_softc *sc) -{ - unsigned i = sc->sc_cur_mode; - - return (udl_modes[i].hdisplay); -} - -static uint32_t -udl_get_fb_height(struct udl_softc *sc) -{ - unsigned i = sc->sc_cur_mode; - - return (udl_modes[i].vdisplay); -} - -static uint32_t -udl_get_fb_hz(struct udl_softc *sc) -{ - unsigned i = sc->sc_cur_mode; - - return (udl_modes[i].hz); -} - -static void -udl_callout(void *arg) -{ - struct udl_softc *sc = arg; - const uint32_t max = udl_get_fb_size(sc); - int fps; - - if (sc->sc_power_save == 0) { - fps = udl_fps; - - /* figure out number of frames per second */ - if (fps < UDL_FPS_MIN) - fps = UDL_FPS_MIN; - else if (fps > UDL_FPS_MAX) - fps = UDL_FPS_MAX; - - if (sc->sc_sync_off >= max) - sc->sc_sync_off = 0; - usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_0]); - usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_1]); - } else { - fps = 1; - } - callout_reset(&sc->sc_callout, hz / fps, &udl_callout, sc); -} - -static int -udl_probe(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != 0) - return (ENXIO); - if (uaa->info.bIfaceIndex != 0) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(udl_devs, sizeof(udl_devs), uaa)); -} - -static int -udl_attach(device_t dev) -{ - struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); - struct sysctl_oid *tree = device_get_sysctl_tree(dev); - struct udl_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - int error; - int i; - - device_set_usb_desc(dev); - - mtx_init(&sc->sc_mtx, "UDL lock", NULL, MTX_DEF); - cv_init(&sc->sc_cv, "UDLCV"); - callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0); - sc->sc_udev = uaa->device; - - error = usbd_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, - sc->sc_xfer, udl_config, UDL_N_TRANSFER, sc, &sc->sc_mtx); - - if (error) { - DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(error)); - goto detach; - } - usbd_xfer_set_priv(sc->sc_xfer[UDL_BULK_WRITE_0], &sc->sc_xfer_head[0]); - usbd_xfer_set_priv(sc->sc_xfer[UDL_BULK_WRITE_1], &sc->sc_xfer_head[1]); - - TAILQ_INIT(&sc->sc_xfer_head[0]); - TAILQ_INIT(&sc->sc_xfer_head[1]); - TAILQ_INIT(&sc->sc_cmd_buf_free); - TAILQ_INIT(&sc->sc_cmd_buf_pending); - - sc->sc_def_chip = -1; - sc->sc_chip = USB_GET_DRIVER_INFO(uaa); - sc->sc_def_mode = -1; - sc->sc_cur_mode = UDL_MAX_MODES; - - /* Allow chip ID to be overwritten */ - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "chipid_force", - CTLFLAG_RWTUN, &sc->sc_def_chip, 0, "chip ID"); - - /* Export current chip ID */ - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "chipid", - CTLFLAG_RD, &sc->sc_chip, 0, "chip ID"); - - if (sc->sc_def_chip > -1 && sc->sc_def_chip <= DLMAX) { - device_printf(dev, "Forcing chip ID to 0x%04x\n", sc->sc_def_chip); - sc->sc_chip = sc->sc_def_chip; - } - /* - * The product might have more than one chip - */ - if (sc->sc_chip == DLUNK) - udl_select_chip(sc, uaa); - - for (i = 0; i != UDL_CMD_MAX_BUFFERS; i++) { - struct udl_cmd_buf *cb = &sc->sc_cmd_buf_temp[i]; - - TAILQ_INSERT_TAIL(&sc->sc_cmd_buf_free, cb, entry); - } - - /* - * Initialize chip. - */ - error = udl_init_chip(sc); - if (error != USB_ERR_NORMAL_COMPLETION) - goto detach; - - /* - * Select edid mode. - */ - udl_select_mode(sc); - - /* Allow default mode to be overwritten */ - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "mode_force", - CTLFLAG_RWTUN, &sc->sc_def_mode, 0, "mode"); - - /* Export current mode */ - SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "mode", - CTLFLAG_RD, &sc->sc_cur_mode, 0, "mode"); - - i = sc->sc_def_mode; - if (i > -1 && i < UDL_MAX_MODES) { - if (udl_modes[i].chip <= sc->sc_chip) { - device_printf(dev, "Forcing mode to %d\n", i); - sc->sc_cur_mode = i; - } - } - /* Printout current mode */ - device_printf(dev, "Mode selected %dx%d @ %dHz\n", - (int)udl_get_fb_width(sc), - (int)udl_get_fb_height(sc), - (int)udl_get_fb_hz(sc)); - - udl_init_resolution(sc); - - /* Allocate frame buffer */ - udl_fbmem_alloc(sc); - - UDL_LOCK(sc); - udl_callout(sc); - UDL_UNLOCK(sc); - - sc->sc_fb_info.fb_name = device_get_nameunit(dev); - sc->sc_fb_info.fb_size = sc->sc_fb_size; - sc->sc_fb_info.fb_bpp = 16; - sc->sc_fb_info.fb_depth = 16; - sc->sc_fb_info.fb_width = udl_get_fb_width(sc); - sc->sc_fb_info.fb_height = udl_get_fb_height(sc); - sc->sc_fb_info.fb_stride = sc->sc_fb_info.fb_width * 2; - sc->sc_fb_info.fb_pbase = 0; - sc->sc_fb_info.fb_vbase = (uintptr_t)sc->sc_fb_addr; - sc->sc_fb_info.fb_priv = sc; - sc->sc_fb_info.setblankmode = &udl_fb_setblankmode; - - sc->sc_fbdev = device_add_child(dev, "fbd", -1); - if (sc->sc_fbdev == NULL) - goto detach; - if (device_probe_and_attach(sc->sc_fbdev) != 0) - goto detach; - - return (0); - -detach: - udl_detach(dev); - - return (ENXIO); -} - -static int -udl_detach(device_t dev) -{ - struct udl_softc *sc = device_get_softc(dev); - - if (sc->sc_fbdev != NULL) { - device_t bdev; - - bdev = sc->sc_fbdev; - sc->sc_fbdev = NULL; - device_detach(bdev); - device_delete_child(dev, bdev); - } - UDL_LOCK(sc); - sc->sc_gone = 1; - callout_stop(&sc->sc_callout); - UDL_UNLOCK(sc); - - usbd_transfer_unsetup(sc->sc_xfer, UDL_N_TRANSFER); - - callout_drain(&sc->sc_callout); - - mtx_destroy(&sc->sc_mtx); - cv_destroy(&sc->sc_cv); - - /* - * Free framebuffer memory, if any. - */ - free(sc->sc_fb_addr, M_DEVBUF); - free(sc->sc_fb_copy, M_DEVBUF); - - return (0); -} - -static struct fb_info * -udl_fb_getinfo(device_t dev) -{ - struct udl_softc *sc = device_get_softc(dev); - - return (&sc->sc_fb_info); -} - -static int -udl_fb_setblankmode(void *arg, int mode) -{ - struct udl_softc *sc = arg; - - switch (mode) { - case V_DISPLAY_ON: - udl_power_save(sc, 1, M_WAITOK); - break; - case V_DISPLAY_BLANK: - udl_power_save(sc, 1, M_WAITOK); - if (sc->sc_fb_addr != 0) { - const uint32_t max = udl_get_fb_size(sc); - - memset((void *)sc->sc_fb_addr, 0, max); - } - break; - case V_DISPLAY_STAND_BY: - case V_DISPLAY_SUSPEND: - udl_power_save(sc, 0, M_WAITOK); - break; - } - return (0); -} - -static struct udl_cmd_buf * -udl_cmd_buf_alloc_locked(struct udl_softc *sc, int flags) -{ - struct udl_cmd_buf *cb; - - while ((cb = TAILQ_FIRST(&sc->sc_cmd_buf_free)) == NULL) { - if (flags != M_WAITOK) - break; - cv_wait(&sc->sc_cv, &sc->sc_mtx); - } - if (cb != NULL) { - TAILQ_REMOVE(&sc->sc_cmd_buf_free, cb, entry); - cb->off = 0; - } - return (cb); -} - -static struct udl_cmd_buf * -udl_cmd_buf_alloc(struct udl_softc *sc, int flags) -{ - struct udl_cmd_buf *cb; - - UDL_LOCK(sc); - cb = udl_cmd_buf_alloc_locked(sc, flags); - UDL_UNLOCK(sc); - return (cb); -} - -static void -udl_cmd_buf_send(struct udl_softc *sc, struct udl_cmd_buf *cb) -{ - UDL_LOCK(sc); - if (sc->sc_gone) { - TAILQ_INSERT_TAIL(&sc->sc_cmd_buf_free, cb, entry); - } else { - /* mark end of command stack */ - udl_cmd_insert_int_1(cb, UDL_BULK_SOC); - udl_cmd_insert_int_1(cb, UDL_BULK_CMD_EOC); - - TAILQ_INSERT_TAIL(&sc->sc_cmd_buf_pending, cb, entry); - usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_0]); - usbd_transfer_start(sc->sc_xfer[UDL_BULK_WRITE_1]); - } - UDL_UNLOCK(sc); -} - -static struct udl_cmd_buf * -udl_fb_synchronize_locked(struct udl_softc *sc) -{ - const uint32_t max = udl_get_fb_size(sc); - - /* check if framebuffer is not ready */ - if (sc->sc_fb_addr == NULL || - sc->sc_fb_copy == NULL) - return (NULL); - - while (sc->sc_sync_off < max) { - uint32_t delta = max - sc->sc_sync_off; - - if (delta > UDL_CMD_MAX_PIXEL_COUNT * 2) - delta = UDL_CMD_MAX_PIXEL_COUNT * 2; - if (bcmp(sc->sc_fb_addr + sc->sc_sync_off, sc->sc_fb_copy + sc->sc_sync_off, delta) != 0) { - struct udl_cmd_buf *cb; - - cb = udl_cmd_buf_alloc_locked(sc, M_NOWAIT); - if (cb == NULL) - goto done; - memcpy(sc->sc_fb_copy + sc->sc_sync_off, - sc->sc_fb_addr + sc->sc_sync_off, delta); - udl_cmd_insert_int_1(cb, UDL_BULK_SOC); - udl_cmd_insert_int_1(cb, UDL_BULK_CMD_FB_WRITE | UDL_BULK_CMD_FB_WORD); - udl_cmd_insert_int_3(cb, sc->sc_sync_off); - udl_cmd_insert_int_1(cb, delta / 2); - udl_cmd_insert_buf_le16(cb, sc->sc_fb_copy + sc->sc_sync_off, delta); - sc->sc_sync_off += delta; - return (cb); - } else { - sc->sc_sync_off += delta; - } - } -done: - return (NULL); -} - -static void -udl_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct udl_softc *sc = usbd_xfer_softc(xfer); - struct udl_cmd_head *phead = usbd_xfer_get_priv(xfer); - struct udl_cmd_buf *cb; - unsigned i; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - TAILQ_CONCAT(&sc->sc_cmd_buf_free, phead, entry); - case USB_ST_SETUP: -tr_setup: - for (i = 0; i != UDL_CMD_MAX_FRAMES; i++) { - cb = TAILQ_FIRST(&sc->sc_cmd_buf_pending); - if (cb == NULL) { - cb = udl_fb_synchronize_locked(sc); - if (cb == NULL) - break; - } else { - TAILQ_REMOVE(&sc->sc_cmd_buf_pending, cb, entry); - } - TAILQ_INSERT_TAIL(phead, cb, entry); - usbd_xfer_set_frame_data(xfer, i, cb->buf, cb->off); - } - if (i != 0) { - usbd_xfer_set_frames(xfer, i); - usbd_transfer_submit(xfer); - } - break; - default: - TAILQ_CONCAT(&sc->sc_cmd_buf_free, phead, entry); - if (error != USB_ERR_CANCELLED) { - /* try clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } - /* wakeup any waiters */ - cv_signal(&sc->sc_cv); -} - -static int -udl_power_save(struct udl_softc *sc, int on, int flags) -{ - struct udl_cmd_buf *cb; - - /* get new buffer */ - cb = udl_cmd_buf_alloc(sc, flags); - if (cb == NULL) - return (EAGAIN); - - DPRINTF("screen %s\n", on ? "ON" : "OFF"); - - sc->sc_power_save = on ? 0 : 1; - - if (on) - udl_cmd_write_reg_1(cb, UDL_REG_SCREEN, UDL_REG_SCREEN_ON); - else - udl_cmd_write_reg_1(cb, UDL_REG_SCREEN, UDL_REG_SCREEN_OFF); - - udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff); - udl_cmd_buf_send(sc, cb); - return (0); -} - -static int -udl_ctrl_msg(struct udl_softc *sc, uint8_t rt, uint8_t r, - uint16_t index, uint16_t value, uint8_t *buf, size_t len) -{ - usb_device_request_t req; - int error; - - req.bmRequestType = rt; - req.bRequest = r; - USETW(req.wIndex, index); - USETW(req.wValue, value); - USETW(req.wLength, len); - - error = usbd_do_request_flags(sc->sc_udev, NULL, - &req, buf, 0, NULL, USB_DEFAULT_TIMEOUT); - - DPRINTF("%s\n", usbd_errstr(error)); - - return (error); -} - -static int -udl_poll(struct udl_softc *sc, uint32_t *buf) -{ - uint32_t lbuf; - int error; - - error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE, - UDL_CTRL_CMD_POLL, 0x0000, 0x0000, (uint8_t *)&lbuf, sizeof(lbuf)); - if (error == USB_ERR_NORMAL_COMPLETION) - *buf = le32toh(lbuf); - return (error); -} - -static int -udl_read_1(struct udl_softc *sc, uint16_t addr, uint8_t *buf) -{ - uint8_t lbuf[1]; - int error; - - error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE, - UDL_CTRL_CMD_READ_1, addr, 0x0000, lbuf, 1); - if (error == USB_ERR_NORMAL_COMPLETION) - *buf = *(uint8_t *)lbuf; - return (error); -} - -static int -udl_write_1(struct udl_softc *sc, uint16_t addr, uint8_t buf) -{ - int error; - - error = udl_ctrl_msg(sc, UT_WRITE_VENDOR_DEVICE, - UDL_CTRL_CMD_WRITE_1, addr, 0x0000, &buf, 1); - return (error); -} - -static int -udl_read_edid(struct udl_softc *sc, uint8_t *buf) -{ - uint8_t lbuf[64]; - uint16_t offset; - int error; - - offset = 0; - - error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE, - UDL_CTRL_CMD_READ_EDID, 0x00a1, (offset << 8), lbuf, 64); - if (error != USB_ERR_NORMAL_COMPLETION) - goto fail; - bcopy(lbuf + 1, buf + offset, 63); - offset += 63; - - error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE, - UDL_CTRL_CMD_READ_EDID, 0x00a1, (offset << 8), lbuf, 64); - if (error != USB_ERR_NORMAL_COMPLETION) - goto fail; - bcopy(lbuf + 1, buf + offset, 63); - offset += 63; - - error = udl_ctrl_msg(sc, UT_READ_VENDOR_DEVICE, - UDL_CTRL_CMD_READ_EDID, 0x00a1, (offset << 8), lbuf, 3); - if (error != USB_ERR_NORMAL_COMPLETION) - goto fail; - bcopy(lbuf + 1, buf + offset, 2); -fail: - return (error); -} - -static uint8_t -udl_lookup_mode(uint16_t hdisplay, uint16_t vdisplay, uint8_t hz, - uint16_t chip, uint32_t clock) -{ - uint8_t idx; - - /* - * Check first if we have a matching mode with pixelclock - */ - for (idx = 0; idx != UDL_MAX_MODES; idx++) { - if ((udl_modes[idx].hdisplay == hdisplay) && - (udl_modes[idx].vdisplay == vdisplay) && - (udl_modes[idx].clock == clock) && - (udl_modes[idx].chip <= chip)) { - return (idx); - } - } - - /* - * If not, check for matching mode with update frequency - */ - for (idx = 0; idx != UDL_MAX_MODES; idx++) { - if ((udl_modes[idx].hdisplay == hdisplay) && - (udl_modes[idx].vdisplay == vdisplay) && - (udl_modes[idx].hz == hz) && - (udl_modes[idx].chip <= chip)) { - return (idx); - } - } - return (idx); -} - -static void -udl_select_chip(struct udl_softc *sc, struct usb_attach_arg *uaa) -{ - const char *pserial; - - pserial = usb_get_serial(uaa->device); - - sc->sc_chip = DL120; - - if ((uaa->info.idVendor == USB_VENDOR_DISPLAYLINK) && - (uaa->info.idProduct == USB_PRODUCT_DISPLAYLINK_WSDVI)) { - - /* - * WS Tech DVI is DL120 or DL160. All deviced uses the - * same revision (0.04) so iSerialNumber must be used - * to determin which chip it is. - */ - - if (strlen(pserial) > 7) { - if (strncmp(pserial, "0198-13", 7) == 0) - sc->sc_chip = DL160; - } - DPRINTF("iSerialNumber (%s) used to select chip (%d)\n", - pserial, sc->sc_chip); - } - if ((uaa->info.idVendor == USB_VENDOR_DISPLAYLINK) && - (uaa->info.idProduct == USB_PRODUCT_DISPLAYLINK_SWDVI)) { - - /* - * SUNWEIT DVI is DL160, DL125, DL165 or DL195. Major revision - * can be used to differ between DL1x0 and DL1x5. Minor to - * differ between DL1x5. iSerialNumber seems not to be uniqe. - */ - - sc->sc_chip = DL160; - - if (uaa->info.bcdDevice >= 0x100) { - sc->sc_chip = DL165; - if (uaa->info.bcdDevice == 0x104) - sc->sc_chip = DL195; - if (uaa->info.bcdDevice == 0x108) - sc->sc_chip = DL125; - } - DPRINTF("bcdDevice (%02x) used to select chip (%d)\n", - uaa->info.bcdDevice, sc->sc_chip); - } -} - -static int -udl_set_enc_key(struct udl_softc *sc, uint8_t *buf, uint8_t len) -{ - int error; - - error = udl_ctrl_msg(sc, UT_WRITE_VENDOR_DEVICE, - UDL_CTRL_CMD_SET_KEY, 0x0000, 0x0000, buf, len); - return (error); -} - -static void -udl_fbmem_alloc(struct udl_softc *sc) -{ - uint32_t size; - - size = udl_get_fb_size(sc); - size = round_page(size); - - /* - * It is assumed that allocations above PAGE_SIZE bytes will - * be PAGE_SIZE aligned for use with mmap() - */ - sc->sc_fb_addr = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); - sc->sc_fb_copy = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); - sc->sc_fb_size = size; -} - -static void -udl_cmd_insert_int_1(struct udl_cmd_buf *cb, uint8_t value) -{ - - cb->buf[cb->off] = value; - cb->off += 1; -} - -#if 0 -static void -udl_cmd_insert_int_2(struct udl_cmd_buf *cb, uint16_t value) -{ - uint16_t lvalue; - - lvalue = htobe16(value); - bcopy(&lvalue, cb->buf + cb->off, 2); - - cb->off += 2; -} - -#endif - -static void -udl_cmd_insert_int_3(struct udl_cmd_buf *cb, uint32_t value) -{ - uint32_t lvalue; - -#if BYTE_ORDER == BIG_ENDIAN - lvalue = htobe32(value) << 8; -#else - lvalue = htobe32(value) >> 8; -#endif - bcopy(&lvalue, cb->buf + cb->off, 3); - - cb->off += 3; -} - -#if 0 -static void -udl_cmd_insert_int_4(struct udl_cmd_buf *cb, uint32_t value) -{ - uint32_t lvalue; - - lvalue = htobe32(value); - bcopy(&lvalue, cb->buf + cb->off, 4); - - cb->off += 4; -} - -#endif - -static void -udl_cmd_insert_buf_le16(struct udl_cmd_buf *cb, const uint8_t *buf, uint32_t len) -{ - uint32_t x; - - for (x = 0; x != len; x += 2) { - /* byte swap from little endian to big endian */ - cb->buf[cb->off + x + 0] = buf[x + 1]; - cb->buf[cb->off + x + 1] = buf[x + 0]; - } - cb->off += len; -} - -static void -udl_cmd_write_reg_1(struct udl_cmd_buf *cb, uint8_t reg, uint8_t val) -{ - - udl_cmd_insert_int_1(cb, UDL_BULK_SOC); - udl_cmd_insert_int_1(cb, UDL_BULK_CMD_REG_WRITE_1); - udl_cmd_insert_int_1(cb, reg); - udl_cmd_insert_int_1(cb, val); -} - -static void -udl_cmd_write_reg_3(struct udl_cmd_buf *cb, uint8_t reg, uint32_t val) -{ - - udl_cmd_write_reg_1(cb, reg + 0, (val >> 16) & 0xff); - udl_cmd_write_reg_1(cb, reg + 1, (val >> 8) & 0xff); - udl_cmd_write_reg_1(cb, reg + 2, (val >> 0) & 0xff); -} - -static int -udl_init_chip(struct udl_softc *sc) -{ - uint32_t ui32; - uint8_t ui8; - int error; - - error = udl_poll(sc, &ui32); - if (error != USB_ERR_NORMAL_COMPLETION) - return (error); - DPRINTF("poll=0x%08x\n", ui32); - - /* Some products may use later chip too */ - switch (ui32 & 0xff) { - case 0xf1: /* DL1x5 */ - switch (sc->sc_chip) { - case DL120: - sc->sc_chip = DL125; - break; - case DL160: - sc->sc_chip = DL165; - break; - } - break; - } - DPRINTF("chip 0x%04x\n", sc->sc_chip); - - error = udl_read_1(sc, 0xc484, &ui8); - if (error != USB_ERR_NORMAL_COMPLETION) - return (error); - DPRINTF("read 0x%02x from 0xc484\n", ui8); - - error = udl_write_1(sc, 0xc41f, 0x01); - if (error != USB_ERR_NORMAL_COMPLETION) - return (error); - DPRINTF("write 0x01 to 0xc41f\n"); - - error = udl_read_edid(sc, sc->sc_edid); - if (error != USB_ERR_NORMAL_COMPLETION) - return (error); - DPRINTF("read EDID\n"); - - error = udl_set_enc_key(sc, __DECONST(void *, udl_null_key_1), - sizeof(udl_null_key_1)); - if (error != USB_ERR_NORMAL_COMPLETION) - return (error); - DPRINTF("set encryption key\n"); - - error = udl_write_1(sc, 0xc40b, 0x00); - if (error != USB_ERR_NORMAL_COMPLETION) - return (error); - DPRINTF("write 0x00 to 0xc40b\n"); - - return (USB_ERR_NORMAL_COMPLETION); -} - -static void -udl_init_fb_offsets(struct udl_cmd_buf *cb, uint32_t start16, uint32_t stride16, - uint32_t start8, uint32_t stride8) -{ - udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0x00); - udl_cmd_write_reg_3(cb, UDL_REG_ADDR_START16, start16); - udl_cmd_write_reg_3(cb, UDL_REG_ADDR_STRIDE16, stride16); - udl_cmd_write_reg_3(cb, UDL_REG_ADDR_START8, start8); - udl_cmd_write_reg_3(cb, UDL_REG_ADDR_STRIDE8, stride8); - udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff); -} - -static int -udl_init_resolution(struct udl_softc *sc) -{ - const uint32_t max = udl_get_fb_size(sc); - const uint8_t *buf = udl_modes[sc->sc_cur_mode].mode; - struct udl_cmd_buf *cb; - uint32_t delta; - uint32_t i; - int error; - - /* get new buffer */ - cb = udl_cmd_buf_alloc(sc, M_WAITOK); - if (cb == NULL) - return (EAGAIN); - - /* write resolution values and set video memory offsets */ - udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0x00); - for (i = 0; i < UDL_MODE_SIZE; i++) - udl_cmd_write_reg_1(cb, i, buf[i]); - udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff); - - udl_init_fb_offsets(cb, 0x000000, 0x000a00, 0x555555, 0x000500); - udl_cmd_buf_send(sc, cb); - - /* fill screen with black color */ - for (i = 0; i < max; i += delta) { - static const uint8_t udl_black[UDL_CMD_MAX_PIXEL_COUNT * 2] __aligned(4); - - delta = max - i; - if (delta > UDL_CMD_MAX_PIXEL_COUNT * 2) - delta = UDL_CMD_MAX_PIXEL_COUNT * 2; - if (i == 0) - error = udl_cmd_write_buf_le16(sc, udl_black, i, delta / 2, M_WAITOK); - else - error = udl_cmd_buf_copy_le16(sc, 0, i, delta / 2, M_WAITOK); - if (error) - return (error); - } - - /* get new buffer */ - cb = udl_cmd_buf_alloc(sc, M_WAITOK); - if (cb == NULL) - return (EAGAIN); - - /* show framebuffer content */ - udl_cmd_write_reg_1(cb, UDL_REG_SCREEN, UDL_REG_SCREEN_ON); - udl_cmd_write_reg_1(cb, UDL_REG_SYNC, 0xff); - udl_cmd_buf_send(sc, cb); - return (0); -} - -static void -udl_select_mode(struct udl_softc *sc) -{ - struct udl_mode mode; - int index = UDL_MAX_MODES; - int i; - - /* try to get the preferred mode from EDID */ - edid_parse(sc->sc_edid, &sc->sc_edid_info); -#ifdef USB_DEBUG - edid_print(&sc->sc_edid_info); -#endif - if (sc->sc_edid_info.edid_preferred_mode != NULL) { - mode.hz = - (sc->sc_edid_info.edid_preferred_mode->dot_clock * 1000) / - (sc->sc_edid_info.edid_preferred_mode->htotal * - sc->sc_edid_info.edid_preferred_mode->vtotal); - mode.clock = - sc->sc_edid_info.edid_preferred_mode->dot_clock / 10; - mode.hdisplay = - sc->sc_edid_info.edid_preferred_mode->hdisplay; - mode.vdisplay = - sc->sc_edid_info.edid_preferred_mode->vdisplay; - index = udl_lookup_mode(mode.hdisplay, mode.vdisplay, mode.hz, - sc->sc_chip, mode.clock); - sc->sc_cur_mode = index; - } else { - DPRINTF("no preferred mode found!\n"); - } - - if (index == UDL_MAX_MODES) { - DPRINTF("no mode line found for %dx%d @ %dHz!\n", - mode.hdisplay, mode.vdisplay, mode.hz); - - i = 0; - while (i < sc->sc_edid_info.edid_nmodes) { - mode.hz = - (sc->sc_edid_info.edid_modes[i].dot_clock * 1000) / - (sc->sc_edid_info.edid_modes[i].htotal * - sc->sc_edid_info.edid_modes[i].vtotal); - mode.clock = - sc->sc_edid_info.edid_modes[i].dot_clock / 10; - mode.hdisplay = - sc->sc_edid_info.edid_modes[i].hdisplay; - mode.vdisplay = - sc->sc_edid_info.edid_modes[i].vdisplay; - index = udl_lookup_mode(mode.hdisplay, mode.vdisplay, - mode.hz, sc->sc_chip, mode.clock); - if (index < UDL_MAX_MODES) - if ((sc->sc_cur_mode == UDL_MAX_MODES) || - (index > sc->sc_cur_mode)) - sc->sc_cur_mode = index; - i++; - } - } - /* - * If no mode found use default. - */ - if (sc->sc_cur_mode == UDL_MAX_MODES) - sc->sc_cur_mode = udl_lookup_mode(800, 600, 60, sc->sc_chip, 0); -} - -static int -udl_cmd_write_buf_le16(struct udl_softc *sc, const uint8_t *buf, uint32_t off, - uint8_t pixels, int flags) -{ - struct udl_cmd_buf *cb; - - cb = udl_cmd_buf_alloc(sc, flags); - if (cb == NULL) - return (EAGAIN); - - udl_cmd_insert_int_1(cb, UDL_BULK_SOC); - udl_cmd_insert_int_1(cb, UDL_BULK_CMD_FB_WRITE | UDL_BULK_CMD_FB_WORD); - udl_cmd_insert_int_3(cb, off); - udl_cmd_insert_int_1(cb, pixels); - udl_cmd_insert_buf_le16(cb, buf, 2 * pixels); - udl_cmd_buf_send(sc, cb); - - return (0); -} - -static int -udl_cmd_buf_copy_le16(struct udl_softc *sc, uint32_t src, uint32_t dst, - uint8_t pixels, int flags) -{ - struct udl_cmd_buf *cb; - - cb = udl_cmd_buf_alloc(sc, flags); - if (cb == NULL) - return (EAGAIN); - - udl_cmd_insert_int_1(cb, UDL_BULK_SOC); - udl_cmd_insert_int_1(cb, UDL_BULK_CMD_FB_COPY | UDL_BULK_CMD_FB_WORD); - udl_cmd_insert_int_3(cb, dst); - udl_cmd_insert_int_1(cb, pixels); - udl_cmd_insert_int_3(cb, src); - udl_cmd_buf_send(sc, cb); - - return (0); -} diff --git a/sys/bus/u4b/video/udl.h b/sys/bus/u4b/video/udl.h deleted file mode 100644 index 1fdae7aed5..0000000000 --- a/sys/bus/u4b/video/udl.h +++ /dev/null @@ -1,311 +0,0 @@ -/* $OpenBSD: udl.h,v 1.21 2013/04/15 09:23:02 mglocker Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (c) 2009 Marcus Glocker - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _UDL_H_ -#define _UDL_H_ - -#include -#include - -/* - * BULK command transfer structure. - */ -#define UDL_CMD_MAX_FRAMES 64 /* units */ -#define UDL_CMD_MAX_DATA_SIZE 512 /* bytes */ -#define UDL_CMD_MAX_HEAD_SIZE 16 /* bytes */ -#define UDL_CMD_MAX_PIXEL_COUNT ((UDL_CMD_MAX_DATA_SIZE - UDL_CMD_MAX_HEAD_SIZE) / 2) -#define UDL_CMD_MAX_BUFFERS (3 * UDL_CMD_MAX_FRAMES) -#define UDL_FONT_HEIGHT 16 /* pixels */ -#define UDL_MAX_MODES 25 /* units */ - -struct udl_cmd_buf { - TAILQ_ENTRY(udl_cmd_buf) entry; - uint32_t off; - uint8_t buf[UDL_CMD_MAX_DATA_SIZE] __aligned(4); -}; - -TAILQ_HEAD(udl_cmd_head, udl_cmd_buf); - -enum { - UDL_BULK_WRITE_0, - UDL_BULK_WRITE_1, - UDL_N_TRANSFER, -}; - -/* - * Our per device structure. - */ -struct udl_softc { - struct mtx sc_mtx; - struct cv sc_cv; - struct callout sc_callout; - struct usb_xfer *sc_xfer[UDL_N_TRANSFER]; - struct usb_device *sc_udev; - device_t sc_fbdev; - struct fb_info sc_fb_info; - uint8_t sc_edid[128]; - struct edid_info sc_edid_info; - struct udl_cmd_head sc_xfer_head[2]; - struct udl_cmd_head sc_cmd_buf_free; - struct udl_cmd_head sc_cmd_buf_pending; - struct udl_cmd_buf sc_cmd_buf_temp[UDL_CMD_MAX_BUFFERS]; - uint32_t sc_sync_off; - uint32_t sc_fb_size; - uint8_t *sc_fb_addr; - uint8_t *sc_fb_copy; - int sc_def_chip; /* default chip version */ - int sc_chip; -#define DLALL 0x0000 -#define DL125 0x0000 /* max 1280x1024, 1440x900 */ -#define DL120 0x0001 /* max 1280x1024, 1440x1050 */ -#define DL160 0x0002 /* max 1600x1200, 1680x1050 */ -#define DL165 0x0003 /* max 1600x1200, 1920x1080 */ -#define DL195 0x0004 /* max 1920x1200, 2048x1152 */ -#define DLMAX 0x0004 -#define DLUNK 0x00ff /* unknown */ - int sc_def_mode; /* default mode */ - int sc_cur_mode; - uint8_t sc_power_save; /* set if power save is enabled */ - uint8_t sc_gone; -}; - -#define UDL_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define UDL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) - -/* - * Chip commands. - */ -#define UDL_CTRL_CMD_READ_EDID 0x02 -#define UDL_CTRL_CMD_WRITE_1 0x03 -#define UDL_CTRL_CMD_READ_1 0x04 -#define UDL_CTRL_CMD_POLL 0x06 -#define UDL_CTRL_CMD_SET_KEY 0x12 - -#define UDL_BULK_SOC 0xaf /* start of command token */ - -#define UDL_BULK_CMD_REG_WRITE_1 0x20 /* write 1 byte to register */ -#define UDL_BULK_CMD_EOC 0xa0 /* end of command stack */ -#define UDL_BULK_CMD_DECOMP 0xe0 /* send decompression table */ - -#define UDL_BULK_CMD_FB_BASE 0x60 -#define UDL_BULK_CMD_FB_WORD 0x08 -#define UDL_BULK_CMD_FB_COMP 0x10 -#define UDL_BULK_CMD_FB_WRITE (UDL_BULK_CMD_FB_BASE | 0x00) -#define UDL_BULK_CMD_FB_COPY (UDL_BULK_CMD_FB_BASE | 0x02) - -/* - * Chip registers. - */ -#define UDL_REG_ADDR_START16 0x20 -#define UDL_REG_ADDR_STRIDE16 0x23 -#define UDL_REG_ADDR_START8 0x26 -#define UDL_REG_ADDR_STRIDE8 0x29 - -#define UDL_REG_SCREEN 0x1f -#define UDL_REG_SCREEN_ON 0x00 -#define UDL_REG_SCREEN_OFF 0x01 -#define UDL_REG_SYNC 0xff - -#define UDL_MODE_SIZE 29 - -/* - * Register values for screen resolution initialization. - */ -static const uint8_t udl_reg_vals_640x480_60[UDL_MODE_SIZE] = { /* 25.17 Mhz 59.9 Hz - * VESA std */ - 0x00, 0x99, 0x30, 0x26, 0x94, 0x60, 0xa9, 0xce, 0x60, 0x07, 0xb3, 0x0f, - 0x79, 0xff, 0xff, 0x02, 0x80, 0x83, 0xbc, 0xff, 0xfc, 0xff, 0xff, 0x01, - 0xe0, 0x01, 0x02, 0xab, 0x13 -}; -static const uint8_t udl_reg_vals_640x480_67[UDL_MODE_SIZE] = { /* 30.25 MHz 66.6 Hz MAC - * std */ - 0x00, 0x1d, 0x33, 0x07, 0xb3, 0x60, 0xa9, 0xce, 0x60, 0xb6, 0xa8, 0xff, - 0xff, 0xbf, 0x70, 0x02, 0x80, 0x83, 0xbc, 0xff, 0xff, 0xff, 0xf9, 0x01, - 0xe0, 0x01, 0x02, 0xa2, 0x17 -}; -static const uint8_t udl_reg_vals_640x480_72[UDL_MODE_SIZE] = { /* 31.50 Mhz 72.8 Hz - * VESA std */ - 0x00, 0x2b, 0xeb, 0x35, 0xd3, 0x0a, 0x95, 0xe6, 0x0e, 0x0f, 0xb5, 0x15, - 0x2a, 0xff, 0xff, 0x02, 0x80, 0xcc, 0x1d, 0xff, 0xf9, 0xff, 0xff, 0x01, - 0xe0, 0x01, 0x02, 0x9c, 0x18 -}; -static const uint8_t udl_reg_vals_640x480_75[UDL_MODE_SIZE] = { /* 31.50 Mhz 75.7 Hz - * VESA std */ - 0x00, 0xeb, 0xf7, 0xd3, 0x0f, 0x4f, 0x93, 0xfa, 0x47, 0xb5, 0x58, 0xff, - 0xff, 0xbf, 0x70, 0x02, 0x80, 0xf4, 0x8f, 0xff, 0xff, 0xff, 0xf9, 0x01, - 0xe0, 0x01, 0x02, 0x9c, 0x18 -}; -static const uint8_t udl_reg_vals_800x480_61[UDL_MODE_SIZE] = { /* 33.00 MHz 61.9 Hz */ - 0x00, 0x20, 0x3c, 0x7a, 0xc9, 0xf2, 0x6c, 0x48, 0xf9, 0x70, 0x53, 0xff, - 0xff, 0x21, 0x27, 0x03, 0x20, 0x91, 0xf3, 0xff, 0xff, 0xff, 0xf9, 0x01, - 0xe0, 0x01, 0x02, 0xc8, 0x19 -}; -static const uint8_t udl_reg_vals_800x600_56[UDL_MODE_SIZE] = { /* 36.00 MHz 56.2 Hz - * VESA std */ - 0x00, 0x65, 0x35, 0x48, 0xf4, 0xf2, 0x6c, 0x19, 0x18, 0xc9, 0x4b, 0xff, - 0xff, 0x70, 0x35, 0x03, 0x20, 0x32, 0x31, 0xff, 0xff, 0xff, 0xfc, 0x02, - 0x58, 0x01, 0x02, 0x20, 0x1c -}; -static const uint8_t udl_reg_vals_800x600_60[UDL_MODE_SIZE] = { /* 40.00 MHz 60.3 Hz - * VESA std */ - 0x00, 0x20, 0x3c, 0x7a, 0xc9, 0x93, 0x60, 0xc8, 0xc7, 0x70, 0x53, 0xff, - 0xff, 0x21, 0x27, 0x03, 0x20, 0x91, 0x8f, 0xff, 0xff, 0xff, 0xf2, 0x02, - 0x58, 0x01, 0x02, 0x40, 0x1f -}; -static const uint8_t udl_reg_vals_800x600_72[UDL_MODE_SIZE] = { /* 50.00 MHz 72.1 Hz - * VESA std */ - 0x00, 0xeb, 0xf7, 0xd1, 0x90, 0x4d, 0x82, 0x23, 0x1f, 0x39, 0xcf, 0xff, - 0xff, 0x43, 0x21, 0x03, 0x20, 0x62, 0xc5, 0xff, 0xff, 0xff, 0xca, 0x02, - 0x58, 0x01, 0x02, 0x10, 0x27 -}; -static const uint8_t udl_reg_vals_800x600_74[UDL_MODE_SIZE] = { /* 50.00 MHz 74.4 Hz */ - 0x00, 0xb3, 0x76, 0x39, 0xcf, 0x60, 0xa9, 0xc7, 0xf4, 0x70, 0x53, 0xff, - 0xff, 0x35, 0x33, 0x03, 0x20, 0x8f, 0xe9, 0xff, 0xff, 0xff, 0xf9, 0x02, - 0x58, 0x01, 0x02, 0x10, 0x27 -}; -static const uint8_t udl_reg_vals_800x600_75[UDL_MODE_SIZE] = { /* 49.50 MHz 75.0 Hz - * VESA std */ - 0x00, 0xb3, 0x76, 0x39, 0xcf, 0xf2, 0x6c, 0x19, 0x18, 0x70, 0x53, 0xff, - 0xff, 0x35, 0x33, 0x03, 0x20, 0x32, 0x31, 0xff, 0xff, 0xff, 0xf9, 0x02, - 0x58, 0x01, 0x02, 0xac, 0x26 -}; -static const uint8_t udl_reg_vals_1024x768_60[UDL_MODE_SIZE] = { /* 65.00 MHz 60.0 Hz - * VESA std */ - 0x00, 0x36, 0x18, 0xd5, 0x10, 0x60, 0xa9, 0x7b, 0x33, 0xa1, 0x2b, 0x27, - 0x32, 0xff, 0xff, 0x04, 0x00, 0xd9, 0x9a, 0xff, 0xca, 0xff, 0xff, 0x03, - 0x00, 0x04, 0x03, 0xc8, 0x32 -}; -static const uint8_t udl_reg_vals_1024x768_70[UDL_MODE_SIZE] = { /* 75.00 MHz 70.0 Hz - * VESA std */ - 0x00, 0xb4, 0xed, 0x4c, 0x5e, 0x60, 0xa9, 0x7b, 0x33, 0x10, 0x4d, 0xff, - 0xff, 0x27, 0x32, 0x04, 0x00, 0xd9, 0x9a, 0xff, 0xff, 0xff, 0xca, 0x03, - 0x00, 0x04, 0x02, 0x98, 0x3a -}; -static const uint8_t udl_reg_vals_1024x768_75[UDL_MODE_SIZE] = { /* 78.75 MHz 75.0 Hz - * VESA std */ - 0x00, 0xec, 0xb4, 0xa0, 0x4c, 0x36, 0x0a, 0x07, 0xb3, 0x5e, 0xd5, 0xff, - 0xff, 0x0f, 0x79, 0x04, 0x00, 0x0f, 0x66, 0xff, 0xff, 0xff, 0xf9, 0x03, - 0x00, 0x04, 0x02, 0x86, 0x3d -}; -static const uint8_t udl_reg_vals_1280x800_60[UDL_MODE_SIZE] = { /* 83.46 MHz 59.9 MHz */ - 0x00, 0xb2, 0x19, 0x34, 0xdf, 0x93, 0x60, 0x30, 0xfb, 0x9f, 0xca, 0xff, - 0xff, 0x27, 0x32, 0x05, 0x00, 0x61, 0xf6, 0xff, 0xff, 0xff, 0xf9, 0x03, - 0x20, 0x04, 0x02, 0x34, 0x41 -}; -static const uint8_t udl_reg_vals_1280x960_60[UDL_MODE_SIZE] = { /* 108.00 MHz 60.0 Hz - * VESA std */ - 0x00, 0xa6, 0x03, 0x5c, 0x7e, 0x0a, 0x95, 0x48, 0xf4, 0x61, 0xbd, 0xff, - 0xff, 0x94, 0x43, 0x05, 0x00, 0x91, 0xe8, 0xff, 0xff, 0xff, 0xf9, 0x03, - 0xc0, 0x04, 0x02, 0x60, 0x54 -}; -static const uint8_t udl_reg_vals_1280x1024_60[UDL_MODE_SIZE] = { /* 108.00 MHz 60.0 Hz - * VESA std */ - 0x00, 0x98, 0xf8, 0x0d, 0x57, 0x2a, 0x55, 0x4d, 0x54, 0xca, 0x0d, 0xff, - 0xff, 0x94, 0x43, 0x05, 0x00, 0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9, 0x04, - 0x00, 0x04, 0x02, 0x60, 0x54 -}; -static const uint8_t udl_reg_vals_1280x1024_75[UDL_MODE_SIZE] = { /* 135.00 MHz 75.0 Hz - * VESA std */ - 0x00, 0xce, 0x12, 0x3f, 0x9f, 0x2a, 0x55, 0x4d, 0x54, 0xca, 0x0d, 0xff, - 0xff, 0x32, 0x60, 0x05, 0x00, 0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9, 0x04, - 0x00, 0x04, 0x02, 0x78, 0x69 -}; -static const uint8_t udl_reg_vals_1366x768_60[UDL_MODE_SIZE] = { /* 90 MHz 60.0 Hz */ - 0x01, 0x19, 0x1e, 0x1f, 0xb0, 0x93, 0x60, 0x40, 0x7b, 0x36, 0xe8, 0x27, - 0x32, 0xff, 0xff, 0x05, 0x56, 0x03, 0xd9, 0xff, 0xff, 0xfc, 0xa7, 0x03, - 0x00, 0x04, 0x02, 0x9a, 0x42 -}; -static const uint8_t udl_reg_vals_1440x900_60[UDL_MODE_SIZE] = { /* 106.47 MHz 59.9 Hz */ - 0x00, 0x24, 0xce, 0xe7, 0x72, 0x36, 0x0a, 0x86, 0xca, 0x1c, 0x10, 0xff, - 0xff, 0x60, 0x3a, 0x05, 0xa0, 0x0d, 0x94, 0xff, 0xff, 0xff, 0xf9, 0x03, - 0x84, 0x04, 0x02, 0x2e, 0x53 -}; -static const uint8_t udl_reg_vals_1440x900_59[UDL_MODE_SIZE] = { /* 106.50 MHz 59.8 Hz */ - 0x00, 0x24, 0xce, 0xe7, 0x72, 0xd8, 0x2a, 0x1b, 0x28, 0x1c, 0x10, 0xff, - 0xff, 0x60, 0x3a, 0x05, 0xa0, 0x36, 0x50, 0xff, 0xff, 0xff, 0xf9, 0x03, - 0x84, 0x04, 0x02, 0x34, 0x53 -}; -static const uint8_t udl_reg_vals_1440x900_75[UDL_MODE_SIZE] = { /* 136.49 MHz 75.0 Hz */ - 0x00, 0x73, 0xa6, 0x14, 0xea, 0x0a, 0x95, 0xca, 0x10, 0x7f, 0x46, 0xff, - 0xff, 0x60, 0x3a, 0x05, 0xa0, 0x94, 0x20, 0xff, 0xff, 0xff, 0xf9, 0x03, - 0x84, 0x04, 0x02, 0xa2, 0x6a -}; -static const uint8_t udl_reg_vals_1680x1050_60[UDL_MODE_SIZE] = { /* 147.14 MHz 60.0 Hz */ - 0x00, 0x53, 0x43, 0xa6, 0x71, 0xc1, 0x52, 0xd9, 0x29, 0x69, 0x9f, 0xff, - 0xff, 0xd7, 0xee, 0x06, 0x90, 0xb2, 0x53, 0xff, 0xff, 0xff, 0xf9, 0x04, - 0x1a, 0x04, 0x02, 0xf4, 0x72 -}; -static const uint8_t udl_reg_vals_1600x1200_60[UDL_MODE_SIZE] = { /* 162.00 MHz 60.0 Hz - * VESA std */ - 0x00, 0xcf, 0xa4, 0x3c, 0x4e, 0x55, 0x73, 0x71, 0x2b, 0x71, 0x52, 0xff, - 0xff, 0xee, 0xca, 0x06, 0x40, 0xe2, 0x57, 0xff, 0xff, 0xff, 0xf9, 0x04, - 0xb0, 0x04, 0x02, 0x90, 0x7e -}; -static const uint8_t udl_reg_vals_1920x1080_60[UDL_MODE_SIZE] = { /* 138.50 MHz 59.9 Hz */ - 0x00, 0x73, 0xa6, 0x28, 0xb3, 0x54, 0xaa, 0x41, 0x5d, 0x0d, 0x9f, 0x32, - 0x60, 0xff, 0xff, 0x07, 0x80, 0x0a, 0xea, 0xff, 0xf9, 0xff, 0xff, 0x04, - 0x38, 0x04, 0x02, 0xe0, 0x7c -}; - -struct udl_mode { - uint16_t hdisplay; - uint16_t vdisplay; - uint8_t hz; - uint16_t chip; - uint32_t clock; - const uint8_t *mode; -}; - -static const struct udl_mode udl_modes[UDL_MAX_MODES] = { - {640, 480, 60, DLALL, 2520, udl_reg_vals_640x480_60}, - {640, 480, 67, DLALL, 3025, udl_reg_vals_640x480_67}, - {640, 480, 72, DLALL, 3150, udl_reg_vals_640x480_72}, - {640, 480, 75, DLALL, 3150, udl_reg_vals_640x480_75}, - {800, 480, 59, DLALL, 5000, udl_reg_vals_800x480_61}, - {800, 480, 61, DLALL, 3300, udl_reg_vals_800x480_61}, - {800, 600, 56, DLALL, 3600, udl_reg_vals_800x600_56}, - {800, 600, 60, DLALL, 4000, udl_reg_vals_800x600_60}, - {800, 600, 72, DLALL, 5000, udl_reg_vals_800x600_72}, - {800, 600, 74, DLALL, 5000, udl_reg_vals_800x600_74}, - {800, 600, 75, DLALL, 4950, udl_reg_vals_800x600_75}, - {1024, 768, 60, DLALL, 6500, udl_reg_vals_1024x768_60}, - {1024, 768, 70, DLALL, 7500, udl_reg_vals_1024x768_70}, - {1024, 768, 75, DLALL, 7850, udl_reg_vals_1024x768_75}, - {1280, 800, 60, DLALL, 8346, udl_reg_vals_1280x800_60}, - {1280, 960, 60, DLALL, 10800, udl_reg_vals_1280x960_60}, - {1280, 1024, 60, DLALL, 10800, udl_reg_vals_1280x1024_60}, - {1280, 1024, 75, DLALL, 13500, udl_reg_vals_1280x1024_75}, - {1366, 768, 60, DLALL, 9000, udl_reg_vals_1366x768_60}, - {1440, 900, 59, DL125, 10650, udl_reg_vals_1440x900_59}, - {1440, 900, 60, DL125, 10647, udl_reg_vals_1440x900_60}, - {1440, 900, 75, DL125, 13649, udl_reg_vals_1440x900_75}, - {1680, 1050, 60, DL160, 14714, udl_reg_vals_1680x1050_60}, - {1600, 1200, 60, DL160, 16200, udl_reg_vals_1600x1200_60}, - {1920, 1080, 60, DL165, 13850, udl_reg_vals_1920x1080_60} -}; - -/* - * Encryption. - */ -static const uint8_t udl_null_key_1[] = { - 0x57, 0xcd, 0xdc, 0xa7, 0x1c, 0x88, 0x5e, 0x15, 0x60, 0xfe, 0xc6, 0x97, - 0x16, 0x3d, 0x47, 0xf2 -}; - -#endif /* _UDL_H_ */ diff --git a/sys/bus/u4b/wlan/if_uath.c b/sys/bus/u4b/wlan/if_uath.c deleted file mode 100644 index 9e224847c3..0000000000 --- a/sys/bus/u4b/wlan/if_uath.c +++ /dev/null @@ -1,2899 +0,0 @@ -/*- - * Copyright (c) 2006 Sam Leffler, Errno Consulting - * Copyright (c) 2008-2009 Weongyo Jeong - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * This driver is distantly derived from a driver of the same name - * by Damien Bergamini. The original copyright is included below: - * - * Copyright (c) 2006 - * Damien Bergamini - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -__FBSDID("$FreeBSD$"); - -/*- - * Driver for Atheros AR5523 USB parts. - * - * The driver requires firmware to be loaded into the device. This - * is done on device discovery from a user application (uathload) - * that is launched by devd when a device with suitable product ID - * is recognized. Once firmware has been loaded the device will - * reset the USB port and re-attach with the original product ID+1 - * and this driver will be attached. The firmware is licensed for - * general use (royalty free) and may be incorporated in products. - * Note that the firmware normally packaged with the NDIS drivers - * for these devices does not work in this way and so does not work - * with this driver. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#include -#endif - -#include -#include -#include - -#include -#include -#include "usbdevs.h" - -#include -#include - -static SYSCTL_NODE(_hw_usb, OID_AUTO, uath, CTLFLAG_RW, 0, "USB Atheros"); - -static int uath_countrycode = CTRY_DEFAULT; /* country code */ -SYSCTL_INT(_hw_usb_uath, OID_AUTO, countrycode, CTLFLAG_RW, &uath_countrycode, - 0, "country code"); -TUNABLE_INT("hw.usb.uath.countrycode", &uath_countrycode); -static int uath_regdomain = 0; /* regulatory domain */ -SYSCTL_INT(_hw_usb_uath, OID_AUTO, regdomain, CTLFLAG_RD, &uath_regdomain, - 0, "regulatory domain"); - -#ifdef UATH_DEBUG -int uath_debug = 0; -SYSCTL_INT(_hw_usb_uath, OID_AUTO, debug, CTLFLAG_RW, &uath_debug, 0, - "uath debug level"); -TUNABLE_INT("hw.usb.uath.debug", &uath_debug); -enum { - UATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - UATH_DEBUG_XMIT_DUMP = 0x00000002, /* xmit dump */ - UATH_DEBUG_RECV = 0x00000004, /* basic recv operation */ - UATH_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */ - UATH_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */ - UATH_DEBUG_RECV_ALL = 0x00000020, /* trace all frames (beacons) */ - UATH_DEBUG_INIT = 0x00000040, /* initialization of dev */ - UATH_DEBUG_DEVCAP = 0x00000080, /* dev caps */ - UATH_DEBUG_CMDS = 0x00000100, /* commands */ - UATH_DEBUG_CMDS_DUMP = 0x00000200, /* command buffer dump */ - UATH_DEBUG_RESET = 0x00000400, /* reset processing */ - UATH_DEBUG_STATE = 0x00000800, /* 802.11 state transitions */ - UATH_DEBUG_MULTICAST = 0x00001000, /* multicast */ - UATH_DEBUG_WME = 0x00002000, /* WME */ - UATH_DEBUG_CHANNEL = 0x00004000, /* channel */ - UATH_DEBUG_RATES = 0x00008000, /* rates */ - UATH_DEBUG_CRYPTO = 0x00010000, /* crypto */ - UATH_DEBUG_LED = 0x00020000, /* LED */ - UATH_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif - -/* unaligned little endian access */ -#define LE_READ_2(p) \ - ((u_int16_t) \ - ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8))) -#define LE_READ_4(p) \ - ((u_int32_t) \ - ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \ - (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24))) - -/* recognized device vendors/products */ -static const STRUCT_USB_HOST_ID uath_devs[] = { -#define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } - UATH_DEV(ACCTON, SMCWUSBTG2), - UATH_DEV(ATHEROS, AR5523), - UATH_DEV(ATHEROS2, AR5523_1), - UATH_DEV(ATHEROS2, AR5523_2), - UATH_DEV(ATHEROS2, AR5523_3), - UATH_DEV(CONCEPTRONIC, AR5523_1), - UATH_DEV(CONCEPTRONIC, AR5523_2), - UATH_DEV(DLINK, DWLAG122), - UATH_DEV(DLINK, DWLAG132), - UATH_DEV(DLINK, DWLG132), - UATH_DEV(DLINK2, DWA120), - UATH_DEV(GIGASET, AR5523), - UATH_DEV(GIGASET, SMCWUSBTG), - UATH_DEV(GLOBALSUN, AR5523_1), - UATH_DEV(GLOBALSUN, AR5523_2), - UATH_DEV(NETGEAR, WG111U), - UATH_DEV(NETGEAR3, WG111T), - UATH_DEV(NETGEAR3, WPN111), - UATH_DEV(NETGEAR3, WPN111_2), - UATH_DEV(UMEDIA, TEW444UBEU), - UATH_DEV(UMEDIA, AR5523_2), - UATH_DEV(WISTRONNEWEB, AR5523_1), - UATH_DEV(WISTRONNEWEB, AR5523_2), - UATH_DEV(ZCOM, AR5523) -#undef UATH_DEV -}; - -static usb_callback_t uath_intr_rx_callback; -static usb_callback_t uath_intr_tx_callback; -static usb_callback_t uath_bulk_rx_callback; -static usb_callback_t uath_bulk_tx_callback; - -static const struct usb_config uath_usbconfig[UATH_N_XFERS] = { - [UATH_INTR_RX] = { - .type = UE_BULK, - .endpoint = 0x1, - .direction = UE_DIR_IN, - .bufsize = UATH_MAX_CMDSZ, - .flags = { - .pipe_bof = 1, - .short_xfer_ok = 1 - }, - .callback = uath_intr_rx_callback - }, - [UATH_INTR_TX] = { - .type = UE_BULK, - .endpoint = 0x1, - .direction = UE_DIR_OUT, - .bufsize = UATH_MAX_CMDSZ, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = uath_intr_tx_callback, - .timeout = UATH_CMD_TIMEOUT - }, - [UATH_BULK_RX] = { - .type = UE_BULK, - .endpoint = 0x2, - .direction = UE_DIR_IN, - .bufsize = MCLBYTES, - .flags = { - .ext_buffer = 1, - .pipe_bof = 1, - .short_xfer_ok = 1 - }, - .callback = uath_bulk_rx_callback - }, - [UATH_BULK_TX] = { - .type = UE_BULK, - .endpoint = 0x2, - .direction = UE_DIR_OUT, - .bufsize = UATH_MAX_TXBUFSZ, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1 - }, - .callback = uath_bulk_tx_callback, - .timeout = UATH_DATA_TIMEOUT - } -}; - -static struct ieee80211vap *uath_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void uath_vap_delete(struct ieee80211vap *); -static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [], - int, int); -static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd [], - int); -static int uath_host_available(struct uath_softc *); -static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *); -static int uath_get_devcap(struct uath_softc *); -static struct uath_cmd * - uath_get_cmdbuf(struct uath_softc *); -static int uath_cmd_read(struct uath_softc *, uint32_t, const void *, - int, void *, int, int); -static int uath_cmd_write(struct uath_softc *, uint32_t, const void *, - int, int); -static void uath_stat(void *); -#ifdef UATH_DEBUG -static void uath_dump_cmd(const uint8_t *, int, char); -static const char * - uath_codename(int); -#endif -static int uath_get_devstatus(struct uath_softc *, - uint8_t macaddr[IEEE80211_ADDR_LEN]); -static int uath_get_status(struct uath_softc *, uint32_t, void *, int); -static int uath_alloc_rx_data_list(struct uath_softc *); -static int uath_alloc_tx_data_list(struct uath_softc *); -static void uath_free_rx_data_list(struct uath_softc *); -static void uath_free_tx_data_list(struct uath_softc *); -static int uath_init_locked(void *); -static void uath_init(void *); -static void uath_stop_locked(struct ifnet *); -static void uath_stop(struct ifnet *); -static int uath_ioctl(struct ifnet *, u_long, caddr_t); -static void uath_start(struct ifnet *); -static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void uath_scan_start(struct ieee80211com *); -static void uath_scan_end(struct ieee80211com *); -static void uath_set_channel(struct ieee80211com *); -static void uath_update_mcast(struct ieee80211com *); -static void uath_update_promisc(struct ieee80211com *); -static int uath_config(struct uath_softc *, uint32_t, uint32_t); -static int uath_config_multi(struct uath_softc *, uint32_t, const void *, - int); -static int uath_switch_channel(struct uath_softc *, - struct ieee80211_channel *); -static int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t); -static void uath_watchdog(void *); -static void uath_abort_xfers(struct uath_softc *); -static int uath_dataflush(struct uath_softc *); -static int uath_cmdflush(struct uath_softc *); -static int uath_flush(struct uath_softc *); -static int uath_set_ledstate(struct uath_softc *, int); -static int uath_set_chan(struct uath_softc *, struct ieee80211_channel *); -static int uath_reset_tx_queues(struct uath_softc *); -static int uath_wme_init(struct uath_softc *); -static struct uath_data * - uath_getbuf(struct uath_softc *); -static int uath_newstate(struct ieee80211vap *, enum ieee80211_state, - int); -static int uath_set_key(struct uath_softc *, - const struct ieee80211_key *, int); -static int uath_set_keys(struct uath_softc *, struct ieee80211vap *); -static void uath_sysctl_node(struct uath_softc *); - -static int -uath_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != UATH_CONFIG_INDEX) - return (ENXIO); - if (uaa->info.bIfaceIndex != UATH_IFACE_INDEX) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(uath_devs, sizeof(uath_devs), uaa)); -} - -static int -uath_attach(device_t dev) -{ - struct uath_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct ieee80211com *ic; - struct ifnet *ifp; - uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */ - usb_error_t error; - uint8_t macaddr[IEEE80211_ADDR_LEN]; - - sc->sc_dev = dev; - sc->sc_udev = uaa->device; -#ifdef UATH_DEBUG - sc->sc_debug = uath_debug; -#endif - device_set_usb_desc(dev); - - /* - * Only post-firmware devices here. - */ - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF); - callout_init(&sc->stat_ch, 0); - callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); - - /* - * Allocate xfers for firmware commands. - */ - error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT, - UATH_MAX_CMDSZ); - if (error != 0) { - device_printf(sc->sc_dev, - "could not allocate Tx command list\n"); - goto fail; - } - - error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, - uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx); - if (error) { - device_printf(dev, "could not allocate USB transfers, " - "err=%s\n", usbd_errstr(error)); - goto fail1; - } - - /* - * We're now ready to send+receive firmware commands. - */ - UATH_LOCK(sc); - error = uath_host_available(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not initialize adapter\n"); - goto fail3; - } - error = uath_get_devcap(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "could not get device capabilities\n"); - goto fail3; - } - UATH_UNLOCK(sc); - - /* Create device sysctl node. */ - uath_sysctl_node(sc); - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not allocate ifnet\n"); - error = ENXIO; - goto fail2; - } - - UATH_LOCK(sc); - error = uath_get_devstatus(sc, macaddr); - if (error != 0) { - device_printf(sc->sc_dev, "could not get device status\n"); - goto fail4; - } - - /* - * Allocate xfers for Rx/Tx data pipes. - */ - error = uath_alloc_rx_data_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Rx data list\n"); - goto fail4; - } - error = uath_alloc_tx_data_list(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate Tx data list\n"); - goto fail4; - } - UATH_UNLOCK(sc); - - ifp->if_softc = sc; - if_initname(ifp, "uath", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = uath_init; - ifp->if_ioctl = uath_ioctl; - ifp->if_start = uath_start; - /* XXX UATH_TX_DATA_LIST_COUNT */ - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(dev); - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA | /* station mode */ - IEEE80211_C_MONITOR | /* monitor mode supported */ - IEEE80211_C_TXPMGT | /* tx power management */ - IEEE80211_C_SHPREAMBLE | /* short preamble supported */ - IEEE80211_C_SHSLOT | /* short slot time supported */ - IEEE80211_C_WPA | /* 802.11i */ - IEEE80211_C_BGSCAN | /* capable of bg scanning */ - IEEE80211_C_TXFRAG; /* handle tx frags */ - - /* put a regulatory domain to reveal informations. */ - uath_regdomain = sc->sc_devcap.regDomain; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - if ((sc->sc_devcap.analog5GhzRevision & 0xf0) == 0x30) - setbit(&bands, IEEE80211_MODE_11A); - /* XXX turbo */ - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic, macaddr); - ic->ic_raw_xmit = uath_raw_xmit; - ic->ic_scan_start = uath_scan_start; - ic->ic_scan_end = uath_scan_end; - ic->ic_set_channel = uath_set_channel; - ic->ic_vap_create = uath_vap_create; - ic->ic_vap_delete = uath_vap_delete; - ic->ic_update_mcast = uath_update_mcast; - ic->ic_update_promisc = uath_update_promisc; - - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - UATH_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - UATH_RX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - return (0); - -fail4: if_free(ifp); -fail3: UATH_UNLOCK(sc); -fail2: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); -fail1: uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT); -fail: - return (error); -} - -static int -uath_detach(device_t dev) -{ - struct uath_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - if (!device_is_attached(dev)) - return (0); - - UATH_LOCK(sc); - sc->sc_flags |= UATH_FLAG_INVALID; - UATH_UNLOCK(sc); - - ieee80211_ifdetach(ic); - uath_stop(ifp); - - callout_drain(&sc->stat_ch); - callout_drain(&sc->watchdog_ch); - - usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS); - - /* free buffers */ - UATH_LOCK(sc); - uath_free_rx_data_list(sc); - uath_free_tx_data_list(sc); - uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT); - UATH_UNLOCK(sc); - - if_free(ifp); - mtx_destroy(&sc->sc_mtx); - return (0); -} - -static void -uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd) -{ - int i; - - for (i = 0; i < ncmd; i++) - if (cmds[i].buf != NULL) - free(cmds[i].buf, M_USBDEV); -} - -static int -uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], - int ncmd, int maxsz) -{ - int i, error; - - STAILQ_INIT(&sc->sc_cmd_active); - STAILQ_INIT(&sc->sc_cmd_pending); - STAILQ_INIT(&sc->sc_cmd_waiting); - STAILQ_INIT(&sc->sc_cmd_inactive); - - for (i = 0; i < ncmd; i++) { - struct uath_cmd *cmd = &cmds[i]; - - cmd->sc = sc; /* backpointer for callbacks */ - cmd->msgid = i; - cmd->buf = malloc(maxsz, M_USBDEV, M_WAITOK); - if (cmd->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate xfer buffer\n"); - error = ENOMEM; - goto fail; - } - STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next); - UATH_STAT_INC(sc, st_cmd_inactive); - } - return (0); - -fail: uath_free_cmd_list(sc, cmds, ncmd); - return (error); -} - -static int -uath_host_available(struct uath_softc *sc) -{ - struct uath_cmd_host_available setup; - - UATH_ASSERT_LOCKED(sc); - - /* inform target the host is available */ - setup.sw_ver_major = htobe32(ATH_SW_VER_MAJOR); - setup.sw_ver_minor = htobe32(ATH_SW_VER_MINOR); - setup.sw_ver_patch = htobe32(ATH_SW_VER_PATCH); - setup.sw_ver_build = htobe32(ATH_SW_VER_BUILD); - return uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE, - &setup, sizeof setup, NULL, 0, 0); -} - -#ifdef UATH_DEBUG -static void -uath_dump_cmd(const uint8_t *buf, int len, char prefix) -{ - const char *sep = ""; - int i; - - for (i = 0; i < len; i++) { - if ((i % 16) == 0) { - printf("%s%c ", sep, prefix); - sep = "\n"; - } - else if ((i % 4) == 0) - printf(" "); - printf("%02x", buf[i]); - } - printf("\n"); -} - -static const char * -uath_codename(int code) -{ - static const char *names[] = { - "0x00", - "HOST_AVAILABLE", - "BIND", - "TARGET_RESET", - "TARGET_GET_CAPABILITY", - "TARGET_SET_CONFIG", - "TARGET_GET_STATUS", - "TARGET_GET_STATS", - "TARGET_START", - "TARGET_STOP", - "TARGET_ENABLE", - "TARGET_DISABLE", - "CREATE_CONNECTION", - "UPDATE_CONNECT_ATTR", - "DELETE_CONNECT", - "SEND", - "FLUSH", - "STATS_UPDATE", - "BMISS", - "DEVICE_AVAIL", - "SEND_COMPLETE", - "DATA_AVAIL", - "SET_PWR_MODE", - "BMISS_ACK", - "SET_LED_STEADY", - "SET_LED_BLINK", - "SETUP_BEACON_DESC", - "BEACON_INIT", - "RESET_KEY_CACHE", - "RESET_KEY_CACHE_ENTRY", - "SET_KEY_CACHE_ENTRY", - "SET_DECOMP_MASK", - "SET_REGULATORY_DOMAIN", - "SET_LED_STATE", - "WRITE_ASSOCID", - "SET_STA_BEACON_TIMERS", - "GET_TSF", - "RESET_TSF", - "SET_ADHOC_MODE", - "SET_BASIC_RATE", - "MIB_CONTROL", - "GET_CHANNEL_DATA", - "GET_CUR_RSSI", - "SET_ANTENNA_SWITCH", - "0x2c", "0x2d", "0x2e", - "USE_SHORT_SLOT_TIME", - "SET_POWER_MODE", - "SETUP_PSPOLL_DESC", - "SET_RX_MULTICAST_FILTER", - "RX_FILTER", - "PER_CALIBRATION", - "RESET", - "DISABLE", - "PHY_DISABLE", - "SET_TX_POWER_LIMIT", - "SET_TX_QUEUE_PARAMS", - "SETUP_TX_QUEUE", - "RELEASE_TX_QUEUE", - }; - static char buf[8]; - - if (code < nitems(names)) - return names[code]; - if (code == WDCMSG_SET_DEFAULT_KEY) - return "SET_DEFAULT_KEY"; - snprintf(buf, sizeof(buf), "0x%02x", code); - return buf; -} -#endif - -/* - * Low-level function to send read or write commands to the firmware. - */ -static int -uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen, - void *odata, int olen, int flags) -{ - struct uath_cmd_hdr *hdr; - struct uath_cmd *cmd; - int error; - - UATH_ASSERT_LOCKED(sc); - - /* grab a xfer */ - cmd = uath_get_cmdbuf(sc); - if (cmd == NULL) { - device_printf(sc->sc_dev, "%s: empty inactive queue\n", - __func__); - return (ENOBUFS); - } - cmd->flags = flags; - /* always bulk-out a multiple of 4 bytes */ - cmd->buflen = roundup2(sizeof(struct uath_cmd_hdr) + ilen, 4); - - hdr = (struct uath_cmd_hdr *)cmd->buf; - memset(hdr, 0, sizeof(struct uath_cmd_hdr)); - hdr->len = htobe32(cmd->buflen); - hdr->code = htobe32(code); - hdr->msgid = cmd->msgid; /* don't care about endianness */ - hdr->magic = htobe32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0); - memcpy((uint8_t *)(hdr + 1), idata, ilen); - -#ifdef UATH_DEBUG - if (sc->sc_debug & UATH_DEBUG_CMDS) { - printf("%s: send %s [flags 0x%x] olen %d\n", - __func__, uath_codename(code), cmd->flags, olen); - if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP) - uath_dump_cmd(cmd->buf, cmd->buflen, '+'); - } -#endif - cmd->odata = odata; - KASSERT(odata == NULL || - olen < UATH_MAX_CMDSZ - sizeof(*hdr) + sizeof(uint32_t), - ("odata %p olen %u", odata, olen)); - cmd->olen = olen; - - STAILQ_INSERT_TAIL(&sc->sc_cmd_pending, cmd, next); - UATH_STAT_INC(sc, st_cmd_pending); - usbd_transfer_start(sc->sc_xfer[UATH_INTR_TX]); - - if (cmd->flags & UATH_CMD_FLAG_READ) { - usbd_transfer_start(sc->sc_xfer[UATH_INTR_RX]); - - /* wait at most two seconds for command reply */ - error = mtx_sleep(cmd, &sc->sc_mtx, 0, "uathcmd", 2 * hz); - cmd->odata = NULL; /* in case reply comes too late */ - if (error != 0) { - device_printf(sc->sc_dev, "timeout waiting for reply " - "to cmd 0x%x (%u)\n", code, code); - } else if (cmd->olen != olen) { - device_printf(sc->sc_dev, "unexpected reply data count " - "to cmd 0x%x (%u), got %u, expected %u\n", - code, code, cmd->olen, olen); - error = EINVAL; - } - return (error); - } - return (0); -} - -static int -uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata, - int ilen, void *odata, int olen, int flags) -{ - - flags |= UATH_CMD_FLAG_READ; - return uath_cmdsend(sc, code, idata, ilen, odata, olen, flags); -} - -static int -uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len, - int flags) -{ - - flags &= ~UATH_CMD_FLAG_READ; - return uath_cmdsend(sc, code, data, len, NULL, 0, flags); -} - -static struct uath_cmd * -uath_get_cmdbuf(struct uath_softc *sc) -{ - struct uath_cmd *uc; - - UATH_ASSERT_LOCKED(sc); - - uc = STAILQ_FIRST(&sc->sc_cmd_inactive); - if (uc != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_cmd_inactive, next); - UATH_STAT_DEC(sc, st_cmd_inactive); - } else - uc = NULL; - if (uc == NULL) - DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__, - "out of command xmit buffers"); - return (uc); -} - -/* - * This function is called periodically (every second) when associated to - * query device statistics. - */ -static void -uath_stat(void *arg) -{ - struct uath_softc *sc = arg; - int error; - - UATH_LOCK(sc); - /* - * Send request for statistics asynchronously. The timer will be - * restarted when we'll get the stats notification. - */ - error = uath_cmd_write(sc, WDCMSG_TARGET_GET_STATS, NULL, 0, - UATH_CMD_FLAG_ASYNC); - if (error != 0) { - device_printf(sc->sc_dev, - "could not query stats, error %d\n", error); - } - UATH_UNLOCK(sc); -} - -static int -uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val) -{ - int error; - - cap = htobe32(cap); - error = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY, - &cap, sizeof cap, val, sizeof(uint32_t), UATH_CMD_FLAG_MAGIC); - if (error != 0) { - device_printf(sc->sc_dev, "could not read capability %u\n", - be32toh(cap)); - return (error); - } - *val = be32toh(*val); - return (error); -} - -static int -uath_get_devcap(struct uath_softc *sc) -{ -#define GETCAP(x, v) do { \ - error = uath_get_capability(sc, x, &v); \ - if (error != 0) \ - return (error); \ - DPRINTF(sc, UATH_DEBUG_DEVCAP, \ - "%s: %s=0x%08x\n", __func__, #x, v); \ -} while (0) - struct uath_devcap *cap = &sc->sc_devcap; - int error; - - /* collect device capabilities */ - GETCAP(CAP_TARGET_VERSION, cap->targetVersion); - GETCAP(CAP_TARGET_REVISION, cap->targetRevision); - GETCAP(CAP_MAC_VERSION, cap->macVersion); - GETCAP(CAP_MAC_REVISION, cap->macRevision); - GETCAP(CAP_PHY_REVISION, cap->phyRevision); - GETCAP(CAP_ANALOG_5GHz_REVISION, cap->analog5GhzRevision); - GETCAP(CAP_ANALOG_2GHz_REVISION, cap->analog2GhzRevision); - - GETCAP(CAP_REG_DOMAIN, cap->regDomain); - GETCAP(CAP_REG_CAP_BITS, cap->regCapBits); -#if 0 - /* NB: not supported in rev 1.5 */ - GETCAP(CAP_COUNTRY_CODE, cap->countryCode); -#endif - GETCAP(CAP_WIRELESS_MODES, cap->wirelessModes); - GETCAP(CAP_CHAN_SPREAD_SUPPORT, cap->chanSpreadSupport); - GETCAP(CAP_COMPRESS_SUPPORT, cap->compressSupport); - GETCAP(CAP_BURST_SUPPORT, cap->burstSupport); - GETCAP(CAP_FAST_FRAMES_SUPPORT, cap->fastFramesSupport); - GETCAP(CAP_CHAP_TUNING_SUPPORT, cap->chapTuningSupport); - GETCAP(CAP_TURBOG_SUPPORT, cap->turboGSupport); - GETCAP(CAP_TURBO_PRIME_SUPPORT, cap->turboPrimeSupport); - GETCAP(CAP_DEVICE_TYPE, cap->deviceType); - GETCAP(CAP_WME_SUPPORT, cap->wmeSupport); - GETCAP(CAP_TOTAL_QUEUES, cap->numTxQueues); - GETCAP(CAP_CONNECTION_ID_MAX, cap->connectionIdMax); - - GETCAP(CAP_LOW_5GHZ_CHAN, cap->low5GhzChan); - GETCAP(CAP_HIGH_5GHZ_CHAN, cap->high5GhzChan); - GETCAP(CAP_LOW_2GHZ_CHAN, cap->low2GhzChan); - GETCAP(CAP_HIGH_2GHZ_CHAN, cap->high2GhzChan); - GETCAP(CAP_TWICE_ANTENNAGAIN_5G, cap->twiceAntennaGain5G); - GETCAP(CAP_TWICE_ANTENNAGAIN_2G, cap->twiceAntennaGain2G); - - GETCAP(CAP_CIPHER_AES_CCM, cap->supportCipherAES_CCM); - GETCAP(CAP_CIPHER_TKIP, cap->supportCipherTKIP); - GETCAP(CAP_MIC_TKIP, cap->supportMicTKIP); - - cap->supportCipherWEP = 1; /* NB: always available */ - - return (0); -} - -static int -uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) -{ - int error; - - /* retrieve MAC address */ - error = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN); - if (error != 0) { - device_printf(sc->sc_dev, "could not read MAC address\n"); - return (error); - } - - error = uath_get_status(sc, ST_SERIAL_NUMBER, - &sc->sc_serial[0], sizeof(sc->sc_serial)); - if (error != 0) { - device_printf(sc->sc_dev, - "could not read device serial number\n"); - return (error); - } - return (0); -} - -static int -uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen) -{ - int error; - - which = htobe32(which); - error = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS, - &which, sizeof(which), odata, olen, UATH_CMD_FLAG_MAGIC); - if (error != 0) - device_printf(sc->sc_dev, - "could not read EEPROM offset 0x%02x\n", be32toh(which)); - return (error); -} - -static void -uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata, - int fillmbuf) -{ - int i; - - for (i = 0; i < ndata; i++) { - struct uath_data *dp = &data[i]; - - if (fillmbuf == 1) { - if (dp->m != NULL) { - m_freem(dp->m); - dp->m = NULL; - dp->buf = NULL; - } - } else { - if (dp->buf != NULL) { - free(dp->buf, M_USBDEV); - dp->buf = NULL; - } - } -#ifdef UATH_DEBUG - if (dp->ni != NULL) - device_printf(sc->sc_dev, "Node isn't NULL\n"); -#endif - } -} - -static int -uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[], - int ndata, int maxsz, int fillmbuf) -{ - int i, error; - - for (i = 0; i < ndata; i++) { - struct uath_data *dp = &data[i]; - - dp->sc = sc; - if (fillmbuf) { - /* XXX check maxsz */ - dp->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (dp->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - dp->buf = mtod(dp->m, uint8_t *); - } else { - dp->m = NULL; - dp->buf = malloc(maxsz, M_USBDEV, M_WAITOK); - if (dp->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate buffer\n"); - error = ENOMEM; - goto fail; - } - } - dp->ni = NULL; - } - - return (0); - -fail: uath_free_data_list(sc, data, ndata, fillmbuf); - return (error); -} - -static int -uath_alloc_rx_data_list(struct uath_softc *sc) -{ - int error, i; - - /* XXX is it enough to store the RX packet with MCLBYTES bytes? */ - error = uath_alloc_data_list(sc, - sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES, - 1 /* setup mbufs */); - if (error != 0) - return (error); - - STAILQ_INIT(&sc->sc_rx_active); - STAILQ_INIT(&sc->sc_rx_inactive); - - for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) { - STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], - next); - UATH_STAT_INC(sc, st_rx_inactive); - } - - return (0); -} - -static int -uath_alloc_tx_data_list(struct uath_softc *sc) -{ - int error, i; - - error = uath_alloc_data_list(sc, - sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ, - 0 /* no mbufs */); - if (error != 0) - return (error); - - STAILQ_INIT(&sc->sc_tx_active); - STAILQ_INIT(&sc->sc_tx_inactive); - STAILQ_INIT(&sc->sc_tx_pending); - - for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) { - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], - next); - UATH_STAT_INC(sc, st_tx_inactive); - } - - return (0); -} - -static void -uath_free_rx_data_list(struct uath_softc *sc) -{ - - STAILQ_INIT(&sc->sc_rx_active); - STAILQ_INIT(&sc->sc_rx_inactive); - - uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT, - 1 /* free mbufs */); -} - -static void -uath_free_tx_data_list(struct uath_softc *sc) -{ - - STAILQ_INIT(&sc->sc_tx_active); - STAILQ_INIT(&sc->sc_tx_inactive); - STAILQ_INIT(&sc->sc_tx_pending); - - uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT, - 0 /* no mbufs */); -} - -static struct ieee80211vap * -uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct uath_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return (NULL); - uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap), - M_80211_VAP, M_WAITOK | M_ZERO); - if (uvp == NULL) - return (NULL); - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = uath_newstate; - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return (vap); -} - -static void -uath_vap_delete(struct ieee80211vap *vap) -{ - struct uath_vap *uvp = UATH_VAP(vap); - - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static int -uath_init_locked(void *arg) -{ - struct uath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t val; - int error; - - UATH_ASSERT_LOCKED(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - uath_stop_locked(ifp); - - /* reset variables */ - sc->sc_intrx_nextnum = sc->sc_msgid = 0; - - val = htobe32(0); - uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0); - - /* set MAC address */ - uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN); - - /* XXX honor net80211 state */ - uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001); - uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001); - uath_config(sc, CFG_ABOLT, 0x0000003f); - uath_config(sc, CFG_WME_ENABLED, 0x00000001); - - uath_config(sc, CFG_SERVICE_TYPE, 1); - uath_config(sc, CFG_TP_SCALE, 0x00000000); - uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c); - uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c); - uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000); - uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000); - uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003); - uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000); - uath_config(sc, CFG_MODE_CTS, 0x00000002); - - error = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0, - &val, sizeof(val), UATH_CMD_FLAG_MAGIC); - if (error) { - device_printf(sc->sc_dev, - "could not start target, error %d\n", error); - goto fail; - } - DPRINTF(sc, UATH_DEBUG_INIT, "%s returns handle: 0x%x\n", - uath_codename(WDCMSG_TARGET_START), be32toh(val)); - - /* set default channel */ - error = uath_switch_channel(sc, ic->ic_curchan); - if (error) { - device_printf(sc->sc_dev, - "could not switch channel, error %d\n", error); - goto fail; - } - - val = htobe32(TARGET_DEVICE_AWAKE); - uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof val, 0); - /* XXX? check */ - uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0); - - usbd_transfer_start(sc->sc_xfer[UATH_BULK_RX]); - /* enable Rx */ - uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT); - uath_set_rxfilter(sc, - UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | - UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON, - UATH_FILTER_OP_SET); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - sc->sc_flags |= UATH_FLAG_INITDONE; - - callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); - - return (0); - -fail: - uath_stop_locked(ifp); - return (error); -} - -static void -uath_init(void *arg) -{ - struct uath_softc *sc = arg; - - UATH_LOCK(sc); - (void)uath_init_locked(sc); - UATH_UNLOCK(sc); -} - -static void -uath_stop_locked(struct ifnet *ifp) -{ - struct uath_softc *sc = ifp->if_softc; - - UATH_ASSERT_LOCKED(sc); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - sc->sc_flags &= ~UATH_FLAG_INITDONE; - - callout_stop(&sc->stat_ch); - callout_stop(&sc->watchdog_ch); - sc->sc_tx_timer = 0; - /* abort pending transmits */ - uath_abort_xfers(sc); - /* flush data & control requests into the target */ - (void)uath_flush(sc); - /* set a LED status to the disconnected. */ - uath_set_ledstate(sc, 0); - /* stop the target */ - uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0); -} - -static void -uath_stop(struct ifnet *ifp) -{ - struct uath_softc *sc = ifp->if_softc; - - UATH_LOCK(sc); - uath_stop_locked(ifp); - UATH_UNLOCK(sc); -} - -static int -uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val) -{ - struct uath_write_mac write; - int error; - - write.reg = htobe32(reg); - write.len = htobe32(0); /* 0 = single write */ - *(uint32_t *)write.data = htobe32(val); - - error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write, - 3 * sizeof (uint32_t), 0); - if (error != 0) { - device_printf(sc->sc_dev, "could not write register 0x%02x\n", - reg); - } - return (error); -} - -static int -uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data, - int len) -{ - struct uath_write_mac write; - int error; - - write.reg = htobe32(reg); - write.len = htobe32(len); - bcopy(data, write.data, len); - - /* properly handle the case where len is zero (reset) */ - error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write, - (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "could not write %d bytes to register 0x%02x\n", len, reg); - } - return (error); -} - -static int -uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c) -{ - int error; - - UATH_ASSERT_LOCKED(sc); - - /* set radio frequency */ - error = uath_set_chan(sc, c); - if (error) { - device_printf(sc->sc_dev, - "could not set channel, error %d\n", error); - goto failed; - } - /* reset Tx rings */ - error = uath_reset_tx_queues(sc); - if (error) { - device_printf(sc->sc_dev, - "could not reset Tx queues, error %d\n", error); - goto failed; - } - /* set Tx rings WME properties */ - error = uath_wme_init(sc); - if (error) { - device_printf(sc->sc_dev, - "could not init Tx queues, error %d\n", error); - goto failed; - } - error = uath_set_ledstate(sc, 0); - if (error) { - device_printf(sc->sc_dev, - "could not set led state, error %d\n", error); - goto failed; - } - error = uath_flush(sc); - if (error) { - device_printf(sc->sc_dev, - "could not flush pipes, error %d\n", error); - goto failed; - } -failed: - return (error); -} - -static int -uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op) -{ - struct uath_cmd_rx_filter rxfilter; - - rxfilter.bits = htobe32(bits); - rxfilter.op = htobe32(op); - - DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, - "setting Rx filter=0x%x flags=0x%x\n", bits, op); - return uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter, - sizeof rxfilter, 0); -} - -static void -uath_watchdog(void *arg) -{ - struct uath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - /*uath_init(ifp); XXX needs a process context! */ - ifp->if_oerrors++; - return; - } - callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); - } -} - -static void -uath_abort_xfers(struct uath_softc *sc) -{ - int i; - - UATH_ASSERT_LOCKED(sc); - /* abort any pending transfers */ - for (i = 0; i < UATH_N_XFERS; i++) - usbd_transfer_stop(sc->sc_xfer[i]); -} - -static int -uath_flush(struct uath_softc *sc) -{ - int error; - - error = uath_dataflush(sc); - if (error != 0) - goto failed; - - error = uath_cmdflush(sc); - if (error != 0) - goto failed; - -failed: - return (error); -} - -static int -uath_cmdflush(struct uath_softc *sc) -{ - - return uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0); -} - -static int -uath_dataflush(struct uath_softc *sc) -{ - struct uath_data *data; - struct uath_chunk *chunk; - struct uath_tx_desc *desc; - - UATH_ASSERT_LOCKED(sc); - - data = uath_getbuf(sc); - if (data == NULL) - return (ENOBUFS); - data->buflen = sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc); - data->m = NULL; - data->ni = NULL; - chunk = (struct uath_chunk *)data->buf; - desc = (struct uath_tx_desc *)(chunk + 1); - - /* one chunk only */ - chunk->seqnum = 0; - chunk->flags = UATH_CFLAGS_FINAL; - chunk->length = htobe16(sizeof (struct uath_tx_desc)); - - memset(desc, 0, sizeof(struct uath_tx_desc)); - desc->msglen = htobe32(sizeof(struct uath_tx_desc)); - desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */ - desc->type = htobe32(WDCMSG_FLUSH); - desc->txqid = htobe32(0); - desc->connid = htobe32(0); - desc->flags = htobe32(0); - -#ifdef UATH_DEBUG - if (sc->sc_debug & UATH_DEBUG_CMDS) { - DPRINTF(sc, UATH_DEBUG_RESET, "send flush ix %d\n", - desc->msgid); - if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP) - uath_dump_cmd(data->buf, data->buflen, '+'); - } -#endif - - STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); - UATH_STAT_INC(sc, st_tx_pending); - sc->sc_tx_timer = 5; - usbd_transfer_start(sc->sc_xfer[UATH_BULK_TX]); - - return (0); -} - -static struct uath_data * -_uath_getbuf(struct uath_softc *sc) -{ - struct uath_data *bf; - - bf = STAILQ_FIRST(&sc->sc_tx_inactive); - if (bf != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next); - UATH_STAT_DEC(sc, st_tx_inactive); - } else - bf = NULL; - if (bf == NULL) - DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__, - "out of xmit buffers"); - return (bf); -} - -static struct uath_data * -uath_getbuf(struct uath_softc *sc) -{ - struct uath_data *bf; - - UATH_ASSERT_LOCKED(sc); - - bf = _uath_getbuf(sc); - if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - } - return (bf); -} - -static int -uath_set_ledstate(struct uath_softc *sc, int connected) -{ - - DPRINTF(sc, UATH_DEBUG_LED, - "set led state %sconnected\n", connected ? "" : "!"); - connected = htobe32(connected); - return uath_cmd_write(sc, WDCMSG_SET_LED_STATE, - &connected, sizeof connected, 0); -} - -static int -uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c) -{ -#ifdef UATH_DEBUG - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; -#endif - struct uath_cmd_reset reset; - - memset(&reset, 0, sizeof(reset)); - if (IEEE80211_IS_CHAN_2GHZ(c)) - reset.flags |= htobe32(UATH_CHAN_2GHZ); - if (IEEE80211_IS_CHAN_5GHZ(c)) - reset.flags |= htobe32(UATH_CHAN_5GHZ); - /* NB: 11g =>'s 11b so don't specify both OFDM and CCK */ - if (IEEE80211_IS_CHAN_OFDM(c)) - reset.flags |= htobe32(UATH_CHAN_OFDM); - else if (IEEE80211_IS_CHAN_CCK(c)) - reset.flags |= htobe32(UATH_CHAN_CCK); - /* turbo can be used in either 2GHz or 5GHz */ - if (c->ic_flags & IEEE80211_CHAN_TURBO) - reset.flags |= htobe32(UATH_CHAN_TURBO); - reset.freq = htobe32(c->ic_freq); - reset.maxrdpower = htobe32(50); /* XXX */ - reset.channelchange = htobe32(1); - reset.keeprccontent = htobe32(0); - - DPRINTF(sc, UATH_DEBUG_CHANNEL, "set channel %d, flags 0x%x freq %u\n", - ieee80211_chan2ieee(ic, c), - be32toh(reset.flags), be32toh(reset.freq)); - return uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof reset, 0); -} - -static int -uath_reset_tx_queues(struct uath_softc *sc) -{ - int ac, error; - - DPRINTF(sc, UATH_DEBUG_RESET, "%s: reset Tx queues\n", __func__); - for (ac = 0; ac < 4; ac++) { - const uint32_t qid = htobe32(ac); - - error = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid, - sizeof qid, 0); - if (error != 0) - break; - } - return (error); -} - -static int -uath_wme_init(struct uath_softc *sc) -{ - /* XXX get from net80211 */ - static const struct uath_wme_settings uath_wme_11g[4] = { - { 7, 4, 10, 0, 0 }, /* Background */ - { 3, 4, 10, 0, 0 }, /* Best-Effort */ - { 3, 3, 4, 26, 0 }, /* Video */ - { 2, 2, 3, 47, 0 } /* Voice */ - }; - struct uath_cmd_txq_setup qinfo; - int ac, error; - - DPRINTF(sc, UATH_DEBUG_WME, "%s: setup Tx queues\n", __func__); - for (ac = 0; ac < 4; ac++) { - qinfo.qid = htobe32(ac); - qinfo.len = htobe32(sizeof(qinfo.attr)); - qinfo.attr.priority = htobe32(ac); /* XXX */ - qinfo.attr.aifs = htobe32(uath_wme_11g[ac].aifsn); - qinfo.attr.logcwmin = htobe32(uath_wme_11g[ac].logcwmin); - qinfo.attr.logcwmax = htobe32(uath_wme_11g[ac].logcwmax); - qinfo.attr.bursttime = htobe32(UATH_TXOP_TO_US( - uath_wme_11g[ac].txop)); - qinfo.attr.mode = htobe32(uath_wme_11g[ac].acm);/*XXX? */ - qinfo.attr.qflags = htobe32(1); /* XXX? */ - - error = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo, - sizeof qinfo, 0); - if (error != 0) - break; - } - return (error); -} - -static int -uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - uath_init(ifp->if_softc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - uath_stop(ifp); - } - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - - return (error); -} - -static int -uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, - struct uath_data *data) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct uath_chunk *chunk; - struct uath_tx_desc *desc; - const struct ieee80211_frame *wh; - struct ieee80211_key *k; - int framelen, msglen; - - UATH_ASSERT_LOCKED(sc); - - data->ni = ni; - data->m = m0; - chunk = (struct uath_chunk *)data->buf; - desc = (struct uath_tx_desc *)(chunk + 1); - - if (ieee80211_radiotap_active_vap(vap)) { - struct uath_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - if (m0->m_flags & M_FRAG) - tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG; - - ieee80211_radiotap_tx(vap, m0); - } - - wh = mtod(m0, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return (ENOBUFS); - } - - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1)); - - framelen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; - msglen = framelen + sizeof (struct uath_tx_desc); - data->buflen = msglen + sizeof (struct uath_chunk); - - /* one chunk only for now */ - chunk->seqnum = sc->sc_seqnum++; - chunk->flags = (m0->m_flags & M_FRAG) ? 0 : UATH_CFLAGS_FINAL; - if (m0->m_flags & M_LASTFRAG) - chunk->flags |= UATH_CFLAGS_FINAL; - chunk->flags = UATH_CFLAGS_FINAL; - chunk->length = htobe16(msglen); - - /* fill Tx descriptor */ - desc->msglen = htobe32(msglen); - /* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0 */ - desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */ - desc->type = htobe32(WDCMSG_SEND); - switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { - case IEEE80211_FC0_TYPE_CTL: - case IEEE80211_FC0_TYPE_MGT: - /* NB: force all management frames to highest queue */ - if (ni->ni_flags & IEEE80211_NODE_QOS) { - /* NB: force all management frames to highest queue */ - desc->txqid = htobe32(WME_AC_VO | UATH_TXQID_MINRATE); - } else - desc->txqid = htobe32(WME_AC_BE | UATH_TXQID_MINRATE); - break; - case IEEE80211_FC0_TYPE_DATA: - /* XXX multicast frames should honor mcastrate */ - desc->txqid = htobe32(M_WME_GETAC(m0)); - break; - default: - device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n", - wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); - m_freem(m0); - return (EIO); - } - if (vap->iv_state == IEEE80211_S_AUTH || - vap->iv_state == IEEE80211_S_ASSOC || - vap->iv_state == IEEE80211_S_RUN) - desc->connid = htobe32(UATH_ID_BSS); - else - desc->connid = htobe32(UATH_ID_INVALID); - desc->flags = htobe32(0 /* no UATH_TX_NOTIFY */); - desc->buflen = htobe32(m0->m_pkthdr.len); - -#ifdef UATH_DEBUG - DPRINTF(sc, UATH_DEBUG_XMIT, - "send frame ix %u framelen %d msglen %d connid 0x%x txqid 0x%x\n", - desc->msgid, framelen, msglen, be32toh(desc->connid), - be32toh(desc->txqid)); - if (sc->sc_debug & UATH_DEBUG_XMIT_DUMP) - uath_dump_cmd(data->buf, data->buflen, '+'); -#endif - - STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); - UATH_STAT_INC(sc, st_tx_pending); - usbd_transfer_start(sc->sc_xfer[UATH_BULK_TX]); - - return (0); -} - -/* - * Cleanup driver resources when we run out of buffers while processing - * fragments; return the tx buffers allocated and drop node references. - */ -static void -uath_txfrag_cleanup(struct uath_softc *sc, - uath_datahead *frags, struct ieee80211_node *ni) -{ - struct uath_data *bf, *next; - - UATH_ASSERT_LOCKED(sc); - - STAILQ_FOREACH_SAFE(bf, frags, next, next) { - /* NB: bf assumed clean */ - STAILQ_REMOVE_HEAD(frags, next); - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - UATH_STAT_INC(sc, st_tx_inactive); - ieee80211_node_decref(ni); - } -} - -/* - * Setup xmit of a fragmented frame. Allocate a buffer for each frag and bump - * the node reference count to reflect the held reference to be setup by - * uath_tx_start. - */ -static int -uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags, - struct mbuf *m0, struct ieee80211_node *ni) -{ - struct mbuf *m; - struct uath_data *bf; - - UATH_ASSERT_LOCKED(sc); - for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) { - bf = uath_getbuf(sc); - if (bf == NULL) { /* out of buffers, cleanup */ - uath_txfrag_cleanup(sc, frags, ni); - break; - } - ieee80211_node_incref(ni); - STAILQ_INSERT_TAIL(frags, bf, next); - } - - return !STAILQ_EMPTY(frags); -} - -/* - * Reclaim mbuf resources. For fragmented frames we need to claim each frag - * chained with m_nextpkt. - */ -static void -uath_freetx(struct mbuf *m) -{ - struct mbuf *next; - - do { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - m_freem(m); - } while ((m = next) != NULL); -} - -static void -uath_start(struct ifnet *ifp) -{ - struct uath_data *bf; - struct uath_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m, *next; - uath_datahead frags; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || - (sc->sc_flags & UATH_FLAG_INVALID)) - return; - - UATH_LOCK(sc); - for (;;) { - bf = uath_getbuf(sc); - if (bf == NULL) - break; - - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) { - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - UATH_STAT_INC(sc, st_tx_inactive); - break; - } - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - - /* - * Check for fragmentation. If this frame has been broken up - * verify we have enough buffers to send all the fragments - * so all go out or none... - */ - STAILQ_INIT(&frags); - if ((m->m_flags & M_FRAG) && - !uath_txfrag_setup(sc, &frags, m, ni)) { - DPRINTF(sc, UATH_DEBUG_XMIT, - "%s: out of txfrag buffers\n", __func__); - uath_freetx(m); - goto bad; - } - sc->sc_seqnum = 0; - nextfrag: - /* - * Pass the frame to the h/w for transmission. - * Fragmented frames have each frag chained together - * with m_nextpkt. We know there are sufficient uath_data's - * to send all the frags because of work done by - * uath_txfrag_setup. - */ - next = m->m_nextpkt; - if (uath_tx_start(sc, m, ni, bf) != 0) { - bad: - ifp->if_oerrors++; - reclaim: - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - UATH_STAT_INC(sc, st_tx_inactive); - uath_txfrag_cleanup(sc, &frags, ni); - ieee80211_free_node(ni); - continue; - } - - if (next != NULL) { - /* - * Beware of state changing between frags. - XXX check sta power-save state? - */ - if (ni->ni_vap->iv_state != IEEE80211_S_RUN) { - DPRINTF(sc, UATH_DEBUG_XMIT, - "%s: flush fragmented packet, state %s\n", - __func__, - ieee80211_state_name[ni->ni_vap->iv_state]); - uath_freetx(next); - goto reclaim; - } - m = next; - bf = STAILQ_FIRST(&frags); - KASSERT(bf != NULL, ("no buf for txfrag")); - STAILQ_REMOVE_HEAD(&frags, next); - goto nextfrag; - } - - sc->sc_tx_timer = 5; - } - UATH_UNLOCK(sc); -} - -static int -uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct uath_data *bf; - struct uath_softc *sc = ifp->if_softc; - - /* prevent management frames from being sent if we're not ready */ - if ((sc->sc_flags & UATH_FLAG_INVALID) || - !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return (ENETDOWN); - } - - UATH_LOCK(sc); - /* grab a TX buffer */ - bf = uath_getbuf(sc); - if (bf == NULL) { - ieee80211_free_node(ni); - m_freem(m); - UATH_UNLOCK(sc); - return (ENOBUFS); - } - - sc->sc_seqnum = 0; - if (uath_tx_start(sc, m, ni, bf) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - UATH_STAT_INC(sc, st_tx_inactive); - UATH_UNLOCK(sc); - return (EIO); - } - UATH_UNLOCK(sc); - - sc->sc_tx_timer = 5; - return (0); -} - -static void -uath_scan_start(struct ieee80211com *ic) -{ - /* do nothing */ -} - -static void -uath_scan_end(struct ieee80211com *ic) -{ - /* do nothing */ -} - -static void -uath_set_channel(struct ieee80211com *ic) -{ - struct ifnet *ifp = ic->ic_ifp; - struct uath_softc *sc = ifp->if_softc; - - UATH_LOCK(sc); - if ((sc->sc_flags & UATH_FLAG_INVALID) || - (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - UATH_UNLOCK(sc); - return; - } - (void)uath_switch_channel(sc, ic->ic_curchan); - UATH_UNLOCK(sc); -} - -static int -uath_set_rxmulti_filter(struct uath_softc *sc) -{ - /* XXX broken */ - return (0); -} -static void -uath_update_mcast(struct ieee80211com *ic) -{ - struct uath_softc *sc = ic->ic_softc; - - UATH_LOCK(sc); - if ((sc->sc_flags & UATH_FLAG_INVALID) || - (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - UATH_UNLOCK(sc); - return; - } - /* - * this is for avoiding the race condition when we're try to - * connect to the AP with WPA. - */ - if (sc->sc_flags & UATH_FLAG_INITDONE) - (void)uath_set_rxmulti_filter(sc); - UATH_UNLOCK(sc); -} - -static void -uath_update_promisc(struct ieee80211com *ic) -{ - struct uath_softc *sc = ic->ic_softc; - - UATH_LOCK(sc); - if ((sc->sc_flags & UATH_FLAG_INVALID) || - (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - UATH_UNLOCK(sc); - return; - } - if (sc->sc_flags & UATH_FLAG_INITDONE) { - uath_set_rxfilter(sc, - UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | - UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON | - UATH_FILTER_RX_PROM, UATH_FILTER_OP_SET); - } - UATH_UNLOCK(sc); -} - -static int -uath_create_connection(struct uath_softc *sc, uint32_t connid) -{ - const struct ieee80211_rateset *rs; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni; - struct uath_cmd_create_connection create; - - ni = ieee80211_ref_node(vap->iv_bss); - memset(&create, 0, sizeof(create)); - create.connid = htobe32(connid); - create.bssid = htobe32(0); - /* XXX packed or not? */ - create.size = htobe32(sizeof(struct uath_cmd_rateset)); - - rs = &ni->ni_rates; - create.connattr.rateset.length = rs->rs_nrates; - bcopy(rs->rs_rates, &create.connattr.rateset.set[0], - rs->rs_nrates); - - /* XXX turbo */ - if (IEEE80211_IS_CHAN_A(ni->ni_chan)) - create.connattr.wlanmode = htobe32(WLAN_MODE_11a); - else if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan)) - create.connattr.wlanmode = htobe32(WLAN_MODE_11g); - else - create.connattr.wlanmode = htobe32(WLAN_MODE_11b); - ieee80211_free_node(ni); - - return uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create, - sizeof create, 0); -} - -static int -uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs) -{ - struct uath_cmd_rates rates; - - memset(&rates, 0, sizeof(rates)); - rates.connid = htobe32(UATH_ID_BSS); /* XXX */ - rates.size = htobe32(sizeof(struct uath_cmd_rateset)); - /* XXX bounds check rs->rs_nrates */ - rates.rateset.length = rs->rs_nrates; - bcopy(rs->rs_rates, &rates.rateset.set[0], rs->rs_nrates); - - DPRINTF(sc, UATH_DEBUG_RATES, - "setting supported rates nrates=%d\n", rs->rs_nrates); - return uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE, - &rates, sizeof rates, 0); -} - -static int -uath_write_associd(struct uath_softc *sc) -{ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni; - struct uath_cmd_set_associd associd; - - ni = ieee80211_ref_node(vap->iv_bss); - memset(&associd, 0, sizeof(associd)); - associd.defaultrateix = htobe32(1); /* XXX */ - associd.associd = htobe32(ni->ni_associd); - associd.timoffset = htobe32(0x3b); /* XXX */ - IEEE80211_ADDR_COPY(associd.bssid, ni->ni_bssid); - ieee80211_free_node(ni); - return uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd, - sizeof associd, 0); -} - -static int -uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode) -{ - struct uath_cmd_ledsteady led; - - led.lednum = htobe32(lednum); - led.ledmode = htobe32(ledmode); - - DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (steady)\n", - (lednum == UATH_LED_LINK) ? "link" : "activity", - ledmode ? "on" : "off"); - return uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof led, 0); -} - -static int -uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode, - int blinkrate, int slowmode) -{ - struct uath_cmd_ledblink led; - - led.lednum = htobe32(lednum); - led.ledmode = htobe32(ledmode); - led.blinkrate = htobe32(blinkrate); - led.slowmode = htobe32(slowmode); - - DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (blink)\n", - (lednum == UATH_LED_LINK) ? "link" : "activity", - ledmode ? "on" : "off"); - return uath_cmd_write(sc, WDCMSG_SET_LED_BLINK, &led, sizeof led, 0); -} - -static int -uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - enum ieee80211_state ostate = vap->iv_state; - int error; - struct ieee80211_node *ni; - struct ieee80211com *ic = vap->iv_ic; - struct uath_softc *sc = ic->ic_ifp->if_softc; - struct uath_vap *uvp = UATH_VAP(vap); - - DPRINTF(sc, UATH_DEBUG_STATE, - "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - IEEE80211_UNLOCK(ic); - UATH_LOCK(sc); - callout_stop(&sc->stat_ch); - callout_stop(&sc->watchdog_ch); - ni = ieee80211_ref_node(vap->iv_bss); - - switch (nstate) { - case IEEE80211_S_INIT: - if (ostate == IEEE80211_S_RUN) { - /* turn link and activity LEDs off */ - uath_set_ledstate(sc, 0); - } - break; - - case IEEE80211_S_SCAN: - break; - - case IEEE80211_S_AUTH: - /* XXX good place? set RTS threshold */ - uath_config(sc, CFG_USER_RTS_THRESHOLD, vap->iv_rtsthreshold); - /* XXX bad place */ - error = uath_set_keys(sc, vap); - if (error != 0) { - device_printf(sc->sc_dev, - "could not set crypto keys, error %d\n", error); - break; - } - if (uath_switch_channel(sc, ni->ni_chan) != 0) { - device_printf(sc->sc_dev, "could not switch channel\n"); - break; - } - if (uath_create_connection(sc, UATH_ID_BSS) != 0) { - device_printf(sc->sc_dev, - "could not create connection\n"); - break; - } - break; - - case IEEE80211_S_ASSOC: - if (uath_set_rates(sc, &ni->ni_rates) != 0) { - device_printf(sc->sc_dev, - "could not set negotiated rate set\n"); - break; - } - break; - - case IEEE80211_S_RUN: - /* XXX monitor mode doesn't be tested */ - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - uath_set_ledstate(sc, 1); - break; - } - - /* - * Tx rate is controlled by firmware, report the maximum - * negotiated rate in ifconfig output. - */ - ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1]; - - if (uath_write_associd(sc) != 0) { - device_printf(sc->sc_dev, - "could not write association id\n"); - break; - } - /* turn link LED on */ - uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON); - /* make activity LED blink */ - uath_set_ledblink(sc, UATH_LED_ACTIVITY, UATH_LED_ON, 1, 2); - /* set state to associated */ - uath_set_ledstate(sc, 1); - - /* start statistics timer */ - callout_reset(&sc->stat_ch, hz, uath_stat, sc); - break; - default: - break; - } - ieee80211_free_node(ni); - UATH_UNLOCK(sc); - IEEE80211_LOCK(ic); - return (uvp->newstate(vap, nstate, arg)); -} - -static int -uath_set_key(struct uath_softc *sc, const struct ieee80211_key *wk, - int index) -{ -#if 0 - struct uath_cmd_crypto crypto; - int i; - - memset(&crypto, 0, sizeof(crypto)); - crypto.keyidx = htobe32(index); - crypto.magic1 = htobe32(1); - crypto.size = htobe32(368); - crypto.mask = htobe32(0xffff); - crypto.flags = htobe32(0x80000068); - if (index != UATH_DEFAULT_KEY) - crypto.flags |= htobe32(index << 16); - memset(crypto.magic2, 0xff, sizeof(crypto.magic2)); - - /* - * Each byte of the key must be XOR'ed with 10101010 before being - * transmitted to the firmware. - */ - for (i = 0; i < wk->wk_keylen; i++) - crypto.key[i] = wk->wk_key[i] ^ 0xaa; - - DPRINTF(sc, UATH_DEBUG_CRYPTO, - "setting crypto key index=%d len=%d\n", index, wk->wk_keylen); - return uath_cmd_write(sc, WDCMSG_SET_KEY_CACHE_ENTRY, &crypto, - sizeof crypto, 0); -#else - /* XXX support H/W cryto */ - return (0); -#endif -} - -static int -uath_set_keys(struct uath_softc *sc, struct ieee80211vap *vap) -{ - int i, error; - - error = 0; - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - const struct ieee80211_key *wk = &vap->iv_nw_keys[i]; - - if (wk->wk_flags & (IEEE80211_KEY_XMIT|IEEE80211_KEY_RECV)) { - error = uath_set_key(sc, wk, i); - if (error) - return (error); - } - } - if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) { - error = uath_set_key(sc, &vap->iv_nw_keys[vap->iv_def_txkey], - UATH_DEFAULT_KEY); - } - return (error); -} - -#define UATH_SYSCTL_STAT_ADD32(c, h, n, p, d) \ - SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) - -static void -uath_sysctl_node(struct uath_softc *sc) -{ - struct sysctl_ctx_list *ctx; - struct sysctl_oid_list *child; - struct sysctl_oid *tree; - struct uath_stat *stats; - - stats = &sc->sc_stat; - ctx = device_get_sysctl_ctx(sc->sc_dev); - child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)); - - tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, - NULL, "UATH statistics"); - child = SYSCTL_CHILDREN(tree); - UATH_SYSCTL_STAT_ADD32(ctx, child, "badchunkseqnum", - &stats->st_badchunkseqnum, "Bad chunk sequence numbers"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "invalidlen", &stats->st_invalidlen, - "Invalid length"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "multichunk", &stats->st_multichunk, - "Multi chunks"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "toobigrxpkt", - &stats->st_toobigrxpkt, "Too big rx packets"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "stopinprogress", - &stats->st_stopinprogress, "Stop in progress"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "crcerrs", &stats->st_crcerr, - "CRC errors"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "phyerr", &stats->st_phyerr, - "PHY errors"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_crcerr", - &stats->st_decrypt_crcerr, "Decryption CRC errors"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_micerr", - &stats->st_decrypt_micerr, "Decryption Misc errors"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "decomperr", &stats->st_decomperr, - "Decomp errors"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "keyerr", &stats->st_keyerr, - "Key errors"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "err", &stats->st_err, - "Unknown errors"); - - UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_active", - &stats->st_cmd_active, "Active numbers in Command queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_inactive", - &stats->st_cmd_inactive, "Inactive numbers in Command queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_pending", - &stats->st_cmd_pending, "Pending numbers in Command queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_waiting", - &stats->st_cmd_waiting, "Waiting numbers in Command queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_active", - &stats->st_rx_active, "Active numbers in RX queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_inactive", - &stats->st_rx_inactive, "Inactive numbers in RX queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_active", - &stats->st_tx_active, "Active numbers in TX queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_inactive", - &stats->st_tx_inactive, "Inactive numbers in TX queue"); - UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_pending", - &stats->st_tx_pending, "Pending numbers in TX queue"); -} - -#undef UATH_SYSCTL_STAT_ADD32 - -static void -uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd) -{ - struct uath_cmd_hdr *hdr; - int dlen; - - hdr = (struct uath_cmd_hdr *)cmd->buf; - /* NB: msgid is passed thru w/o byte swapping */ -#ifdef UATH_DEBUG - if (sc->sc_debug & UATH_DEBUG_CMDS) { - int len = be32toh(hdr->len); - printf("%s: %s [ix %u] len %u status %u\n", - __func__, uath_codename(be32toh(hdr->code)), - hdr->msgid, len, be32toh(hdr->magic)); - if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP) - uath_dump_cmd(cmd->buf, - len > UATH_MAX_CMDSZ ? sizeof(*hdr) : len, '-'); - } -#endif - hdr->code = be32toh(hdr->code); - hdr->len = be32toh(hdr->len); - hdr->magic = be32toh(hdr->magic); /* target status on return */ - - switch (hdr->code & 0xff) { - /* reply to a read command */ - default: - dlen = hdr->len - sizeof(*hdr); - DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, - "%s: code %d data len %u\n", - __func__, hdr->code & 0xff, dlen); - /* - * The first response from the target after the - * HOST_AVAILABLE has an invalid msgid so we must - * treat it specially. - */ - if (hdr->msgid < UATH_CMD_LIST_COUNT) { - uint32_t *rp = (uint32_t *)(hdr+1); - u_int olen; - - if (!(sizeof(*hdr) <= hdr->len && - hdr->len < UATH_MAX_CMDSZ)) { - device_printf(sc->sc_dev, - "%s: invalid WDC msg length %u; " - "msg ignored\n", __func__, hdr->len); - return; - } - /* - * Calculate return/receive payload size; the - * first word, if present, always gives the - * number of bytes--unless it's 0 in which - * case a single 32-bit word should be present. - */ - if (dlen >= sizeof(uint32_t)) { - olen = be32toh(rp[0]); - dlen -= sizeof(uint32_t); - if (olen == 0) { - /* convention is 0 =>'s one word */ - olen = sizeof(uint32_t); - /* XXX KASSERT(olen == dlen ) */ - } - } else - olen = 0; - if (cmd->odata != NULL) { - /* NB: cmd->olen validated in uath_cmd */ - if (olen > cmd->olen) { - /* XXX complain? */ - device_printf(sc->sc_dev, - "%s: cmd 0x%x olen %u cmd olen %u\n", - __func__, hdr->code, olen, - cmd->olen); - olen = cmd->olen; - } - if (olen > dlen) { - /* XXX complain, shouldn't happen */ - device_printf(sc->sc_dev, - "%s: cmd 0x%x olen %u dlen %u\n", - __func__, hdr->code, olen, dlen); - olen = dlen; - } - /* XXX have submitter do this */ - /* copy answer into caller's supplied buffer */ - bcopy(&rp[1], cmd->odata, olen); - cmd->olen = olen; - } - } - wakeup_one(cmd); /* wake up caller */ - break; - - case WDCMSG_TARGET_START: - if (hdr->msgid >= UATH_CMD_LIST_COUNT) { - /* XXX */ - return; - } - dlen = hdr->len - sizeof(*hdr); - if (dlen != sizeof(uint32_t)) { - /* XXX something wrong */ - return; - } - /* XXX have submitter do this */ - /* copy answer into caller's supplied buffer */ - bcopy(hdr+1, cmd->odata, sizeof(uint32_t)); - cmd->olen = sizeof(uint32_t); - wakeup_one(cmd); /* wake up caller */ - break; - - case WDCMSG_SEND_COMPLETE: - /* this notification is sent when UATH_TX_NOTIFY is set */ - DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, - "%s: received Tx notification\n", __func__); - break; - - case WDCMSG_TARGET_GET_STATS: - DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL, - "%s: received device statistics\n", __func__); - callout_reset(&sc->stat_ch, hz, uath_stat, sc); - break; - } -} - -static void -uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uath_softc *sc = usbd_xfer_softc(xfer); - struct uath_cmd *cmd; - struct usb_page_cache *pc; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - UATH_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - cmd = STAILQ_FIRST(&sc->sc_cmd_waiting); - if (cmd == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_cmd_waiting, next); - UATH_STAT_DEC(sc, st_cmd_waiting); - STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next); - UATH_STAT_INC(sc, st_cmd_inactive); - - KASSERT(actlen >= sizeof(struct uath_cmd_hdr), - ("short xfer error")); - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, cmd->buf, actlen); - uath_cmdeof(sc, cmd); - case USB_ST_SETUP: -setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - default: - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto setup; - } - break; - } -} - -static void -uath_intr_tx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uath_softc *sc = usbd_xfer_softc(xfer); - struct uath_cmd *cmd; - - UATH_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - cmd = STAILQ_FIRST(&sc->sc_cmd_active); - if (cmd == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next); - UATH_STAT_DEC(sc, st_cmd_active); - STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ? - &sc->sc_cmd_waiting : &sc->sc_cmd_inactive, cmd, next); - if (cmd->flags & UATH_CMD_FLAG_READ) - UATH_STAT_INC(sc, st_cmd_waiting); - else - UATH_STAT_INC(sc, st_cmd_inactive); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - cmd = STAILQ_FIRST(&sc->sc_cmd_pending); - if (cmd == NULL) { - DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n", - __func__); - return; - } - STAILQ_REMOVE_HEAD(&sc->sc_cmd_pending, next); - UATH_STAT_DEC(sc, st_cmd_pending); - STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_ASYNC) ? - &sc->sc_cmd_inactive : &sc->sc_cmd_active, cmd, next); - if (cmd->flags & UATH_CMD_FLAG_ASYNC) - UATH_STAT_INC(sc, st_cmd_inactive); - else - UATH_STAT_INC(sc, st_cmd_active); - - usbd_xfer_set_frame_data(xfer, 0, cmd->buf, cmd->buflen); - usbd_transfer_submit(xfer); - break; - default: - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto setup; - } - break; - } -} - -static void -uath_update_rxstat(struct uath_softc *sc, uint32_t status) -{ - - switch (status) { - case UATH_STATUS_STOP_IN_PROGRESS: - UATH_STAT_INC(sc, st_stopinprogress); - break; - case UATH_STATUS_CRC_ERR: - UATH_STAT_INC(sc, st_crcerr); - break; - case UATH_STATUS_PHY_ERR: - UATH_STAT_INC(sc, st_phyerr); - break; - case UATH_STATUS_DECRYPT_CRC_ERR: - UATH_STAT_INC(sc, st_decrypt_crcerr); - break; - case UATH_STATUS_DECRYPT_MIC_ERR: - UATH_STAT_INC(sc, st_decrypt_micerr); - break; - case UATH_STATUS_DECOMP_ERR: - UATH_STAT_INC(sc, st_decomperr); - break; - case UATH_STATUS_KEY_ERR: - UATH_STAT_INC(sc, st_keyerr); - break; - case UATH_STATUS_ERR: - UATH_STAT_INC(sc, st_err); - break; - default: - break; - } -} - -static struct mbuf * -uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data, - struct uath_rx_desc **pdesc) -{ - struct uath_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct uath_chunk *chunk; - struct uath_rx_desc *desc; - struct mbuf *m = data->m, *mnew, *mp; - uint16_t chunklen; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - if (actlen < UATH_MIN_RXBUFSZ) { - DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, - "%s: wrong xfer size (len=%d)\n", __func__, actlen); - ifp->if_ierrors++; - return (NULL); - } - - chunk = (struct uath_chunk *)data->buf; - if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) { - device_printf(sc->sc_dev, "%s: strange response\n", __func__); - ifp->if_ierrors++; - UATH_RESET_INTRX(sc); - return (NULL); - } - - if (chunk->seqnum != sc->sc_intrx_nextnum) { - DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n", - chunk->seqnum, sc->sc_intrx_nextnum); - UATH_STAT_INC(sc, st_badchunkseqnum); - if (sc->sc_intrx_head != NULL) - m_freem(sc->sc_intrx_head); - UATH_RESET_INTRX(sc); - return (NULL); - } - - /* check multi-chunk frames */ - if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) || - (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) || - chunk->flags & UATH_CFLAGS_RXMSG) - UATH_STAT_INC(sc, st_multichunk); - - chunklen = be16toh(chunk->length); - if (chunk->flags & UATH_CFLAGS_FINAL) - chunklen -= sizeof(struct uath_rx_desc); - - if (chunklen > 0 && - (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) { - /* we should use intermediate RX buffer */ - if (chunk->seqnum == 0) - UATH_RESET_INTRX(sc); - if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) + - chunklen) > UATH_MAX_INTRX_SIZE) { - UATH_STAT_INC(sc, st_invalidlen); - ifp->if_iqdrops++; - if (sc->sc_intrx_head != NULL) - m_freem(sc->sc_intrx_head); - UATH_RESET_INTRX(sc); - return (NULL); - } - - m->m_len = chunklen; - m->m_data += sizeof(struct uath_chunk); - - if (sc->sc_intrx_head == NULL) { - sc->sc_intrx_head = m; - sc->sc_intrx_tail = m; - } else { - m->m_flags &= ~M_PKTHDR; - sc->sc_intrx_tail->m_next = m; - sc->sc_intrx_tail = m; - } - } - sc->sc_intrx_len += chunklen; - - mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (mnew == NULL) { - DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, - "%s: can't get new mbuf, drop frame\n", __func__); - ifp->if_ierrors++; - if (sc->sc_intrx_head != NULL) - m_freem(sc->sc_intrx_head); - UATH_RESET_INTRX(sc); - return (NULL); - } - - data->m = mnew; - data->buf = mtod(mnew, uint8_t *); - - /* if the frame is not final continue the transfer */ - if (!(chunk->flags & UATH_CFLAGS_FINAL)) { - sc->sc_intrx_nextnum++; - UATH_RESET_INTRX(sc); - return (NULL); - } - - /* - * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is - * located at the end, 32-bit aligned - */ - desc = (chunk->flags & UATH_CFLAGS_RXMSG) ? - (struct uath_rx_desc *)(chunk + 1) : - (struct uath_rx_desc *)(((uint8_t *)chunk) + - sizeof(struct uath_chunk) + be16toh(chunk->length) - - sizeof(struct uath_rx_desc)); - *pdesc = desc; - - DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, - "%s: frame len %u code %u status %u rate %u antenna %u " - "rssi %d channel %u phyerror %u connix %u decrypterror %u " - "keycachemiss %u\n", __func__, be32toh(desc->framelen) - , be32toh(desc->code), be32toh(desc->status), be32toh(desc->rate) - , be32toh(desc->antenna), be32toh(desc->rssi), be32toh(desc->channel) - , be32toh(desc->phyerror), be32toh(desc->connix) - , be32toh(desc->decrypterror), be32toh(desc->keycachemiss)); - - if (be32toh(desc->len) > MCLBYTES) { - DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL, - "%s: bad descriptor (len=%d)\n", __func__, - be32toh(desc->len)); - ifp->if_iqdrops++; - UATH_STAT_INC(sc, st_toobigrxpkt); - if (sc->sc_intrx_head != NULL) - m_freem(sc->sc_intrx_head); - UATH_RESET_INTRX(sc); - return (NULL); - } - - uath_update_rxstat(sc, be32toh(desc->status)); - - /* finalize mbuf */ - if (sc->sc_intrx_head == NULL) { - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = - be32toh(desc->framelen) - UATH_RX_DUMMYSIZE; - m->m_data += sizeof(struct uath_chunk); - } else { - mp = sc->sc_intrx_head; - mp->m_pkthdr.rcvif = ifp; - mp->m_flags |= M_PKTHDR; - mp->m_pkthdr.len = sc->sc_intrx_len; - m = mp; - } - - /* there are a lot more fields in the RX descriptor */ - if ((sc->sc_flags & UATH_FLAG_INVALID) == 0 && - ieee80211_radiotap_active(ic)) { - struct uath_rx_radiotap_header *tap = &sc->sc_rxtap; - uint32_t tsf_hi = be32toh(desc->tstamp_high); - uint32_t tsf_lo = be32toh(desc->tstamp_low); - - /* XXX only get low order 24bits of tsf from h/w */ - tap->wr_tsf = htole64(((uint64_t)tsf_hi << 32) | tsf_lo); - tap->wr_flags = 0; - if (be32toh(desc->status) == UATH_STATUS_CRC_ERR) - tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; - /* XXX map other status to BADFCS? */ - /* XXX ath h/w rate code, need to map */ - tap->wr_rate = be32toh(desc->rate); - tap->wr_antenna = be32toh(desc->antenna); - tap->wr_antsignal = -95 + be32toh(desc->rssi); - tap->wr_antnoise = -95; - } - - ifp->if_ipackets++; - UATH_RESET_INTRX(sc); - - return (m); -} - -static void -uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uath_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct mbuf *m = NULL; - struct uath_data *data; - struct uath_rx_desc *desc = NULL; - int8_t nf; - - UATH_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - data = STAILQ_FIRST(&sc->sc_rx_active); - if (data == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); - UATH_STAT_DEC(sc, st_rx_active); - m = uath_data_rxeof(xfer, data, &desc); - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - UATH_STAT_INC(sc, st_rx_inactive); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - data = STAILQ_FIRST(&sc->sc_rx_inactive); - if (data == NULL) - return; - STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next); - UATH_STAT_DEC(sc, st_rx_inactive); - STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next); - UATH_STAT_INC(sc, st_rx_active); - usbd_xfer_set_frame_data(xfer, 0, data->buf, - usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - - /* - * To avoid LOR we should unlock our private mutex here to call - * ieee80211_input() because here is at the end of a USB - * callback and safe to unlock. - */ - if (sc->sc_flags & UATH_FLAG_INVALID) { - if (m != NULL) - m_freem(m); - return; - } - UATH_UNLOCK(sc); - if (m != NULL && desc != NULL) { - wh = mtod(m, struct ieee80211_frame *); - ni = ieee80211_find_rxnode(ic, - (struct ieee80211_frame_min *)wh); - nf = -95; /* XXX */ - if (ni != NULL) { - (void) ieee80211_input(ni, m, - (int)be32toh(desc->rssi), nf); - /* node is no longer needed */ - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, - (int)be32toh(desc->rssi), nf); - m = NULL; - desc = NULL; - } - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && - !IFQ_IS_EMPTY(&ifp->if_snd)) - uath_start(ifp); - UATH_LOCK(sc); - break; - default: - /* needs it to the inactive queue due to a error. */ - data = STAILQ_FIRST(&sc->sc_rx_active); - if (data != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); - UATH_STAT_DEC(sc, st_rx_active); - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - UATH_STAT_INC(sc, st_rx_inactive); - } - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - ifp->if_ierrors++; - goto setup; - } - break; - } -} - -static void -uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data) -{ - struct uath_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - - UATH_ASSERT_LOCKED(sc); - - /* - * Do any tx complete callback. Note this must be done before releasing - * the node reference. - */ - if (data->m) { - m = data->m; - if (m->m_flags & M_TXCB && - (sc->sc_flags & UATH_FLAG_INVALID) == 0) { - /* XXX status? */ - ieee80211_process_callback(data->ni, m, 0); - } - m_freem(m); - data->m = NULL; - } - if (data->ni) { - if ((sc->sc_flags & UATH_FLAG_INVALID) == 0) - ieee80211_free_node(data->ni); - data->ni = NULL; - } - sc->sc_tx_timer = 0; - ifp->if_opackets++; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; -} - -static void -uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct uath_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct uath_data *data; - - UATH_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - data = STAILQ_FIRST(&sc->sc_tx_active); - if (data == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next); - UATH_STAT_DEC(sc, st_tx_active); - uath_data_txeof(xfer, data); - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); - UATH_STAT_INC(sc, st_tx_inactive); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - data = STAILQ_FIRST(&sc->sc_tx_pending); - if (data == NULL) { - DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n", - __func__); - return; - } - STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next); - UATH_STAT_DEC(sc, st_tx_pending); - STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next); - UATH_STAT_INC(sc, st_tx_active); - - usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); - usbd_transfer_submit(xfer); - - UATH_UNLOCK(sc); - uath_start(ifp); - UATH_LOCK(sc); - break; - default: - data = STAILQ_FIRST(&sc->sc_tx_active); - if (data == NULL) - goto setup; - if (data->ni != NULL) { - if ((sc->sc_flags & UATH_FLAG_INVALID) == 0) - ieee80211_free_node(data->ni); - data->ni = NULL; - ifp->if_oerrors++; - } - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto setup; - } - break; - } -} - -static device_method_t uath_methods[] = { - DEVMETHOD(device_probe, uath_match), - DEVMETHOD(device_attach, uath_attach), - DEVMETHOD(device_detach, uath_detach), - DEVMETHOD_END -}; -static driver_t uath_driver = { - "uath", - uath_methods, - sizeof(struct uath_softc) -}; -static devclass_t uath_devclass; - -DRIVER_MODULE(uath, uhub, uath_driver, uath_devclass, NULL, NULL); -MODULE_DEPEND(uath, wlan, 1, 1, 1); -MODULE_DEPEND(uath, usb, 1, 1, 1); -MODULE_VERSION(uath, 1); diff --git a/sys/bus/u4b/wlan/if_uathreg.h b/sys/bus/u4b/wlan/if_uathreg.h deleted file mode 100644 index 1e7929bc7e..0000000000 --- a/sys/bus/u4b/wlan/if_uathreg.h +++ /dev/null @@ -1,601 +0,0 @@ -/* $OpenBSD: if_uathreg.h,v 1.2 2006/09/18 16:34:23 damien Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2006 - * Damien Bergamini - * Copyright (c) 2006 Sam Leffler, Errno Consulting - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define UATH_CONFIG_INDEX 0 -#define UATH_IFACE_INDEX 0 - -/* all fields are big endian */ -struct uath_fwblock { - uint32_t flags; -#define UATH_WRITE_BLOCK (1 << 4) - - uint32_t len; -#define UATH_MAX_FWBLOCK_SIZE 2048 - - uint32_t total; - uint32_t remain; - uint32_t rxtotal; - uint32_t pad[123]; -} __packed; - -#define UATH_MAX_CMDSZ 512 - -/* - * Messages are passed in Target Endianness. All fixed-size - * fields of a WDS Control Message are treated as 32-bit - * values and Control Msgs are guaranteed to be 32-bit aligned. - * - * The format of a WDS Control Message is as follows: - * Message Length 32 bits - * Message Opcode 32 bits - * Message ID 32 bits - * parameter 1 - * parameter 2 - * ... - * - * A variable-length parameter, or a parmeter that is larger than - * 32 bits is passed as pair, where length is a - * 32-bit quantity and data is padded to 32 bits. - */ -struct uath_cmd_hdr { - uint32_t len; /* msg length including header */ - uint32_t code; /* operation code */ -/* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */ -/* messages from Host -> Target */ -#define WDCMSG_HOST_AVAILABLE 0x01 -#define WDCMSG_BIND 0x02 -#define WDCMSG_TARGET_RESET 0x03 -#define WDCMSG_TARGET_GET_CAPABILITY 0x04 -#define WDCMSG_TARGET_SET_CONFIG 0x05 -#define WDCMSG_TARGET_GET_STATUS 0x06 -#define WDCMSG_TARGET_GET_STATS 0x07 -#define WDCMSG_TARGET_START 0x08 -#define WDCMSG_TARGET_STOP 0x09 -#define WDCMSG_TARGET_ENABLE 0x0a -#define WDCMSG_TARGET_DISABLE 0x0b -#define WDCMSG_CREATE_CONNECTION 0x0c -#define WDCMSG_UPDATE_CONNECT_ATTR 0x0d -#define WDCMSG_DELETE_CONNECT 0x0e -#define WDCMSG_SEND 0x0f -#define WDCMSG_FLUSH 0x10 -/* messages from Target -> Host */ -#define WDCMSG_STATS_UPDATE 0x11 -#define WDCMSG_BMISS 0x12 -#define WDCMSG_DEVICE_AVAIL 0x13 -#define WDCMSG_SEND_COMPLETE 0x14 -#define WDCMSG_DATA_AVAIL 0x15 -#define WDCMSG_SET_PWR_MODE 0x16 -#define WDCMSG_BMISS_ACK 0x17 -#define WDCMSG_SET_LED_STEADY 0x18 -#define WDCMSG_SET_LED_BLINK 0x19 -/* more messages */ -#define WDCMSG_SETUP_BEACON_DESC 0x1a -#define WDCMSG_BEACON_INIT 0x1b -#define WDCMSG_RESET_KEY_CACHE 0x1c -#define WDCMSG_RESET_KEY_CACHE_ENTRY 0x1d -#define WDCMSG_SET_KEY_CACHE_ENTRY 0x1e -#define WDCMSG_SET_DECOMP_MASK 0x1f -#define WDCMSG_SET_REGULATORY_DOMAIN 0x20 -#define WDCMSG_SET_LED_STATE 0x21 -#define WDCMSG_WRITE_ASSOCID 0x22 -#define WDCMSG_SET_STA_BEACON_TIMERS 0x23 -#define WDCMSG_GET_TSF 0x24 -#define WDCMSG_RESET_TSF 0x25 -#define WDCMSG_SET_ADHOC_MODE 0x26 -#define WDCMSG_SET_BASIC_RATE 0x27 -#define WDCMSG_MIB_CONTROL 0x28 -#define WDCMSG_GET_CHANNEL_DATA 0x29 -#define WDCMSG_GET_CUR_RSSI 0x2a -#define WDCMSG_SET_ANTENNA_SWITCH 0x2b -#define WDCMSG_USE_SHORT_SLOT_TIME 0x2f -#define WDCMSG_SET_POWER_MODE 0x30 -#define WDCMSG_SETUP_PSPOLL_DESC 0x31 -#define WDCMSG_SET_RX_MULTICAST_FILTER 0x32 -#define WDCMSG_RX_FILTER 0x33 -#define WDCMSG_PER_CALIBRATION 0x34 -#define WDCMSG_RESET 0x35 -#define WDCMSG_DISABLE 0x36 -#define WDCMSG_PHY_DISABLE 0x37 -#define WDCMSG_SET_TX_POWER_LIMIT 0x38 -#define WDCMSG_SET_TX_QUEUE_PARAMS 0x39 -#define WDCMSG_SETUP_TX_QUEUE 0x3a -#define WDCMSG_RELEASE_TX_QUEUE 0x3b -#define WDCMSG_SET_DEFAULT_KEY 0x43 - uint32_t msgid; /* msg id (supplied by host) */ - uint32_t magic; /* response desired/target status */ - uint32_t debug[4]; /* debug data area */ - /* msg data follows */ -} __packed; - -struct uath_chunk { - uint8_t seqnum; /* sequence number for ordering */ - uint8_t flags; -#define UATH_CFLAGS_FINAL 0x01 /* final chunk of a msg */ -#define UATH_CFLAGS_RXMSG 0x02 /* chunk contains rx completion */ -#define UATH_CFLAGS_DEBUG 0x04 /* for debugging */ - uint16_t length; /* chunk size in bytes */ - /* chunk data follows */ -} __packed; - -#define UATH_RX_DUMMYSIZE 4 - -/* - * Message format for a WDCMSG_DATA_AVAIL message from Target to Host. - */ -struct uath_rx_desc { - uint32_t len; /* msg length including header */ - uint32_t code; /* WDCMSG_DATA_AVAIL */ - uint32_t gennum; /* generation number */ - uint32_t status; /* start of RECEIVE_INFO */ -#define UATH_STATUS_OK 0 -#define UATH_STATUS_STOP_IN_PROGRESS 1 -#define UATH_STATUS_CRC_ERR 2 -#define UATH_STATUS_PHY_ERR 3 -#define UATH_STATUS_DECRYPT_CRC_ERR 4 -#define UATH_STATUS_DECRYPT_MIC_ERR 5 -#define UATH_STATUS_DECOMP_ERR 6 -#define UATH_STATUS_KEY_ERR 7 -#define UATH_STATUS_ERR 8 - uint32_t tstamp_low; /* low-order 32-bits of rx timestamp */ - uint32_t tstamp_high; /* high-order 32-bits of rx timestamp */ - uint32_t framelen; /* frame length */ - uint32_t rate; /* rx rate code */ - uint32_t antenna; - int32_t rssi; - uint32_t channel; - uint32_t phyerror; - uint32_t connix; /* key table ix for bss traffic */ - uint32_t decrypterror; - uint32_t keycachemiss; - uint32_t pad; /* XXX? */ -} __packed; - -struct uath_tx_desc { - uint32_t msglen; - uint32_t msgid; /* msg id (supplied by host) */ - uint32_t type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */ - uint32_t txqid; /* tx queue id and flags */ -#define UATH_TXQID_MASK 0x0f -#define UATH_TXQID_MINRATE 0x10 /* use min tx rate */ -#define UATH_TXQID_FF 0x20 /* content is fast frame */ - uint32_t connid; /* tx connection id */ -#define UATH_ID_INVALID 0xffffffff /* for sending prior to connection */ - uint32_t flags; /* non-zero if response desired */ -#define UATH_TX_NOTIFY (1 << 24) /* f/w will send a UATH_NOTIF_TX */ - uint32_t buflen; /* payload length */ -} __packed; - -struct uath_cmd_host_available { - uint32_t sw_ver_major; - uint32_t sw_ver_minor; - uint32_t sw_ver_patch; - uint32_t sw_ver_build; -} __packed; -#define ATH_SW_VER_MAJOR 1 -#define ATH_SW_VER_MINOR 5 -#define ATH_SW_VER_PATCH 0 -#define ATH_SW_VER_BUILD 9999 - -struct uath_cmd_bind { - uint32_t targethandle; - uint32_t hostapiversion; -} __packed; - -/* structure for command WDCMSG_RESET */ -struct uath_cmd_reset { - uint32_t flags; /* channel flags */ -#define UATH_CHAN_TURBO 0x0100 -#define UATH_CHAN_CCK 0x0200 -#define UATH_CHAN_OFDM 0x0400 -#define UATH_CHAN_2GHZ 0x1000 -#define UATH_CHAN_5GHZ 0x2000 - uint32_t freq; /* channel frequency */ - uint32_t maxrdpower; - uint32_t cfgctl; - uint32_t twiceantennareduction; - uint32_t channelchange; - uint32_t keeprccontent; -} __packed; - -/* structure for commands UATH_CMD_READ_MAC and UATH_CMD_READ_EEPROM */ -struct uath_read_mac { - uint32_t len; - uint8_t data[32]; -} __packed; - -/* structure for command UATH_CMD_WRITE_MAC */ -struct uath_write_mac { - uint32_t reg; - uint32_t len; - uint8_t data[32]; -} __packed; - -/* structure for command UATH_CMD_STA_JOIN */ -struct uath_cmd_join_bss { - uint32_t bssid; /* NB: use zero */ - uint32_t bssmac[2]; /* bssid mac address */ - uint32_t bsstype; - uint32_t wlanmode; - uint32_t beaconinterval; - uint32_t dtiminterval; - uint32_t cfpinterval; - uint32_t atimwindow; - uint32_t defaultrateix; - uint32_t shortslottime11g; - uint32_t sleepduration; - uint32_t bmissthreshold; - uint32_t tcppowerlimit; - uint32_t quietduration; - uint32_t quietoffset; - uint32_t quietackctsallow; - uint32_t bssdefaultkey; /* XXX? */ -} __packed; - -struct uath_cmd_assoc_bss { - uint32_t bssid; - uint32_t associd; -} __packed; - -struct uath_cmd_start_bss { - uint32_t bssid; -} __packed; - -/* structure for command UATH_CMD_0C */ -struct uath_cmd_0c { - uint32_t magic1; - uint32_t magic2; - uint32_t magic3; -} __packed; - -struct uath_cmd_ledsteady { /* WDCMSG_SET_LED_STEADY */ - uint32_t lednum; -#define UATH_LED_LINK 0 -#define UATH_LED_ACTIVITY 1 - uint32_t ledmode; -#define UATH_LED_OFF 0 -#define UATH_LED_ON 1 -} __packed; - -struct uath_cmd_ledblink { /* WDCMSG_SET_LED_BLINK */ - uint32_t lednum; - uint32_t ledmode; - uint32_t blinkrate; - uint32_t slowmode; -} __packed; - -struct uath_cmd_ledstate { /* WDCMSG_SET_LED_STATE */ - uint32_t connected; -} __packed; - -struct uath_connkey_rec { - uint8_t bssid[IEEE80211_ADDR_LEN]; - uint32_t keyiv; - uint32_t extkeyiv; - uint16_t keyflags; - uint16_t keylen; - uint16_t keytype; /* WEP, TKIP or AES */ - /* As far as I know, MIPS 4Kp is 32-bit processor */ - uint32_t priv; - uint8_t keyval[32]; - uint16_t aes_keylen; - uint8_t aes_keyval[16]; - uint8_t mic_txkeyval[8]; - uint8_t mic_rxkeyval[8]; - int64_t keyrsc[17]; - int32_t keytsc[17]; - int32_t keyexttsc[17]; -} __packed; - -/* structure for command UATH_CMD_CRYPTO */ -struct uath_cmd_crypto { - uint32_t keyidx; -#define UATH_DEFAULT_KEY 6 - uint32_t xorkey; - uint32_t size; - struct uath_connkey_rec rec; -} __packed; - -struct uath_cmd_rateset { - uint8_t length; -#define UATH_MAX_NRATES 32 - uint8_t set[UATH_MAX_NRATES]; -}; - -/* structure for command WDCMSG_SET_BASIC_RATE */ -struct uath_cmd_rates { - uint32_t connid; - uint32_t keeprccontent; - uint32_t size; - struct uath_cmd_rateset rateset; -} __packed; - -enum { - WLAN_MODE_NONE = 0, - WLAN_MODE_11b, - WLAN_MODE_11a, - WLAN_MODE_11g, - WLAN_MODE_11a_TURBO, - WLAN_MODE_11g_TURBO, - WLAN_MODE_11a_TURBO_PRIME, - WLAN_MODE_11g_TURBO_PRIME, - WLAN_MODE_11a_XR, - WLAN_MODE_11g_XR, -}; - -struct uath_cmd_connection_attr { - uint32_t longpreambleonly; - struct uath_cmd_rateset rateset; - uint32_t wlanmode; -} __packed; - -/* structure for command WDCMSG_CREATE_CONNECTION */ -struct uath_cmd_create_connection { - uint32_t connid; - uint32_t bssid; - uint32_t size; - struct uath_cmd_connection_attr connattr; -} __packed; - -struct uath_cmd_txq_setparams { /* WDCMSG_SET_TX_QUEUE_PARAMS */ - uint32_t qnum; - uint32_t aifs; - uint32_t logcwmin; - uint32_t logcwmax; - uint32_t bursttime; - uint32_t qflags; -} __packed; - -struct uath_cmd_txq_attr { - uint32_t priority; - uint32_t aifs; - uint32_t logcwmin; - uint32_t logcwmax; - uint32_t bursttime; - uint32_t mode; - uint32_t qflags; -} __packed; - -struct uath_cmd_txq_setup { /* WDCMSG_SETUP_TX_QUEUE */ - uint32_t qid; - uint32_t len; - struct uath_cmd_txq_attr attr; -} __packed; - -struct uath_cmd_stoptxdma { /* WDCMSG_STOP_TX_DMA */ - uint32_t qnum; - uint32_t msec; -} __packed; - -/* structure for command UATH_CMD_31 */ -struct uath_cmd_31 { - uint32_t magic1; - uint32_t magic2; -} __packed; - -struct uath_cmd_rx_filter { /* WDCMSG_RX_FILTER */ - uint32_t bits; -#define UATH_FILTER_RX_UCAST 0x00000001 -#define UATH_FILTER_RX_MCAST 0x00000002 -#define UATH_FILTER_RX_BCAST 0x00000004 -#define UATH_FILTER_RX_CONTROL 0x00000008 -#define UATH_FILTER_RX_BEACON 0x00000010 /* beacon frames */ -#define UATH_FILTER_RX_PROM 0x00000020 /* promiscuous mode */ -#define UATH_FILTER_RX_PHY_ERR 0x00000040 /* phy errors */ -#define UATH_FILTER_RX_PHY_RADAR 0x00000080 /* radar phy errors */ -#define UATH_FILTER_RX_XR_POOL 0x00000400 /* XR group polls */ -#define UATH_FILTER_RX_PROBE_REQ 0x00000800 - uint32_t op; -#define UATH_FILTER_OP_INIT 0x0 -#define UATH_FILTER_OP_SET 0x1 -#define UATH_FILTER_OP_CLEAR 0x2 -#define UATH_FILTER_OP_TEMP 0x3 -#define UATH_FILTER_OP_RESTORE 0x4 -} __packed; - -struct uath_cmd_rx_mcast_filter { /* WDCMSG_SET_RX_MCAST_FILTER */ - uint32_t filter0; - uint32_t filter1; -} __packed; - -struct uath_cmd_set_associd { /* WDCMSG_WRITE_ASSOCID */ - uint32_t defaultrateix; - uint32_t associd; - uint32_t timoffset; - uint32_t turboprime; - uint32_t bssid[2]; -} __packed; - -struct uath_cmd_set_stabeacon_timers { /* WDCMSG_SET_STA_BEACON_TIMERS */ - uint32_t nexttbtt; - uint32_t nextdtim; - uint32_t nextcfp; - uint32_t beaconperiod; - uint32_t dtimperiod; - uint32_t cfpperiod; - uint32_t cfpduration; - uint32_t sleepduration; - uint32_t bsmissthreshold; -} __packed; - -enum { - CFG_NONE, /* Sentinal to indicate "no config" */ - CFG_REG_DOMAIN, /* Regulatory Domain */ - CFG_RATE_CONTROL_ENABLE, - CFG_DEF_XMIT_DATA_RATE, /* NB: if rate control is not enabled */ - CFG_HW_TX_RETRIES, - CFG_SW_TX_RETRIES, - CFG_SLOW_CLOCK_ENABLE, - CFG_COMP_PROC, - CFG_USER_RTS_THRESHOLD, - CFG_XR2NORM_RATE_THRESHOLD, - CFG_XRMODE_SWITCH_COUNT, - CFG_PROTECTION_TYPE, - CFG_BURST_SEQ_THRESHOLD, - CFG_ABOLT, - CFG_IQ_LOG_COUNT_MAX, - CFG_MODE_CTS, - CFG_WME_ENABLED, - CFG_GPRS_CBR_PERIOD, - CFG_SERVICE_TYPE, - /* MAC Address to use. Overrides EEPROM */ - CFG_MAC_ADDR, - CFG_DEBUG_EAR, - CFG_INIT_REGS, - /* An ID for use in error & debug messages */ - CFG_DEBUG_ID, - CFG_COMP_WIN_SZ, - CFG_DIVERSITY_CTL, - CFG_TP_SCALE, - CFG_TPC_HALF_DBM5, - CFG_TPC_HALF_DBM2, - CFG_OVERRD_TX_POWER, - CFG_USE_32KHZ_CLOCK, - CFG_GMODE_PROTECTION, - CFG_GMODE_PROTECT_RATE_INDEX, - CFG_GMODE_NON_ERP_PREAMBLE, - CFG_WDC_TRANSPORT_CHUNK_SIZE, -}; - -enum { - /* Sentinal to indicate "no capability" */ - CAP_NONE, - CAP_ALL, /* ALL capabilities */ - CAP_TARGET_VERSION, - CAP_TARGET_REVISION, - CAP_MAC_VERSION, - CAP_MAC_REVISION, - CAP_PHY_REVISION, - CAP_ANALOG_5GHz_REVISION, - CAP_ANALOG_2GHz_REVISION, - /* Target supports WDC message debug features */ - CAP_DEBUG_WDCMSG_SUPPORT, - - CAP_REG_DOMAIN, - CAP_COUNTRY_CODE, - CAP_REG_CAP_BITS, - - CAP_WIRELESS_MODES, - CAP_CHAN_SPREAD_SUPPORT, - CAP_SLEEP_AFTER_BEACON_BROKEN, - CAP_COMPRESS_SUPPORT, - CAP_BURST_SUPPORT, - CAP_FAST_FRAMES_SUPPORT, - CAP_CHAP_TUNING_SUPPORT, - CAP_TURBOG_SUPPORT, - CAP_TURBO_PRIME_SUPPORT, - CAP_DEVICE_TYPE, - CAP_XR_SUPPORT, - CAP_WME_SUPPORT, - CAP_TOTAL_QUEUES, - CAP_CONNECTION_ID_MAX, /* Should absorb CAP_KEY_CACHE_SIZE */ - - CAP_LOW_5GHZ_CHAN, - CAP_HIGH_5GHZ_CHAN, - CAP_LOW_2GHZ_CHAN, - CAP_HIGH_2GHZ_CHAN, - - CAP_MIC_AES_CCM, - CAP_MIC_CKIP, - CAP_MIC_TKIP, - CAP_MIC_TKIP_WME, - CAP_CIPHER_AES_CCM, - CAP_CIPHER_CKIP, - CAP_CIPHER_TKIP, - - CAP_TWICE_ANTENNAGAIN_5G, - CAP_TWICE_ANTENNAGAIN_2G, -}; - -enum { - ST_NONE, /* Sentinal to indicate "no status" */ - ST_ALL, - ST_SERVICE_TYPE, - ST_WLAN_MODE, - ST_FREQ, - ST_BAND, - ST_LAST_RSSI, - ST_PS_FRAMES_DROPPED, - ST_CACHED_DEF_ANT, - ST_COUNT_OTHER_RX_ANT, - ST_USE_FAST_DIVERSITY, - ST_MAC_ADDR, - ST_RX_GENERATION_NUM, - ST_TX_QUEUE_DEPTH, - ST_SERIAL_NUMBER, - ST_WDC_TRANSPORT_CHUNK_SIZE, -}; - -enum { - BSS_ATTR_BEACON_INTERVAL, - BSS_ATTR_DTIM_INTERVAL, - BSS_ATTR_CFP_INTERVAL, - BSS_ATTR_CFP_MAX_DURATION, - BSS_ATTR_ATIM_WINDOW, - BSS_ATTR_DEFAULT_RATE_INDEX, - BSS_ATTR_SHORT_SLOT_TIME_11g, - BSS_ATTR_SLEEP_DURATION, - BSS_ATTR_BMISS_THRESHOLD, - BSS_ATTR_TPC_POWER_LIMIT, - BSS_ATTR_BSS_KEY_UPDATE, -}; - -struct uath_cmd_update_bss_attribute { - uint32_t bssid; - uint32_t attribute; /* BSS_ATTR_BEACON_INTERVAL, et al. */ - uint32_t cfgsize; /* should be zero 0 */ - uint32_t cfgdata; -}; - -struct uath_cmd_update_bss_attribute_key { - uint32_t bssid; - uint32_t attribute; /* BSS_ATTR_BSS_KEY_UPDATE */ - uint32_t cfgsize; /* size of remaining data */ - uint32_t bsskeyix; - uint32_t isdefaultkey; - uint32_t keyiv; /* IV generation control */ - uint32_t extkeyiv; /* extended IV for TKIP & CCM */ - uint32_t keyflags; - uint32_t keytype; - uint32_t initvalue; /* XXX */ - uint32_t keyval[4]; - uint32_t mictxkeyval[2]; - uint32_t micrxkeyval[2]; - uint32_t keyrsc[2]; -}; - -enum { - TARGET_DEVICE_AWAKE, - TARGET_DEVICE_SLEEP, - TARGET_DEVICE_PWRDN, - TARGET_DEVICE_PWRSAVE, - TARGET_DEVICE_SUSPEND, - TARGET_DEVICE_RESUME, -}; - -#define UATH_MAX_TXBUFSZ \ - (sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc) + \ - IEEE80211_MAX_LEN) - -/* - * it's not easy to measure how the chunk is passed into the host if the target - * passed the multi-chunks so just we check a minimal size we can imagine. - */ -#define UATH_MIN_RXBUFSZ (sizeof(struct uath_chunk)) diff --git a/sys/bus/u4b/wlan/if_uathvar.h b/sys/bus/u4b/wlan/if_uathvar.h deleted file mode 100644 index 6e58d93a89..0000000000 --- a/sys/bus/u4b/wlan/if_uathvar.h +++ /dev/null @@ -1,245 +0,0 @@ -/* $OpenBSD: if_uathvar.h,v 1.3 2006/09/20 19:47:17 damien Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2006 - * Damien Bergamini - * Copyright (c) 2006 Sam Leffler, Errno Consulting - * Copyright (c) 2008-2009 Weongyo Jeong - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -enum { - UATH_INTR_RX, - UATH_INTR_TX, - UATH_BULK_RX, - UATH_BULK_TX, - UATH_N_XFERS = 4, -}; - -#define UATH_ID_BSS 2 /* Connection ID */ - -#define UATH_RX_DATA_LIST_COUNT 128 -#define UATH_TX_DATA_LIST_COUNT 16 -#define UATH_CMD_LIST_COUNT 60 - -#define UATH_DATA_TIMEOUT 10000 -#define UATH_CMD_TIMEOUT 1000 - -/* flags for sending firmware commands */ -#define UATH_CMD_FLAG_ASYNC (1 << 0) -#define UATH_CMD_FLAG_READ (1 << 1) -#define UATH_CMD_FLAG_MAGIC (1 << 2) - -struct uath_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - u_int64_t wr_tsf; - u_int8_t wr_flags; - u_int8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; - int8_t wr_antnoise; - u_int8_t wr_antenna; -} __packed; - -#define UATH_RX_RADIOTAP_PRESENT ( \ - (1 << IEEE80211_RADIOTAP_TSFT) | \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ - 0) - -struct uath_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define UATH_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct uath_data { - struct uath_softc *sc; - uint8_t *buf; - uint16_t buflen; - struct mbuf *m; - struct ieee80211_node *ni; /* NB: tx only */ - STAILQ_ENTRY(uath_data) next; -}; -typedef STAILQ_HEAD(, uath_data) uath_datahead; - -struct uath_cmd { - struct uath_softc *sc; - uint32_t flags; - uint32_t msgid; - uint8_t *buf; - uint16_t buflen; - void *odata; /* NB: tx only */ - int olen; /* space in odata */ - STAILQ_ENTRY(uath_cmd) next; -}; -typedef STAILQ_HEAD(, uath_cmd) uath_cmdhead; - -struct uath_wme_settings { - uint8_t aifsn; - uint8_t logcwmin; - uint8_t logcwmax; - uint16_t txop; -#define UATH_TXOP_TO_US(txop) ((txop) << 5) - uint8_t acm; -}; - -struct uath_devcap { - uint32_t targetVersion; - uint32_t targetRevision; - uint32_t macVersion; - uint32_t macRevision; - uint32_t phyRevision; - uint32_t analog5GhzRevision; - uint32_t analog2GhzRevision; - uint32_t regDomain; - uint32_t regCapBits; - uint32_t countryCode; - uint32_t keyCacheSize; - uint32_t numTxQueues; - uint32_t connectionIdMax; - uint32_t wirelessModes; -#define UATH_WIRELESS_MODE_11A 0x01 -#define UATH_WIRELESS_MODE_TURBO 0x02 -#define UATH_WIRELESS_MODE_11B 0x04 -#define UATH_WIRELESS_MODE_11G 0x08 -#define UATH_WIRELESS_MODE_108G 0x10 - uint32_t chanSpreadSupport; - uint32_t compressSupport; - uint32_t burstSupport; - uint32_t fastFramesSupport; - uint32_t chapTuningSupport; - uint32_t turboGSupport; - uint32_t turboPrimeSupport; - uint32_t deviceType; - uint32_t wmeSupport; - uint32_t low2GhzChan; - uint32_t high2GhzChan; - uint32_t low5GhzChan; - uint32_t high5GhzChan; - uint32_t supportCipherWEP; - uint32_t supportCipherAES_CCM; - uint32_t supportCipherTKIP; - uint32_t supportCipherMicAES_CCM; - uint32_t supportMicTKIP; - uint32_t twiceAntennaGain5G; - uint32_t twiceAntennaGain2G; -}; - -struct uath_stat { - uint32_t st_badchunkseqnum; - uint32_t st_invalidlen; - uint32_t st_multichunk; - uint32_t st_toobigrxpkt; - uint32_t st_stopinprogress; - uint32_t st_crcerr; - uint32_t st_phyerr; - uint32_t st_decrypt_crcerr; - uint32_t st_decrypt_micerr; - uint32_t st_decomperr; - uint32_t st_keyerr; - uint32_t st_err; - /* CMD/RX/TX queues */ - uint32_t st_cmd_active; - uint32_t st_cmd_inactive; - uint32_t st_cmd_pending; - uint32_t st_cmd_waiting; - uint32_t st_rx_active; - uint32_t st_rx_inactive; - uint32_t st_tx_active; - uint32_t st_tx_inactive; - uint32_t st_tx_pending; -}; -#define UATH_STAT_INC(sc, var) (sc)->sc_stat.var++ -#define UATH_STAT_DEC(sc, var) (sc)->sc_stat.var-- - -struct uath_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define UATH_VAP(vap) ((struct uath_vap *)(vap)) - -struct uath_softc { - struct ifnet *sc_ifp; - device_t sc_dev; - struct usb_device *sc_udev; - struct mtx sc_mtx; - uint32_t sc_debug; - - struct uath_stat sc_stat; - int (*sc_newstate)(struct ieee80211com *, - enum ieee80211_state, int); - - struct usb_xfer *sc_xfer[UATH_N_XFERS]; - struct uath_cmd sc_cmd[UATH_CMD_LIST_COUNT]; - uath_cmdhead sc_cmd_active; - uath_cmdhead sc_cmd_inactive; - uath_cmdhead sc_cmd_pending; - uath_cmdhead sc_cmd_waiting; - struct uath_data sc_rx[UATH_RX_DATA_LIST_COUNT]; - uath_datahead sc_rx_active; - uath_datahead sc_rx_inactive; - struct uath_data sc_tx[UATH_TX_DATA_LIST_COUNT]; - uath_datahead sc_tx_active; - uath_datahead sc_tx_inactive; - uath_datahead sc_tx_pending; - - uint32_t sc_msgid; - uint32_t sc_seqnum; - int sc_tx_timer; - struct callout watchdog_ch; - struct callout stat_ch; - /* multi-chunked support */ - struct mbuf *sc_intrx_head; - struct mbuf *sc_intrx_tail; - uint8_t sc_intrx_nextnum; - uint32_t sc_intrx_len; -#define UATH_MAX_INTRX_SIZE 3616 - - struct uath_devcap sc_devcap; - uint8_t sc_serial[16]; - - /* unsorted */ - uint32_t sc_flags; -#define UATH_FLAG_INVALID (1 << 1) -#define UATH_FLAG_INITDONE (1 << 2) - - struct uath_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct uath_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define UATH_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define UATH_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define UATH_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) - -#define UATH_RESET_INTRX(sc) do { \ - (sc)->sc_intrx_head = NULL; \ - (sc)->sc_intrx_tail = NULL; \ - (sc)->sc_intrx_nextnum = 0; \ - (sc)->sc_intrx_len = 0; \ -} while (0) diff --git a/sys/bus/u4b/wlan/if_upgt.c b/sys/bus/u4b/wlan/if_upgt.c deleted file mode 100644 index ebac62f646..0000000000 --- a/sys/bus/u4b/wlan/if_upgt.c +++ /dev/null @@ -1,2397 +0,0 @@ -/* $OpenBSD: if_upgt.c,v 1.35 2008/04/16 18:32:15 damien Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (c) 2007 Marcus Glocker - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include "usbdevs.h" - -#include - -/* - * Driver for the USB PrismGT devices. - * - * For now just USB 2.0 devices with the GW3887 chipset are supported. - * The driver has been written based on the firmware version 2.13.1.0_LM87. - * - * TODO's: - * - MONITOR mode test. - * - Add HOSTAP mode. - * - Add IBSS mode. - * - Support the USB 1.0 devices (NET2280, ISL3880, ISL3886 chipsets). - * - * Parts of this driver has been influenced by reading the p54u driver - * written by Jean-Baptiste Note and - * Sebastien Bourdeauducq . - */ - -static SYSCTL_NODE(_hw, OID_AUTO, upgt, CTLFLAG_RD, 0, - "USB PrismGT GW3887 driver parameters"); - -#ifdef UPGT_DEBUG -int upgt_debug = 0; -SYSCTL_INT(_hw_upgt, OID_AUTO, debug, CTLFLAG_RW, &upgt_debug, - 0, "control debugging printfs"); -TUNABLE_INT("hw.upgt.debug", &upgt_debug); -enum { - UPGT_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - UPGT_DEBUG_RECV = 0x00000002, /* basic recv operation */ - UPGT_DEBUG_RESET = 0x00000004, /* reset processing */ - UPGT_DEBUG_INTR = 0x00000008, /* INTR */ - UPGT_DEBUG_TX_PROC = 0x00000010, /* tx ISR proc */ - UPGT_DEBUG_RX_PROC = 0x00000020, /* rx ISR proc */ - UPGT_DEBUG_STATE = 0x00000040, /* 802.11 state transitions */ - UPGT_DEBUG_STAT = 0x00000080, /* statistic */ - UPGT_DEBUG_FW = 0x00000100, /* firmware */ - UPGT_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif - -/* - * Prototypes. - */ -static device_probe_t upgt_match; -static device_attach_t upgt_attach; -static device_detach_t upgt_detach; -static int upgt_alloc_tx(struct upgt_softc *); -static int upgt_alloc_rx(struct upgt_softc *); -static int upgt_device_reset(struct upgt_softc *); -static void upgt_bulk_tx(struct upgt_softc *, struct upgt_data *); -static int upgt_fw_verify(struct upgt_softc *); -static int upgt_mem_init(struct upgt_softc *); -static int upgt_fw_load(struct upgt_softc *); -static int upgt_fw_copy(const uint8_t *, char *, int); -static uint32_t upgt_crc32_le(const void *, size_t); -static struct mbuf * - upgt_rxeof(struct usb_xfer *, struct upgt_data *, int *); -static struct mbuf * - upgt_rx(struct upgt_softc *, uint8_t *, int, int *); -static void upgt_txeof(struct usb_xfer *, struct upgt_data *); -static int upgt_eeprom_read(struct upgt_softc *); -static int upgt_eeprom_parse(struct upgt_softc *); -static void upgt_eeprom_parse_hwrx(struct upgt_softc *, uint8_t *); -static void upgt_eeprom_parse_freq3(struct upgt_softc *, uint8_t *, int); -static void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int); -static void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int); -static uint32_t upgt_chksum_le(const uint32_t *, size_t); -static void upgt_tx_done(struct upgt_softc *, uint8_t *); -static void upgt_init(void *); -static void upgt_init_locked(struct upgt_softc *); -static int upgt_ioctl(struct ifnet *, u_long, caddr_t); -static void upgt_start(struct ifnet *); -static int upgt_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void upgt_scan_start(struct ieee80211com *); -static void upgt_scan_end(struct ieee80211com *); -static void upgt_set_channel(struct ieee80211com *); -static struct ieee80211vap *upgt_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void upgt_vap_delete(struct ieee80211vap *); -static void upgt_update_mcast(struct ieee80211com *); -static uint8_t upgt_rx_rate(struct upgt_softc *, const int); -static void upgt_set_multi(void *); -static void upgt_stop(struct upgt_softc *); -static void upgt_setup_rates(struct ieee80211vap *, struct ieee80211com *); -static int upgt_set_macfilter(struct upgt_softc *, uint8_t); -static int upgt_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static void upgt_set_chan(struct upgt_softc *, struct ieee80211_channel *); -static void upgt_set_led(struct upgt_softc *, int); -static void upgt_set_led_blink(void *); -static void upgt_get_stats(struct upgt_softc *); -static void upgt_mem_free(struct upgt_softc *, uint32_t); -static uint32_t upgt_mem_alloc(struct upgt_softc *); -static void upgt_free_tx(struct upgt_softc *); -static void upgt_free_rx(struct upgt_softc *); -static void upgt_watchdog(void *); -static void upgt_abort_xfers(struct upgt_softc *); -static void upgt_abort_xfers_locked(struct upgt_softc *); -static void upgt_sysctl_node(struct upgt_softc *); -static struct upgt_data * - upgt_getbuf(struct upgt_softc *); -static struct upgt_data * - upgt_gettxbuf(struct upgt_softc *); -static int upgt_tx_start(struct upgt_softc *, struct mbuf *, - struct ieee80211_node *, struct upgt_data *); - -static const char *upgt_fwname = "upgt-gw3887"; - -static const STRUCT_USB_HOST_ID upgt_devs[] = { -#define UPGT_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } - /* version 2 devices */ - UPGT_DEV(ACCTON, PRISM_GT), - UPGT_DEV(BELKIN, F5D7050), - UPGT_DEV(CISCOLINKSYS, WUSB54AG), - UPGT_DEV(CONCEPTRONIC, PRISM_GT), - UPGT_DEV(DELL, PRISM_GT_1), - UPGT_DEV(DELL, PRISM_GT_2), - UPGT_DEV(FSC, E5400), - UPGT_DEV(GLOBESPAN, PRISM_GT_1), - UPGT_DEV(GLOBESPAN, PRISM_GT_2), - UPGT_DEV(NETGEAR, WG111V1_2), - UPGT_DEV(INTERSIL, PRISM_GT), - UPGT_DEV(SMC, 2862WG), - UPGT_DEV(USR, USR5422), - UPGT_DEV(WISTRONNEWEB, UR045G), - UPGT_DEV(XYRATEX, PRISM_GT_1), - UPGT_DEV(XYRATEX, PRISM_GT_2), - UPGT_DEV(ZCOM, XG703A), - UPGT_DEV(ZCOM, XM142) -}; - -static usb_callback_t upgt_bulk_rx_callback; -static usb_callback_t upgt_bulk_tx_callback; - -static const struct usb_config upgt_config[UPGT_N_XFERS] = { - [UPGT_BULK_TX] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = MCLBYTES, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1 - }, - .callback = upgt_bulk_tx_callback, - .timeout = UPGT_USB_TIMEOUT, /* ms */ - }, - [UPGT_BULK_RX] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = MCLBYTES, - .flags = { - .ext_buffer = 1, - .pipe_bof = 1, - .short_xfer_ok = 1 - }, - .callback = upgt_bulk_rx_callback, - }, -}; - -static int -upgt_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != UPGT_CONFIG_INDEX) - return (ENXIO); - if (uaa->info.bIfaceIndex != UPGT_IFACE_INDEX) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(upgt_devs, sizeof(upgt_devs), uaa)); -} - -static int -upgt_attach(device_t dev) -{ - int error; - struct ieee80211com *ic; - struct ifnet *ifp; - struct upgt_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - uint8_t bands, iface_index = UPGT_IFACE_INDEX; - - sc->sc_dev = dev; - sc->sc_udev = uaa->device; -#ifdef UPGT_DEBUG - sc->sc_debug = upgt_debug; -#endif - device_set_usb_desc(dev); - - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF); - callout_init(&sc->sc_led_ch, 0); - callout_init(&sc->sc_watchdog_ch, 0); - - /* Allocate TX and RX xfers. */ - error = upgt_alloc_tx(sc); - if (error) - goto fail1; - error = upgt_alloc_rx(sc); - if (error) - goto fail2; - - error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, - upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx); - if (error) { - device_printf(dev, "could not allocate USB transfers, " - "err=%s\n", usbd_errstr(error)); - goto fail3; - } - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(dev, "can not if_alloc()\n"); - goto fail4; - } - - /* Initialize the device. */ - error = upgt_device_reset(sc); - if (error) - goto fail5; - /* Verify the firmware. */ - error = upgt_fw_verify(sc); - if (error) - goto fail5; - /* Calculate device memory space. */ - if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) { - device_printf(dev, - "could not find memory space addresses on FW\n"); - error = EIO; - goto fail5; - } - sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1; - sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1; - - DPRINTF(sc, UPGT_DEBUG_FW, "memory address frame start=0x%08x\n", - sc->sc_memaddr_frame_start); - DPRINTF(sc, UPGT_DEBUG_FW, "memory address frame end=0x%08x\n", - sc->sc_memaddr_frame_end); - DPRINTF(sc, UPGT_DEBUG_FW, "memory address rx start=0x%08x\n", - sc->sc_memaddr_rx_start); - - upgt_mem_init(sc); - - /* Load the firmware. */ - error = upgt_fw_load(sc); - if (error) - goto fail5; - - /* Read the whole EEPROM content and parse it. */ - error = upgt_eeprom_read(sc); - if (error) - goto fail5; - error = upgt_eeprom_parse(sc); - if (error) - goto fail5; - - /* all works related with the device have done here. */ - upgt_abort_xfers(sc); - - /* Setup the 802.11 device. */ - ifp->if_softc = sc; - if_initname(ifp, "upgt", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = upgt_init; - ifp->if_ioctl = upgt_ioctl; - ifp->if_start = upgt_start; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(dev); - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode */ - | IEEE80211_C_MONITOR /* monitor mode */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* capable of bg scanning */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic, sc->sc_myaddr); - ic->ic_raw_xmit = upgt_raw_xmit; - ic->ic_scan_start = upgt_scan_start; - ic->ic_scan_end = upgt_scan_end; - ic->ic_set_channel = upgt_set_channel; - ic->ic_vap_create = upgt_vap_create; - ic->ic_vap_delete = upgt_vap_delete; - ic->ic_update_mcast = upgt_update_mcast; - - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - UPGT_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - UPGT_RX_RADIOTAP_PRESENT); - - upgt_sysctl_node(sc); - - if (bootverbose) - ieee80211_announce(ic); - - return (0); - -fail5: if_free(ifp); -fail4: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS); -fail3: upgt_free_rx(sc); -fail2: upgt_free_tx(sc); -fail1: mtx_destroy(&sc->sc_mtx); - - return (error); -} - -static void -upgt_txeof(struct usb_xfer *xfer, struct upgt_data *data) -{ - struct upgt_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - - UPGT_ASSERT_LOCKED(sc); - - /* - * Do any tx complete callback. Note this must be done before releasing - * the node reference. - */ - if (data->m) { - m = data->m; - if (m->m_flags & M_TXCB) { - /* XXX status? */ - ieee80211_process_callback(data->ni, m, 0); - } - m_freem(m); - data->m = NULL; - } - if (data->ni) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - ifp->if_opackets++; -} - -static void -upgt_get_stats(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd; - struct upgt_lmac_mem *mem; - struct upgt_lmac_stats *stats; - - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - device_printf(sc->sc_dev, "%s: out of buffer.\n", __func__); - return; - } - - /* - * Transmit the URB containing the CMD data. - */ - memset(data_cmd->buf, 0, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - stats = (struct upgt_lmac_stats *)(mem + 1); - - stats->header1.flags = 0; - stats->header1.type = UPGT_H1_TYPE_CTRL; - stats->header1.len = htole16( - sizeof(struct upgt_lmac_stats) - sizeof(struct upgt_lmac_header)); - - stats->header2.reqid = htole32(sc->sc_memaddr_frame_start); - stats->header2.type = htole16(UPGT_H2_TYPE_STATS); - stats->header2.flags = 0; - - data_cmd->buflen = sizeof(*mem) + sizeof(*stats); - - mem->chksum = upgt_chksum_le((uint32_t *)stats, - data_cmd->buflen - sizeof(*mem)); - - upgt_bulk_tx(sc, data_cmd); -} - -static int -upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct upgt_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if ((ifp->if_flags ^ sc->sc_if_flags) & - (IFF_ALLMULTI | IFF_PROMISC)) - upgt_set_multi(sc); - } else { - upgt_init(sc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - upgt_stop(sc); - } - sc->sc_if_flags = ifp->if_flags; - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - return error; -} - -static void -upgt_stop_locked(struct upgt_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - - UPGT_ASSERT_LOCKED(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - upgt_set_macfilter(sc, IEEE80211_S_INIT); - upgt_abort_xfers_locked(sc); -} - -static void -upgt_stop(struct upgt_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - - UPGT_LOCK(sc); - upgt_stop_locked(sc); - UPGT_UNLOCK(sc); - - /* device down */ - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - sc->sc_flags &= ~UPGT_FLAG_INITDONE; -} - -static void -upgt_set_led(struct upgt_softc *sc, int action) -{ - struct upgt_data *data_cmd; - struct upgt_lmac_mem *mem; - struct upgt_lmac_led *led; - - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - device_printf(sc->sc_dev, "%s: out of buffers.\n", __func__); - return; - } - - /* - * Transmit the URB containing the CMD data. - */ - memset(data_cmd->buf, 0, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - led = (struct upgt_lmac_led *)(mem + 1); - - led->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK; - led->header1.type = UPGT_H1_TYPE_CTRL; - led->header1.len = htole16( - sizeof(struct upgt_lmac_led) - - sizeof(struct upgt_lmac_header)); - - led->header2.reqid = htole32(sc->sc_memaddr_frame_start); - led->header2.type = htole16(UPGT_H2_TYPE_LED); - led->header2.flags = 0; - - switch (action) { - case UPGT_LED_OFF: - led->mode = htole16(UPGT_LED_MODE_SET); - led->action_fix = 0; - led->action_tmp = htole16(UPGT_LED_ACTION_OFF); - led->action_tmp_dur = 0; - break; - case UPGT_LED_ON: - led->mode = htole16(UPGT_LED_MODE_SET); - led->action_fix = 0; - led->action_tmp = htole16(UPGT_LED_ACTION_ON); - led->action_tmp_dur = 0; - break; - case UPGT_LED_BLINK: - if (sc->sc_state != IEEE80211_S_RUN) { - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data_cmd, next); - return; - } - if (sc->sc_led_blink) { - /* previous blink was not finished */ - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data_cmd, next); - return; - } - led->mode = htole16(UPGT_LED_MODE_SET); - led->action_fix = htole16(UPGT_LED_ACTION_OFF); - led->action_tmp = htole16(UPGT_LED_ACTION_ON); - led->action_tmp_dur = htole16(UPGT_LED_ACTION_TMP_DUR); - /* lock blink */ - sc->sc_led_blink = 1; - callout_reset(&sc->sc_led_ch, hz, upgt_set_led_blink, sc); - break; - default: - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data_cmd, next); - return; - } - - data_cmd->buflen = sizeof(*mem) + sizeof(*led); - - mem->chksum = upgt_chksum_le((uint32_t *)led, - data_cmd->buflen - sizeof(*mem)); - - upgt_bulk_tx(sc, data_cmd); -} - -static void -upgt_set_led_blink(void *arg) -{ - struct upgt_softc *sc = arg; - - /* blink finished, we are ready for a next one */ - sc->sc_led_blink = 0; -} - -static void -upgt_init(void *priv) -{ - struct upgt_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - UPGT_LOCK(sc); - upgt_init_locked(sc); - UPGT_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -upgt_init_locked(struct upgt_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - - UPGT_ASSERT_LOCKED(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - upgt_stop_locked(sc); - - usbd_transfer_start(sc->sc_xfer[UPGT_BULK_RX]); - - (void)upgt_set_macfilter(sc, IEEE80211_S_SCAN); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - sc->sc_flags |= UPGT_FLAG_INITDONE; - - callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc); -} - -static int -upgt_set_macfilter(struct upgt_softc *sc, uint8_t state) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni; - struct upgt_data *data_cmd; - struct upgt_lmac_mem *mem; - struct upgt_lmac_filter *filter; - uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - UPGT_ASSERT_LOCKED(sc); - - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - device_printf(sc->sc_dev, "out of TX buffers.\n"); - return (ENOBUFS); - } - - /* - * Transmit the URB containing the CMD data. - */ - memset(data_cmd->buf, 0, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - filter = (struct upgt_lmac_filter *)(mem + 1); - - filter->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK; - filter->header1.type = UPGT_H1_TYPE_CTRL; - filter->header1.len = htole16( - sizeof(struct upgt_lmac_filter) - - sizeof(struct upgt_lmac_header)); - - filter->header2.reqid = htole32(sc->sc_memaddr_frame_start); - filter->header2.type = htole16(UPGT_H2_TYPE_MACFILTER); - filter->header2.flags = 0; - - switch (state) { - case IEEE80211_S_INIT: - DPRINTF(sc, UPGT_DEBUG_STATE, "%s: set MAC filter to INIT\n", - __func__); - filter->type = htole16(UPGT_FILTER_TYPE_RESET); - break; - case IEEE80211_S_SCAN: - DPRINTF(sc, UPGT_DEBUG_STATE, - "set MAC filter to SCAN (bssid %s)\n", - ether_sprintf(broadcast)); - filter->type = htole16(UPGT_FILTER_TYPE_NONE); - IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr); - IEEE80211_ADDR_COPY(filter->src, broadcast); - filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1); - filter->rxaddr = htole32(sc->sc_memaddr_rx_start); - filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2); - filter->rxhw = htole32(sc->sc_eeprom_hwrx); - filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3); - break; - case IEEE80211_S_RUN: - ni = ieee80211_ref_node(vap->iv_bss); - /* XXX monitor mode isn't tested yet. */ - if (vap->iv_opmode == IEEE80211_M_MONITOR) { - filter->type = htole16(UPGT_FILTER_TYPE_MONITOR); - IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr); - IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid); - filter->unknown1 = htole16(UPGT_FILTER_MONITOR_UNKNOWN1); - filter->rxaddr = htole32(sc->sc_memaddr_rx_start); - filter->unknown2 = htole16(UPGT_FILTER_MONITOR_UNKNOWN2); - filter->rxhw = htole32(sc->sc_eeprom_hwrx); - filter->unknown3 = htole16(UPGT_FILTER_MONITOR_UNKNOWN3); - } else { - DPRINTF(sc, UPGT_DEBUG_STATE, - "set MAC filter to RUN (bssid %s)\n", - ether_sprintf(ni->ni_bssid)); - filter->type = htole16(UPGT_FILTER_TYPE_STA); - IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr); - IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid); - filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1); - filter->rxaddr = htole32(sc->sc_memaddr_rx_start); - filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2); - filter->rxhw = htole32(sc->sc_eeprom_hwrx); - filter->unknown3 = htole16(UPGT_FILTER_UNKNOWN3); - } - ieee80211_free_node(ni); - break; - default: - device_printf(sc->sc_dev, - "MAC filter does not know that state\n"); - break; - } - - data_cmd->buflen = sizeof(*mem) + sizeof(*filter); - - mem->chksum = upgt_chksum_le((uint32_t *)filter, - data_cmd->buflen - sizeof(*mem)); - - upgt_bulk_tx(sc, data_cmd); - - return (0); -} - -static void -upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic) -{ - struct ifnet *ifp = ic->ic_ifp; - struct upgt_softc *sc = ifp->if_softc; - const struct ieee80211_txparam *tp; - - /* - * 0x01 = OFMD6 0x10 = DS1 - * 0x04 = OFDM9 0x11 = DS2 - * 0x06 = OFDM12 0x12 = DS5 - * 0x07 = OFDM18 0x13 = DS11 - * 0x08 = OFDM24 - * 0x09 = OFDM36 - * 0x0a = OFDM48 - * 0x0b = OFDM54 - */ - const uint8_t rateset_auto_11b[] = - { 0x13, 0x13, 0x12, 0x11, 0x11, 0x10, 0x10, 0x10 }; - const uint8_t rateset_auto_11g[] = - { 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x04, 0x01 }; - const uint8_t rateset_fix_11bg[] = - { 0x10, 0x11, 0x12, 0x13, 0x01, 0x04, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b }; - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - - /* XXX */ - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { - /* - * Automatic rate control is done by the device. - * We just pass the rateset from which the device - * will pickup a rate. - */ - if (ic->ic_curmode == IEEE80211_MODE_11B) - memcpy(sc->sc_cur_rateset, rateset_auto_11b, - sizeof(sc->sc_cur_rateset)); - if (ic->ic_curmode == IEEE80211_MODE_11G || - ic->ic_curmode == IEEE80211_MODE_AUTO) - memcpy(sc->sc_cur_rateset, rateset_auto_11g, - sizeof(sc->sc_cur_rateset)); - } else { - /* set a fixed rate */ - memset(sc->sc_cur_rateset, rateset_fix_11bg[tp->ucastrate], - sizeof(sc->sc_cur_rateset)); - } -} - -static void -upgt_set_multi(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (!(ifp->if_flags & IFF_UP)) - return; - - /* - * XXX don't know how to set a device. Lack of docs. Just try to set - * IFF_ALLMULTI flag here. - */ - ifp->if_flags |= IFF_ALLMULTI; -} - -static void -upgt_start(struct ifnet *ifp) -{ - struct upgt_softc *sc = ifp->if_softc; - struct upgt_data *data_tx; - struct ieee80211_node *ni; - struct mbuf *m; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - UPGT_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - data_tx = upgt_gettxbuf(sc); - if (data_tx == NULL) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - break; - } - - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - - if (upgt_tx_start(sc, m, ni, data_tx) != 0) { - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next); - UPGT_STAT_INC(sc, st_tx_inactive); - ieee80211_free_node(ni); - ifp->if_oerrors++; - continue; - } - sc->sc_tx_timer = 5; - } - UPGT_UNLOCK(sc); -} - -static int -upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct upgt_softc *sc = ifp->if_softc; - struct upgt_data *data_tx = NULL; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - - UPGT_LOCK(sc); - data_tx = upgt_gettxbuf(sc); - if (data_tx == NULL) { - ieee80211_free_node(ni); - m_freem(m); - UPGT_UNLOCK(sc); - return (ENOBUFS); - } - - if (upgt_tx_start(sc, m, ni, data_tx) != 0) { - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next); - UPGT_STAT_INC(sc, st_tx_inactive); - ieee80211_free_node(ni); - ifp->if_oerrors++; - UPGT_UNLOCK(sc); - return (EIO); - } - UPGT_UNLOCK(sc); - - sc->sc_tx_timer = 5; - return (0); -} - -static void -upgt_watchdog(void *arg) -{ - struct upgt_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - device_printf(sc->sc_dev, "watchdog timeout\n"); - /* upgt_init(ifp); XXX needs a process context ? */ - ifp->if_oerrors++; - return; - } - callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc); - } -} - -static uint32_t -upgt_mem_alloc(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < sc->sc_memory.pages; i++) { - if (sc->sc_memory.page[i].used == 0) { - sc->sc_memory.page[i].used = 1; - return (sc->sc_memory.page[i].addr); - } - } - - return (0); -} - -static void -upgt_scan_start(struct ieee80211com *ic) -{ - /* do nothing. */ -} - -static void -upgt_scan_end(struct ieee80211com *ic) -{ - /* do nothing. */ -} - -static void -upgt_set_channel(struct ieee80211com *ic) -{ - struct upgt_softc *sc = ic->ic_ifp->if_softc; - - UPGT_LOCK(sc); - upgt_set_chan(sc, ic->ic_curchan); - UPGT_UNLOCK(sc); -} - -static void -upgt_set_chan(struct upgt_softc *sc, struct ieee80211_channel *c) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct upgt_data *data_cmd; - struct upgt_lmac_mem *mem; - struct upgt_lmac_channel *chan; - int channel; - - UPGT_ASSERT_LOCKED(sc); - - channel = ieee80211_chan2ieee(ic, c); - if (channel == 0 || channel == IEEE80211_CHAN_ANY) { - /* XXX should NEVER happen */ - device_printf(sc->sc_dev, - "%s: invalid channel %x\n", __func__, channel); - return; - } - - DPRINTF(sc, UPGT_DEBUG_STATE, "%s: channel %d\n", __func__, channel); - - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - device_printf(sc->sc_dev, "%s: out of buffers.\n", __func__); - return; - } - /* - * Transmit the URB containing the CMD data. - */ - memset(data_cmd->buf, 0, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - chan = (struct upgt_lmac_channel *)(mem + 1); - - chan->header1.flags = UPGT_H1_FLAGS_TX_NO_CALLBACK; - chan->header1.type = UPGT_H1_TYPE_CTRL; - chan->header1.len = htole16( - sizeof(struct upgt_lmac_channel) - sizeof(struct upgt_lmac_header)); - - chan->header2.reqid = htole32(sc->sc_memaddr_frame_start); - chan->header2.type = htole16(UPGT_H2_TYPE_CHANNEL); - chan->header2.flags = 0; - - chan->unknown1 = htole16(UPGT_CHANNEL_UNKNOWN1); - chan->unknown2 = htole16(UPGT_CHANNEL_UNKNOWN2); - chan->freq6 = sc->sc_eeprom_freq6[channel]; - chan->settings = sc->sc_eeprom_freq6_settings; - chan->unknown3 = UPGT_CHANNEL_UNKNOWN3; - - memcpy(chan->freq3_1, &sc->sc_eeprom_freq3[channel].data, - sizeof(chan->freq3_1)); - memcpy(chan->freq4, &sc->sc_eeprom_freq4[channel], - sizeof(sc->sc_eeprom_freq4[channel])); - memcpy(chan->freq3_2, &sc->sc_eeprom_freq3[channel].data, - sizeof(chan->freq3_2)); - - data_cmd->buflen = sizeof(*mem) + sizeof(*chan); - - mem->chksum = upgt_chksum_le((uint32_t *)chan, - data_cmd->buflen - sizeof(*mem)); - - upgt_bulk_tx(sc, data_cmd); -} - -static struct ieee80211vap * -upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct upgt_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - uvp = (struct upgt_vap *) malloc(sizeof(struct upgt_vap), - M_80211_VAP, M_WAITOK | M_ZERO); - if (uvp == NULL) - return NULL; - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = upgt_newstate; - - /* setup device rates */ - upgt_setup_rates(vap, ic); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return vap; -} - -static int -upgt_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct upgt_vap *uvp = UPGT_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct upgt_softc *sc = ic->ic_ifp->if_softc; - - /* do it in a process context */ - sc->sc_state = nstate; - - IEEE80211_UNLOCK(ic); - UPGT_LOCK(sc); - callout_stop(&sc->sc_led_ch); - callout_stop(&sc->sc_watchdog_ch); - - switch (nstate) { - case IEEE80211_S_INIT: - /* do not accept any frames if the device is down */ - (void)upgt_set_macfilter(sc, sc->sc_state); - upgt_set_led(sc, UPGT_LED_OFF); - break; - case IEEE80211_S_SCAN: - upgt_set_chan(sc, ic->ic_curchan); - break; - case IEEE80211_S_AUTH: - upgt_set_chan(sc, ic->ic_curchan); - break; - case IEEE80211_S_ASSOC: - break; - case IEEE80211_S_RUN: - upgt_set_macfilter(sc, sc->sc_state); - upgt_set_led(sc, UPGT_LED_ON); - break; - default: - break; - } - UPGT_UNLOCK(sc); - IEEE80211_LOCK(ic); - return (uvp->newstate(vap, nstate, arg)); -} - -static void -upgt_vap_delete(struct ieee80211vap *vap) -{ - struct upgt_vap *uvp = UPGT_VAP(vap); - - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static void -upgt_update_mcast(struct ieee80211com *ic) -{ - struct upgt_softc *sc = ic->ic_softc; - - upgt_set_multi(sc); -} - -static int -upgt_eeprom_parse(struct upgt_softc *sc) -{ - struct upgt_eeprom_header *eeprom_header; - struct upgt_eeprom_option *eeprom_option; - uint16_t option_len; - uint16_t option_type; - uint16_t preamble_len; - int option_end = 0; - - /* calculate eeprom options start offset */ - eeprom_header = (struct upgt_eeprom_header *)sc->sc_eeprom; - preamble_len = le16toh(eeprom_header->preamble_len); - eeprom_option = (struct upgt_eeprom_option *)(sc->sc_eeprom + - (sizeof(struct upgt_eeprom_header) + preamble_len)); - - while (!option_end) { - /* the eeprom option length is stored in words */ - option_len = - (le16toh(eeprom_option->len) - 1) * sizeof(uint16_t); - option_type = - le16toh(eeprom_option->type); - - switch (option_type) { - case UPGT_EEPROM_TYPE_NAME: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM name len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_SERIAL: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM serial len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_MAC: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM mac len=%d\n", option_len); - - IEEE80211_ADDR_COPY(sc->sc_myaddr, eeprom_option->data); - break; - case UPGT_EEPROM_TYPE_HWRX: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM hwrx len=%d\n", option_len); - - upgt_eeprom_parse_hwrx(sc, eeprom_option->data); - break; - case UPGT_EEPROM_TYPE_CHIP: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM chip len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_FREQ3: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq3 len=%d\n", option_len); - - upgt_eeprom_parse_freq3(sc, eeprom_option->data, - option_len); - break; - case UPGT_EEPROM_TYPE_FREQ4: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq4 len=%d\n", option_len); - - upgt_eeprom_parse_freq4(sc, eeprom_option->data, - option_len); - break; - case UPGT_EEPROM_TYPE_FREQ5: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq5 len=%d\n", option_len); - break; - case UPGT_EEPROM_TYPE_FREQ6: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM freq6 len=%d\n", option_len); - - upgt_eeprom_parse_freq6(sc, eeprom_option->data, - option_len); - break; - case UPGT_EEPROM_TYPE_END: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM end len=%d\n", option_len); - option_end = 1; - break; - case UPGT_EEPROM_TYPE_OFF: - DPRINTF(sc, UPGT_DEBUG_FW, - "%s: EEPROM off without end option\n", __func__); - return (EIO); - default: - DPRINTF(sc, UPGT_DEBUG_FW, - "EEPROM unknown type 0x%04x len=%d\n", - option_type, option_len); - break; - } - - /* jump to next EEPROM option */ - eeprom_option = (struct upgt_eeprom_option *) - (eeprom_option->data + option_len); - } - - return (0); -} - -static void -upgt_eeprom_parse_freq3(struct upgt_softc *sc, uint8_t *data, int len) -{ - struct upgt_eeprom_freq3_header *freq3_header; - struct upgt_lmac_freq3 *freq3; - int i, elements, flags; - unsigned channel; - - freq3_header = (struct upgt_eeprom_freq3_header *)data; - freq3 = (struct upgt_lmac_freq3 *)(freq3_header + 1); - - flags = freq3_header->flags; - elements = freq3_header->elements; - - DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d\n", - flags, elements); - - for (i = 0; i < elements; i++) { - channel = ieee80211_mhz2ieee(le16toh(freq3[i].freq), 0); - if (!(channel >= 0 && channel < IEEE80211_CHAN_MAX)) - continue; - - sc->sc_eeprom_freq3[channel] = freq3[i]; - - DPRINTF(sc, UPGT_DEBUG_FW, "frequency=%d, channel=%d\n", - le16toh(sc->sc_eeprom_freq3[channel].freq), channel); - } -} - -void -upgt_eeprom_parse_freq4(struct upgt_softc *sc, uint8_t *data, int len) -{ - struct upgt_eeprom_freq4_header *freq4_header; - struct upgt_eeprom_freq4_1 *freq4_1; - struct upgt_eeprom_freq4_2 *freq4_2; - int i, j, elements, settings, flags; - unsigned channel; - - freq4_header = (struct upgt_eeprom_freq4_header *)data; - freq4_1 = (struct upgt_eeprom_freq4_1 *)(freq4_header + 1); - flags = freq4_header->flags; - elements = freq4_header->elements; - settings = freq4_header->settings; - - /* we need this value later */ - sc->sc_eeprom_freq6_settings = freq4_header->settings; - - DPRINTF(sc, UPGT_DEBUG_FW, "flags=0x%02x elements=%d settings=%d\n", - flags, elements, settings); - - for (i = 0; i < elements; i++) { - channel = ieee80211_mhz2ieee(le16toh(freq4_1[i].freq), 0); - if (!(channel >= 0 && channel < IEEE80211_CHAN_MAX)) - continue; - - freq4_2 = (struct upgt_eeprom_freq4_2 *)freq4_1[i].data; - for (j = 0; j < settings; j++) { - sc->sc_eeprom_freq4[channel][j].cmd = freq4_2[j]; - sc->sc_eeprom_freq4[channel][j].pad = 0; - } - - DPRINTF(sc, UPGT_DEBUG_FW, "frequency=%d, channel=%d\n", - le16toh(freq4_1[i].freq), channel); - } -} - -void -upgt_eeprom_parse_freq6(struct upgt_softc *sc, uint8_t *data, int len) -{ - struct upgt_lmac_freq6 *freq6; - int i, elements; - unsigned channel; - - freq6 = (struct upgt_lmac_freq6 *)data; - elements = len / sizeof(struct upgt_lmac_freq6); - - DPRINTF(sc, UPGT_DEBUG_FW, "elements=%d\n", elements); - - for (i = 0; i < elements; i++) { - channel = ieee80211_mhz2ieee(le16toh(freq6[i].freq), 0); - if (!(channel >= 0 && channel < IEEE80211_CHAN_MAX)) - continue; - - sc->sc_eeprom_freq6[channel] = freq6[i]; - - DPRINTF(sc, UPGT_DEBUG_FW, "frequency=%d, channel=%d\n", - le16toh(sc->sc_eeprom_freq6[channel].freq), channel); - } -} - -static void -upgt_eeprom_parse_hwrx(struct upgt_softc *sc, uint8_t *data) -{ - struct upgt_eeprom_option_hwrx *option_hwrx; - - option_hwrx = (struct upgt_eeprom_option_hwrx *)data; - - sc->sc_eeprom_hwrx = option_hwrx->rxfilter - UPGT_EEPROM_RX_CONST; - - DPRINTF(sc, UPGT_DEBUG_FW, "hwrx option value=0x%04x\n", - sc->sc_eeprom_hwrx); -} - -static int -upgt_eeprom_read(struct upgt_softc *sc) -{ - struct upgt_data *data_cmd; - struct upgt_lmac_mem *mem; - struct upgt_lmac_eeprom *eeprom; - int block, error, offset; - - UPGT_LOCK(sc); - usb_pause_mtx(&sc->sc_mtx, 100); - - offset = 0; - block = UPGT_EEPROM_BLOCK_SIZE; - while (offset < UPGT_EEPROM_SIZE) { - DPRINTF(sc, UPGT_DEBUG_FW, - "request EEPROM block (offset=%d, len=%d)\n", offset, block); - - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - UPGT_UNLOCK(sc); - return (ENOBUFS); - } - - /* - * Transmit the URB containing the CMD data. - */ - memset(data_cmd->buf, 0, MCLBYTES); - - mem = (struct upgt_lmac_mem *)data_cmd->buf; - mem->addr = htole32(sc->sc_memaddr_frame_start + - UPGT_MEMSIZE_FRAME_HEAD); - - eeprom = (struct upgt_lmac_eeprom *)(mem + 1); - eeprom->header1.flags = 0; - eeprom->header1.type = UPGT_H1_TYPE_CTRL; - eeprom->header1.len = htole16(( - sizeof(struct upgt_lmac_eeprom) - - sizeof(struct upgt_lmac_header)) + block); - - eeprom->header2.reqid = htole32(sc->sc_memaddr_frame_start); - eeprom->header2.type = htole16(UPGT_H2_TYPE_EEPROM); - eeprom->header2.flags = 0; - - eeprom->offset = htole16(offset); - eeprom->len = htole16(block); - - data_cmd->buflen = sizeof(*mem) + sizeof(*eeprom) + block; - - mem->chksum = upgt_chksum_le((uint32_t *)eeprom, - data_cmd->buflen - sizeof(*mem)); - upgt_bulk_tx(sc, data_cmd); - - error = mtx_sleep(sc, &sc->sc_mtx, 0, "eeprom_request", hz); - if (error != 0) { - device_printf(sc->sc_dev, - "timeout while waiting for EEPROM data\n"); - UPGT_UNLOCK(sc); - return (EIO); - } - - offset += block; - if (UPGT_EEPROM_SIZE - offset < block) - block = UPGT_EEPROM_SIZE - offset; - } - - UPGT_UNLOCK(sc); - return (0); -} - -/* - * When a rx data came in the function returns a mbuf and a rssi values. - */ -static struct mbuf * -upgt_rxeof(struct usb_xfer *xfer, struct upgt_data *data, int *rssi) -{ - struct mbuf *m = NULL; - struct upgt_softc *sc = usbd_xfer_softc(xfer); - struct upgt_lmac_header *header; - struct upgt_lmac_eeprom *eeprom; - uint8_t h1_type; - uint16_t h2_type; - int actlen, sumlen; - - usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL); - - UPGT_ASSERT_LOCKED(sc); - - if (actlen < 1) - return (NULL); - - /* Check only at the very beginning. */ - if (!(sc->sc_flags & UPGT_FLAG_FWLOADED) && - (memcmp(data->buf, "OK", 2) == 0)) { - sc->sc_flags |= UPGT_FLAG_FWLOADED; - wakeup_one(sc); - return (NULL); - } - - if (actlen < UPGT_RX_MINSZ) - return (NULL); - - /* - * Check what type of frame came in. - */ - header = (struct upgt_lmac_header *)(data->buf + 4); - - h1_type = header->header1.type; - h2_type = le16toh(header->header2.type); - - if (h1_type == UPGT_H1_TYPE_CTRL && h2_type == UPGT_H2_TYPE_EEPROM) { - eeprom = (struct upgt_lmac_eeprom *)(data->buf + 4); - uint16_t eeprom_offset = le16toh(eeprom->offset); - uint16_t eeprom_len = le16toh(eeprom->len); - - DPRINTF(sc, UPGT_DEBUG_FW, - "received EEPROM block (offset=%d, len=%d)\n", - eeprom_offset, eeprom_len); - - memcpy(sc->sc_eeprom + eeprom_offset, - data->buf + sizeof(struct upgt_lmac_eeprom) + 4, - eeprom_len); - - /* EEPROM data has arrived in time, wakeup. */ - wakeup(sc); - } else if (h1_type == UPGT_H1_TYPE_CTRL && - h2_type == UPGT_H2_TYPE_TX_DONE) { - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: received 802.11 TX done\n", - __func__); - upgt_tx_done(sc, data->buf + 4); - } else if (h1_type == UPGT_H1_TYPE_RX_DATA || - h1_type == UPGT_H1_TYPE_RX_DATA_MGMT) { - DPRINTF(sc, UPGT_DEBUG_RECV, "%s: received 802.11 RX data\n", - __func__); - m = upgt_rx(sc, data->buf + 4, le16toh(header->header1.len), - rssi); - } else if (h1_type == UPGT_H1_TYPE_CTRL && - h2_type == UPGT_H2_TYPE_STATS) { - DPRINTF(sc, UPGT_DEBUG_STAT, "%s: received statistic data\n", - __func__); - /* TODO: what could we do with the statistic data? */ - } else { - /* ignore unknown frame types */ - DPRINTF(sc, UPGT_DEBUG_INTR, - "received unknown frame type 0x%02x\n", - header->header1.type); - } - return (m); -} - -/* - * The firmware awaits a checksum for each frame we send to it. - * The algorithm used therefor is uncommon but somehow similar to CRC32. - */ -static uint32_t -upgt_chksum_le(const uint32_t *buf, size_t size) -{ - int i; - uint32_t crc = 0; - - for (i = 0; i < size; i += sizeof(uint32_t)) { - crc = htole32(crc ^ *buf++); - crc = htole32((crc >> 5) ^ (crc << 3)); - } - - return (crc); -} - -static struct mbuf * -upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct upgt_lmac_rx_desc *rxdesc; - struct mbuf *m; - - /* - * don't pass packets to the ieee80211 framework if the driver isn't - * RUNNING. - */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - return (NULL); - - /* access RX packet descriptor */ - rxdesc = (struct upgt_lmac_rx_desc *)data; - - /* create mbuf which is suitable for strict alignment archs */ - KASSERT((pkglen + ETHER_ALIGN) < MCLBYTES, - ("A current mbuf storage is small (%d)", pkglen + ETHER_ALIGN)); - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - device_printf(sc->sc_dev, "could not create RX mbuf\n"); - return (NULL); - } - m_adj(m, ETHER_ALIGN); - memcpy(mtod(m, char *), rxdesc->data, pkglen); - /* trim FCS */ - m->m_len = m->m_pkthdr.len = pkglen - IEEE80211_CRC_LEN; - m->m_pkthdr.rcvif = ifp; - - if (ieee80211_radiotap_active(ic)) { - struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = 0; - tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate); - tap->wr_antsignal = rxdesc->rssi; - } - ifp->if_ipackets++; - - DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__); - *rssi = rxdesc->rssi; - return (m); -} - -static uint8_t -upgt_rx_rate(struct upgt_softc *sc, const int rate) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - static const uint8_t cck_upgt2rate[4] = { 2, 4, 11, 22 }; - static const uint8_t ofdm_upgt2rate[12] = - { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - - if (ic->ic_curmode == IEEE80211_MODE_11B && - !(rate < 0 || rate > 3)) - return cck_upgt2rate[rate & 0xf]; - - if (ic->ic_curmode == IEEE80211_MODE_11G && - !(rate < 0 || rate > 11)) - return ofdm_upgt2rate[rate & 0xf]; - - return (0); -} - -static void -upgt_tx_done(struct upgt_softc *sc, uint8_t *data) -{ - struct ifnet *ifp = sc->sc_ifp; - struct upgt_lmac_tx_done_desc *desc; - int i, freed = 0; - - UPGT_ASSERT_LOCKED(sc); - - desc = (struct upgt_lmac_tx_done_desc *)data; - - for (i = 0; i < UPGT_TX_MAXCOUNT; i++) { - struct upgt_data *data_tx = &sc->sc_tx_data[i]; - - if (data_tx->addr == le32toh(desc->header2.reqid)) { - upgt_mem_free(sc, data_tx->addr); - data_tx->ni = NULL; - data_tx->addr = 0; - data_tx->m = NULL; - data_tx->use = 0; - - DPRINTF(sc, UPGT_DEBUG_TX_PROC, - "TX done: memaddr=0x%08x, status=0x%04x, rssi=%d, ", - le32toh(desc->header2.reqid), - le16toh(desc->status), le16toh(desc->rssi)); - DPRINTF(sc, UPGT_DEBUG_TX_PROC, "seq=%d\n", - le16toh(desc->seq)); - - freed++; - } - } - - if (freed != 0) { - sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - UPGT_UNLOCK(sc); - upgt_start(ifp); - UPGT_LOCK(sc); - } -} - -static void -upgt_mem_free(struct upgt_softc *sc, uint32_t addr) -{ - int i; - - for (i = 0; i < sc->sc_memory.pages; i++) { - if (sc->sc_memory.page[i].addr == addr) { - sc->sc_memory.page[i].used = 0; - return; - } - } - - device_printf(sc->sc_dev, - "could not free memory address 0x%08x\n", addr); -} - -static int -upgt_fw_load(struct upgt_softc *sc) -{ - const struct firmware *fw; - struct upgt_data *data_cmd; - struct upgt_fw_x2_header *x2; - char start_fwload_cmd[] = { 0x3c, 0x0d }; - int error = 0, offset, bsize, n; - uint32_t crc32; - - fw = firmware_get(upgt_fwname); - if (fw == NULL) { - device_printf(sc->sc_dev, "could not read microcode %s\n", - upgt_fwname); - return (EIO); - } - - UPGT_LOCK(sc); - - /* send firmware start load command */ - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - error = ENOBUFS; - goto fail; - } - data_cmd->buflen = sizeof(start_fwload_cmd); - memcpy(data_cmd->buf, start_fwload_cmd, data_cmd->buflen); - upgt_bulk_tx(sc, data_cmd); - - /* send X2 header */ - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - error = ENOBUFS; - goto fail; - } - data_cmd->buflen = sizeof(struct upgt_fw_x2_header); - x2 = (struct upgt_fw_x2_header *)data_cmd->buf; - memcpy(x2->signature, UPGT_X2_SIGNATURE, UPGT_X2_SIGNATURE_SIZE); - x2->startaddr = htole32(UPGT_MEMADDR_FIRMWARE_START); - x2->len = htole32(fw->datasize); - x2->crc = upgt_crc32_le((uint8_t *)data_cmd->buf + - UPGT_X2_SIGNATURE_SIZE, - sizeof(struct upgt_fw_x2_header) - UPGT_X2_SIGNATURE_SIZE - - sizeof(uint32_t)); - upgt_bulk_tx(sc, data_cmd); - - /* download firmware */ - for (offset = 0; offset < fw->datasize; offset += bsize) { - if (fw->datasize - offset > UPGT_FW_BLOCK_SIZE) - bsize = UPGT_FW_BLOCK_SIZE; - else - bsize = fw->datasize - offset; - - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - error = ENOBUFS; - goto fail; - } - n = upgt_fw_copy((const uint8_t *)fw->data + offset, - data_cmd->buf, bsize); - data_cmd->buflen = bsize; - upgt_bulk_tx(sc, data_cmd); - - DPRINTF(sc, UPGT_DEBUG_FW, "FW offset=%d, read=%d, sent=%d\n", - offset, n, bsize); - bsize = n; - } - DPRINTF(sc, UPGT_DEBUG_FW, "%s: firmware downloaded\n", __func__); - - /* load firmware */ - data_cmd = upgt_getbuf(sc); - if (data_cmd == NULL) { - error = ENOBUFS; - goto fail; - } - crc32 = upgt_crc32_le(fw->data, fw->datasize); - *((uint32_t *)(data_cmd->buf) ) = crc32; - *((uint8_t *)(data_cmd->buf) + 4) = 'g'; - *((uint8_t *)(data_cmd->buf) + 5) = '\r'; - data_cmd->buflen = 6; - upgt_bulk_tx(sc, data_cmd); - - /* waiting 'OK' response. */ - usbd_transfer_start(sc->sc_xfer[UPGT_BULK_RX]); - error = mtx_sleep(sc, &sc->sc_mtx, 0, "upgtfw", 2 * hz); - if (error != 0) { - device_printf(sc->sc_dev, "firmware load failed\n"); - error = EIO; - } - - DPRINTF(sc, UPGT_DEBUG_FW, "%s: firmware loaded\n", __func__); -fail: - UPGT_UNLOCK(sc); - firmware_put(fw, FIRMWARE_UNLOAD); - return (error); -} - -static uint32_t -upgt_crc32_le(const void *buf, size_t size) -{ - uint32_t crc; - - crc = ether_crc32_le(buf, size); - - /* apply final XOR value as common for CRC-32 */ - crc = htole32(crc ^ 0xffffffffU); - - return (crc); -} - -/* - * While copying the version 2 firmware, we need to replace two characters: - * - * 0x7e -> 0x7d 0x5e - * 0x7d -> 0x7d 0x5d - */ -static int -upgt_fw_copy(const uint8_t *src, char *dst, int size) -{ - int i, j; - - for (i = 0, j = 0; i < size && j < size; i++) { - switch (src[i]) { - case 0x7e: - dst[j] = 0x7d; - j++; - dst[j] = 0x5e; - j++; - break; - case 0x7d: - dst[j] = 0x7d; - j++; - dst[j] = 0x5d; - j++; - break; - default: - dst[j] = src[i]; - j++; - break; - } - } - - return (i); -} - -static int -upgt_mem_init(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < UPGT_MEMORY_MAX_PAGES; i++) { - sc->sc_memory.page[i].used = 0; - - if (i == 0) { - /* - * The first memory page is always reserved for - * command data. - */ - sc->sc_memory.page[i].addr = - sc->sc_memaddr_frame_start + MCLBYTES; - } else { - sc->sc_memory.page[i].addr = - sc->sc_memory.page[i - 1].addr + MCLBYTES; - } - - if (sc->sc_memory.page[i].addr + MCLBYTES >= - sc->sc_memaddr_frame_end) - break; - - DPRINTF(sc, UPGT_DEBUG_FW, "memory address page %d=0x%08x\n", - i, sc->sc_memory.page[i].addr); - } - - sc->sc_memory.pages = i; - - DPRINTF(sc, UPGT_DEBUG_FW, "memory pages=%d\n", sc->sc_memory.pages); - return (0); -} - -static int -upgt_fw_verify(struct upgt_softc *sc) -{ - const struct firmware *fw; - const struct upgt_fw_bra_option *bra_opt; - const struct upgt_fw_bra_descr *descr; - const uint8_t *p; - const uint32_t *uc; - uint32_t bra_option_type, bra_option_len; - int offset, bra_end = 0, error = 0; - - fw = firmware_get(upgt_fwname); - if (fw == NULL) { - device_printf(sc->sc_dev, "could not read microcode %s\n", - upgt_fwname); - return EIO; - } - - /* - * Seek to beginning of Boot Record Area (BRA). - */ - for (offset = 0; offset < fw->datasize; offset += sizeof(*uc)) { - uc = (const uint32_t *)((const uint8_t *)fw->data + offset); - if (*uc == 0) - break; - } - for (; offset < fw->datasize; offset += sizeof(*uc)) { - uc = (const uint32_t *)((const uint8_t *)fw->data + offset); - if (*uc != 0) - break; - } - if (offset == fw->datasize) { - device_printf(sc->sc_dev, - "firmware Boot Record Area not found\n"); - error = EIO; - goto fail; - } - - DPRINTF(sc, UPGT_DEBUG_FW, - "firmware Boot Record Area found at offset %d\n", offset); - - /* - * Parse Boot Record Area (BRA) options. - */ - while (offset < fw->datasize && bra_end == 0) { - /* get current BRA option */ - p = (const uint8_t *)fw->data + offset; - bra_opt = (const struct upgt_fw_bra_option *)p; - bra_option_type = le32toh(bra_opt->type); - bra_option_len = le32toh(bra_opt->len) * sizeof(*uc); - - switch (bra_option_type) { - case UPGT_BRA_TYPE_FW: - DPRINTF(sc, UPGT_DEBUG_FW, "UPGT_BRA_TYPE_FW len=%d\n", - bra_option_len); - - if (bra_option_len != UPGT_BRA_FWTYPE_SIZE) { - device_printf(sc->sc_dev, - "wrong UPGT_BRA_TYPE_FW len\n"); - error = EIO; - goto fail; - } - if (memcmp(UPGT_BRA_FWTYPE_LM86, bra_opt->data, - bra_option_len) == 0) { - sc->sc_fw_type = UPGT_FWTYPE_LM86; - break; - } - if (memcmp(UPGT_BRA_FWTYPE_LM87, bra_opt->data, - bra_option_len) == 0) { - sc->sc_fw_type = UPGT_FWTYPE_LM87; - break; - } - device_printf(sc->sc_dev, - "unsupported firmware type\n"); - error = EIO; - goto fail; - case UPGT_BRA_TYPE_VERSION: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_VERSION len=%d\n", bra_option_len); - break; - case UPGT_BRA_TYPE_DEPIF: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_DEPIF len=%d\n", bra_option_len); - break; - case UPGT_BRA_TYPE_EXPIF: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_EXPIF len=%d\n", bra_option_len); - break; - case UPGT_BRA_TYPE_DESCR: - DPRINTF(sc, UPGT_DEBUG_FW, - "UPGT_BRA_TYPE_DESCR len=%d\n", bra_option_len); - - descr = (const struct upgt_fw_bra_descr *)bra_opt->data; - - sc->sc_memaddr_frame_start = - le32toh(descr->memaddr_space_start); - sc->sc_memaddr_frame_end = - le32toh(descr->memaddr_space_end); - - DPRINTF(sc, UPGT_DEBUG_FW, - "memory address space start=0x%08x\n", - sc->sc_memaddr_frame_start); - DPRINTF(sc, UPGT_DEBUG_FW, - "memory address space end=0x%08x\n", - sc->sc_memaddr_frame_end); - break; - case UPGT_BRA_TYPE_END: - DPRINTF(sc, UPGT_DEBUG_FW, "UPGT_BRA_TYPE_END len=%d\n", - bra_option_len); - bra_end = 1; - break; - default: - DPRINTF(sc, UPGT_DEBUG_FW, "unknown BRA option len=%d\n", - bra_option_len); - error = EIO; - goto fail; - } - - /* jump to next BRA option */ - offset += sizeof(struct upgt_fw_bra_option) + bra_option_len; - } - - DPRINTF(sc, UPGT_DEBUG_FW, "%s: firmware verified", __func__); -fail: - firmware_put(fw, FIRMWARE_UNLOAD); - return (error); -} - -static void -upgt_bulk_tx(struct upgt_softc *sc, struct upgt_data *data) -{ - - UPGT_ASSERT_LOCKED(sc); - - STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); - UPGT_STAT_INC(sc, st_tx_pending); - usbd_transfer_start(sc->sc_xfer[UPGT_BULK_TX]); -} - -static int -upgt_device_reset(struct upgt_softc *sc) -{ - struct upgt_data *data; - char init_cmd[] = { 0x7e, 0x7e, 0x7e, 0x7e }; - - UPGT_LOCK(sc); - - data = upgt_getbuf(sc); - if (data == NULL) { - UPGT_UNLOCK(sc); - return (ENOBUFS); - } - memcpy(data->buf, init_cmd, sizeof(init_cmd)); - data->buflen = sizeof(init_cmd); - upgt_bulk_tx(sc, data); - usb_pause_mtx(&sc->sc_mtx, 100); - - UPGT_UNLOCK(sc); - DPRINTF(sc, UPGT_DEBUG_FW, "%s: device initialized\n", __func__); - return (0); -} - -static int -upgt_alloc_tx(struct upgt_softc *sc) -{ - int i; - - STAILQ_INIT(&sc->sc_tx_active); - STAILQ_INIT(&sc->sc_tx_inactive); - STAILQ_INIT(&sc->sc_tx_pending); - - for (i = 0; i < UPGT_TX_MAXCOUNT; i++) { - struct upgt_data *data = &sc->sc_tx_data[i]; - - data->buf = malloc(MCLBYTES, M_USBDEV, M_WAITOK | M_ZERO); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate TX buffer\n"); - return (ENOMEM); - } - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); - UPGT_STAT_INC(sc, st_tx_inactive); - } - - return (0); -} - -static int -upgt_alloc_rx(struct upgt_softc *sc) -{ - int i; - - STAILQ_INIT(&sc->sc_rx_active); - STAILQ_INIT(&sc->sc_rx_inactive); - - for (i = 0; i < UPGT_RX_MAXCOUNT; i++) { - struct upgt_data *data = &sc->sc_rx_data[i]; - - data->buf = malloc(MCLBYTES, M_USBDEV, M_WAITOK | M_ZERO); - if (data->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate RX buffer\n"); - return (ENOMEM); - } - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - } - - return (0); -} - -static int -upgt_detach(device_t dev) -{ - struct upgt_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - if (!device_is_attached(dev)) - return 0; - - upgt_stop(sc); - - callout_drain(&sc->sc_led_ch); - callout_drain(&sc->sc_watchdog_ch); - - usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS); - ieee80211_ifdetach(ic); - upgt_free_rx(sc); - upgt_free_tx(sc); - - if_free(ifp); - mtx_destroy(&sc->sc_mtx); - - return (0); -} - -static void -upgt_free_rx(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < UPGT_RX_MAXCOUNT; i++) { - struct upgt_data *data = &sc->sc_rx_data[i]; - - free(data->buf, M_USBDEV); - data->ni = NULL; - } -} - -static void -upgt_free_tx(struct upgt_softc *sc) -{ - int i; - - for (i = 0; i < UPGT_TX_MAXCOUNT; i++) { - struct upgt_data *data = &sc->sc_tx_data[i]; - - free(data->buf, M_USBDEV); - data->ni = NULL; - } -} - -static void -upgt_abort_xfers_locked(struct upgt_softc *sc) -{ - int i; - - UPGT_ASSERT_LOCKED(sc); - /* abort any pending transfers */ - for (i = 0; i < UPGT_N_XFERS; i++) - usbd_transfer_stop(sc->sc_xfer[i]); -} - -static void -upgt_abort_xfers(struct upgt_softc *sc) -{ - - UPGT_LOCK(sc); - upgt_abort_xfers_locked(sc); - UPGT_UNLOCK(sc); -} - -#define UPGT_SYSCTL_STAT_ADD32(c, h, n, p, d) \ - SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) - -static void -upgt_sysctl_node(struct upgt_softc *sc) -{ - struct sysctl_ctx_list *ctx; - struct sysctl_oid_list *child; - struct sysctl_oid *tree; - struct upgt_stat *stats; - - stats = &sc->sc_stat; - ctx = device_get_sysctl_ctx(sc->sc_dev); - child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)); - - tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, - NULL, "UPGT statistics"); - child = SYSCTL_CHILDREN(tree); - UPGT_SYSCTL_STAT_ADD32(ctx, child, "tx_active", - &stats->st_tx_active, "Active numbers in TX queue"); - UPGT_SYSCTL_STAT_ADD32(ctx, child, "tx_inactive", - &stats->st_tx_inactive, "Inactive numbers in TX queue"); - UPGT_SYSCTL_STAT_ADD32(ctx, child, "tx_pending", - &stats->st_tx_pending, "Pending numbers in TX queue"); -} - -#undef UPGT_SYSCTL_STAT_ADD32 - -static struct upgt_data * -_upgt_getbuf(struct upgt_softc *sc) -{ - struct upgt_data *bf; - - bf = STAILQ_FIRST(&sc->sc_tx_inactive); - if (bf != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next); - UPGT_STAT_DEC(sc, st_tx_inactive); - } else - bf = NULL; - if (bf == NULL) - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: %s\n", __func__, - "out of xmit buffers"); - return (bf); -} - -static struct upgt_data * -upgt_getbuf(struct upgt_softc *sc) -{ - struct upgt_data *bf; - - UPGT_ASSERT_LOCKED(sc); - - bf = _upgt_getbuf(sc); - if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: stop queue\n", __func__); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - } - - return (bf); -} - -static struct upgt_data * -upgt_gettxbuf(struct upgt_softc *sc) -{ - struct upgt_data *bf; - - UPGT_ASSERT_LOCKED(sc); - - bf = upgt_getbuf(sc); - if (bf == NULL) - return (NULL); - - bf->addr = upgt_mem_alloc(sc); - if (bf->addr == 0) { - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: no free prism memory!\n", - __func__); - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - UPGT_STAT_INC(sc, st_tx_inactive); - if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE)) - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - return (NULL); - } - return (bf); -} - -static int -upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni, - struct upgt_data *data) -{ - struct ieee80211vap *vap = ni->ni_vap; - int error = 0, len; - struct ieee80211_frame *wh; - struct ieee80211_key *k; - struct ifnet *ifp = sc->sc_ifp; - struct upgt_lmac_mem *mem; - struct upgt_lmac_tx_desc *txdesc; - - UPGT_ASSERT_LOCKED(sc); - - upgt_set_led(sc, UPGT_LED_BLINK); - - /* - * Software crypto. - */ - wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m); - if (k == NULL) { - device_printf(sc->sc_dev, - "ieee80211_crypto_encap returns NULL.\n"); - error = EIO; - goto done; - } - - /* in case packet header moved, reset pointer */ - wh = mtod(m, struct ieee80211_frame *); - } - - /* Transmit the URB containing the TX data. */ - memset(data->buf, 0, MCLBYTES); - mem = (struct upgt_lmac_mem *)data->buf; - mem->addr = htole32(data->addr); - txdesc = (struct upgt_lmac_tx_desc *)(mem + 1); - - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT) { - /* mgmt frames */ - txdesc->header1.flags = UPGT_H1_FLAGS_TX_MGMT; - /* always send mgmt frames at lowest rate (DS1) */ - memset(txdesc->rates, 0x10, sizeof(txdesc->rates)); - } else { - /* data frames */ - txdesc->header1.flags = UPGT_H1_FLAGS_TX_DATA; - memcpy(txdesc->rates, sc->sc_cur_rateset, sizeof(txdesc->rates)); - } - txdesc->header1.type = UPGT_H1_TYPE_TX_DATA; - txdesc->header1.len = htole16(m->m_pkthdr.len); - txdesc->header2.reqid = htole32(data->addr); - txdesc->header2.type = htole16(UPGT_H2_TYPE_TX_ACK_YES); - txdesc->header2.flags = htole16(UPGT_H2_FLAGS_TX_ACK_YES); - txdesc->type = htole32(UPGT_TX_DESC_TYPE_DATA); - txdesc->pad3[0] = UPGT_TX_DESC_PAD3_SIZE; - - if (ieee80211_radiotap_active_vap(vap)) { - struct upgt_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = 0; /* XXX where to get from? */ - - ieee80211_radiotap_tx(vap, m); - } - - /* copy frame below our TX descriptor header */ - m_copydata(m, 0, m->m_pkthdr.len, - data->buf + (sizeof(*mem) + sizeof(*txdesc))); - /* calculate frame size */ - len = sizeof(*mem) + sizeof(*txdesc) + m->m_pkthdr.len; - /* we need to align the frame to a 4 byte boundary */ - len = (len + 3) & ~3; - /* calculate frame checksum */ - mem->chksum = upgt_chksum_le((uint32_t *)txdesc, len - sizeof(*mem)); - data->ni = ni; - data->m = m; - data->buflen = len; - - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: TX start data sending (%d bytes)\n", - __func__, len); - KASSERT(len <= MCLBYTES, ("mbuf is small for saving data")); - - upgt_bulk_tx(sc, data); -done: - /* - * If we don't regulary read the device statistics, the RX queue - * will stall. It's strange, but it works, so we keep reading - * the statistics here. *shrug* - */ - if (!(ifp->if_opackets % UPGT_TX_STAT_INTERVAL)) - upgt_get_stats(sc); - - return (error); -} - -static void -upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct upgt_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct mbuf *m = NULL; - struct upgt_data *data; - int8_t nf; - int rssi = -1; - - UPGT_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - data = STAILQ_FIRST(&sc->sc_rx_active); - if (data == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); - m = upgt_rxeof(xfer, data, &rssi); - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - data = STAILQ_FIRST(&sc->sc_rx_inactive); - if (data == NULL) - return; - STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next); - STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next); - usbd_xfer_set_frame_data(xfer, 0, data->buf, - usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - - /* - * To avoid LOR we should unlock our private mutex here to call - * ieee80211_input() because here is at the end of a USB - * callback and safe to unlock. - */ - UPGT_UNLOCK(sc); - if (m != NULL) { - wh = mtod(m, struct ieee80211_frame *); - ni = ieee80211_find_rxnode(ic, - (struct ieee80211_frame_min *)wh); - nf = -95; /* XXX */ - if (ni != NULL) { - (void) ieee80211_input(ni, m, rssi, nf); - /* node is no longer needed */ - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, rssi, nf); - m = NULL; - } - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && - !IFQ_IS_EMPTY(&ifp->if_snd)) - upgt_start(ifp); - UPGT_LOCK(sc); - break; - default: - /* needs it to the inactive queue due to a error. */ - data = STAILQ_FIRST(&sc->sc_rx_active); - if (data != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - } - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - ifp->if_ierrors++; - goto setup; - } - break; - } -} - -static void -upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct upgt_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct upgt_data *data; - - UPGT_ASSERT_LOCKED(sc); - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - data = STAILQ_FIRST(&sc->sc_tx_active); - if (data == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next); - UPGT_STAT_DEC(sc, st_tx_active); - upgt_txeof(xfer, data); - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); - UPGT_STAT_INC(sc, st_tx_inactive); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - data = STAILQ_FIRST(&sc->sc_tx_pending); - if (data == NULL) { - DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: empty pending queue\n", - __func__); - return; - } - STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next); - UPGT_STAT_DEC(sc, st_tx_pending); - STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next); - UPGT_STAT_INC(sc, st_tx_active); - - usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); - usbd_transfer_submit(xfer); - UPGT_UNLOCK(sc); - upgt_start(ifp); - UPGT_LOCK(sc); - break; - default: - data = STAILQ_FIRST(&sc->sc_tx_active); - if (data == NULL) - goto setup; - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - ifp->if_oerrors++; - } - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto setup; - } - break; - } -} - -static device_method_t upgt_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, upgt_match), - DEVMETHOD(device_attach, upgt_attach), - DEVMETHOD(device_detach, upgt_detach), - - DEVMETHOD_END -}; - -static driver_t upgt_driver = { - "upgt", - upgt_methods, - sizeof(struct upgt_softc) -}; - -static devclass_t upgt_devclass; - -DRIVER_MODULE(if_upgt, uhub, upgt_driver, upgt_devclass, NULL, NULL); -MODULE_VERSION(if_upgt, 1); -MODULE_DEPEND(if_upgt, usb, 1, 1, 1); -MODULE_DEPEND(if_upgt, wlan, 1, 1, 1); -MODULE_DEPEND(if_upgt, upgtfw_fw, 1, 1, 1); diff --git a/sys/bus/u4b/wlan/if_upgtvar.h b/sys/bus/u4b/wlan/if_upgtvar.h deleted file mode 100644 index db64a88949..0000000000 --- a/sys/bus/u4b/wlan/if_upgtvar.h +++ /dev/null @@ -1,482 +0,0 @@ -/* $OpenBSD: if_upgtvar.h,v 1.14 2008/02/02 13:48:44 mglocker Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (c) 2007 Marcus Glocker - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -struct upgt_softc; - -/* - * General values. - */ -enum { - UPGT_BULK_RX, - UPGT_BULK_TX, - UPGT_N_XFERS = 2, -}; - -#define UPGT_CONFIG_INDEX 0 -#define UPGT_IFACE_INDEX 0 -#define UPGT_USB_TIMEOUT 1000 -#define UPGT_FIRMWARE_TIMEOUT 10 - -#define UPGT_MEMADDR_FIRMWARE_START 0x00020000 /* 512 bytes large */ -#define UPGT_MEMSIZE_FRAME_HEAD 0x0070 -#define UPGT_MEMSIZE_RX 0x3500 - -#define UPGT_RX_MAXCOUNT 6 -#define UPGT_TX_MAXCOUNT 128 -#define UPGT_TX_STAT_INTERVAL 5 -#define UPGT_RX_MINSZ (sizeof(struct upgt_lmac_header) + 4) - -/* device flags */ -#define UPGT_DEVICE_ATTACHED (1 << 0) - -/* leds */ -#define UPGT_LED_OFF 0 -#define UPGT_LED_ON 1 -#define UPGT_LED_BLINK 2 - -/* - * Firmware. - */ -#define UPGT_FW_BLOCK_SIZE 256 - -#define UPGT_BRA_FWTYPE_SIZE 4 -#define UPGT_BRA_FWTYPE_LM86 "LM86" -#define UPGT_BRA_FWTYPE_LM87 "LM87" -enum upgt_fw_type { - UPGT_FWTYPE_LM86, - UPGT_FWTYPE_LM87 -}; - -#define UPGT_BRA_TYPE_FW 0x80000001 -#define UPGT_BRA_TYPE_VERSION 0x80000002 -#define UPGT_BRA_TYPE_DEPIF 0x80000003 -#define UPGT_BRA_TYPE_EXPIF 0x80000004 -#define UPGT_BRA_TYPE_DESCR 0x80000101 -#define UPGT_BRA_TYPE_END 0xff0000ff -struct upgt_fw_bra_option { - uint32_t type; - uint32_t len; - uint8_t data[]; -} __packed; - -struct upgt_fw_bra_descr { - uint32_t unknown1; - uint32_t memaddr_space_start; - uint32_t memaddr_space_end; - uint32_t unknown2; - uint32_t unknown3; - uint8_t rates[20]; -} __packed; - -#define UPGT_X2_SIGNATURE_SIZE 4 -#define UPGT_X2_SIGNATURE "x2 " -struct upgt_fw_x2_header { - uint8_t signature[4]; - uint32_t startaddr; - uint32_t len; - uint32_t crc; -} __packed; - -/* - * EEPROM. - */ -#define UPGT_EEPROM_SIZE 8192 -#define UPGT_EEPROM_BLOCK_SIZE 1020 - -struct upgt_eeprom_header { - /* 14 bytes */ - uint32_t magic; - uint16_t pad1; - uint16_t preamble_len; - uint32_t pad2; - /* data */ -} __packed; - -#define UPGT_EEPROM_TYPE_END 0x0000 -#define UPGT_EEPROM_TYPE_NAME 0x0001 -#define UPGT_EEPROM_TYPE_SERIAL 0x0003 -#define UPGT_EEPROM_TYPE_MAC 0x0101 -#define UPGT_EEPROM_TYPE_HWRX 0x1001 -#define UPGT_EEPROM_TYPE_CHIP 0x1002 -#define UPGT_EEPROM_TYPE_FREQ3 0x1903 -#define UPGT_EEPROM_TYPE_FREQ4 0x1904 -#define UPGT_EEPROM_TYPE_FREQ5 0x1905 -#define UPGT_EEPROM_TYPE_FREQ6 0x1906 -#define UPGT_EEPROM_TYPE_OFF 0xffff -struct upgt_eeprom_option { - uint16_t len; - uint16_t type; - uint8_t data[]; - /* data */ -} __packed; - -#define UPGT_EEPROM_RX_CONST 0x88 -struct upgt_eeprom_option_hwrx { - uint32_t pad1; - uint8_t rxfilter; - uint8_t pad2[15]; -} __packed; - -struct upgt_eeprom_freq3_header { - uint8_t flags; - uint8_t elements; -} __packed; - -struct upgt_eeprom_freq4_header { - uint8_t flags; - uint8_t elements; - uint8_t settings; - uint8_t type; -} __packed; - -struct upgt_eeprom_freq4_1 { - uint16_t freq; - uint8_t data[50]; -} __packed; - -struct upgt_eeprom_freq4_2 { - uint16_t head; - uint8_t subtails[4]; - uint8_t tail; -} __packed; - -/* - * LMAC protocol. - */ -struct upgt_lmac_mem { - uint32_t addr; - uint32_t chksum; -} __packed; - -#define UPGT_H1_FLAGS_TX_MGMT 0x00 /* for TX: mgmt frame */ -#define UPGT_H1_FLAGS_TX_NO_CALLBACK 0x01 /* for TX: no USB callback */ -#define UPGT_H1_FLAGS_TX_DATA 0x10 /* for TX: data frame */ -#define UPGT_H1_TYPE_RX_DATA 0x00 /* 802.11 RX data frame */ -#define UPGT_H1_TYPE_RX_DATA_MGMT 0x04 /* 802.11 RX mgmt frame */ -#define UPGT_H1_TYPE_TX_DATA 0x40 /* 802.11 TX data frame */ -#define UPGT_H1_TYPE_CTRL 0x80 /* control frame */ -struct upgt_lmac_h1 { - /* 4 bytes */ - uint8_t flags; - uint8_t type; - uint16_t len; -} __packed; - -#define UPGT_H2_TYPE_TX_ACK_NO 0x0000 -#define UPGT_H2_TYPE_TX_ACK_YES 0x0001 -#define UPGT_H2_TYPE_MACFILTER 0x0000 -#define UPGT_H2_TYPE_CHANNEL 0x0001 -#define UPGT_H2_TYPE_TX_DONE 0x0008 -#define UPGT_H2_TYPE_STATS 0x000a -#define UPGT_H2_TYPE_EEPROM 0x000c -#define UPGT_H2_TYPE_LED 0x000d -#define UPGT_H2_FLAGS_TX_ACK_NO 0x0101 -#define UPGT_H2_FLAGS_TX_ACK_YES 0x0707 -struct upgt_lmac_h2 { - /* 8 bytes */ - uint32_t reqid; - uint16_t type; - uint16_t flags; -} __packed; - -struct upgt_lmac_header { - /* 12 bytes */ - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; -} __packed; - -struct upgt_lmac_eeprom { - /* 16 bytes */ - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint16_t offset; - uint16_t len; - /* data */ -} __packed; - -#define UPGT_FILTER_TYPE_NONE 0x0000 -#define UPGT_FILTER_TYPE_STA 0x0001 -#define UPGT_FILTER_TYPE_IBSS 0x0002 -#define UPGT_FILTER_TYPE_HOSTAP 0x0004 -#define UPGT_FILTER_TYPE_MONITOR 0x0010 -#define UPGT_FILTER_TYPE_RESET 0x0020 -#define UPGT_FILTER_UNKNOWN1 0x0002 -#define UPGT_FILTER_UNKNOWN2 0x0ca8 -#define UPGT_FILTER_UNKNOWN3 0xffff -#define UPGT_FILTER_MONITOR_UNKNOWN1 0x0000 -#define UPGT_FILTER_MONITOR_UNKNOWN2 0x0000 -#define UPGT_FILTER_MONITOR_UNKNOWN3 0x0000 -struct upgt_lmac_filter { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - /* 32 bytes */ - uint16_t type; - uint8_t dst[IEEE80211_ADDR_LEN]; - uint8_t src[IEEE80211_ADDR_LEN]; - uint16_t unknown1; - uint32_t rxaddr; - uint16_t unknown2; - uint32_t rxhw; - uint16_t unknown3; - uint32_t unknown4; -} __packed; - -/* frequency 3 data */ -struct upgt_lmac_freq3 { - uint16_t freq; - uint8_t data[6]; -} __packed; - -/* frequency 4 data */ -struct upgt_lmac_freq4 { - struct upgt_eeprom_freq4_2 cmd; - uint8_t pad; -}; - -/* frequency 6 data */ -struct upgt_lmac_freq6 { - uint16_t freq; - uint8_t data[8]; -} __packed; - -#define UPGT_CHANNEL_UNKNOWN1 0x0001 -#define UPGT_CHANNEL_UNKNOWN2 0x0000 -#define UPGT_CHANNEL_UNKNOWN3 0x48 -struct upgt_lmac_channel { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - /* 112 bytes */ - uint16_t unknown1; - uint16_t unknown2; - uint8_t pad1[20]; - struct upgt_lmac_freq6 freq6; - uint8_t settings; - uint8_t unknown3; - uint8_t freq3_1[4]; - struct upgt_lmac_freq4 freq4[8]; - uint8_t freq3_2[4]; - uint32_t pad2; -} __packed; - -#define UPGT_LED_MODE_SET 0x0003 -#define UPGT_LED_ACTION_OFF 0x0002 -#define UPGT_LED_ACTION_ON 0x0003 -#define UPGT_LED_ACTION_TMP_DUR 100 /* ms */ -struct upgt_lmac_led { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint16_t mode; - uint16_t action_fix; - uint16_t action_tmp; - uint16_t action_tmp_dur; -} __packed; - -struct upgt_lmac_stats { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint8_t data[76]; -} __packed; - -struct upgt_lmac_rx_desc { - struct upgt_lmac_h1 header1; - /* 16 bytes */ - uint16_t freq; - uint8_t unknown1; - uint8_t rate; - uint8_t rssi; - uint8_t pad; - uint16_t unknown2; - uint32_t timestamp; - uint32_t unknown3; - uint8_t data[]; -} __packed; - -#define UPGT_TX_DESC_KEY_EXISTS 0x01 -struct upgt_lmac_tx_desc_wep { - uint8_t key_exists; - uint8_t key_len; - uint8_t key_val[16]; -} __packed; - -#define UPGT_TX_DESC_TYPE_BEACON 0x00000000 -#define UPGT_TX_DESC_TYPE_PROBE 0x00000001 -#define UPGT_TX_DESC_TYPE_MGMT 0x00000002 -#define UPGT_TX_DESC_TYPE_DATA 0x00000004 -#define UPGT_TX_DESC_PAD3_SIZE 2 -struct upgt_lmac_tx_desc { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint8_t rates[8]; - uint16_t pad1; - struct upgt_lmac_tx_desc_wep wep_key; - uint32_t type; - uint32_t pad2; - uint32_t unknown1; - uint32_t unknown2; - uint8_t pad3[2]; - /* 802.11 frame data */ -} __packed; - -#define UPGT_TX_DONE_DESC_STATUS_OK 0x0001 -struct upgt_lmac_tx_done_desc { - struct upgt_lmac_h1 header1; - struct upgt_lmac_h2 header2; - uint16_t status; - uint16_t rssi; - uint16_t seq; - uint16_t unknown; -} __packed; - -/* - * USB xfers. - */ -struct upgt_data { - uint8_t *buf; - uint32_t buflen; - struct ieee80211_node *ni; - struct mbuf *m; - uint32_t addr; - uint8_t use; - STAILQ_ENTRY(upgt_data) next; -}; -typedef STAILQ_HEAD(, upgt_data) upgt_datahead; - -/* - * Prism memory. - */ -struct upgt_memory_page { - uint8_t used; - uint32_t addr; -} __packed; - -#define UPGT_MEMORY_MAX_PAGES 8 -struct upgt_memory { - uint8_t pages; - struct upgt_memory_page page[UPGT_MEMORY_MAX_PAGES]; -} __packed; - -/* - * BPF - */ -struct upgt_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; -} __packed; - -#define UPGT_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)) - -struct upgt_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define UPGT_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct upgt_stat { - uint32_t st_tx_active; - uint32_t st_tx_inactive; - uint32_t st_tx_pending; -}; - -#define UPGT_STAT_INC(sc, var) (sc)->sc_stat.var++ -#define UPGT_STAT_DEC(sc, var) (sc)->sc_stat.var-- - -struct upgt_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define UPGT_VAP(vap) ((struct upgt_vap *)(vap)) - -struct upgt_softc { - device_t sc_dev; - struct ifnet *sc_ifp; - struct usb_device *sc_udev; - struct mtx sc_mtx; - struct upgt_stat sc_stat; - int sc_flags; -#define UPGT_FLAG_FWLOADED (1 << 0) -#define UPGT_FLAG_INITDONE (1 << 1) - int sc_if_flags; - int sc_debug; - - uint8_t sc_myaddr[IEEE80211_ADDR_LEN]; - - enum ieee80211_state sc_state; - int sc_arg; - int sc_led_blink; - struct callout sc_led_ch; - uint8_t sc_cur_rateset[8]; - - /* watchdog */ - int sc_tx_timer; - struct callout sc_watchdog_ch; - - /* Firmware. */ - int sc_fw_type; - /* memory addresses on device */ - uint32_t sc_memaddr_frame_start; - uint32_t sc_memaddr_frame_end; - uint32_t sc_memaddr_rx_start; - struct upgt_memory sc_memory; - - /* data which we found in the EEPROM */ - uint8_t sc_eeprom[UPGT_EEPROM_SIZE]; - uint16_t sc_eeprom_hwrx; - struct upgt_lmac_freq3 sc_eeprom_freq3[IEEE80211_CHAN_MAX]; - struct upgt_lmac_freq4 sc_eeprom_freq4[IEEE80211_CHAN_MAX][8]; - struct upgt_lmac_freq6 sc_eeprom_freq6[IEEE80211_CHAN_MAX]; - uint8_t sc_eeprom_freq6_settings; - - /* RX/TX */ - struct usb_xfer *sc_xfer[UPGT_N_XFERS]; - int sc_rx_no; - int sc_tx_no; - struct upgt_data sc_rx_data[UPGT_RX_MAXCOUNT]; - upgt_datahead sc_rx_active; - upgt_datahead sc_rx_inactive; - struct upgt_data sc_tx_data[UPGT_TX_MAXCOUNT]; - upgt_datahead sc_tx_active; - upgt_datahead sc_tx_inactive; - upgt_datahead sc_tx_pending; - - /* BPF */ - struct upgt_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct upgt_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define UPGT_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define UPGT_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define UPGT_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) diff --git a/sys/bus/u4b/wlan/if_ural.c b/sys/bus/u4b/wlan/if_ural.c deleted file mode 100644 index a4bc7ea5b0..0000000000 --- a/sys/bus/u4b/wlan/if_ural.c +++ /dev/null @@ -1,2271 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005, 2006 - * Damien Bergamini - * - * Copyright (c) 2006, 2008 - * Hans Petter Selasky - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/*- - * Ralink Technology RT2500USB chipset driver - * http://www.ralinktech.com/ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include "usbdevs.h" - -#define USB_DEBUG_VAR ural_debug -#include - -#include -#include - -#ifdef USB_DEBUG -static int ural_debug = 0; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural"); -SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RWTUN, &ural_debug, 0, - "Debug level"); -#endif - -#define URAL_RSSI(rssi) \ - ((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ? \ - ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0) - -/* various supported device vendors/products */ -static const STRUCT_USB_HOST_ID ural_devs[] = { -#define URAL_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) } - URAL_DEV(ASUS, WL167G), - URAL_DEV(ASUS, RT2570), - URAL_DEV(BELKIN, F5D7050), - URAL_DEV(BELKIN, F5D7051), - URAL_DEV(CISCOLINKSYS, HU200TS), - URAL_DEV(CISCOLINKSYS, WUSB54G), - URAL_DEV(CISCOLINKSYS, WUSB54GP), - URAL_DEV(CONCEPTRONIC2, C54RU), - URAL_DEV(DLINK, DWLG122), - URAL_DEV(GIGABYTE, GN54G), - URAL_DEV(GIGABYTE, GNWBKG), - URAL_DEV(GUILLEMOT, HWGUSB254), - URAL_DEV(MELCO, KG54), - URAL_DEV(MELCO, KG54AI), - URAL_DEV(MELCO, KG54YB), - URAL_DEV(MELCO, NINWIFI), - URAL_DEV(MSI, RT2570), - URAL_DEV(MSI, RT2570_2), - URAL_DEV(MSI, RT2570_3), - URAL_DEV(NOVATECH, NV902), - URAL_DEV(RALINK, RT2570), - URAL_DEV(RALINK, RT2570_2), - URAL_DEV(RALINK, RT2570_3), - URAL_DEV(SIEMENS2, WL54G), - URAL_DEV(SMC, 2862WG), - URAL_DEV(SPHAIRON, UB801R), - URAL_DEV(SURECOM, RT2570), - URAL_DEV(VTECH, RT2570), - URAL_DEV(ZINWELL, RT2570), -#undef URAL_DEV -}; - -static usb_callback_t ural_bulk_read_callback; -static usb_callback_t ural_bulk_write_callback; - -static usb_error_t ural_do_request(struct ural_softc *sc, - struct usb_device_request *req, void *data); -static struct ieee80211vap *ural_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, - int, const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void ural_vap_delete(struct ieee80211vap *); -static void ural_tx_free(struct ural_tx_data *, int); -static void ural_setup_tx_list(struct ural_softc *); -static void ural_unsetup_tx_list(struct ural_softc *); -static int ural_newstate(struct ieee80211vap *, - enum ieee80211_state, int); -static void ural_setup_tx_desc(struct ural_softc *, - struct ural_tx_desc *, uint32_t, int, int); -static int ural_tx_bcn(struct ural_softc *, struct mbuf *, - struct ieee80211_node *); -static int ural_tx_mgt(struct ural_softc *, struct mbuf *, - struct ieee80211_node *); -static int ural_tx_data(struct ural_softc *, struct mbuf *, - struct ieee80211_node *); -static void ural_start(struct ifnet *); -static int ural_ioctl(struct ifnet *, u_long, caddr_t); -static void ural_set_testmode(struct ural_softc *); -static void ural_eeprom_read(struct ural_softc *, uint16_t, void *, - int); -static uint16_t ural_read(struct ural_softc *, uint16_t); -static void ural_read_multi(struct ural_softc *, uint16_t, void *, - int); -static void ural_write(struct ural_softc *, uint16_t, uint16_t); -static void ural_write_multi(struct ural_softc *, uint16_t, void *, - int) __unused; -static void ural_bbp_write(struct ural_softc *, uint8_t, uint8_t); -static uint8_t ural_bbp_read(struct ural_softc *, uint8_t); -static void ural_rf_write(struct ural_softc *, uint8_t, uint32_t); -static void ural_scan_start(struct ieee80211com *); -static void ural_scan_end(struct ieee80211com *); -static void ural_set_channel(struct ieee80211com *); -static void ural_set_chan(struct ural_softc *, - struct ieee80211_channel *); -static void ural_disable_rf_tune(struct ural_softc *); -static void ural_enable_tsf_sync(struct ural_softc *); -static void ural_enable_tsf(struct ural_softc *); -static void ural_update_slot(struct ifnet *); -static void ural_set_txpreamble(struct ural_softc *); -static void ural_set_basicrates(struct ural_softc *, - const struct ieee80211_channel *); -static void ural_set_bssid(struct ural_softc *, const uint8_t *); -static void ural_set_macaddr(struct ural_softc *, uint8_t *); -static void ural_update_promisc(struct ieee80211com *); -static void ural_setpromisc(struct ural_softc *); -static const char *ural_get_rf(int); -static void ural_read_eeprom(struct ural_softc *); -static int ural_bbp_init(struct ural_softc *); -static void ural_set_txantenna(struct ural_softc *, int); -static void ural_set_rxantenna(struct ural_softc *, int); -static void ural_init_locked(struct ural_softc *); -static void ural_init(void *); -static void ural_stop(struct ural_softc *); -static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void ural_ratectl_start(struct ural_softc *, - struct ieee80211_node *); -static void ural_ratectl_timeout(void *); -static void ural_ratectl_task(void *, int); -static int ural_pause(struct ural_softc *sc, int timeout); - -/* - * Default values for MAC registers; values taken from the reference driver. - */ -static const struct { - uint16_t reg; - uint16_t val; -} ural_def_mac[] = { - { RAL_TXRX_CSR5, 0x8c8d }, - { RAL_TXRX_CSR6, 0x8b8a }, - { RAL_TXRX_CSR7, 0x8687 }, - { RAL_TXRX_CSR8, 0x0085 }, - { RAL_MAC_CSR13, 0x1111 }, - { RAL_MAC_CSR14, 0x1e11 }, - { RAL_TXRX_CSR21, 0xe78f }, - { RAL_MAC_CSR9, 0xff1d }, - { RAL_MAC_CSR11, 0x0002 }, - { RAL_MAC_CSR22, 0x0053 }, - { RAL_MAC_CSR15, 0x0000 }, - { RAL_MAC_CSR8, RAL_FRAME_SIZE }, - { RAL_TXRX_CSR19, 0x0000 }, - { RAL_TXRX_CSR18, 0x005a }, - { RAL_PHY_CSR2, 0x0000 }, - { RAL_TXRX_CSR0, 0x1ec0 }, - { RAL_PHY_CSR4, 0x000f } -}; - -/* - * Default values for BBP registers; values taken from the reference driver. - */ -static const struct { - uint8_t reg; - uint8_t val; -} ural_def_bbp[] = { - { 3, 0x02 }, - { 4, 0x19 }, - { 14, 0x1c }, - { 15, 0x30 }, - { 16, 0xac }, - { 17, 0x48 }, - { 18, 0x18 }, - { 19, 0xff }, - { 20, 0x1e }, - { 21, 0x08 }, - { 22, 0x08 }, - { 23, 0x08 }, - { 24, 0x80 }, - { 25, 0x50 }, - { 26, 0x08 }, - { 27, 0x23 }, - { 30, 0x10 }, - { 31, 0x2b }, - { 32, 0xb9 }, - { 34, 0x12 }, - { 35, 0x50 }, - { 39, 0xc4 }, - { 40, 0x02 }, - { 41, 0x60 }, - { 53, 0x10 }, - { 54, 0x18 }, - { 56, 0x08 }, - { 57, 0x10 }, - { 58, 0x08 }, - { 61, 0x60 }, - { 62, 0x10 }, - { 75, 0xff } -}; - -/* - * Default values for RF register R2 indexed by channel numbers. - */ -static const uint32_t ural_rf2522_r2[] = { - 0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814, - 0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e -}; - -static const uint32_t ural_rf2523_r2[] = { - 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, - 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 -}; - -static const uint32_t ural_rf2524_r2[] = { - 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d, - 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346 -}; - -static const uint32_t ural_rf2525_r2[] = { - 0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d, - 0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346 -}; - -static const uint32_t ural_rf2525_hi_r2[] = { - 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345, - 0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e -}; - -static const uint32_t ural_rf2525e_r2[] = { - 0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463, - 0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b -}; - -static const uint32_t ural_rf2526_hi_r2[] = { - 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d, - 0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241 -}; - -static const uint32_t ural_rf2526_r2[] = { - 0x00226, 0x00227, 0x00227, 0x00228, 0x00228, 0x00229, 0x00229, - 0x0022a, 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d -}; - -/* - * For dual-band RF, RF registers R1 and R4 also depend on channel number; - * values taken from the reference driver. - */ -static const struct { - uint8_t chan; - uint32_t r1; - uint32_t r2; - uint32_t r4; -} ural_rf5222[] = { - { 1, 0x08808, 0x0044d, 0x00282 }, - { 2, 0x08808, 0x0044e, 0x00282 }, - { 3, 0x08808, 0x0044f, 0x00282 }, - { 4, 0x08808, 0x00460, 0x00282 }, - { 5, 0x08808, 0x00461, 0x00282 }, - { 6, 0x08808, 0x00462, 0x00282 }, - { 7, 0x08808, 0x00463, 0x00282 }, - { 8, 0x08808, 0x00464, 0x00282 }, - { 9, 0x08808, 0x00465, 0x00282 }, - { 10, 0x08808, 0x00466, 0x00282 }, - { 11, 0x08808, 0x00467, 0x00282 }, - { 12, 0x08808, 0x00468, 0x00282 }, - { 13, 0x08808, 0x00469, 0x00282 }, - { 14, 0x08808, 0x0046b, 0x00286 }, - - { 36, 0x08804, 0x06225, 0x00287 }, - { 40, 0x08804, 0x06226, 0x00287 }, - { 44, 0x08804, 0x06227, 0x00287 }, - { 48, 0x08804, 0x06228, 0x00287 }, - { 52, 0x08804, 0x06229, 0x00287 }, - { 56, 0x08804, 0x0622a, 0x00287 }, - { 60, 0x08804, 0x0622b, 0x00287 }, - { 64, 0x08804, 0x0622c, 0x00287 }, - - { 100, 0x08804, 0x02200, 0x00283 }, - { 104, 0x08804, 0x02201, 0x00283 }, - { 108, 0x08804, 0x02202, 0x00283 }, - { 112, 0x08804, 0x02203, 0x00283 }, - { 116, 0x08804, 0x02204, 0x00283 }, - { 120, 0x08804, 0x02205, 0x00283 }, - { 124, 0x08804, 0x02206, 0x00283 }, - { 128, 0x08804, 0x02207, 0x00283 }, - { 132, 0x08804, 0x02208, 0x00283 }, - { 136, 0x08804, 0x02209, 0x00283 }, - { 140, 0x08804, 0x0220a, 0x00283 }, - - { 149, 0x08808, 0x02429, 0x00281 }, - { 153, 0x08808, 0x0242b, 0x00281 }, - { 157, 0x08808, 0x0242d, 0x00281 }, - { 161, 0x08808, 0x0242f, 0x00281 } -}; - -static const struct usb_config ural_config[URAL_N_TRANSFER] = { - [URAL_BULK_WR] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE + 4), - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = ural_bulk_write_callback, - .timeout = 5000, /* ms */ - }, - [URAL_BULK_RD] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = (RAL_FRAME_SIZE + RAL_RX_DESC_SIZE), - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = ural_bulk_read_callback, - }, -}; - -static device_probe_t ural_match; -static device_attach_t ural_attach; -static device_detach_t ural_detach; - -static device_method_t ural_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ural_match), - DEVMETHOD(device_attach, ural_attach), - DEVMETHOD(device_detach, ural_detach), - - DEVMETHOD_END -}; - -static driver_t ural_driver = { - .name = "ural", - .methods = ural_methods, - .size = sizeof(struct ural_softc), -}; - -static devclass_t ural_devclass; - -DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, NULL, NULL); -MODULE_DEPEND(ural, usb, 1, 1, 1); -MODULE_DEPEND(ural, wlan, 1, 1, 1); -MODULE_VERSION(ural, 1); - -static int -ural_match(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != 0) - return (ENXIO); - if (uaa->info.bIfaceIndex != RAL_IFACE_INDEX) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(ural_devs, sizeof(ural_devs), uaa)); -} - -static int -ural_attach(device_t self) -{ - struct usb_attach_arg *uaa = device_get_ivars(self); - struct ural_softc *sc = device_get_softc(self); - struct ifnet *ifp; - struct ieee80211com *ic; - uint8_t iface_index, bands; - int error; - - device_set_usb_desc(self); - sc->sc_udev = uaa->device; - sc->sc_dev = self; - - mtx_init(&sc->sc_mtx, device_get_nameunit(self), - MTX_NETWORK_LOCK, MTX_DEF); - - iface_index = RAL_IFACE_INDEX; - error = usbd_transfer_setup(uaa->device, - &iface_index, sc->sc_xfer, ural_config, - URAL_N_TRANSFER, sc, &sc->sc_mtx); - if (error) { - device_printf(self, "could not allocate USB transfers, " - "err=%s\n", usbd_errstr(error)); - goto detach; - } - - RAL_LOCK(sc); - /* retrieve RT2570 rev. no */ - sc->asic_rev = ural_read(sc, RAL_MAC_CSR0); - - /* retrieve MAC address and various other things from EEPROM */ - ural_read_eeprom(sc); - RAL_UNLOCK(sc); - - device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n", - sc->asic_rev, ural_get_rf(sc->rf_rev)); - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - goto detach; - } - ic = ifp->if_l2com; - - ifp->if_softc = sc; - if_initname(ifp, "ural", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = ural_init; - ifp->if_ioctl = ural_ioctl; - ifp->if_start = ural_start; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - ic->ic_ifp = ifp; - ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(dev); - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode supported */ - | IEEE80211_C_IBSS /* IBSS mode supported */ - | IEEE80211_C_MONITOR /* monitor mode supported */ - | IEEE80211_C_HOSTAP /* HostAp mode supported */ - | IEEE80211_C_TXPMGT /* tx power management */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* bg scanning supported */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - if (sc->rf_rev == RAL_RF_5222) - setbit(&bands, IEEE80211_MODE_11A); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic, sc->sc_bssid); - ic->ic_update_promisc = ural_update_promisc; - ic->ic_raw_xmit = ural_raw_xmit; - ic->ic_scan_start = ural_scan_start; - ic->ic_scan_end = ural_scan_end; - ic->ic_set_channel = ural_set_channel; - - ic->ic_vap_create = ural_vap_create; - ic->ic_vap_delete = ural_vap_delete; - - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - RAL_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - RAL_RX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - return (0); - -detach: - ural_detach(self); - return (ENXIO); /* failure */ -} - -static int -ural_detach(device_t self) -{ - struct ural_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; - - /* stop all USB transfers */ - usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER); - - /* free TX list, if any */ - RAL_LOCK(sc); - ural_unsetup_tx_list(sc); - RAL_UNLOCK(sc); - - if (ifp) { - ic = ifp->if_l2com; - ieee80211_ifdetach(ic); - if_free(ifp); - } - mtx_destroy(&sc->sc_mtx); - - return (0); -} - -static usb_error_t -ural_do_request(struct ural_softc *sc, - struct usb_device_request *req, void *data) -{ - usb_error_t err; - int ntries = 10; - - while (ntries--) { - err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, - req, data, 0, NULL, 250 /* ms */); - if (err == 0) - break; - - DPRINTFN(1, "Control request failed, %s (retrying)\n", - usbd_errstr(err)); - if (ural_pause(sc, hz / 100)) - break; - } - return (err); -} - -static struct ieee80211vap * -ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct ural_softc *sc = ic->ic_ifp->if_softc; - struct ural_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return NULL; - uvp = (struct ural_vap *) malloc(sizeof(struct ural_vap), - M_80211_VAP, M_WAITOK | M_ZERO); - if (uvp == NULL) - return NULL; - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = ural_newstate; - - usb_callout_init_mtx(&uvp->ratectl_ch, &sc->sc_mtx, 0); - TASK_INIT(&uvp->ratectl_task, 0, ural_ratectl_task, uvp); - ieee80211_ratectl_init(vap); - ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); - ic->ic_opmode = opmode; - return vap; -} - -static void -ural_vap_delete(struct ieee80211vap *vap) -{ - struct ural_vap *uvp = URAL_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - - usb_callout_drain(&uvp->ratectl_ch); - ieee80211_draintask(ic, &uvp->ratectl_task); - ieee80211_ratectl_deinit(vap); - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static void -ural_tx_free(struct ural_tx_data *data, int txerr) -{ - struct ural_softc *sc = data->sc; - - if (data->m != NULL) { - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, - txerr ? ETIMEDOUT : 0); - m_freem(data->m); - data->m = NULL; - - ieee80211_free_node(data->ni); - data->ni = NULL; - } - STAILQ_INSERT_TAIL(&sc->tx_free, data, next); - sc->tx_nfree++; -} - -static void -ural_setup_tx_list(struct ural_softc *sc) -{ - struct ural_tx_data *data; - int i; - - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); - - for (i = 0; i < RAL_TX_LIST_COUNT; i++) { - data = &sc->tx_data[i]; - - data->sc = sc; - STAILQ_INSERT_TAIL(&sc->tx_free, data, next); - sc->tx_nfree++; - } -} - -static void -ural_unsetup_tx_list(struct ural_softc *sc) -{ - struct ural_tx_data *data; - int i; - - /* make sure any subsequent use of the queues will fail */ - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); - - /* free up all node references and mbufs */ - for (i = 0; i < RAL_TX_LIST_COUNT; i++) { - data = &sc->tx_data[i]; - - if (data->m != NULL) { - m_freem(data->m); - data->m = NULL; - } - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - } -} - -static int -ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct ural_vap *uvp = URAL_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct ural_softc *sc = ic->ic_ifp->if_softc; - const struct ieee80211_txparam *tp; - struct ieee80211_node *ni; - struct mbuf *m; - - DPRINTF("%s -> %s\n", - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - IEEE80211_UNLOCK(ic); - RAL_LOCK(sc); - usb_callout_stop(&uvp->ratectl_ch); - - switch (nstate) { - case IEEE80211_S_INIT: - if (vap->iv_state == IEEE80211_S_RUN) { - /* abort TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - - /* force tx led to stop blinking */ - ural_write(sc, RAL_MAC_CSR20, 0); - } - break; - - case IEEE80211_S_RUN: - ni = ieee80211_ref_node(vap->iv_bss); - - if (vap->iv_opmode != IEEE80211_M_MONITOR) { - ural_update_slot(ic->ic_ifp); - ural_set_txpreamble(sc); - ural_set_basicrates(sc, ic->ic_bsschan); - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); - ural_set_bssid(sc, sc->sc_bssid); - } - - if (vap->iv_opmode == IEEE80211_M_HOSTAP || - vap->iv_opmode == IEEE80211_M_IBSS) { - m = ieee80211_beacon_alloc(ni, &uvp->bo); - if (m == NULL) { - device_printf(sc->sc_dev, - "could not allocate beacon\n"); - RAL_UNLOCK(sc); - IEEE80211_LOCK(ic); - ieee80211_free_node(ni); - return (-1); - } - ieee80211_ref_node(ni); - if (ural_tx_bcn(sc, m, ni) != 0) { - device_printf(sc->sc_dev, - "could not send beacon\n"); - RAL_UNLOCK(sc); - IEEE80211_LOCK(ic); - ieee80211_free_node(ni); - return (-1); - } - } - - /* make tx led blink on tx (controlled by ASIC) */ - ural_write(sc, RAL_MAC_CSR20, 1); - - if (vap->iv_opmode != IEEE80211_M_MONITOR) - ural_enable_tsf_sync(sc); - else - ural_enable_tsf(sc); - - /* enable automatic rate adaptation */ - /* XXX should use ic_bsschan but not valid until after newstate call below */ - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - ural_ratectl_start(sc, ni); - ieee80211_free_node(ni); - break; - - default: - break; - } - RAL_UNLOCK(sc); - IEEE80211_LOCK(ic); - return (uvp->newstate(vap, nstate, arg)); -} - - -static void -ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct ural_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211vap *vap; - struct ural_tx_data *data; - struct mbuf *m; - struct usb_page_cache *pc; - int len; - - usbd_xfer_status(xfer, &len, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTFN(11, "transfer complete, %d bytes\n", len); - - /* free resources */ - data = usbd_xfer_get_priv(xfer); - ural_tx_free(data, 0); - usbd_xfer_set_priv(xfer, NULL); - - ifp->if_opackets++; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - data = STAILQ_FIRST(&sc->tx_q); - if (data) { - STAILQ_REMOVE_HEAD(&sc->tx_q, next); - m = data->m; - - if (m->m_pkthdr.len > (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE)) { - DPRINTFN(0, "data overflow, %u bytes\n", - m->m_pkthdr.len); - m->m_pkthdr.len = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE); - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &data->desc, RAL_TX_DESC_SIZE); - usbd_m_copy_in(pc, RAL_TX_DESC_SIZE, m, 0, - m->m_pkthdr.len); - - vap = data->ni->ni_vap; - if (ieee80211_radiotap_active_vap(vap)) { - struct ural_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = data->rate; - tap->wt_antenna = sc->tx_ant; - - ieee80211_radiotap_tx(vap, m); - } - - /* xfer length needs to be a multiple of two! */ - len = (RAL_TX_DESC_SIZE + m->m_pkthdr.len + 1) & ~1; - if ((len % 64) == 0) - len += 2; - - DPRINTFN(11, "sending frame len=%u xferlen=%u\n", - m->m_pkthdr.len, len); - - usbd_xfer_set_frame_len(xfer, 0, len); - usbd_xfer_set_priv(xfer, data); - - usbd_transfer_submit(xfer); - } - RAL_UNLOCK(sc); - ural_start(ifp); - RAL_LOCK(sc); - break; - - default: /* Error */ - DPRINTFN(11, "transfer error, %s\n", - usbd_errstr(error)); - - ifp->if_oerrors++; - data = usbd_xfer_get_priv(xfer); - if (data != NULL) { - ural_tx_free(data, error); - usbd_xfer_set_priv(xfer, NULL); - } - - if (error == USB_ERR_STALLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - if (error == USB_ERR_TIMEOUT) - device_printf(sc->sc_dev, "device timeout\n"); - break; - } -} - -static void -ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct ural_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_node *ni; - struct mbuf *m = NULL; - struct usb_page_cache *pc; - uint32_t flags; - int8_t rssi = 0, nf = 0; - int len; - - usbd_xfer_status(xfer, &len, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - - DPRINTFN(15, "rx done, actlen=%d\n", len); - - if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) { - DPRINTF("%s: xfer too short %d\n", - device_get_nameunit(sc->sc_dev), len); - ifp->if_ierrors++; - goto tr_setup; - } - - len -= RAL_RX_DESC_SIZE; - /* rx descriptor is located at the end */ - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, len, &sc->sc_rx_desc, RAL_RX_DESC_SIZE); - - rssi = URAL_RSSI(sc->sc_rx_desc.rssi); - nf = RAL_NOISE_FLOOR; - flags = le32toh(sc->sc_rx_desc.flags); - if (flags & (RAL_RX_PHY_ERROR | RAL_RX_CRC_ERROR)) { - /* - * This should not happen since we did not - * request to receive those frames when we - * filled RAL_TXRX_CSR2: - */ - DPRINTFN(5, "PHY or CRC error\n"); - ifp->if_ierrors++; - goto tr_setup; - } - - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (m == NULL) { - DPRINTF("could not allocate mbuf\n"); - ifp->if_ierrors++; - goto tr_setup; - } - usbd_copy_out(pc, 0, mtod(m, uint8_t *), len); - - /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff; - - if (ieee80211_radiotap_active(ic)) { - struct ural_rx_radiotap_header *tap = &sc->sc_rxtap; - - /* XXX set once */ - tap->wr_flags = 0; - tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate, - (flags & RAL_RX_OFDM) ? - IEEE80211_T_OFDM : IEEE80211_T_CCK); - tap->wr_antenna = sc->rx_ant; - tap->wr_antsignal = nf + rssi; - tap->wr_antnoise = nf; - } - /* Strip trailing 802.11 MAC FCS. */ - m_adj(m, -IEEE80211_CRC_LEN); - - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - - /* - * At the end of a USB callback it is always safe to unlock - * the private mutex of a device! That is why we do the - * "ieee80211_input" here, and not some lines up! - */ - RAL_UNLOCK(sc); - if (m) { - ni = ieee80211_find_rxnode(ic, - mtod(m, struct ieee80211_frame_min *)); - if (ni != NULL) { - (void) ieee80211_input(ni, m, rssi, nf); - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, rssi, nf); - } - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && - !IFQ_IS_EMPTY(&ifp->if_snd)) - ural_start(ifp); - RAL_LOCK(sc); - return; - - default: /* Error */ - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - return; - } -} - -static uint8_t -ural_plcp_signal(int rate) -{ - switch (rate) { - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: return 0xb; - case 18: return 0xf; - case 24: return 0xa; - case 36: return 0xe; - case 48: return 0x9; - case 72: return 0xd; - case 96: return 0x8; - case 108: return 0xc; - - /* CCK rates (NB: not IEEE std, device-specific) */ - case 2: return 0x0; - case 4: return 0x1; - case 11: return 0x2; - case 22: return 0x3; - } - return 0xff; /* XXX unsupported/unknown rate */ -} - -static void -ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, - uint32_t flags, int len, int rate) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t plcp_length; - int remainder; - - desc->flags = htole32(flags); - desc->flags |= htole32(RAL_TX_NEWSEQ); - desc->flags |= htole32(len << 16); - - desc->wme = htole16(RAL_AIFSN(2) | RAL_LOGCWMIN(3) | RAL_LOGCWMAX(5)); - desc->wme |= htole16(RAL_IVOFFSET(sizeof (struct ieee80211_frame))); - - /* setup PLCP fields */ - desc->plcp_signal = ural_plcp_signal(rate); - desc->plcp_service = 4; - - len += IEEE80211_CRC_LEN; - if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) { - desc->flags |= htole32(RAL_TX_OFDM); - - plcp_length = len & 0xfff; - desc->plcp_length_hi = plcp_length >> 6; - desc->plcp_length_lo = plcp_length & 0x3f; - } else { - plcp_length = (16 * len + rate - 1) / rate; - if (rate == 22) { - remainder = (16 * len) % 22; - if (remainder != 0 && remainder < 7) - desc->plcp_service |= RAL_PLCP_LENGEXT; - } - desc->plcp_length_hi = plcp_length >> 8; - desc->plcp_length_lo = plcp_length & 0xff; - - if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) - desc->plcp_signal |= 0x08; - } - - desc->iv = 0; - desc->eiv = 0; -} - -#define RAL_TX_TIMEOUT 5000 - -static int -ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = sc->sc_ifp; - const struct ieee80211_txparam *tp; - struct ural_tx_data *data; - - if (sc->tx_nfree == 0) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - m_freem(m0); - ieee80211_free_node(ni); - return EIO; - } - data = STAILQ_FIRST(&sc->tx_free); - STAILQ_REMOVE_HEAD(&sc->tx_free, next); - sc->tx_nfree--; - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; - - data->m = m0; - data->ni = ni; - data->rate = tp->mgmtrate; - - ural_setup_tx_desc(sc, &data->desc, - RAL_TX_IFS_NEWBACKOFF | RAL_TX_TIMESTAMP, m0->m_pkthdr.len, - tp->mgmtrate); - - DPRINTFN(10, "sending beacon frame len=%u rate=%u\n", - m0->m_pkthdr.len, tp->mgmtrate); - - STAILQ_INSERT_TAIL(&sc->tx_q, data, next); - usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); - - return (0); -} - -static int -ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - const struct ieee80211_txparam *tp; - struct ural_tx_data *data; - struct ieee80211_frame *wh; - struct ieee80211_key *k; - uint32_t flags; - uint16_t dur; - - RAL_LOCK_ASSERT(sc, MA_OWNED); - - data = STAILQ_FIRST(&sc->tx_free); - STAILQ_REMOVE_HEAD(&sc->tx_free, next); - sc->tx_nfree--; - - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - - wh = mtod(m0, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return ENOBUFS; - } - wh = mtod(m0, struct ieee80211_frame *); - } - - data->m = m0; - data->ni = ni; - data->rate = tp->mgmtrate; - - flags = 0; - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= RAL_TX_ACK; - - dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate, - ic->ic_flags & IEEE80211_F_SHPREAMBLE); - *(uint16_t *)wh->i_dur = htole16(dur); - - /* tell hardware to add timestamp for probe responses */ - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT && - (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == - IEEE80211_FC0_SUBTYPE_PROBE_RESP) - flags |= RAL_TX_TIMESTAMP; - } - - ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, tp->mgmtrate); - - DPRINTFN(10, "sending mgt frame len=%u rate=%u\n", - m0->m_pkthdr.len, tp->mgmtrate); - - STAILQ_INSERT_TAIL(&sc->tx_q, data, next); - usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); - - return 0; -} - -static int -ural_sendprot(struct ural_softc *sc, - const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) -{ - struct ieee80211com *ic = ni->ni_ic; - const struct ieee80211_frame *wh; - struct ural_tx_data *data; - struct mbuf *mprot; - int protrate, ackrate, pktlen, flags, isshort; - uint16_t dur; - - KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, - ("protection %d", prot)); - - wh = mtod(m, const struct ieee80211_frame *); - pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; - - protrate = ieee80211_ctl_rate(ic->ic_rt, rate); - ackrate = ieee80211_ack_rate(ic->ic_rt, rate); - - isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; - dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort) - + ieee80211_ack_duration(ic->ic_rt, rate, isshort); - flags = RAL_TX_RETRY(7); - if (prot == IEEE80211_PROT_RTSCTS) { - /* NB: CTS is the same size as an ACK */ - dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort); - flags |= RAL_TX_ACK; - mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); - } else { - mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); - } - if (mprot == NULL) { - /* XXX stat + msg */ - return ENOBUFS; - } - data = STAILQ_FIRST(&sc->tx_free); - STAILQ_REMOVE_HEAD(&sc->tx_free, next); - sc->tx_nfree--; - - data->m = mprot; - data->ni = ieee80211_ref_node(ni); - data->rate = protrate; - ural_setup_tx_desc(sc, &data->desc, flags, mprot->m_pkthdr.len, protrate); - - STAILQ_INSERT_TAIL(&sc->tx_q, data, next); - usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); - - return 0; -} - -static int -ural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ural_tx_data *data; - uint32_t flags; - int error; - int rate; - - RAL_LOCK_ASSERT(sc, MA_OWNED); - KASSERT(params != NULL, ("no raw xmit params")); - - rate = params->ibp_rate0; - if (!ieee80211_isratevalid(ic->ic_rt, rate)) { - m_freem(m0); - return EINVAL; - } - flags = 0; - if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) - flags |= RAL_TX_ACK; - if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { - error = ural_sendprot(sc, m0, ni, - params->ibp_flags & IEEE80211_BPF_RTS ? - IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, - rate); - if (error || sc->tx_nfree == 0) { - m_freem(m0); - return ENOBUFS; - } - flags |= RAL_TX_IFS_SIFS; - } - - data = STAILQ_FIRST(&sc->tx_free); - STAILQ_REMOVE_HEAD(&sc->tx_free, next); - sc->tx_nfree--; - - data->m = m0; - data->ni = ni; - data->rate = rate; - - /* XXX need to setup descriptor ourself */ - ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); - - DPRINTFN(10, "sending raw frame len=%u rate=%u\n", - m0->m_pkthdr.len, rate); - - STAILQ_INSERT_TAIL(&sc->tx_q, data, next); - usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); - - return 0; -} - -static int -ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct ural_tx_data *data; - struct ieee80211_frame *wh; - const struct ieee80211_txparam *tp; - struct ieee80211_key *k; - uint32_t flags = 0; - uint16_t dur; - int error, rate; - - RAL_LOCK_ASSERT(sc, MA_OWNED); - - wh = mtod(m0, struct ieee80211_frame *); - - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else - rate = ni->ni_txrate; - - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return ENOBUFS; - } - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - int prot = IEEE80211_PROT_NONE; - if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) - prot = IEEE80211_PROT_RTSCTS; - else if ((ic->ic_flags & IEEE80211_F_USEPROT) && - ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) - prot = ic->ic_protmode; - if (prot != IEEE80211_PROT_NONE) { - error = ural_sendprot(sc, m0, ni, prot, rate); - if (error || sc->tx_nfree == 0) { - m_freem(m0); - return ENOBUFS; - } - flags |= RAL_TX_IFS_SIFS; - } - } - - data = STAILQ_FIRST(&sc->tx_free); - STAILQ_REMOVE_HEAD(&sc->tx_free, next); - sc->tx_nfree--; - - data->m = m0; - data->ni = ni; - data->rate = rate; - - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - flags |= RAL_TX_ACK; - flags |= RAL_TX_RETRY(7); - - dur = ieee80211_ack_duration(ic->ic_rt, rate, - ic->ic_flags & IEEE80211_F_SHPREAMBLE); - *(uint16_t *)wh->i_dur = htole16(dur); - } - - ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate); - - DPRINTFN(10, "sending data frame len=%u rate=%u\n", - m0->m_pkthdr.len, rate); - - STAILQ_INSERT_TAIL(&sc->tx_q, data, next); - usbd_transfer_start(sc->sc_xfer[URAL_BULK_WR]); - - return 0; -} - -static void -ural_start(struct ifnet *ifp) -{ - struct ural_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - RAL_LOCK(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - RAL_UNLOCK(sc); - return; - } - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->tx_nfree < RAL_TX_MINFREE) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (ural_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } - } - RAL_UNLOCK(sc); -} - -static int -ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct ural_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - RAL_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ural_init_locked(sc); - startall = 1; - } else - ural_setpromisc(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ural_stop(sc); - } - RAL_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - default: - error = ether_ioctl(ifp, cmd, data); - break; - } - return error; -} - -static void -ural_set_testmode(struct ural_softc *sc) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RAL_VENDOR_REQUEST; - USETW(req.wValue, 4); - USETW(req.wIndex, 1); - USETW(req.wLength, 0); - - error = ural_do_request(sc, &req, NULL); - if (error != 0) { - device_printf(sc->sc_dev, "could not set test mode: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_EEPROM; - USETW(req.wValue, 0); - USETW(req.wIndex, addr); - USETW(req.wLength, len); - - error = ural_do_request(sc, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not read EEPROM: %s\n", - usbd_errstr(error)); - } -} - -static uint16_t -ural_read(struct ural_softc *sc, uint16_t reg) -{ - struct usb_device_request req; - usb_error_t error; - uint16_t val; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, sizeof (uint16_t)); - - error = ural_do_request(sc, &req, &val); - if (error != 0) { - device_printf(sc->sc_dev, "could not read MAC register: %s\n", - usbd_errstr(error)); - return 0; - } - - return le16toh(val); -} - -static void -ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = RAL_READ_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, len); - - error = ural_do_request(sc, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not read MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RAL_WRITE_MAC; - USETW(req.wValue, val); - USETW(req.wIndex, reg); - USETW(req.wLength, 0); - - error = ural_do_request(sc, &req, NULL); - if (error != 0) { - device_printf(sc->sc_dev, "could not write MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = RAL_WRITE_MULTI_MAC; - USETW(req.wValue, 0); - USETW(req.wIndex, reg); - USETW(req.wLength, len); - - error = ural_do_request(sc, &req, buf); - if (error != 0) { - device_printf(sc->sc_dev, "could not write MAC register: %s\n", - usbd_errstr(error)); - } -} - -static void -ural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val) -{ - uint16_t tmp; - int ntries; - - for (ntries = 0; ntries < 100; ntries++) { - if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) - break; - if (ural_pause(sc, hz / 100)) - break; - } - if (ntries == 100) { - device_printf(sc->sc_dev, "could not write to BBP\n"); - return; - } - - tmp = reg << 8 | val; - ural_write(sc, RAL_PHY_CSR7, tmp); -} - -static uint8_t -ural_bbp_read(struct ural_softc *sc, uint8_t reg) -{ - uint16_t val; - int ntries; - - val = RAL_BBP_WRITE | reg << 8; - ural_write(sc, RAL_PHY_CSR7, val); - - for (ntries = 0; ntries < 100; ntries++) { - if (!(ural_read(sc, RAL_PHY_CSR8) & RAL_BBP_BUSY)) - break; - if (ural_pause(sc, hz / 100)) - break; - } - if (ntries == 100) { - device_printf(sc->sc_dev, "could not read BBP\n"); - return 0; - } - - return ural_read(sc, RAL_PHY_CSR7) & 0xff; -} - -static void -ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val) -{ - uint32_t tmp; - int ntries; - - for (ntries = 0; ntries < 100; ntries++) { - if (!(ural_read(sc, RAL_PHY_CSR10) & RAL_RF_LOBUSY)) - break; - if (ural_pause(sc, hz / 100)) - break; - } - if (ntries == 100) { - device_printf(sc->sc_dev, "could not write to RF\n"); - return; - } - - tmp = RAL_RF_BUSY | RAL_RF_20BIT | (val & 0xfffff) << 2 | (reg & 0x3); - ural_write(sc, RAL_PHY_CSR9, tmp & 0xffff); - ural_write(sc, RAL_PHY_CSR10, tmp >> 16); - - /* remember last written value in sc */ - sc->rf_regs[reg] = val; - - DPRINTFN(15, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff); -} - -static void -ural_scan_start(struct ieee80211com *ic) -{ - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; - - RAL_LOCK(sc); - ural_write(sc, RAL_TXRX_CSR19, 0); - ural_set_bssid(sc, ifp->if_broadcastaddr); - RAL_UNLOCK(sc); -} - -static void -ural_scan_end(struct ieee80211com *ic) -{ - struct ural_softc *sc = ic->ic_ifp->if_softc; - - RAL_LOCK(sc); - ural_enable_tsf_sync(sc); - ural_set_bssid(sc, sc->sc_bssid); - RAL_UNLOCK(sc); - -} - -static void -ural_set_channel(struct ieee80211com *ic) -{ - struct ural_softc *sc = ic->ic_ifp->if_softc; - - RAL_LOCK(sc); - ural_set_chan(sc, ic->ic_curchan); - RAL_UNLOCK(sc); -} - -static void -ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t power, tmp; - int i, chan; - - chan = ieee80211_chan2ieee(ic, c); - if (chan == 0 || chan == IEEE80211_CHAN_ANY) - return; - - if (IEEE80211_IS_CHAN_2GHZ(c)) - power = min(sc->txpow[chan - 1], 31); - else - power = 31; - - /* adjust txpower using ifconfig settings */ - power -= (100 - ic->ic_txpowlimit) / 8; - - DPRINTFN(2, "setting channel to %u, txpower to %u\n", chan, power); - - switch (sc->rf_rev) { - case RAL_RF_2522: - ural_rf_write(sc, RAL_RF1, 0x00814); - ural_rf_write(sc, RAL_RF2, ural_rf2522_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); - break; - - case RAL_RF_2523: - ural_rf_write(sc, RAL_RF1, 0x08804); - ural_rf_write(sc, RAL_RF2, ural_rf2523_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x38044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - break; - - case RAL_RF_2524: - ural_rf_write(sc, RAL_RF1, 0x0c808); - ural_rf_write(sc, RAL_RF2, ural_rf2524_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - break; - - case RAL_RF_2525: - ural_rf_write(sc, RAL_RF1, 0x08808); - ural_rf_write(sc, RAL_RF2, ural_rf2525_hi_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - - ural_rf_write(sc, RAL_RF1, 0x08808); - ural_rf_write(sc, RAL_RF2, ural_rf2525_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); - break; - - case RAL_RF_2525E: - ural_rf_write(sc, RAL_RF1, 0x08808); - ural_rf_write(sc, RAL_RF2, ural_rf2525e_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282); - break; - - case RAL_RF_2526: - ural_rf_write(sc, RAL_RF2, ural_rf2526_hi_r2[chan - 1]); - ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); - ural_rf_write(sc, RAL_RF1, 0x08804); - - ural_rf_write(sc, RAL_RF2, ural_rf2526_r2[chan - 1]); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x18044); - ural_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); - break; - - /* dual-band RF */ - case RAL_RF_5222: - for (i = 0; ural_rf5222[i].chan != chan; i++); - - ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1); - ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2); - ural_rf_write(sc, RAL_RF3, power << 7 | 0x00040); - ural_rf_write(sc, RAL_RF4, ural_rf5222[i].r4); - break; - } - - if (ic->ic_opmode != IEEE80211_M_MONITOR && - (ic->ic_flags & IEEE80211_F_SCAN) == 0) { - /* set Japan filter bit for channel 14 */ - tmp = ural_bbp_read(sc, 70); - - tmp &= ~RAL_JAPAN_FILTER; - if (chan == 14) - tmp |= RAL_JAPAN_FILTER; - - ural_bbp_write(sc, 70, tmp); - - /* clear CRC errors */ - ural_read(sc, RAL_STA_CSR0); - - ural_pause(sc, hz / 100); - ural_disable_rf_tune(sc); - } - - /* XXX doesn't belong here */ - /* update basic rate set */ - ural_set_basicrates(sc, c); - - /* give the hardware some time to do the switchover */ - ural_pause(sc, hz / 100); -} - -/* - * Disable RF auto-tuning. - */ -static void -ural_disable_rf_tune(struct ural_softc *sc) -{ - uint32_t tmp; - - if (sc->rf_rev != RAL_RF_2523) { - tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE; - ural_rf_write(sc, RAL_RF1, tmp); - } - - tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE; - ural_rf_write(sc, RAL_RF3, tmp); - - DPRINTFN(2, "disabling RF autotune\n"); -} - -/* - * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF - * synchronization. - */ -static void -ural_enable_tsf_sync(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint16_t logcwmin, preload, tmp; - - /* first, disable TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - - tmp = (16 * vap->iv_bss->ni_intval) << 4; - ural_write(sc, RAL_TXRX_CSR18, tmp); - - logcwmin = (ic->ic_opmode == IEEE80211_M_IBSS) ? 2 : 0; - preload = (ic->ic_opmode == IEEE80211_M_IBSS) ? 320 : 6; - tmp = logcwmin << 12 | preload; - ural_write(sc, RAL_TXRX_CSR20, tmp); - - /* finally, enable TSF synchronization */ - tmp = RAL_ENABLE_TSF | RAL_ENABLE_TBCN; - if (ic->ic_opmode == IEEE80211_M_STA) - tmp |= RAL_ENABLE_TSF_SYNC(1); - else - tmp |= RAL_ENABLE_TSF_SYNC(2) | RAL_ENABLE_BEACON_GENERATOR; - ural_write(sc, RAL_TXRX_CSR19, tmp); - - DPRINTF("enabling TSF synchronization\n"); -} - -static void -ural_enable_tsf(struct ural_softc *sc) -{ - /* first, disable TSF synchronization */ - ural_write(sc, RAL_TXRX_CSR19, 0); - ural_write(sc, RAL_TXRX_CSR19, RAL_ENABLE_TSF | RAL_ENABLE_TSF_SYNC(2)); -} - -#define RAL_RXTX_TURNAROUND 5 /* us */ -static void -ural_update_slot(struct ifnet *ifp) -{ - struct ural_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t slottime, sifs, eifs; - - slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; - - /* - * These settings may sound a bit inconsistent but this is what the - * reference driver does. - */ - if (ic->ic_curmode == IEEE80211_MODE_11B) { - sifs = 16 - RAL_RXTX_TURNAROUND; - eifs = 364; - } else { - sifs = 10 - RAL_RXTX_TURNAROUND; - eifs = 64; - } - - ural_write(sc, RAL_MAC_CSR10, slottime); - ural_write(sc, RAL_MAC_CSR11, sifs); - ural_write(sc, RAL_MAC_CSR12, eifs); -} - -static void -ural_set_txpreamble(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t tmp; - - tmp = ural_read(sc, RAL_TXRX_CSR10); - - tmp &= ~RAL_SHORT_PREAMBLE; - if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) - tmp |= RAL_SHORT_PREAMBLE; - - ural_write(sc, RAL_TXRX_CSR10, tmp); -} - -static void -ural_set_basicrates(struct ural_softc *sc, const struct ieee80211_channel *c) -{ - /* XXX wrong, take from rate set */ - /* update basic rate set */ - if (IEEE80211_IS_CHAN_5GHZ(c)) { - /* 11a basic rates: 6, 12, 24Mbps */ - ural_write(sc, RAL_TXRX_CSR11, 0x150); - } else if (IEEE80211_IS_CHAN_ANYG(c)) { - /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */ - ural_write(sc, RAL_TXRX_CSR11, 0x15f); - } else { - /* 11b basic rates: 1, 2Mbps */ - ural_write(sc, RAL_TXRX_CSR11, 0x3); - } -} - -static void -ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid) -{ - uint16_t tmp; -#ifdef USB_DEBUG - char ethstr[ETHER_ADDRSTRLEN + 1]; -#endif - - tmp = bssid[0] | bssid[1] << 8; - ural_write(sc, RAL_MAC_CSR5, tmp); - - tmp = bssid[2] | bssid[3] << 8; - ural_write(sc, RAL_MAC_CSR6, tmp); - - tmp = bssid[4] | bssid[5] << 8; - ural_write(sc, RAL_MAC_CSR7, tmp); - - DPRINTF("setting BSSID to %s\n", kether_ntoa(bssid, ethstr)); -} - -static void -ural_set_macaddr(struct ural_softc *sc, uint8_t *addr) -{ - uint16_t tmp; -#ifdef USB_DEBUG - char ethstr[ETHER_ADDRSTRLEN + 1]; -#endif - - tmp = addr[0] | addr[1] << 8; - ural_write(sc, RAL_MAC_CSR2, tmp); - - tmp = addr[2] | addr[3] << 8; - ural_write(sc, RAL_MAC_CSR3, tmp); - - tmp = addr[4] | addr[5] << 8; - ural_write(sc, RAL_MAC_CSR4, tmp); - - DPRINTF("setting MAC address to %s\n", kether_ntoa(addr, ethstr)); -} - -static void -ural_setpromisc(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - uint32_t tmp; - - tmp = ural_read(sc, RAL_TXRX_CSR2); - - tmp &= ~RAL_DROP_NOT_TO_ME; - if (!(ifp->if_flags & IFF_PROMISC)) - tmp |= RAL_DROP_NOT_TO_ME; - - ural_write(sc, RAL_TXRX_CSR2, tmp); - - DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? - "entering" : "leaving"); -} - -static void -ural_update_promisc(struct ieee80211com *ic) -{ - struct ural_softc *sc = ic->ic_softc; - - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - RAL_LOCK(sc); - ural_setpromisc(sc); - RAL_UNLOCK(sc); -} - -static const char * -ural_get_rf(int rev) -{ - switch (rev) { - case RAL_RF_2522: return "RT2522"; - case RAL_RF_2523: return "RT2523"; - case RAL_RF_2524: return "RT2524"; - case RAL_RF_2525: return "RT2525"; - case RAL_RF_2525E: return "RT2525e"; - case RAL_RF_2526: return "RT2526"; - case RAL_RF_5222: return "RT5222"; - default: return "unknown"; - } -} - -static void -ural_read_eeprom(struct ural_softc *sc) -{ - uint16_t val; - - ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2); - val = le16toh(val); - sc->rf_rev = (val >> 11) & 0x7; - sc->hw_radio = (val >> 10) & 0x1; - sc->led_mode = (val >> 6) & 0x7; - sc->rx_ant = (val >> 4) & 0x3; - sc->tx_ant = (val >> 2) & 0x3; - sc->nb_ant = val & 0x3; - - /* read MAC address */ - ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6); - - /* read default values for BBP registers */ - ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); - - /* read Tx power for all b/g channels */ - ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14); -} - -static int -ural_bbp_init(struct ural_softc *sc) -{ - int i, ntries; - - /* wait for BBP to be ready */ - for (ntries = 0; ntries < 100; ntries++) { - if (ural_bbp_read(sc, RAL_BBP_VERSION) != 0) - break; - if (ural_pause(sc, hz / 100)) - break; - } - if (ntries == 100) { - device_printf(sc->sc_dev, "timeout waiting for BBP\n"); - return EIO; - } - - /* initialize BBP registers to default values */ - for (i = 0; i < nitems(ural_def_bbp); i++) - ural_bbp_write(sc, ural_def_bbp[i].reg, ural_def_bbp[i].val); - -#if 0 - /* initialize BBP registers to values stored in EEPROM */ - for (i = 0; i < 16; i++) { - if (sc->bbp_prom[i].reg == 0xff) - continue; - ural_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); - } -#endif - - return 0; -} - -static void -ural_set_txantenna(struct ural_softc *sc, int antenna) -{ - uint16_t tmp; - uint8_t tx; - - tx = ural_bbp_read(sc, RAL_BBP_TX) & ~RAL_BBP_ANTMASK; - if (antenna == 1) - tx |= RAL_BBP_ANTA; - else if (antenna == 2) - tx |= RAL_BBP_ANTB; - else - tx |= RAL_BBP_DIVERSITY; - - /* need to force I/Q flip for RF 2525e, 2526 and 5222 */ - if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526 || - sc->rf_rev == RAL_RF_5222) - tx |= RAL_BBP_FLIPIQ; - - ural_bbp_write(sc, RAL_BBP_TX, tx); - - /* update values in PHY_CSR5 and PHY_CSR6 */ - tmp = ural_read(sc, RAL_PHY_CSR5) & ~0x7; - ural_write(sc, RAL_PHY_CSR5, tmp | (tx & 0x7)); - - tmp = ural_read(sc, RAL_PHY_CSR6) & ~0x7; - ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7)); -} - -static void -ural_set_rxantenna(struct ural_softc *sc, int antenna) -{ - uint8_t rx; - - rx = ural_bbp_read(sc, RAL_BBP_RX) & ~RAL_BBP_ANTMASK; - if (antenna == 1) - rx |= RAL_BBP_ANTA; - else if (antenna == 2) - rx |= RAL_BBP_ANTB; - else - rx |= RAL_BBP_DIVERSITY; - - /* need to force no I/Q flip for RF 2525e and 2526 */ - if (sc->rf_rev == RAL_RF_2525E || sc->rf_rev == RAL_RF_2526) - rx &= ~RAL_BBP_FLIPIQ; - - ural_bbp_write(sc, RAL_BBP_RX, rx); -} - -static void -ural_init_locked(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint16_t tmp; - int i, ntries; - - RAL_LOCK_ASSERT(sc, MA_OWNED); - - ural_set_testmode(sc); - ural_write(sc, 0x308, 0x00f0); /* XXX magic */ - - ural_stop(sc); - - /* initialize MAC registers to default values */ - for (i = 0; i < nitems(ural_def_mac); i++) - ural_write(sc, ural_def_mac[i].reg, ural_def_mac[i].val); - - /* wait for BBP and RF to wake up (this can take a long time!) */ - for (ntries = 0; ntries < 100; ntries++) { - tmp = ural_read(sc, RAL_MAC_CSR17); - if ((tmp & (RAL_BBP_AWAKE | RAL_RF_AWAKE)) == - (RAL_BBP_AWAKE | RAL_RF_AWAKE)) - break; - if (ural_pause(sc, hz / 100)) - break; - } - if (ntries == 100) { - device_printf(sc->sc_dev, - "timeout waiting for BBP/RF to wakeup\n"); - goto fail; - } - - /* we're ready! */ - ural_write(sc, RAL_MAC_CSR1, RAL_HOST_READY); - - /* set basic rate set (will be updated later) */ - ural_write(sc, RAL_TXRX_CSR11, 0x15f); - - if (ural_bbp_init(sc) != 0) - goto fail; - - ural_set_chan(sc, ic->ic_curchan); - - /* clear statistic registers (STA_CSR0 to STA_CSR10) */ - ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); - - ural_set_txantenna(sc, sc->tx_ant); - ural_set_rxantenna(sc, sc->rx_ant); - - ural_set_macaddr(sc, IF_LLADDR(ifp)); - - /* - * Allocate Tx and Rx xfer queues. - */ - ural_setup_tx_list(sc); - - /* kick Rx */ - tmp = RAL_DROP_PHY | RAL_DROP_CRC; - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; - if (ic->ic_opmode != IEEE80211_M_HOSTAP) - tmp |= RAL_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) - tmp |= RAL_DROP_NOT_TO_ME; - } - ural_write(sc, RAL_TXRX_CSR2, tmp); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]); - usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]); - return; - -fail: ural_stop(sc); -} - -static void -ural_init(void *priv) -{ - struct ural_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - RAL_LOCK(sc); - ural_init_locked(sc); - RAL_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -ural_stop(struct ural_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - - RAL_LOCK_ASSERT(sc, MA_OWNED); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - /* - * Drain all the transfers, if not already drained: - */ - RAL_UNLOCK(sc); - usbd_transfer_drain(sc->sc_xfer[URAL_BULK_WR]); - usbd_transfer_drain(sc->sc_xfer[URAL_BULK_RD]); - RAL_LOCK(sc); - - ural_unsetup_tx_list(sc); - - /* disable Rx */ - ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX); - /* reset ASIC and BBP (but won't reset MAC registers!) */ - ural_write(sc, RAL_MAC_CSR1, RAL_RESET_ASIC | RAL_RESET_BBP); - /* wait a little */ - ural_pause(sc, hz / 10); - ural_write(sc, RAL_MAC_CSR1, 0); - /* wait a little */ - ural_pause(sc, hz / 10); -} - -static int -ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; - - RAL_LOCK(sc); - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - RAL_UNLOCK(sc); - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - if (sc->tx_nfree < RAL_TX_MINFREE) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - RAL_UNLOCK(sc); - m_freem(m); - ieee80211_free_node(ni); - return EIO; - } - - ifp->if_opackets++; - - if (params == NULL) { - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - */ - if (ural_tx_mgt(sc, m, ni) != 0) - goto bad; - } else { - /* - * Caller supplied explicit parameters to use in - * sending the frame. - */ - if (ural_tx_raw(sc, m, ni, params) != 0) - goto bad; - } - RAL_UNLOCK(sc); - return 0; -bad: - ifp->if_oerrors++; - RAL_UNLOCK(sc); - ieee80211_free_node(ni); - return EIO; /* XXX */ -} - -static void -ural_ratectl_start(struct ural_softc *sc, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ural_vap *uvp = URAL_VAP(vap); - - /* clear statistic registers (STA_CSR0 to STA_CSR10) */ - ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); - - usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); -} - -static void -ural_ratectl_timeout(void *arg) -{ - struct ural_vap *uvp = arg; - struct ieee80211vap *vap = &uvp->vap; - struct ieee80211com *ic = vap->iv_ic; - - ieee80211_runtask(ic, &uvp->ratectl_task); -} - -static void -ural_ratectl_task(void *arg, int pending) -{ - struct ural_vap *uvp = arg; - struct ieee80211vap *vap = &uvp->vap; - struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - int ok, fail; - int sum, retrycnt; - - ni = ieee80211_ref_node(vap->iv_bss); - RAL_LOCK(sc); - /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ - ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta)); - - ok = sc->sta[7] + /* TX ok w/o retry */ - sc->sta[8]; /* TX ok w/ retry */ - fail = sc->sta[9]; /* TX retry-fail count */ - sum = ok+fail; - retrycnt = sc->sta[8] + fail; - - ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); - (void) ieee80211_ratectl_rate(ni, NULL, 0); - - ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */ - - usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); - RAL_UNLOCK(sc); - ieee80211_free_node(ni); -} - -static int -ural_pause(struct ural_softc *sc, int timeout) -{ - - usb_pause_mtx(&sc->sc_mtx, timeout); - return (0); -} diff --git a/sys/bus/u4b/wlan/if_uralreg.h b/sys/bus/u4b/wlan/if_uralreg.h deleted file mode 100644 index 042cf5ace5..0000000000 --- a/sys/bus/u4b/wlan/if_uralreg.h +++ /dev/null @@ -1,211 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005, 2006 - * Damien Bergamini - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define RAL_NOISE_FLOOR -95 -#define RAL_RSSI_CORR 120 - -#define RAL_RX_DESC_SIZE (sizeof (struct ural_rx_desc)) -#define RAL_TX_DESC_SIZE (sizeof (struct ural_tx_desc)) -#define RAL_FRAME_SIZE 0x780 /* NOTE: using 0x980 does not work */ - -#define RAL_CONFIG_NO 1 -#define RAL_IFACE_INDEX 0 - -#define RAL_VENDOR_REQUEST 0x01 -#define RAL_WRITE_MAC 0x02 -#define RAL_READ_MAC 0x03 -#define RAL_WRITE_MULTI_MAC 0x06 -#define RAL_READ_MULTI_MAC 0x07 -#define RAL_READ_EEPROM 0x09 - -/* - * MAC registers. - */ -#define RAL_MAC_CSR0 0x0400 /* ASIC Version */ -#define RAL_MAC_CSR1 0x0402 /* System control */ -#define RAL_MAC_CSR2 0x0404 /* MAC addr0 */ -#define RAL_MAC_CSR3 0x0406 /* MAC addr1 */ -#define RAL_MAC_CSR4 0x0408 /* MAC addr2 */ -#define RAL_MAC_CSR5 0x040a /* BSSID0 */ -#define RAL_MAC_CSR6 0x040c /* BSSID1 */ -#define RAL_MAC_CSR7 0x040e /* BSSID2 */ -#define RAL_MAC_CSR8 0x0410 /* Max frame length */ -#define RAL_MAC_CSR9 0x0412 /* Timer control */ -#define RAL_MAC_CSR10 0x0414 /* Slot time */ -#define RAL_MAC_CSR11 0x0416 /* IFS */ -#define RAL_MAC_CSR12 0x0418 /* EIFS */ -#define RAL_MAC_CSR13 0x041a /* Power mode0 */ -#define RAL_MAC_CSR14 0x041c /* Power mode1 */ -#define RAL_MAC_CSR15 0x041e /* Power saving transition0 */ -#define RAL_MAC_CSR16 0x0420 /* Power saving transition1 */ -#define RAL_MAC_CSR17 0x0422 /* Power state control */ -#define RAL_MAC_CSR18 0x0424 /* Auto wake-up control */ -#define RAL_MAC_CSR19 0x0426 /* GPIO control */ -#define RAL_MAC_CSR20 0x0428 /* LED control0 */ -#define RAL_MAC_CSR22 0x042c /* XXX not documented */ - -/* - * Tx/Rx Registers. - */ -#define RAL_TXRX_CSR0 0x0440 /* Security control */ -#define RAL_TXRX_CSR2 0x0444 /* Rx control */ -#define RAL_TXRX_CSR5 0x044a /* CCK Tx BBP ID0 */ -#define RAL_TXRX_CSR6 0x044c /* CCK Tx BBP ID1 */ -#define RAL_TXRX_CSR7 0x044e /* OFDM Tx BBP ID0 */ -#define RAL_TXRX_CSR8 0x0450 /* OFDM Tx BBP ID1 */ -#define RAL_TXRX_CSR10 0x0454 /* Auto responder control */ -#define RAL_TXRX_CSR11 0x0456 /* Auto responder basic rate */ -#define RAL_TXRX_CSR18 0x0464 /* Beacon interval */ -#define RAL_TXRX_CSR19 0x0466 /* Beacon/sync control */ -#define RAL_TXRX_CSR20 0x0468 /* Beacon alignment */ -#define RAL_TXRX_CSR21 0x046a /* XXX not documented */ - -/* - * Security registers. - */ -#define RAL_SEC_CSR0 0x0480 /* Shared key 0, word 0 */ - -/* - * PHY registers. - */ -#define RAL_PHY_CSR2 0x04c4 /* Tx MAC configuration */ -#define RAL_PHY_CSR4 0x04c8 /* Interface configuration */ -#define RAL_PHY_CSR5 0x04ca /* BBP Pre-Tx CCK */ -#define RAL_PHY_CSR6 0x04cc /* BBP Pre-Tx OFDM */ -#define RAL_PHY_CSR7 0x04ce /* BBP serial control */ -#define RAL_PHY_CSR8 0x04d0 /* BBP serial status */ -#define RAL_PHY_CSR9 0x04d2 /* RF serial control0 */ -#define RAL_PHY_CSR10 0x04d4 /* RF serial control1 */ - -/* - * Statistics registers. - */ -#define RAL_STA_CSR0 0x04e0 /* FCS error */ - - -#define RAL_DISABLE_RX (1 << 0) -#define RAL_DROP_CRC (1 << 1) -#define RAL_DROP_PHY (1 << 2) -#define RAL_DROP_CTL (1 << 3) -#define RAL_DROP_NOT_TO_ME (1 << 4) -#define RAL_DROP_TODS (1 << 5) -#define RAL_DROP_BAD_VERSION (1 << 6) -#define RAL_DROP_MULTICAST (1 << 9) -#define RAL_DROP_BROADCAST (1 << 10) - -#define RAL_SHORT_PREAMBLE (1 << 2) - -#define RAL_RESET_ASIC (1 << 0) -#define RAL_RESET_BBP (1 << 1) -#define RAL_HOST_READY (1 << 2) - -#define RAL_ENABLE_TSF (1 << 0) -#define RAL_ENABLE_TSF_SYNC(x) (((x) & 0x3) << 1) -#define RAL_ENABLE_TBCN (1 << 3) -#define RAL_ENABLE_BEACON_GENERATOR (1 << 4) - -#define RAL_RF_AWAKE (3 << 7) -#define RAL_BBP_AWAKE (3 << 5) - -#define RAL_BBP_WRITE (1 << 15) -#define RAL_BBP_BUSY (1 << 0) - -#define RAL_RF1_AUTOTUNE 0x08000 -#define RAL_RF3_AUTOTUNE 0x00040 - -#define RAL_RF_2522 0x00 -#define RAL_RF_2523 0x01 -#define RAL_RF_2524 0x02 -#define RAL_RF_2525 0x03 -#define RAL_RF_2525E 0x04 -#define RAL_RF_2526 0x05 -/* dual-band RF */ -#define RAL_RF_5222 0x10 - -#define RAL_BBP_VERSION 0 -#define RAL_BBP_TX 2 -#define RAL_BBP_RX 14 - -#define RAL_BBP_ANTA 0x00 -#define RAL_BBP_DIVERSITY 0x01 -#define RAL_BBP_ANTB 0x02 -#define RAL_BBP_ANTMASK 0x03 -#define RAL_BBP_FLIPIQ 0x04 - -#define RAL_JAPAN_FILTER 0x08 - -struct ural_tx_desc { - uint32_t flags; -#define RAL_TX_RETRY(x) ((x) << 4) -#define RAL_TX_MORE_FRAG (1 << 8) -#define RAL_TX_ACK (1 << 9) -#define RAL_TX_TIMESTAMP (1 << 10) -#define RAL_TX_OFDM (1 << 11) -#define RAL_TX_NEWSEQ (1 << 12) - -#define RAL_TX_IFS_MASK 0x00006000 -#define RAL_TX_IFS_BACKOFF (0 << 13) -#define RAL_TX_IFS_SIFS (1 << 13) -#define RAL_TX_IFS_NEWBACKOFF (2 << 13) -#define RAL_TX_IFS_NONE (3 << 13) - - uint16_t wme; -#define RAL_LOGCWMAX(x) (((x) & 0xf) << 12) -#define RAL_LOGCWMIN(x) (((x) & 0xf) << 8) -#define RAL_AIFSN(x) (((x) & 0x3) << 6) -#define RAL_IVOFFSET(x) (((x) & 0x3f)) - - uint16_t reserved1; - uint8_t plcp_signal; - uint8_t plcp_service; -#define RAL_PLCP_LENGEXT 0x80 - - uint8_t plcp_length_lo; - uint8_t plcp_length_hi; - uint32_t iv; - uint32_t eiv; -} __packed; - -struct ural_rx_desc { - uint32_t flags; -#define RAL_RX_CRC_ERROR (1 << 5) -#define RAL_RX_OFDM (1 << 6) -#define RAL_RX_PHY_ERROR (1 << 7) - - uint8_t rssi; - uint8_t rate; - uint16_t reserved; - - uint32_t iv; - uint32_t eiv; -} __packed; - -#define RAL_RF_LOBUSY (1 << 15) -#define RAL_RF_BUSY (1 << 31) -#define RAL_RF_20BIT (20 << 24) - -#define RAL_RF1 0 -#define RAL_RF2 2 -#define RAL_RF3 1 -#define RAL_RF4 3 - -#define RAL_EEPROM_ADDRESS 0x0004 -#define RAL_EEPROM_TXPOWER 0x003c -#define RAL_EEPROM_CONFIG0 0x0016 -#define RAL_EEPROM_BBP_BASE 0x001c diff --git a/sys/bus/u4b/wlan/if_uralvar.h b/sys/bus/u4b/wlan/if_uralvar.h deleted file mode 100644 index 46dbfbddc8..0000000000 --- a/sys/bus/u4b/wlan/if_uralvar.h +++ /dev/null @@ -1,134 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2005 - * Damien Bergamini - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define RAL_TX_LIST_COUNT 8 -#define RAL_TX_MINFREE 2 - -#define URAL_SCAN_START 1 -#define URAL_SCAN_END 2 -#define URAL_SET_CHANNEL 3 - - -struct ural_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; - int8_t wr_antnoise; - uint8_t wr_antenna; -}; - -#define RAL_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) - -struct ural_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; - uint8_t wt_antenna; -}; - -#define RAL_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA)) - -struct ural_softc; - -struct ural_tx_data { - STAILQ_ENTRY(ural_tx_data) next; - struct ural_softc *sc; - struct ural_tx_desc desc; - struct mbuf *m; - struct ieee80211_node *ni; - int rate; -}; -typedef STAILQ_HEAD(, ural_tx_data) ural_txdhead; - -struct ural_vap { - struct ieee80211vap vap; - struct ieee80211_beacon_offsets bo; - struct usb_callout ratectl_ch; - struct task ratectl_task; - - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define URAL_VAP(vap) ((struct ural_vap *)(vap)) - -enum { - URAL_BULK_WR, - URAL_BULK_RD, - URAL_N_TRANSFER = 2, -}; - -struct ural_softc { - struct ifnet *sc_ifp; - device_t sc_dev; - struct usb_device *sc_udev; - - uint32_t asic_rev; - uint8_t rf_rev; - - struct usb_xfer *sc_xfer[URAL_N_TRANSFER]; - - struct ural_tx_data tx_data[RAL_TX_LIST_COUNT]; - ural_txdhead tx_q; - ural_txdhead tx_free; - int tx_nfree; - struct ural_rx_desc sc_rx_desc; - - struct mtx sc_mtx; - - uint16_t sta[11]; - uint32_t rf_regs[4]; - uint8_t txpow[14]; - uint8_t sc_bssid[6]; - - struct { - uint8_t val; - uint8_t reg; - } __packed bbp_prom[16]; - - int led_mode; - int hw_radio; - int rx_ant; - int tx_ant; - int nb_ant; - - struct ural_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - - struct ural_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define RAL_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define RAL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define RAL_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) diff --git a/sys/bus/u4b/wlan/if_urtw.c b/sys/bus/u4b/wlan/if_urtw.c deleted file mode 100644 index a9731033b5..0000000000 --- a/sys/bus/u4b/wlan/if_urtw.c +++ /dev/null @@ -1,4430 +0,0 @@ -/*- - * Copyright (c) 2008 Weongyo Jeong - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -__FBSDID("$FreeBSD$"); -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#include -#endif - -#include -#include -#include - -#include -#include -#include "usbdevs.h" - -#include -#include - -static SYSCTL_NODE(_hw_usb, OID_AUTO, urtw, CTLFLAG_RW, 0, "USB Realtek 8187L"); -#ifdef URTW_DEBUG -int urtw_debug = 0; -SYSCTL_INT(_hw_usb_urtw, OID_AUTO, debug, CTLFLAG_RW, &urtw_debug, 0, - "control debugging printfs"); -TUNABLE_INT("hw.usb.urtw.debug", &urtw_debug); -enum { - URTW_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - URTW_DEBUG_RECV = 0x00000002, /* basic recv operation */ - URTW_DEBUG_RESET = 0x00000004, /* reset processing */ - URTW_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */ - URTW_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */ - URTW_DEBUG_STATE = 0x00000020, /* 802.11 state transitions */ - URTW_DEBUG_STAT = 0x00000040, /* statistic */ - URTW_DEBUG_INIT = 0x00000080, /* initialization of dev */ - URTW_DEBUG_TXSTATUS = 0x00000100, /* tx status */ - URTW_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (sc->sc_debug & (m)) \ - printf(fmt, __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif -static int urtw_preamble_mode = URTW_PREAMBLE_MODE_LONG; -SYSCTL_INT(_hw_usb_urtw, OID_AUTO, preamble_mode, CTLFLAG_RW, - &urtw_preamble_mode, 0, "set the preable mode (long or short)"); -TUNABLE_INT("hw.usb.urtw.preamble_mode", &urtw_preamble_mode); - -/* recognized device vendors/products */ -#define urtw_lookup(v, p) \ - ((const struct urtw_type *)usb_lookup(urtw_devs, v, p)) -#define URTW_DEV_B(v,p) \ - { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187B) } -#define URTW_DEV_L(v,p) \ - { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, URTW_REV_RTL8187L) } -#define URTW_REV_RTL8187B 0 -#define URTW_REV_RTL8187L 1 -static const STRUCT_USB_HOST_ID urtw_devs[] = { - URTW_DEV_B(NETGEAR, WG111V3), - URTW_DEV_B(REALTEK, RTL8187B_0), - URTW_DEV_B(REALTEK, RTL8187B_1), - URTW_DEV_B(REALTEK, RTL8187B_2), - URTW_DEV_B(SITECOMEU, WL168V4), - URTW_DEV_L(ASUS, P5B_WIFI), - URTW_DEV_L(BELKIN, F5D7050E), - URTW_DEV_L(LINKSYS4, WUSB54GCV2), - URTW_DEV_L(NETGEAR, WG111V2), - URTW_DEV_L(REALTEK, RTL8187), - URTW_DEV_L(SITECOMEU, WL168V1), - URTW_DEV_L(SURECOM, EP9001G2A), - { USB_VPI(USB_VENDOR_OVISLINK, 0x8187, URTW_REV_RTL8187L) }, - { USB_VPI(USB_VENDOR_DICKSMITH, 0x9401, URTW_REV_RTL8187L) }, - { USB_VPI(USB_VENDOR_HP, 0xca02, URTW_REV_RTL8187L) }, - { USB_VPI(USB_VENDOR_LOGITEC, 0x010c, URTW_REV_RTL8187L) }, - { USB_VPI(USB_VENDOR_NETGEAR, 0x6100, URTW_REV_RTL8187L) }, - { USB_VPI(USB_VENDOR_SPHAIRON, 0x0150, URTW_REV_RTL8187L) }, - { USB_VPI(USB_VENDOR_QCOM, 0x6232, URTW_REV_RTL8187L) }, -#undef URTW_DEV_L -#undef URTW_DEV_B -}; - -#define urtw_read8_m(sc, val, data) do { \ - error = urtw_read8_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_write8_m(sc, val, data) do { \ - error = urtw_write8_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_read16_m(sc, val, data) do { \ - error = urtw_read16_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_write16_m(sc, val, data) do { \ - error = urtw_write16_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_read32_m(sc, val, data) do { \ - error = urtw_read32_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_write32_m(sc, val, data) do { \ - error = urtw_write32_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_8187_write_phy_ofdm(sc, val, data) do { \ - error = urtw_8187_write_phy_ofdm_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_8187_write_phy_cck(sc, val, data) do { \ - error = urtw_8187_write_phy_cck_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define urtw_8225_write(sc, val, data) do { \ - error = urtw_8225_write_c(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) - -struct urtw_pair { - uint32_t reg; - uint32_t val; -}; - -static uint8_t urtw_8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9d, 0x9c, 0x9b, - 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, - 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, - 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, - 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, - 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, - 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -}; - -static uint8_t urtw_8225z2_agc[] = { - 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, - 0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, - 0x39, 0x37, 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, - 0x23, 0x21, 0x1f, 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, - 0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, - 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x20, 0x21, 0x22, 0x23, - 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2a, - 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d, - 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 -}; - -static uint32_t urtw_8225_channel[] = { - 0x0000, /* dummy channel 0 */ - 0x085c, /* 1 */ - 0x08dc, /* 2 */ - 0x095c, /* 3 */ - 0x09dc, /* 4 */ - 0x0a5c, /* 5 */ - 0x0adc, /* 6 */ - 0x0b5c, /* 7 */ - 0x0bdc, /* 8 */ - 0x0c5c, /* 9 */ - 0x0cdc, /* 10 */ - 0x0d5c, /* 11 */ - 0x0ddc, /* 12 */ - 0x0e5c, /* 13 */ - 0x0f72, /* 14 */ -}; - -static uint8_t urtw_8225_gain[] = { - 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ - 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ - 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ - 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ - 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ -}; - -static struct urtw_pair urtw_8225_rf_part1[] = { - { 0x00, 0x0067 }, { 0x01, 0x0fe0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, - { 0x04, 0x0486 }, { 0x05, 0x0bc0 }, { 0x06, 0x0ae6 }, { 0x07, 0x082a }, - { 0x08, 0x001f }, { 0x09, 0x0334 }, { 0x0a, 0x0fd4 }, { 0x0b, 0x0391 }, - { 0x0c, 0x0050 }, { 0x0d, 0x06db }, { 0x0e, 0x0029 }, { 0x0f, 0x0914 }, -}; - -static struct urtw_pair urtw_8225_rf_part2[] = { - { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, - { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, - { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x09 }, { 0x0b, 0x80 }, - { 0x0c, 0x01 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, { 0x10, 0x84 }, - { 0x11, 0x06 }, { 0x12, 0x20 }, { 0x13, 0x20 }, { 0x14, 0x00 }, - { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, { 0x18, 0xef }, - { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x76 }, { 0x1c, 0x04 }, - { 0x1e, 0x95 }, { 0x1f, 0x75 }, { 0x20, 0x1f }, { 0x21, 0x27 }, - { 0x22, 0x16 }, { 0x24, 0x46 }, { 0x25, 0x20 }, { 0x26, 0x90 }, - { 0x27, 0x88 } -}; - -static struct urtw_pair urtw_8225_rf_part3[] = { - { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, - { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x10, 0x9b }, - { 0x11, 0x88 }, { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, - { 0x1a, 0xa0 }, { 0x1b, 0x08 }, { 0x40, 0x86 }, { 0x41, 0x8d }, - { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x1f }, { 0x45, 0x1e }, - { 0x46, 0x1a }, { 0x47, 0x15 }, { 0x48, 0x10 }, { 0x49, 0x0a }, - { 0x4a, 0x05 }, { 0x4b, 0x02 }, { 0x4c, 0x05 } -}; - -static uint16_t urtw_8225_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, - 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb -}; - -static uint8_t urtw_8225_threshold[] = { - 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd, -}; - -static uint8_t urtw_8225_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static uint8_t urtw_8225_txpwr_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static uint8_t urtw_8225_txpwr_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static uint8_t urtw_8225_txpwr_ofdm[]={ - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static uint8_t urtw_8225v2_gain_bg[]={ - 0x23, 0x15, 0xa5, /* -82-1dbm */ - 0x23, 0x15, 0xb5, /* -82-2dbm */ - 0x23, 0x15, 0xc5, /* -82-3dbm */ - 0x33, 0x15, 0xc5, /* -78dbm */ - 0x43, 0x15, 0xc5, /* -74dbm */ - 0x53, 0x15, 0xc5, /* -70dbm */ - 0x63, 0x15, 0xc5, /* -66dbm */ -}; - -static struct urtw_pair urtw_8225v2_rf_part1[] = { - { 0x00, 0x02bf }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, - { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, - { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, - { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } -}; - -static struct urtw_pair urtw_8225v2b_rf_part0[] = { - { 0x00, 0x00b7 }, { 0x01, 0x0ee0 }, { 0x02, 0x044d }, { 0x03, 0x0441 }, - { 0x04, 0x08c3 }, { 0x05, 0x0c72 }, { 0x06, 0x00e6 }, { 0x07, 0x082a }, - { 0x08, 0x003f }, { 0x09, 0x0335 }, { 0x0a, 0x09d4 }, { 0x0b, 0x07bb }, - { 0x0c, 0x0850 }, { 0x0d, 0x0cdf }, { 0x0e, 0x002b }, { 0x0f, 0x0114 } -}; - -static struct urtw_pair urtw_8225v2b_rf_part1[] = { - {0x0f0, 0x32}, {0x0f1, 0x32}, {0x0f2, 0x00}, - {0x0f3, 0x00}, {0x0f4, 0x32}, {0x0f5, 0x43}, - {0x0f6, 0x00}, {0x0f7, 0x00}, {0x0f8, 0x46}, - {0x0f9, 0xa4}, {0x0fa, 0x00}, {0x0fb, 0x00}, - {0x0fc, 0x96}, {0x0fd, 0xa4}, {0x0fe, 0x00}, - {0x0ff, 0x00}, {0x158, 0x4b}, {0x159, 0x00}, - {0x15a, 0x4b}, {0x15b, 0x00}, {0x160, 0x4b}, - {0x161, 0x09}, {0x162, 0x4b}, {0x163, 0x09}, - {0x1ce, 0x0f}, {0x1cf, 0x00}, {0x1e0, 0xff}, - {0x1e1, 0x0f}, {0x1e2, 0x00}, {0x1f0, 0x4e}, - {0x1f1, 0x01}, {0x1f2, 0x02}, {0x1f3, 0x03}, - {0x1f4, 0x04}, {0x1f5, 0x05}, {0x1f6, 0x06}, - {0x1f7, 0x07}, {0x1f8, 0x08}, {0x24e, 0x00}, - {0x20c, 0x04}, {0x221, 0x61}, {0x222, 0x68}, - {0x223, 0x6f}, {0x224, 0x76}, {0x225, 0x7d}, - {0x226, 0x84}, {0x227, 0x8d}, {0x24d, 0x08}, - {0x250, 0x05}, {0x251, 0xf5}, {0x252, 0x04}, - {0x253, 0xa0}, {0x254, 0x1f}, {0x255, 0x23}, - {0x256, 0x45}, {0x257, 0x67}, {0x258, 0x08}, - {0x259, 0x08}, {0x25a, 0x08}, {0x25b, 0x08}, - {0x260, 0x08}, {0x261, 0x08}, {0x262, 0x08}, - {0x263, 0x08}, {0x264, 0xcf}, {0x272, 0x56}, - {0x273, 0x9a}, {0x034, 0xf0}, {0x035, 0x0f}, - {0x05b, 0x40}, {0x084, 0x88}, {0x085, 0x24}, - {0x088, 0x54}, {0x08b, 0xb8}, {0x08c, 0x07}, - {0x08d, 0x00}, {0x094, 0x1b}, {0x095, 0x12}, - {0x096, 0x00}, {0x097, 0x06}, {0x09d, 0x1a}, - {0x09f, 0x10}, {0x0b4, 0x22}, {0x0be, 0x80}, - {0x0db, 0x00}, {0x0ee, 0x00}, {0x091, 0x03}, - {0x24c, 0x00}, {0x39f, 0x00}, {0x08c, 0x01}, - {0x08d, 0x10}, {0x08e, 0x08}, {0x08f, 0x00} -}; - -static struct urtw_pair urtw_8225v2_rf_part2[] = { - { 0x00, 0x01 }, { 0x01, 0x02 }, { 0x02, 0x42 }, { 0x03, 0x00 }, - { 0x04, 0x00 }, { 0x05, 0x00 }, { 0x06, 0x40 }, { 0x07, 0x00 }, - { 0x08, 0x40 }, { 0x09, 0xfe }, { 0x0a, 0x08 }, { 0x0b, 0x80 }, - { 0x0c, 0x01 }, { 0x0d, 0x43 }, { 0x0e, 0xd3 }, { 0x0f, 0x38 }, - { 0x10, 0x84 }, { 0x11, 0x07 }, { 0x12, 0x20 }, { 0x13, 0x20 }, - { 0x14, 0x00 }, { 0x15, 0x40 }, { 0x16, 0x00 }, { 0x17, 0x40 }, - { 0x18, 0xef }, { 0x19, 0x19 }, { 0x1a, 0x20 }, { 0x1b, 0x15 }, - { 0x1c, 0x04 }, { 0x1d, 0xc5 }, { 0x1e, 0x95 }, { 0x1f, 0x75 }, - { 0x20, 0x1f }, { 0x21, 0x17 }, { 0x22, 0x16 }, { 0x23, 0x80 }, - { 0x24, 0x46 }, { 0x25, 0x00 }, { 0x26, 0x90 }, { 0x27, 0x88 } -}; - -static struct urtw_pair urtw_8225v2b_rf_part2[] = { - { 0x00, 0x10 }, { 0x01, 0x0d }, { 0x02, 0x01 }, { 0x03, 0x00 }, - { 0x04, 0x14 }, { 0x05, 0xfb }, { 0x06, 0xfb }, { 0x07, 0x60 }, - { 0x08, 0x00 }, { 0x09, 0x60 }, { 0x0a, 0x00 }, { 0x0b, 0x00 }, - { 0x0c, 0x00 }, { 0x0d, 0x5c }, { 0x0e, 0x00 }, { 0x0f, 0x00 }, - { 0x10, 0x40 }, { 0x11, 0x00 }, { 0x12, 0x40 }, { 0x13, 0x00 }, - { 0x14, 0x00 }, { 0x15, 0x00 }, { 0x16, 0xa8 }, { 0x17, 0x26 }, - { 0x18, 0x32 }, { 0x19, 0x33 }, { 0x1a, 0x07 }, { 0x1b, 0xa5 }, - { 0x1c, 0x6f }, { 0x1d, 0x55 }, { 0x1e, 0xc8 }, { 0x1f, 0xb3 }, - { 0x20, 0x0a }, { 0x21, 0xe1 }, { 0x22, 0x2C }, { 0x23, 0x8a }, - { 0x24, 0x86 }, { 0x25, 0x83 }, { 0x26, 0x34 }, { 0x27, 0x0f }, - { 0x28, 0x4f }, { 0x29, 0x24 }, { 0x2a, 0x6f }, { 0x2b, 0xc2 }, - { 0x2c, 0x6b }, { 0x2d, 0x40 }, { 0x2e, 0x80 }, { 0x2f, 0x00 }, - { 0x30, 0xc0 }, { 0x31, 0xc1 }, { 0x32, 0x58 }, { 0x33, 0xf1 }, - { 0x34, 0x00 }, { 0x35, 0xe4 }, { 0x36, 0x90 }, { 0x37, 0x3e }, - { 0x38, 0x6d }, { 0x39, 0x3c }, { 0x3a, 0xfb }, { 0x3b, 0x07 } -}; - -static struct urtw_pair urtw_8225v2_rf_part3[] = { - { 0x00, 0x98 }, { 0x03, 0x20 }, { 0x04, 0x7e }, { 0x05, 0x12 }, - { 0x06, 0xfc }, { 0x07, 0x78 }, { 0x08, 0x2e }, { 0x09, 0x11 }, - { 0x0a, 0x17 }, { 0x0b, 0x11 }, { 0x10, 0x9b }, { 0x11, 0x88 }, - { 0x12, 0x47 }, { 0x13, 0xd0 }, { 0x19, 0x00 }, { 0x1a, 0xa0 }, - { 0x1b, 0x08 }, { 0x1d, 0x00 }, { 0x40, 0x86 }, { 0x41, 0x9d }, - { 0x42, 0x15 }, { 0x43, 0x18 }, { 0x44, 0x36 }, { 0x45, 0x35 }, - { 0x46, 0x2e }, { 0x47, 0x25 }, { 0x48, 0x1c }, { 0x49, 0x12 }, - { 0x4a, 0x09 }, { 0x4b, 0x04 }, { 0x4c, 0x05 } -}; - -static uint16_t urtw_8225v2_rxgain[] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, - 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, - 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, - 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, - 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, - 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, - 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static uint16_t urtw_8225v2b_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static uint8_t urtw_8225v2_tx_gain_cck_ofdm[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, -}; - -static uint8_t urtw_8225v2_txpwr_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 -}; - -static uint8_t urtw_8225v2_txpwr_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 -}; - -static uint8_t urtw_8225v2b_txpwr_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, - 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 -}; - -static uint8_t urtw_8225v2b_txpwr_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static struct urtw_pair urtw_ratetable[] = { - { 2, 0 }, { 4, 1 }, { 11, 2 }, { 12, 4 }, { 18, 5 }, - { 22, 3 }, { 24, 6 }, { 36, 7 }, { 48, 8 }, { 72, 9 }, - { 96, 10 }, { 108, 11 } -}; - -static const uint8_t urtw_8187b_reg_table[][3] = { - { 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 }, - { 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 }, - { 0xf6, 0x00, 0 }, { 0xf7, 0x00, 0 }, { 0xf8, 0x46, 0 }, - { 0xf9, 0xa4, 0 }, { 0xfa, 0x00, 0 }, { 0xfb, 0x00, 0 }, - { 0xfc, 0x96, 0 }, { 0xfd, 0xa4, 0 }, { 0xfe, 0x00, 0 }, - { 0xff, 0x00, 0 }, { 0x58, 0x4b, 1 }, { 0x59, 0x00, 1 }, - { 0x5a, 0x4b, 1 }, { 0x5b, 0x00, 1 }, { 0x60, 0x4b, 1 }, - { 0x61, 0x09, 1 }, { 0x62, 0x4b, 1 }, { 0x63, 0x09, 1 }, - { 0xce, 0x0f, 1 }, { 0xcf, 0x00, 1 }, { 0xe0, 0xff, 1 }, - { 0xe1, 0x0f, 1 }, { 0xe2, 0x00, 1 }, { 0xf0, 0x4e, 1 }, - { 0xf1, 0x01, 1 }, { 0xf2, 0x02, 1 }, { 0xf3, 0x03, 1 }, - { 0xf4, 0x04, 1 }, { 0xf5, 0x05, 1 }, { 0xf6, 0x06, 1 }, - { 0xf7, 0x07, 1 }, { 0xf8, 0x08, 1 }, { 0x4e, 0x00, 2 }, - { 0x0c, 0x04, 2 }, { 0x21, 0x61, 2 }, { 0x22, 0x68, 2 }, - { 0x23, 0x6f, 2 }, { 0x24, 0x76, 2 }, { 0x25, 0x7d, 2 }, - { 0x26, 0x84, 2 }, { 0x27, 0x8d, 2 }, { 0x4d, 0x08, 2 }, - { 0x50, 0x05, 2 }, { 0x51, 0xf5, 2 }, { 0x52, 0x04, 2 }, - { 0x53, 0xa0, 2 }, { 0x54, 0x1f, 2 }, { 0x55, 0x23, 2 }, - { 0x56, 0x45, 2 }, { 0x57, 0x67, 2 }, { 0x58, 0x08, 2 }, - { 0x59, 0x08, 2 }, { 0x5a, 0x08, 2 }, { 0x5b, 0x08, 2 }, - { 0x60, 0x08, 2 }, { 0x61, 0x08, 2 }, { 0x62, 0x08, 2 }, - { 0x63, 0x08, 2 }, { 0x64, 0xcf, 2 }, { 0x72, 0x56, 2 }, - { 0x73, 0x9a, 2 }, { 0x34, 0xf0, 0 }, { 0x35, 0x0f, 0 }, - { 0x5b, 0x40, 0 }, { 0x84, 0x88, 0 }, { 0x85, 0x24, 0 }, - { 0x88, 0x54, 0 }, { 0x8b, 0xb8, 0 }, { 0x8c, 0x07, 0 }, - { 0x8d, 0x00, 0 }, { 0x94, 0x1b, 0 }, { 0x95, 0x12, 0 }, - { 0x96, 0x00, 0 }, { 0x97, 0x06, 0 }, { 0x9d, 0x1a, 0 }, - { 0x9f, 0x10, 0 }, { 0xb4, 0x22, 0 }, { 0xbe, 0x80, 0 }, - { 0xdb, 0x00, 0 }, { 0xee, 0x00, 0 }, { 0x91, 0x03, 0 }, - { 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 }, - { 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 } -}; - -static usb_callback_t urtw_bulk_rx_callback; -static usb_callback_t urtw_bulk_tx_callback; -static usb_callback_t urtw_bulk_tx_status_callback; - -static const struct usb_config urtw_8187b_usbconfig[URTW_8187B_N_XFERS] = { - [URTW_8187B_BULK_RX] = { - .type = UE_BULK, - .endpoint = 0x83, - .direction = UE_DIR_IN, - .bufsize = MCLBYTES, - .flags = { - .ext_buffer = 1, - .pipe_bof = 1, - .short_xfer_ok = 1 - }, - .callback = urtw_bulk_rx_callback - }, - [URTW_8187B_BULK_TX_STATUS] = { - .type = UE_BULK, - .endpoint = 0x89, - .direction = UE_DIR_IN, - .bufsize = MCLBYTES, - .flags = { - .ext_buffer = 1, - .pipe_bof = 1, - .short_xfer_ok = 1 - }, - .callback = urtw_bulk_tx_status_callback - }, - [URTW_8187B_BULK_TX_BE] = { - .type = UE_BULK, - .endpoint = URTW_8187B_TXPIPE_BE, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - }, - [URTW_8187B_BULK_TX_BK] = { - .type = UE_BULK, - .endpoint = URTW_8187B_TXPIPE_BK, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - }, - [URTW_8187B_BULK_TX_VI] = { - .type = UE_BULK, - .endpoint = URTW_8187B_TXPIPE_VI, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - }, - [URTW_8187B_BULK_TX_VO] = { - .type = UE_BULK, - .endpoint = URTW_8187B_TXPIPE_VO, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - }, - [URTW_8187B_BULK_TX_EP12] = { - .type = UE_BULK, - .endpoint = 0xc, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - } -}; - -static const struct usb_config urtw_8187l_usbconfig[URTW_8187L_N_XFERS] = { - [URTW_8187L_BULK_RX] = { - .type = UE_BULK, - .endpoint = 0x81, - .direction = UE_DIR_IN, - .bufsize = MCLBYTES, - .flags = { - .ext_buffer = 1, - .pipe_bof = 1, - .short_xfer_ok = 1 - }, - .callback = urtw_bulk_rx_callback - }, - [URTW_8187L_BULK_TX_LOW] = { - .type = UE_BULK, - .endpoint = 0x2, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - }, - [URTW_8187L_BULK_TX_NORMAL] = { - .type = UE_BULK, - .endpoint = 0x3, - .direction = UE_DIR_OUT, - .bufsize = URTW_TX_MAXSIZE, - .flags = { - .ext_buffer = 1, - .force_short_xfer = 1, - .pipe_bof = 1, - }, - .callback = urtw_bulk_tx_callback, - .timeout = URTW_DATA_TIMEOUT - }, -}; - -static struct ieee80211vap *urtw_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, - int, const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void urtw_vap_delete(struct ieee80211vap *); -static void urtw_init(void *); -static void urtw_stop(struct ifnet *, int); -static void urtw_stop_locked(struct ifnet *, int); -static int urtw_ioctl(struct ifnet *, u_long, caddr_t); -static void urtw_start(struct ifnet *); -static int urtw_alloc_rx_data_list(struct urtw_softc *); -static int urtw_alloc_tx_data_list(struct urtw_softc *); -static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static void urtw_scan_start(struct ieee80211com *); -static void urtw_scan_end(struct ieee80211com *); -static void urtw_set_channel(struct ieee80211com *); -static void urtw_update_mcast(struct ieee80211com *); -static int urtw_tx_start(struct urtw_softc *, - struct ieee80211_node *, struct mbuf *, - struct urtw_data *, int); -static int urtw_newstate(struct ieee80211vap *, - enum ieee80211_state, int); -static void urtw_led_ch(void *); -static void urtw_ledtask(void *, int); -static void urtw_watchdog(void *); -static void urtw_set_multi(void *); -static int urtw_isbmode(uint16_t); -static uint16_t urtw_rate2rtl(int); -static uint16_t urtw_rtl2rate(int); -static usb_error_t urtw_set_rate(struct urtw_softc *); -static usb_error_t urtw_update_msr(struct urtw_softc *); -static usb_error_t urtw_read8_c(struct urtw_softc *, int, uint8_t *); -static usb_error_t urtw_read16_c(struct urtw_softc *, int, uint16_t *); -static usb_error_t urtw_read32_c(struct urtw_softc *, int, uint32_t *); -static usb_error_t urtw_write8_c(struct urtw_softc *, int, uint8_t); -static usb_error_t urtw_write16_c(struct urtw_softc *, int, uint16_t); -static usb_error_t urtw_write32_c(struct urtw_softc *, int, uint32_t); -static usb_error_t urtw_eprom_cs(struct urtw_softc *, int); -static usb_error_t urtw_eprom_ck(struct urtw_softc *); -static usb_error_t urtw_eprom_sendbits(struct urtw_softc *, int16_t *, - int); -static usb_error_t urtw_eprom_read32(struct urtw_softc *, uint32_t, - uint32_t *); -static usb_error_t urtw_eprom_readbit(struct urtw_softc *, int16_t *); -static usb_error_t urtw_eprom_writebit(struct urtw_softc *, int16_t); -static usb_error_t urtw_get_macaddr(struct urtw_softc *); -static usb_error_t urtw_get_txpwr(struct urtw_softc *); -static usb_error_t urtw_get_rfchip(struct urtw_softc *); -static usb_error_t urtw_led_init(struct urtw_softc *); -static usb_error_t urtw_8185_rf_pins_enable(struct urtw_softc *); -static usb_error_t urtw_8185_tx_antenna(struct urtw_softc *, uint8_t); -static usb_error_t urtw_8187_write_phy(struct urtw_softc *, uint8_t, - uint32_t); -static usb_error_t urtw_8187_write_phy_ofdm_c(struct urtw_softc *, - uint8_t, uint32_t); -static usb_error_t urtw_8187_write_phy_cck_c(struct urtw_softc *, uint8_t, - uint32_t); -static usb_error_t urtw_8225_setgain(struct urtw_softc *, int16_t); -static usb_error_t urtw_8225_usb_init(struct urtw_softc *); -static usb_error_t urtw_8225_write_c(struct urtw_softc *, uint8_t, - uint16_t); -static usb_error_t urtw_8225_write_s16(struct urtw_softc *, uint8_t, int, - uint16_t *); -static usb_error_t urtw_8225_read(struct urtw_softc *, uint8_t, - uint32_t *); -static usb_error_t urtw_8225_rf_init(struct urtw_softc *); -static usb_error_t urtw_8225_rf_set_chan(struct urtw_softc *, int); -static usb_error_t urtw_8225_rf_set_sens(struct urtw_softc *, int); -static usb_error_t urtw_8225_set_txpwrlvl(struct urtw_softc *, int); -static usb_error_t urtw_8225_rf_stop(struct urtw_softc *); -static usb_error_t urtw_8225v2_rf_init(struct urtw_softc *); -static usb_error_t urtw_8225v2_rf_set_chan(struct urtw_softc *, int); -static usb_error_t urtw_8225v2_set_txpwrlvl(struct urtw_softc *, int); -static usb_error_t urtw_8225v2_setgain(struct urtw_softc *, int16_t); -static usb_error_t urtw_8225_isv2(struct urtw_softc *, int *); -static usb_error_t urtw_8225v2b_rf_init(struct urtw_softc *); -static usb_error_t urtw_8225v2b_rf_set_chan(struct urtw_softc *, int); -static usb_error_t urtw_read8e(struct urtw_softc *, int, uint8_t *); -static usb_error_t urtw_write8e(struct urtw_softc *, int, uint8_t); -static usb_error_t urtw_8180_set_anaparam(struct urtw_softc *, uint32_t); -static usb_error_t urtw_8185_set_anaparam2(struct urtw_softc *, uint32_t); -static usb_error_t urtw_intr_enable(struct urtw_softc *); -static usb_error_t urtw_intr_disable(struct urtw_softc *); -static usb_error_t urtw_reset(struct urtw_softc *); -static usb_error_t urtw_led_on(struct urtw_softc *, int); -static usb_error_t urtw_led_ctl(struct urtw_softc *, int); -static usb_error_t urtw_led_blink(struct urtw_softc *); -static usb_error_t urtw_led_mode0(struct urtw_softc *, int); -static usb_error_t urtw_led_mode1(struct urtw_softc *, int); -static usb_error_t urtw_led_mode2(struct urtw_softc *, int); -static usb_error_t urtw_led_mode3(struct urtw_softc *, int); -static usb_error_t urtw_rx_setconf(struct urtw_softc *); -static usb_error_t urtw_rx_enable(struct urtw_softc *); -static usb_error_t urtw_tx_enable(struct urtw_softc *sc); -static void urtw_free_tx_data_list(struct urtw_softc *); -static void urtw_free_rx_data_list(struct urtw_softc *); -static void urtw_free_data_list(struct urtw_softc *, - struct urtw_data data[], int, int); -static usb_error_t urtw_adapter_start(struct urtw_softc *); -static usb_error_t urtw_adapter_start_b(struct urtw_softc *); -static usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t); -static usb_error_t urtw_8187b_cmd_reset(struct urtw_softc *); -static usb_error_t urtw_do_request(struct urtw_softc *, - struct usb_device_request *, void *); -static usb_error_t urtw_8225v2b_set_txpwrlvl(struct urtw_softc *, int); -static usb_error_t urtw_led_off(struct urtw_softc *, int); -static void urtw_abort_xfers(struct urtw_softc *); -static struct urtw_data * - urtw_getbuf(struct urtw_softc *sc); -static int urtw_compute_txtime(uint16_t, uint16_t, uint8_t, - uint8_t); -static void urtw_updateslot(struct ieee80211com *); -static void urtw_updateslottask(void *, int); -static void urtw_sysctl_node(struct urtw_softc *); - -static int -urtw_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != URTW_CONFIG_INDEX) - return (ENXIO); - if (uaa->info.bIfaceIndex != URTW_IFACE_INDEX) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(urtw_devs, sizeof(urtw_devs), uaa)); -} - -static int -urtw_attach(device_t dev) -{ - const struct usb_config *setup_start; - int ret = ENXIO; - struct urtw_softc *sc = device_get_softc(dev); - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct ieee80211com *ic; - struct ifnet *ifp; - uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */ - uint16_t n_setup; - uint32_t data; - usb_error_t error; - - device_set_usb_desc(dev); - - sc->sc_dev = dev; - sc->sc_udev = uaa->device; - if (USB_GET_DRIVER_INFO(uaa) == URTW_REV_RTL8187B) - sc->sc_flags |= URTW_RTL8187B; -#ifdef URTW_DEBUG - sc->sc_debug = urtw_debug; -#endif - - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, - MTX_DEF); - usb_callout_init_mtx(&sc->sc_led_ch, &sc->sc_mtx, 0); - TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc); - TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc); - callout_init(&sc->sc_watchdog_ch, 0); - - if (sc->sc_flags & URTW_RTL8187B) { - setup_start = urtw_8187b_usbconfig; - n_setup = URTW_8187B_N_XFERS; - } else { - setup_start = urtw_8187l_usbconfig; - n_setup = URTW_8187L_N_XFERS; - } - - error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, - setup_start, n_setup, sc, &sc->sc_mtx); - if (error) { - device_printf(dev, "could not allocate USB transfers, " - "err=%s\n", usbd_errstr(error)); - ret = ENXIO; - goto fail0; - } - - URTW_LOCK(sc); - - urtw_read32_m(sc, URTW_RX, &data); - sc->sc_epromtype = (data & URTW_RX_9356SEL) ? URTW_EEPROM_93C56 : - URTW_EEPROM_93C46; - - error = urtw_get_rfchip(sc); - if (error != 0) - goto fail; - error = urtw_get_macaddr(sc); - if (error != 0) - goto fail; - error = urtw_get_txpwr(sc); - if (error != 0) - goto fail; - error = urtw_led_init(sc); - if (error != 0) - goto fail; - - URTW_UNLOCK(sc); - - sc->sc_rts_retry = URTW_DEFAULT_RTS_RETRY; - sc->sc_tx_retry = URTW_DEFAULT_TX_RETRY; - sc->sc_currate = 3; - sc->sc_preamble_mode = urtw_preamble_mode; - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not allocate ifnet\n"); - ret = ENOMEM; - goto fail1; - } - - ifp->if_softc = sc; - if_initname(ifp, "urtw", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = urtw_init; - ifp->if_ioctl = urtw_ioctl; - ifp->if_start = urtw_start; - /* XXX URTW_TX_DATA_LIST_COUNT */ - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(dev); - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA | /* station mode */ - IEEE80211_C_MONITOR | /* monitor mode supported */ - IEEE80211_C_TXPMGT | /* tx power management */ - IEEE80211_C_SHPREAMBLE | /* short preamble supported */ - IEEE80211_C_SHSLOT | /* short slot time supported */ - IEEE80211_C_BGSCAN | /* capable of bg scanning */ - IEEE80211_C_WPA; /* 802.11i */ - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic, sc->sc_bssid); - ic->ic_raw_xmit = urtw_raw_xmit; - ic->ic_scan_start = urtw_scan_start; - ic->ic_scan_end = urtw_scan_end; - ic->ic_set_channel = urtw_set_channel; - ic->ic_updateslot = urtw_updateslot; - ic->ic_vap_create = urtw_vap_create; - ic->ic_vap_delete = urtw_vap_delete; - ic->ic_update_mcast = urtw_update_mcast; - - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - URTW_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - URTW_RX_RADIOTAP_PRESENT); - - urtw_sysctl_node(sc); - - if (bootverbose) - ieee80211_announce(ic); - return (0); - -fail: URTW_UNLOCK(sc); -fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? - URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); -fail0: - return (ret); -} - -static int -urtw_detach(device_t dev) -{ - struct urtw_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - if (!device_is_attached(dev)) - return (0); - - urtw_stop(ifp, 1); - ieee80211_draintask(ic, &sc->sc_updateslot_task); - ieee80211_draintask(ic, &sc->sc_led_task); - - usb_callout_drain(&sc->sc_led_ch); - callout_drain(&sc->sc_watchdog_ch); - - usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? - URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); - ieee80211_ifdetach(ic); - - urtw_free_tx_data_list(sc); - urtw_free_rx_data_list(sc); - - if_free(ifp); - mtx_destroy(&sc->sc_mtx); - - return (0); -} - -static void -urtw_free_tx_data_list(struct urtw_softc *sc) -{ - urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0); -} - -static void -urtw_free_rx_data_list(struct urtw_softc *sc) -{ - urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1); -} - -static void -urtw_free_data_list(struct urtw_softc *sc, struct urtw_data data[], int ndata, - int fillmbuf) -{ - int i; - - for (i = 0; i < ndata; i++) { - struct urtw_data *dp = &data[i]; - - if (fillmbuf == 1) { - if (dp->m != NULL) { - m_freem(dp->m); - dp->m = NULL; - dp->buf = NULL; - } - } else { - if (dp->buf != NULL) { - free(dp->buf, M_USBDEV); - dp->buf = NULL; - } - } - if (dp->ni != NULL) { - ieee80211_free_node(dp->ni); - dp->ni = NULL; - } - } -} - -static struct ieee80211vap * -urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct urtw_vap *uvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return (NULL); - uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap), - M_80211_VAP, M_WAITOK | M_ZERO); - if (uvp == NULL) - return (NULL); - vap = &uvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - uvp->newstate = vap->iv_newstate; - vap->iv_newstate = urtw_newstate; - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return (vap); -} - -static void -urtw_vap_delete(struct ieee80211vap *vap) -{ - struct urtw_vap *uvp = URTW_VAP(vap); - - ieee80211_vap_detach(vap); - free(uvp, M_80211_VAP); -} - -static void -urtw_init_locked(void *arg) -{ - int ret; - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - usb_error_t error; - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop_locked(ifp, 0); - - error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) : - urtw_adapter_start(sc); - if (error != 0) - goto fail; - - /* reset softc variables */ - sc->sc_txtimer = 0; - - if (!(sc->sc_flags & URTW_INIT_ONCE)) { - ret = urtw_alloc_rx_data_list(sc); - if (ret != 0) - goto fail; - ret = urtw_alloc_tx_data_list(sc); - if (ret != 0) - goto fail; - sc->sc_flags |= URTW_INIT_ONCE; - } - - error = urtw_rx_enable(sc); - if (error != 0) - goto fail; - error = urtw_tx_enable(sc); - if (error != 0) - goto fail; - - if (sc->sc_flags & URTW_RTL8187B) - usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - - callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); -fail: - return; -} - -static void -urtw_init(void *arg) -{ - struct urtw_softc *sc = arg; - - URTW_LOCK(sc); - urtw_init_locked(arg); - URTW_UNLOCK(sc); -} - -static usb_error_t -urtw_adapter_start_b(struct urtw_softc *sc) -{ - uint8_t data8; - usb_error_t error; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - urtw_read8_m(sc, URTW_CONFIG3, &data8); - urtw_write8_m(sc, URTW_CONFIG3, - data8 | URTW_CONFIG3_ANAPARAM_WRITE | URTW_CONFIG3_GNT_SELECT); - urtw_write32_m(sc, URTW_ANAPARAM2, URTW_8187B_8225_ANAPARAM2_ON); - urtw_write32_m(sc, URTW_ANAPARAM, URTW_8187B_8225_ANAPARAM_ON); - urtw_write8_m(sc, URTW_ANAPARAM3, URTW_8187B_8225_ANAPARAM3_ON); - - urtw_write8_m(sc, 0x61, 0x10); - urtw_read8_m(sc, 0x62, &data8); - urtw_write8_m(sc, 0x62, data8 & ~(1 << 5)); - urtw_write8_m(sc, 0x62, data8 | (1 << 5)); - - urtw_read8_m(sc, URTW_CONFIG3, &data8); - data8 &= ~URTW_CONFIG3_ANAPARAM_WRITE; - urtw_write8_m(sc, URTW_CONFIG3, data8); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_8187b_cmd_reset(sc); - if (error) - goto fail; - - error = sc->sc_rf_init(sc); - if (error != 0) - goto fail; - urtw_write8_m(sc, URTW_CMD, URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE); - - /* fix RTL8187B RX stall */ - error = urtw_intr_enable(sc); - if (error) - goto fail; - - error = urtw_write8e(sc, 0x41, 0xf4); - if (error) - goto fail; - error = urtw_write8e(sc, 0x40, 0x00); - if (error) - goto fail; - error = urtw_write8e(sc, 0x42, 0x00); - if (error) - goto fail; - error = urtw_write8e(sc, 0x42, 0x01); - if (error) - goto fail; - error = urtw_write8e(sc, 0x40, 0x0f); - if (error) - goto fail; - error = urtw_write8e(sc, 0x42, 0x00); - if (error) - goto fail; - error = urtw_write8e(sc, 0x42, 0x01); - if (error) - goto fail; - - urtw_read8_m(sc, 0xdb, &data8); - urtw_write8_m(sc, 0xdb, data8 | (1 << 2)); - urtw_write16_m(sc, 0x372, 0x59fa); - urtw_write16_m(sc, 0x374, 0x59d2); - urtw_write16_m(sc, 0x376, 0x59d2); - urtw_write16_m(sc, 0x378, 0x19fa); - urtw_write16_m(sc, 0x37a, 0x19fa); - urtw_write16_m(sc, 0x37c, 0x00d0); - urtw_write8_m(sc, 0x61, 0); - - urtw_write8_m(sc, 0x180, 0x0f); - urtw_write8_m(sc, 0x183, 0x03); - urtw_write8_m(sc, 0xda, 0x10); - urtw_write8_m(sc, 0x24d, 0x08); - urtw_write32_m(sc, URTW_HSSI_PARA, 0x0600321b); - - urtw_write16_m(sc, 0x1ec, 0x800); /* RX MAX SIZE */ -fail: - return (error); -} - -static usb_error_t -urtw_adapter_start(struct urtw_softc *sc) -{ - usb_error_t error; - - error = urtw_reset(sc); - if (error) - goto fail; - - urtw_write8_m(sc, URTW_ADDR_MAGIC1, 0); - urtw_write8_m(sc, URTW_GPIO, 0); - - /* for led */ - urtw_write8_m(sc, URTW_ADDR_MAGIC1, 4); - error = urtw_led_ctl(sc, URTW_LED_CTL_POWER_ON); - if (error != 0) - goto fail; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_update_msr(sc); - if (error) - goto fail; - - urtw_write32_m(sc, URTW_INT_TIMEOUT, 0); - urtw_write8_m(sc, URTW_WPA_CONFIG, 0); - urtw_write8_m(sc, URTW_RATE_FALLBACK, URTW_RATE_FALLBACK_ENABLE | 0x1); - error = urtw_set_rate(sc); - if (error != 0) - goto fail; - - error = sc->sc_rf_init(sc); - if (error != 0) - goto fail; - if (sc->sc_rf_set_sens != NULL) - sc->sc_rf_set_sens(sc, sc->sc_sens); - - /* XXX correct? to call write16 */ - urtw_write16_m(sc, URTW_PSR, 1); - urtw_write16_m(sc, URTW_ADDR_MAGIC2, 0x10); - urtw_write8_m(sc, URTW_TALLY_SEL, 0x80); - urtw_write8_m(sc, URTW_ADDR_MAGIC3, 0x60); - /* XXX correct? to call write16 */ - urtw_write16_m(sc, URTW_PSR, 0); - urtw_write8_m(sc, URTW_ADDR_MAGIC1, 4); - - error = urtw_intr_enable(sc); - if (error != 0) - goto fail; - -fail: - return (error); -} - -static usb_error_t -urtw_set_mode(struct urtw_softc *sc, uint32_t mode) -{ - uint8_t data; - usb_error_t error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - data = (data & ~URTW_EPROM_CMD_MASK) | (mode << URTW_EPROM_CMD_SHIFT); - data = data & ~(URTW_EPROM_CS | URTW_EPROM_CK); - urtw_write8_m(sc, URTW_EPROM_CMD, data); -fail: - return (error); -} - -static usb_error_t -urtw_8187b_cmd_reset(struct urtw_softc *sc) -{ - int i; - uint8_t data8; - usb_error_t error; - - /* XXX the code can be duplicate with urtw_reset(). */ - urtw_read8_m(sc, URTW_CMD, &data8); - data8 = (data8 & 0x2) | URTW_CMD_RST; - urtw_write8_m(sc, URTW_CMD, data8); - - for (i = 0; i < 20; i++) { - usb_pause_mtx(&sc->sc_mtx, 2); - urtw_read8_m(sc, URTW_CMD, &data8); - if (!(data8 & URTW_CMD_RST)) - break; - } - if (i >= 20) { - device_printf(sc->sc_dev, "reset timeout\n"); - goto fail; - } -fail: - return (error); -} - -static usb_error_t -urtw_do_request(struct urtw_softc *sc, - struct usb_device_request *req, void *data) -{ - usb_error_t err; - int ntries = 10; - - URTW_ASSERT_LOCKED(sc); - - while (ntries--) { - err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx, - req, data, 0, NULL, 250 /* ms */); - if (err == 0) - break; - - DPRINTF(sc, URTW_DEBUG_INIT, - "Control request failed, %s (retrying)\n", - usbd_errstr(err)); - usb_pause_mtx(&sc->sc_mtx, hz / 100); - } - return (err); -} - -static void -urtw_stop_locked(struct ifnet *ifp, int disable) -{ - struct urtw_softc *sc = ifp->if_softc; - uint8_t data8; - usb_error_t error; - - (void)disable; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - error = urtw_intr_disable(sc); - if (error) - goto fail; - urtw_read8_m(sc, URTW_CMD, &data8); - data8 &= ~(URTW_CMD_RX_ENABLE | URTW_CMD_TX_ENABLE); - urtw_write8_m(sc, URTW_CMD, data8); - - error = sc->sc_rf_stop(sc); - if (error != 0) - goto fail; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - urtw_read8_m(sc, URTW_CONFIG4, &data8); - urtw_write8_m(sc, URTW_CONFIG4, data8 | URTW_CONFIG4_VCOOFF); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; -fail: - if (error) - device_printf(sc->sc_dev, "failed to stop (%s)\n", - usbd_errstr(error)); - - usb_callout_stop(&sc->sc_led_ch); - callout_stop(&sc->sc_watchdog_ch); - - urtw_abort_xfers(sc); -} - -static void -urtw_stop(struct ifnet *ifp, int disable) -{ - struct urtw_softc *sc = ifp->if_softc; - - URTW_LOCK(sc); - urtw_stop_locked(ifp, disable); - URTW_UNLOCK(sc); -} - -static void -urtw_abort_xfers(struct urtw_softc *sc) -{ - int i, max; - - URTW_ASSERT_LOCKED(sc); - - max = (sc->sc_flags & URTW_RTL8187B) ? URTW_8187B_N_XFERS : - URTW_8187L_N_XFERS; - - /* abort any pending transfers */ - for (i = 0; i < max; i++) - usbd_transfer_stop(sc->sc_xfer[i]); -} - -static int -urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct urtw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - if ((ifp->if_flags ^ sc->sc_if_flags) & - (IFF_ALLMULTI | IFF_PROMISC)) - urtw_set_multi(sc); - } else { - urtw_init(ifp->if_softc); - startall = 1; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop(ifp, 1); - } - sc->sc_if_flags = ifp->if_flags; - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - - return (error); -} - -static void -urtw_start(struct ifnet *ifp) -{ - struct urtw_data *bf; - struct urtw_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - URTW_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - bf = urtw_getbuf(sc); - if (bf == NULL) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - break; - } - - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - m->m_pkthdr.rcvif = NULL; - - if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) { - ifp->if_oerrors++; - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - ieee80211_free_node(ni); - break; - } - - sc->sc_txtimer = 5; - callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); - } - URTW_UNLOCK(sc); -} - -static int -urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[], - int ndata, int maxsz, int fillmbuf) -{ - int i, error; - - for (i = 0; i < ndata; i++) { - struct urtw_data *dp = &data[i]; - - dp->sc = sc; - if (fillmbuf) { - dp->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (dp->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - dp->buf = mtod(dp->m, uint8_t *); - } else { - dp->m = NULL; - dp->buf = malloc(maxsz, M_USBDEV, M_WAITOK); - if (dp->buf == NULL) { - device_printf(sc->sc_dev, - "could not allocate buffer\n"); - error = ENOMEM; - goto fail; - } - if (((unsigned long)dp->buf) % 4) - device_printf(sc->sc_dev, - "warn: unaligned buffer %p\n", dp->buf); - } - dp->ni = NULL; - } - - return 0; - -fail: urtw_free_data_list(sc, data, ndata, fillmbuf); - return error; -} - -static int -urtw_alloc_rx_data_list(struct urtw_softc *sc) -{ - int error, i; - - error = urtw_alloc_data_list(sc, - sc->sc_rx, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */); - if (error != 0) - return (error); - - STAILQ_INIT(&sc->sc_rx_active); - STAILQ_INIT(&sc->sc_rx_inactive); - - for (i = 0; i < URTW_RX_DATA_LIST_COUNT; i++) - STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next); - - return (0); -} - -static int -urtw_alloc_tx_data_list(struct urtw_softc *sc) -{ - int error, i; - - error = urtw_alloc_data_list(sc, - sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE, - 0 /* no mbufs */); - if (error != 0) - return (error); - - STAILQ_INIT(&sc->sc_tx_active); - STAILQ_INIT(&sc->sc_tx_inactive); - STAILQ_INIT(&sc->sc_tx_pending); - - for (i = 0; i < URTW_TX_DATA_LIST_COUNT; i++) - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], - next); - - return (0); -} - -static int -urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct urtw_data *bf; - struct urtw_softc *sc = ifp->if_softc; - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - m_freem(m); - ieee80211_free_node(ni); - return ENETDOWN; - } - URTW_LOCK(sc); - bf = urtw_getbuf(sc); - if (bf == NULL) { - ieee80211_free_node(ni); - m_freem(m); - URTW_UNLOCK(sc); - return (ENOBUFS); /* XXX */ - } - - ifp->if_opackets++; - if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); - URTW_UNLOCK(sc); - return (EIO); - } - URTW_UNLOCK(sc); - - sc->sc_txtimer = 5; - return (0); -} - -static void -urtw_scan_start(struct ieee80211com *ic) -{ - - /* XXX do nothing? */ -} - -static void -urtw_scan_end(struct ieee80211com *ic) -{ - - /* XXX do nothing? */ -} - -static void -urtw_set_channel(struct ieee80211com *ic) -{ - struct urtw_softc *sc = ic->ic_ifp->if_softc; - struct ifnet *ifp = sc->sc_ifp; - uint32_t data, orig; - usb_error_t error; - - /* - * if the user set a channel explicitly using ifconfig(8) this function - * can be called earlier than we're expected that in some cases the - * initialization would be failed if setting a channel is called before - * the init have done. - */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) - return; - - if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan) - return; - - URTW_LOCK(sc); - - /* - * during changing th channel we need to temporarily be disable - * TX. - */ - urtw_read32_m(sc, URTW_TX_CONF, &orig); - data = orig & ~URTW_TX_LOOPBACK_MASK; - urtw_write32_m(sc, URTW_TX_CONF, data | URTW_TX_LOOPBACK_MAC); - - error = sc->sc_rf_set_chan(sc, ieee80211_chan2ieee(ic, ic->ic_curchan)); - if (error != 0) - goto fail; - usb_pause_mtx(&sc->sc_mtx, 10); - urtw_write32_m(sc, URTW_TX_CONF, orig); - - urtw_write16_m(sc, URTW_ATIM_WND, 2); - urtw_write16_m(sc, URTW_ATIM_TR_ITV, 100); - urtw_write16_m(sc, URTW_BEACON_INTERVAL, 100); - urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 100); - -fail: - URTW_UNLOCK(sc); - - sc->sc_curchan = ic->ic_curchan; - - if (error != 0) - device_printf(sc->sc_dev, "could not change the channel\n"); -} - -static void -urtw_update_mcast(struct ieee80211com *ic) -{ - - /* XXX do nothing? */ -} - -static int -urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, - struct urtw_data *data, int prior) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *); - struct ieee80211_key *k; - const struct ieee80211_txparam *tp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = ni->ni_vap; - struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = { - sc->sc_xfer[URTW_8187B_BULK_TX_BE], - sc->sc_xfer[URTW_8187B_BULK_TX_BK], - sc->sc_xfer[URTW_8187B_BULK_TX_VI], - sc->sc_xfer[URTW_8187B_BULK_TX_VO] - }; - struct usb_xfer *xfer; - int dur = 0, rtsdur = 0, rtsenable = 0, ctsenable = 0, rate, - pkttime = 0, txdur = 0, isshort = 0, xferlen; - uint16_t acktime, rtstime, ctstime; - uint32_t flags; - usb_error_t error; - - URTW_ASSERT_LOCKED(sc); - - /* - * Software crypto. - */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - device_printf(sc->sc_dev, - "ieee80211_crypto_encap returns NULL.\n"); - /* XXX we don't expect the fragmented frames */ - m_freem(m0); - return (ENOBUFS); - } - - /* in case packet header moved, reset pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - if (ieee80211_radiotap_active_vap(vap)) { - struct urtw_tx_radiotap_header *tap = &sc->sc_txtap; - - /* XXX Are variables correct? */ - tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - - ieee80211_radiotap_tx(vap, m0); - } - - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT || - (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) { - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - rate = tp->mgmtrate; - } else { - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - /* for data frames */ - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else - rate = urtw_rtl2rate(sc->sc_currate); - } - - sc->sc_stats.txrates[sc->sc_currate]++; - - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - txdur = pkttime = urtw_compute_txtime(m0->m_pkthdr.len + - IEEE80211_CRC_LEN, rate, 0, 0); - else { - acktime = urtw_compute_txtime(14, 2,0, 0); - if ((m0->m_pkthdr.len + 4) > vap->iv_rtsthreshold) { - rtsenable = 1; - ctsenable = 0; - rtstime = urtw_compute_txtime(URTW_ACKCTS_LEN, 2, 0, 0); - ctstime = urtw_compute_txtime(14, 2, 0, 0); - pkttime = urtw_compute_txtime(m0->m_pkthdr.len + - IEEE80211_CRC_LEN, rate, 0, isshort); - rtsdur = ctstime + pkttime + acktime + - 3 * URTW_ASIFS_TIME; - txdur = rtstime + rtsdur; - } else { - rtsenable = ctsenable = rtsdur = 0; - pkttime = urtw_compute_txtime(m0->m_pkthdr.len + - IEEE80211_CRC_LEN, rate, 0, isshort); - txdur = pkttime + URTW_ASIFS_TIME + acktime; - } - - if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) - dur = urtw_compute_txtime(m0->m_pkthdr.len + - IEEE80211_CRC_LEN, rate, 0, isshort) + - 3 * URTW_ASIFS_TIME + - 2 * acktime; - else - dur = URTW_ASIFS_TIME + acktime; - } - *(uint16_t *)wh->i_dur = htole16(dur); - - xferlen = m0->m_pkthdr.len; - xferlen += (sc->sc_flags & URTW_RTL8187B) ? (4 * 8) : (4 * 3); - if ((0 == xferlen % 64) || (0 == xferlen % 512)) - xferlen += 1; - - memset(data->buf, 0, URTW_TX_MAXSIZE); - flags = m0->m_pkthdr.len & 0xfff; - flags |= URTW_TX_FLAG_NO_ENC; - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) && - (sc->sc_preamble_mode == URTW_PREAMBLE_MODE_SHORT) && - (sc->sc_currate != 0)) - flags |= URTW_TX_FLAG_SPLCP; - if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) - flags |= URTW_TX_FLAG_MOREFRAG; - - flags |= (sc->sc_currate & 0xf) << URTW_TX_FLAG_TXRATE_SHIFT; - - if (sc->sc_flags & URTW_RTL8187B) { - struct urtw_8187b_txhdr *tx; - - tx = (struct urtw_8187b_txhdr *)data->buf; - if (ctsenable) - flags |= URTW_TX_FLAG_CTS; - if (rtsenable) { - flags |= URTW_TX_FLAG_RTS; - flags |= (urtw_rate2rtl(11) & 0xf) << - URTW_TX_FLAG_RTSRATE_SHIFT; - tx->rtsdur = rtsdur; - } - tx->flag = htole32(flags); - tx->txdur = txdur; - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == - IEEE80211_FC0_TYPE_MGT && - (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == - IEEE80211_FC0_SUBTYPE_PROBE_RESP) - tx->retry = 1; - else - tx->retry = URTW_TX_MAXRETRY; - m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(tx + 1)); - } else { - struct urtw_8187l_txhdr *tx; - - tx = (struct urtw_8187l_txhdr *)data->buf; - if (rtsenable) { - flags |= URTW_TX_FLAG_RTS; - tx->rtsdur = rtsdur; - } - flags |= (urtw_rate2rtl(11) & 0xf) << URTW_TX_FLAG_RTSRATE_SHIFT; - tx->flag = htole32(flags); - tx->retry = 3; /* CW minimum */ - tx->retry |= 7 << 4; /* CW maximum */ - tx->retry |= URTW_TX_MAXRETRY << 8; /* retry limitation */ - m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(tx + 1)); - } - - data->buflen = xferlen; - data->ni = ni; - data->m = m0; - - if (sc->sc_flags & URTW_RTL8187B) { - switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { - case IEEE80211_FC0_TYPE_CTL: - case IEEE80211_FC0_TYPE_MGT: - xfer = sc->sc_xfer[URTW_8187B_BULK_TX_EP12]; - break; - default: - KASSERT(M_WME_GETAC(m0) < URTW_8187B_TXPIPE_MAX, - ("unsupported WME pipe %d", M_WME_GETAC(m0))); - xfer = rtl8187b_pipes[M_WME_GETAC(m0)]; - break; - } - } else - xfer = (prior == URTW_PRIORITY_LOW) ? - sc->sc_xfer[URTW_8187L_BULK_TX_LOW] : - sc->sc_xfer[URTW_8187L_BULK_TX_NORMAL]; - - STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next); - usbd_transfer_start(xfer); - - error = urtw_led_ctl(sc, URTW_LED_CTL_TX); - if (error != 0) - device_printf(sc->sc_dev, "could not control LED (%d)\n", - error); - return (0); -} - -static int -urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct ieee80211com *ic = vap->iv_ic; - struct urtw_softc *sc = ic->ic_ifp->if_softc; - struct urtw_vap *uvp = URTW_VAP(vap); - struct ieee80211_node *ni; - usb_error_t error = 0; - - DPRINTF(sc, URTW_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - sc->sc_state = nstate; - - IEEE80211_UNLOCK(ic); - URTW_LOCK(sc); - usb_callout_stop(&sc->sc_led_ch); - callout_stop(&sc->sc_watchdog_ch); - - switch (nstate) { - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - case IEEE80211_S_AUTH: - case IEEE80211_S_ASSOC: - break; - case IEEE80211_S_RUN: - ni = ieee80211_ref_node(vap->iv_bss); - /* setting bssid. */ - urtw_write32_m(sc, URTW_BSSID, ((uint32_t *)ni->ni_bssid)[0]); - urtw_write16_m(sc, URTW_BSSID + 4, - ((uint16_t *)ni->ni_bssid)[2]); - urtw_update_msr(sc); - /* XXX maybe the below would be incorrect. */ - urtw_write16_m(sc, URTW_ATIM_WND, 2); - urtw_write16_m(sc, URTW_ATIM_TR_ITV, 100); - urtw_write16_m(sc, URTW_BEACON_INTERVAL, 0x64); - urtw_write16_m(sc, URTW_BEACON_INTERVAL_TIME, 100); - error = urtw_led_ctl(sc, URTW_LED_CTL_LINK); - if (error != 0) - device_printf(sc->sc_dev, - "could not control LED (%d)\n", error); - ieee80211_free_node(ni); - break; - default: - break; - } -fail: - URTW_UNLOCK(sc); - IEEE80211_LOCK(ic); - return (uvp->newstate(vap, nstate, arg)); -} - -static void -urtw_watchdog(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (sc->sc_txtimer > 0) { - if (--sc->sc_txtimer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - ifp->if_oerrors++; - return; - } - callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); - } -} - -static void -urtw_set_multi(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - - if (!(ifp->if_flags & IFF_UP)) - return; - - /* - * XXX don't know how to set a device. Lack of docs. Just try to set - * IFF_ALLMULTI flag here. - */ - ifp->if_flags |= IFF_ALLMULTI; -} - -static usb_error_t -urtw_set_rate(struct urtw_softc *sc) -{ - int i, basic_rate, min_rr_rate, max_rr_rate; - uint16_t data; - usb_error_t error; - - basic_rate = urtw_rate2rtl(48); - min_rr_rate = urtw_rate2rtl(12); - max_rr_rate = urtw_rate2rtl(48); - - urtw_write8_m(sc, URTW_RESP_RATE, - max_rr_rate << URTW_RESP_MAX_RATE_SHIFT | - min_rr_rate << URTW_RESP_MIN_RATE_SHIFT); - - urtw_read16_m(sc, URTW_BRSR, &data); - data &= ~URTW_BRSR_MBR_8185; - - for (i = 0; i <= basic_rate; i++) - data |= (1 << i); - - urtw_write16_m(sc, URTW_BRSR, data); -fail: - return (error); -} - -static uint16_t -urtw_rate2rtl(int rate) -{ - int i; - - for (i = 0; i < nitems(urtw_ratetable); i++) { - if (rate == urtw_ratetable[i].reg) - return urtw_ratetable[i].val; - } - - return (3); -} - -static uint16_t -urtw_rtl2rate(int rate) -{ - int i; - - for (i = 0; i < nitems(urtw_ratetable); i++) { - if (rate == urtw_ratetable[i].val) - return urtw_ratetable[i].reg; - } - - return (0); -} - -static usb_error_t -urtw_update_msr(struct urtw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t data; - usb_error_t error; - - urtw_read8_m(sc, URTW_MSR, &data); - data &= ~URTW_MSR_LINK_MASK; - - if (sc->sc_state == IEEE80211_S_RUN) { - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - case IEEE80211_M_MONITOR: - data |= URTW_MSR_LINK_STA; - if (sc->sc_flags & URTW_RTL8187B) - data |= URTW_MSR_LINK_ENEDCA; - break; - case IEEE80211_M_IBSS: - data |= URTW_MSR_LINK_ADHOC; - break; - case IEEE80211_M_HOSTAP: - data |= URTW_MSR_LINK_HOSTAP; - break; - default: - panic("unsupported operation mode 0x%x\n", - ic->ic_opmode); - /* never reach */ - } - } else - data |= URTW_MSR_LINK_NONE; - - urtw_write8_m(sc, URTW_MSR, data); -fail: - return (error); -} - -static usb_error_t -urtw_read8_c(struct urtw_softc *sc, int val, uint8_t *data) -{ - struct usb_device_request req; - usb_error_t error; - - URTW_ASSERT_LOCKED(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, (val & 0xff) | 0xff00); - USETW(req.wIndex, (val >> 8) & 0x3); - USETW(req.wLength, sizeof(uint8_t)); - - error = urtw_do_request(sc, &req, data); - return (error); -} - -static usb_error_t -urtw_read16_c(struct urtw_softc *sc, int val, uint16_t *data) -{ - struct usb_device_request req; - usb_error_t error; - - URTW_ASSERT_LOCKED(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, (val & 0xff) | 0xff00); - USETW(req.wIndex, (val >> 8) & 0x3); - USETW(req.wLength, sizeof(uint16_t)); - - error = urtw_do_request(sc, &req, data); - return (error); -} - -static usb_error_t -urtw_read32_c(struct urtw_softc *sc, int val, uint32_t *data) -{ - struct usb_device_request req; - usb_error_t error; - - URTW_ASSERT_LOCKED(sc); - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, (val & 0xff) | 0xff00); - USETW(req.wIndex, (val >> 8) & 0x3); - USETW(req.wLength, sizeof(uint32_t)); - - error = urtw_do_request(sc, &req, data); - return (error); -} - -static usb_error_t -urtw_write8_c(struct urtw_softc *sc, int val, uint8_t data) -{ - struct usb_device_request req; - - URTW_ASSERT_LOCKED(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, (val & 0xff) | 0xff00); - USETW(req.wIndex, (val >> 8) & 0x3); - USETW(req.wLength, sizeof(uint8_t)); - - return (urtw_do_request(sc, &req, &data)); -} - -static usb_error_t -urtw_write16_c(struct urtw_softc *sc, int val, uint16_t data) -{ - struct usb_device_request req; - - URTW_ASSERT_LOCKED(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, (val & 0xff) | 0xff00); - USETW(req.wIndex, (val >> 8) & 0x3); - USETW(req.wLength, sizeof(uint16_t)); - - return (urtw_do_request(sc, &req, &data)); -} - -static usb_error_t -urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data) -{ - struct usb_device_request req; - - URTW_ASSERT_LOCKED(sc); - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, (val & 0xff) | 0xff00); - USETW(req.wIndex, (val >> 8) & 0x3); - USETW(req.wLength, sizeof(uint32_t)); - - return (urtw_do_request(sc, &req, &data)); -} - -static usb_error_t -urtw_get_macaddr(struct urtw_softc *sc) -{ - uint32_t data; - usb_error_t error; - - error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data); - if (error != 0) - goto fail; - sc->sc_bssid[0] = data & 0xff; - sc->sc_bssid[1] = (data & 0xff00) >> 8; - error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); - if (error != 0) - goto fail; - sc->sc_bssid[2] = data & 0xff; - sc->sc_bssid[3] = (data & 0xff00) >> 8; - error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); - if (error != 0) - goto fail; - sc->sc_bssid[4] = data & 0xff; - sc->sc_bssid[5] = (data & 0xff00) >> 8; -fail: - return (error); -} - -static usb_error_t -urtw_eprom_read32(struct urtw_softc *sc, uint32_t addr, uint32_t *data) -{ -#define URTW_READCMD_LEN 3 - int addrlen, i; - int16_t addrstr[8], data16, readcmd[] = { 1, 1, 0 }; - usb_error_t error; - - /* NB: make sure the buffer is initialized */ - *data = 0; - - /* enable EPROM programming */ - urtw_write8_m(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_PROGRAM_MODE); - DELAY(URTW_EPROM_DELAY); - - error = urtw_eprom_cs(sc, URTW_EPROM_ENABLE); - if (error != 0) - goto fail; - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - error = urtw_eprom_sendbits(sc, readcmd, URTW_READCMD_LEN); - if (error != 0) - goto fail; - if (sc->sc_epromtype == URTW_EEPROM_93C56) { - addrlen = 8; - addrstr[0] = addr & (1 << 7); - addrstr[1] = addr & (1 << 6); - addrstr[2] = addr & (1 << 5); - addrstr[3] = addr & (1 << 4); - addrstr[4] = addr & (1 << 3); - addrstr[5] = addr & (1 << 2); - addrstr[6] = addr & (1 << 1); - addrstr[7] = addr & (1 << 0); - } else { - addrlen=6; - addrstr[0] = addr & (1 << 5); - addrstr[1] = addr & (1 << 4); - addrstr[2] = addr & (1 << 3); - addrstr[3] = addr & (1 << 2); - addrstr[4] = addr & (1 << 1); - addrstr[5] = addr & (1 << 0); - } - error = urtw_eprom_sendbits(sc, addrstr, addrlen); - if (error != 0) - goto fail; - - error = urtw_eprom_writebit(sc, 0); - if (error != 0) - goto fail; - - for (i = 0; i < 16; i++) { - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - error = urtw_eprom_readbit(sc, &data16); - if (error != 0) - goto fail; - - (*data) |= (data16 << (15 - i)); - } - - error = urtw_eprom_cs(sc, URTW_EPROM_DISABLE); - if (error != 0) - goto fail; - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - - /* now disable EPROM programming */ - urtw_write8_m(sc, URTW_EPROM_CMD, URTW_EPROM_CMD_NORMAL_MODE); -fail: - return (error); -#undef URTW_READCMD_LEN -} - -static usb_error_t -urtw_eprom_cs(struct urtw_softc *sc, int able) -{ - uint8_t data; - usb_error_t error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - if (able == URTW_EPROM_ENABLE) - urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CS); - else - urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CS); - DELAY(URTW_EPROM_DELAY); -fail: - return (error); -} - -static usb_error_t -urtw_eprom_ck(struct urtw_softc *sc) -{ - uint8_t data; - usb_error_t error; - - /* masking */ - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_CK); - DELAY(URTW_EPROM_DELAY); - /* unmasking */ - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_CK); - DELAY(URTW_EPROM_DELAY); -fail: - return (error); -} - -static usb_error_t -urtw_eprom_readbit(struct urtw_softc *sc, int16_t *data) -{ - uint8_t data8; - usb_error_t error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data8); - *data = (data8 & URTW_EPROM_READBIT) ? 1 : 0; - DELAY(URTW_EPROM_DELAY); - -fail: - return (error); -} - -static usb_error_t -urtw_eprom_writebit(struct urtw_softc *sc, int16_t bit) -{ - uint8_t data; - usb_error_t error; - - urtw_read8_m(sc, URTW_EPROM_CMD, &data); - if (bit != 0) - urtw_write8_m(sc, URTW_EPROM_CMD, data | URTW_EPROM_WRITEBIT); - else - urtw_write8_m(sc, URTW_EPROM_CMD, data & ~URTW_EPROM_WRITEBIT); - DELAY(URTW_EPROM_DELAY); -fail: - return (error); -} - -static usb_error_t -urtw_eprom_sendbits(struct urtw_softc *sc, int16_t *buf, int buflen) -{ - int i = 0; - usb_error_t error = 0; - - for (i = 0; i < buflen; i++) { - error = urtw_eprom_writebit(sc, buf[i]); - if (error != 0) - goto fail; - error = urtw_eprom_ck(sc); - if (error != 0) - goto fail; - } -fail: - return (error); -} - - -static usb_error_t -urtw_get_txpwr(struct urtw_softc *sc) -{ - int i, j; - uint32_t data; - usb_error_t error; - - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW_BASE, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck_base = data & 0xf; - sc->sc_txpwr_ofdm_base = (data >> 4) & 0xf; - - for (i = 1, j = 0; i < 6; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW0 + j, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[i] = data & 0xf; - sc->sc_txpwr_cck[i + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 1] = (data & 0xf000) >> 12; - } - for (i = 1, j = 0; i < 4; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW1 + j, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[i + 6] = data & 0xf; - sc->sc_txpwr_cck[i + 6 + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i + 6] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 6 + 1] = (data & 0xf000) >> 12; - } - if (sc->sc_flags & URTW_RTL8187B) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[1 + 6 + 4] = data & 0xf; - sc->sc_txpwr_ofdm[1 + 6 + 4] = (data & 0xf0) >> 4; - error = urtw_eprom_read32(sc, 0x0a, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[2 + 6 + 4] = data & 0xf; - sc->sc_txpwr_ofdm[2 + 6 + 4] = (data & 0xf0) >> 4; - error = urtw_eprom_read32(sc, 0x1c, &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[3 + 6 + 4] = data & 0xf; - sc->sc_txpwr_cck[3 + 6 + 4 + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[3 + 6 + 4] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[3 + 6 + 4 + 1] = (data & 0xf000) >> 12; - } else { - for (i = 1, j = 0; i < 4; i += 2, j++) { - error = urtw_eprom_read32(sc, URTW_EPROM_TXPW2 + j, - &data); - if (error != 0) - goto fail; - sc->sc_txpwr_cck[i + 6 + 4] = data & 0xf; - sc->sc_txpwr_cck[i + 6 + 4 + 1] = (data & 0xf00) >> 8; - sc->sc_txpwr_ofdm[i + 6 + 4] = (data & 0xf0) >> 4; - sc->sc_txpwr_ofdm[i + 6 + 4 + 1] = (data & 0xf000) >> 12; - } - } -fail: - return (error); -} - - -static usb_error_t -urtw_get_rfchip(struct urtw_softc *sc) -{ - int ret; - uint8_t data8; - uint32_t data; - usb_error_t error; - - if (sc->sc_flags & URTW_RTL8187B) { - urtw_read8_m(sc, 0xe1, &data8); - switch (data8) { - case 0: - sc->sc_flags |= URTW_RTL8187B_REV_B; - break; - case 1: - sc->sc_flags |= URTW_RTL8187B_REV_D; - break; - case 2: - sc->sc_flags |= URTW_RTL8187B_REV_E; - break; - default: - device_printf(sc->sc_dev, "unknown type: %#x\n", data8); - sc->sc_flags |= URTW_RTL8187B_REV_B; - break; - } - } else { - urtw_read32_m(sc, URTW_TX_CONF, &data); - switch (data & URTW_TX_HWMASK) { - case URTW_TX_R8187vD_B: - sc->sc_flags |= URTW_RTL8187B; - break; - case URTW_TX_R8187vD: - break; - default: - device_printf(sc->sc_dev, "unknown RTL8187L type: %#x\n", - data & URTW_TX_HWMASK); - break; - } - } - - error = urtw_eprom_read32(sc, URTW_EPROM_RFCHIPID, &data); - if (error != 0) - goto fail; - switch (data & 0xff) { - case URTW_EPROM_RFCHIPID_RTL8225U: - error = urtw_8225_isv2(sc, &ret); - if (error != 0) - goto fail; - if (ret == 0) { - sc->sc_rf_init = urtw_8225_rf_init; - sc->sc_rf_set_sens = urtw_8225_rf_set_sens; - sc->sc_rf_set_chan = urtw_8225_rf_set_chan; - sc->sc_rf_stop = urtw_8225_rf_stop; - } else { - sc->sc_rf_init = urtw_8225v2_rf_init; - sc->sc_rf_set_chan = urtw_8225v2_rf_set_chan; - sc->sc_rf_stop = urtw_8225_rf_stop; - } - sc->sc_max_sens = URTW_8225_RF_MAX_SENS; - sc->sc_sens = URTW_8225_RF_DEF_SENS; - break; - case URTW_EPROM_RFCHIPID_RTL8225Z2: - sc->sc_rf_init = urtw_8225v2b_rf_init; - sc->sc_rf_set_chan = urtw_8225v2b_rf_set_chan; - sc->sc_max_sens = URTW_8225_RF_MAX_SENS; - sc->sc_sens = URTW_8225_RF_DEF_SENS; - sc->sc_rf_stop = urtw_8225_rf_stop; - break; - default: - panic("unsupported RF chip %d\n", data & 0xff); - /* never reach */ - } - - device_printf(sc->sc_dev, "%s rf %s hwrev %s\n", - (sc->sc_flags & URTW_RTL8187B) ? "rtl8187b" : "rtl8187l", - ((data & 0xff) == URTW_EPROM_RFCHIPID_RTL8225U) ? "rtl8225u" : - "rtl8225z2", - (sc->sc_flags & URTW_RTL8187B) ? ((data8 == 0) ? "b" : - (data8 == 1) ? "d" : "e") : "none"); - -fail: - return (error); -} - - -static usb_error_t -urtw_led_init(struct urtw_softc *sc) -{ - uint32_t rev; - usb_error_t error; - - urtw_read8_m(sc, URTW_PSR, &sc->sc_psr); - error = urtw_eprom_read32(sc, URTW_EPROM_SWREV, &rev); - if (error != 0) - goto fail; - - switch (rev & URTW_EPROM_CID_MASK) { - case URTW_EPROM_CID_ALPHA0: - sc->sc_strategy = URTW_SW_LED_MODE1; - break; - case URTW_EPROM_CID_SERCOMM_PS: - sc->sc_strategy = URTW_SW_LED_MODE3; - break; - case URTW_EPROM_CID_HW_LED: - sc->sc_strategy = URTW_HW_LED; - break; - case URTW_EPROM_CID_RSVD0: - case URTW_EPROM_CID_RSVD1: - default: - sc->sc_strategy = URTW_SW_LED_MODE0; - break; - } - - sc->sc_gpio_ledpin = URTW_LED_PIN_GPIO0; - -fail: - return (error); -} - - -static usb_error_t -urtw_8225_rf_init(struct urtw_softc *sc) -{ - int i; - uint16_t data; - usb_error_t error; - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - - error = urtw_8225_usb_init(sc); - if (error) - goto fail; - - urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008); - urtw_read16_m(sc, URTW_BRSR, &data); /* XXX ??? */ - urtw_write16_m(sc, URTW_BRSR, 0xffff); - urtw_write32_m(sc, URTW_RF_PARA, 0x100044); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - urtw_write8_m(sc, URTW_CONFIG3, 0x44); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_8185_rf_pins_enable(sc); - if (error) - goto fail; - usb_pause_mtx(&sc->sc_mtx, 1000); - - for (i = 0; i < nitems(urtw_8225_rf_part1); i++) { - urtw_8225_write(sc, urtw_8225_rf_part1[i].reg, - urtw_8225_rf_part1[i].val); - usb_pause_mtx(&sc->sc_mtx, 1); - } - usb_pause_mtx(&sc->sc_mtx, 100); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); - usb_pause_mtx(&sc->sc_mtx, 200); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); - usb_pause_mtx(&sc->sc_mtx, 200); - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC3); - - for (i = 0; i < 95; i++) { - urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, urtw_8225_rxgain[i]); - } - - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC4); - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC5); - - for (i = 0; i < 128; i++) { - urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80); - usb_pause_mtx(&sc->sc_mtx, 1); - } - - for (i = 0; i < nitems(urtw_8225_rf_part2); i++) { - urtw_8187_write_phy_ofdm(sc, urtw_8225_rf_part2[i].reg, - urtw_8225_rf_part2[i].val); - usb_pause_mtx(&sc->sc_mtx, 1); - } - - error = urtw_8225_setgain(sc, 4); - if (error) - goto fail; - - for (i = 0; i < nitems(urtw_8225_rf_part3); i++) { - urtw_8187_write_phy_cck(sc, urtw_8225_rf_part3[i].reg, - urtw_8225_rf_part3[i].val); - usb_pause_mtx(&sc->sc_mtx, 1); - } - - urtw_write8_m(sc, URTW_TESTR, 0x0d); - - error = urtw_8225_set_txpwrlvl(sc, 1); - if (error) - goto fail; - - urtw_8187_write_phy_cck(sc, 0x10, 0x9b); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8187_write_phy_ofdm(sc, 0x26, 0x90); - usb_pause_mtx(&sc->sc_mtx, 1); - - /* TX ant A, 0x0 for B */ - error = urtw_8185_tx_antenna(sc, 0x3); - if (error) - goto fail; - urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002); - - error = urtw_8225_rf_set_chan(sc, 1); -fail: - return (error); -} - -static usb_error_t -urtw_8185_rf_pins_enable(struct urtw_softc *sc) -{ - usb_error_t error = 0; - - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1ff7); -fail: - return (error); -} - -static usb_error_t -urtw_8185_tx_antenna(struct urtw_softc *sc, uint8_t ant) -{ - usb_error_t error; - - urtw_write8_m(sc, URTW_TX_ANTENNA, ant); - usb_pause_mtx(&sc->sc_mtx, 1); -fail: - return (error); -} - -static usb_error_t -urtw_8187_write_phy_ofdm_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) -{ - - data = data & 0xff; - return urtw_8187_write_phy(sc, addr, data); -} - -static usb_error_t -urtw_8187_write_phy_cck_c(struct urtw_softc *sc, uint8_t addr, uint32_t data) -{ - - data = data & 0xff; - return urtw_8187_write_phy(sc, addr, data | 0x10000); -} - -static usb_error_t -urtw_8187_write_phy(struct urtw_softc *sc, uint8_t addr, uint32_t data) -{ - uint32_t phyw; - usb_error_t error; - - phyw = ((data << 8) | (addr | 0x80)); - urtw_write8_m(sc, URTW_PHY_MAGIC4, ((phyw & 0xff000000) >> 24)); - urtw_write8_m(sc, URTW_PHY_MAGIC3, ((phyw & 0x00ff0000) >> 16)); - urtw_write8_m(sc, URTW_PHY_MAGIC2, ((phyw & 0x0000ff00) >> 8)); - urtw_write8_m(sc, URTW_PHY_MAGIC1, ((phyw & 0x000000ff))); - usb_pause_mtx(&sc->sc_mtx, 1); -fail: - return (error); -} - -static usb_error_t -urtw_8225_setgain(struct urtw_softc *sc, int16_t gain) -{ - usb_error_t error; - - urtw_8187_write_phy_ofdm(sc, 0x0d, urtw_8225_gain[gain * 4]); - urtw_8187_write_phy_ofdm(sc, 0x1b, urtw_8225_gain[gain * 4 + 2]); - urtw_8187_write_phy_ofdm(sc, 0x1d, urtw_8225_gain[gain * 4 + 3]); - urtw_8187_write_phy_ofdm(sc, 0x23, urtw_8225_gain[gain * 4 + 1]); -fail: - return (error); -} - -static usb_error_t -urtw_8225_usb_init(struct urtw_softc *sc) -{ - uint8_t data; - usb_error_t error; - - urtw_write8_m(sc, URTW_RF_PINS_SELECT + 1, 0); - urtw_write8_m(sc, URTW_GPIO, 0); - error = urtw_read8e(sc, 0x53, &data); - if (error) - goto fail; - error = urtw_write8e(sc, 0x53, data | (1 << 7)); - if (error) - goto fail; - urtw_write8_m(sc, URTW_RF_PINS_SELECT + 1, 4); - urtw_write8_m(sc, URTW_GPIO, 0x20); - urtw_write8_m(sc, URTW_GP_ENABLE, 0); - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 0x80); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, 0x80); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x80); - - usb_pause_mtx(&sc->sc_mtx, 500); -fail: - return (error); -} - -static usb_error_t -urtw_8225_write_c(struct urtw_softc *sc, uint8_t addr, uint16_t data) -{ - uint16_t d80, d82, d84; - usb_error_t error; - - urtw_read16_m(sc, URTW_RF_PINS_OUTPUT, &d80); - d80 &= URTW_RF_PINS_MAGIC1; - urtw_read16_m(sc, URTW_RF_PINS_ENABLE, &d82); - urtw_read16_m(sc, URTW_RF_PINS_SELECT, &d84); - d84 &= URTW_RF_PINS_MAGIC2; - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, d82 | URTW_RF_PINS_MAGIC3); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84 | URTW_RF_PINS_MAGIC3); - DELAY(10); - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80); - DELAY(10); - - error = urtw_8225_write_s16(sc, addr, 0x8225, &data); - if (error != 0) - goto fail; - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); - DELAY(10); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, d80 | URTW_BB_HOST_BANG_EN); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, d84); - usb_pause_mtx(&sc->sc_mtx, 2); -fail: - return (error); -} - -/* XXX why we should allocalte memory buffer instead of using memory stack? */ -static usb_error_t -urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index, - uint16_t *data) -{ - uint8_t *buf; - uint16_t data16; - struct usb_device_request *req; - usb_error_t error = 0; - - data16 = *data; - req = (usb_device_request_t *)malloc(sizeof(usb_device_request_t), - M_80211_VAP, M_WAITOK | M_ZERO); - if (req == NULL) { - device_printf(sc->sc_dev, "could not allocate a memory\n"); - goto fail0; - } - buf = (uint8_t *)malloc(2, M_80211_VAP, M_WAITOK | M_ZERO); - if (req == NULL) { - device_printf(sc->sc_dev, "could not allocate a memory\n"); - goto fail1; - } - - req->bmRequestType = UT_WRITE_VENDOR_DEVICE; - req->bRequest = URTW_8187_SETREGS_REQ; - USETW(req->wValue, addr); - USETW(req->wIndex, index); - USETW(req->wLength, sizeof(uint16_t)); - buf[0] = (data16 & 0x00ff); - buf[1] = (data16 & 0xff00) >> 8; - - error = urtw_do_request(sc, req, buf); - - free(buf, M_80211_VAP); -fail1: free(req, M_80211_VAP); -fail0: return (error); -} - -static usb_error_t -urtw_8225_rf_set_chan(struct urtw_softc *sc, int chan) -{ - usb_error_t error; - - error = urtw_8225_set_txpwrlvl(sc, chan); - if (error) - goto fail; - urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); - usb_pause_mtx(&sc->sc_mtx, 10); -fail: - return (error); -} - -static usb_error_t -urtw_8225_rf_set_sens(struct urtw_softc *sc, int sens) -{ - usb_error_t error; - - if (sens < 0 || sens > 6) - return -1; - - if (sens > 4) - urtw_8225_write(sc, - URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC1); - else - urtw_8225_write(sc, - URTW_8225_ADDR_C_MAGIC, URTW_8225_ADDR_C_DATA_MAGIC2); - - sens = 6 - sens; - error = urtw_8225_setgain(sc, sens); - if (error) - goto fail; - - urtw_8187_write_phy_cck(sc, 0x41, urtw_8225_threshold[sens]); - -fail: - return (error); -} - -static usb_error_t -urtw_8225_set_txpwrlvl(struct urtw_softc *sc, int chan) -{ - int i, idx, set; - uint8_t *cck_pwltable; - uint8_t cck_pwrlvl_max, ofdm_pwrlvl_min, ofdm_pwrlvl_max; - uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; - uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; - usb_error_t error; - - cck_pwrlvl_max = 11; - ofdm_pwrlvl_max = 25; /* 12 -> 25 */ - ofdm_pwrlvl_min = 10; - - /* CCK power setting */ - cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl; - idx = cck_pwrlvl % 6; - set = cck_pwrlvl / 6; - cck_pwltable = (chan == 14) ? urtw_8225_txpwr_cck_ch14 : - urtw_8225_txpwr_cck; - - urtw_write8_m(sc, URTW_TX_GAIN_CCK, - urtw_8225_tx_gain_cck_ofdm[set] >> 1); - for (i = 0; i < 8; i++) { - urtw_8187_write_phy_cck(sc, 0x44 + i, - cck_pwltable[idx * 8 + i]); - } - usb_pause_mtx(&sc->sc_mtx, 1); - - /* OFDM power setting */ - ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? - ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; - ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; - - idx = ofdm_pwrlvl % 6; - set = ofdm_pwrlvl / 6; - - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; - urtw_8187_write_phy_ofdm(sc, 2, 0x42); - urtw_8187_write_phy_ofdm(sc, 6, 0); - urtw_8187_write_phy_ofdm(sc, 8, 0); - - urtw_write8_m(sc, URTW_TX_GAIN_OFDM, - urtw_8225_tx_gain_cck_ofdm[set] >> 1); - urtw_8187_write_phy_ofdm(sc, 0x5, urtw_8225_txpwr_ofdm[idx]); - urtw_8187_write_phy_ofdm(sc, 0x7, urtw_8225_txpwr_ofdm[idx]); - usb_pause_mtx(&sc->sc_mtx, 1); -fail: - return (error); -} - - -static usb_error_t -urtw_8225_rf_stop(struct urtw_softc *sc) -{ - uint8_t data; - usb_error_t error; - - urtw_8225_write(sc, 0x4, 0x1f); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); - if (sc->sc_flags & URTW_RTL8187B) { - urtw_write32_m(sc, URTW_ANAPARAM2, - URTW_8187B_8225_ANAPARAM2_OFF); - urtw_write32_m(sc, URTW_ANAPARAM, URTW_8187B_8225_ANAPARAM_OFF); - urtw_write32_m(sc, URTW_ANAPARAM3, - URTW_8187B_8225_ANAPARAM3_OFF); - } else { - urtw_write32_m(sc, URTW_ANAPARAM2, URTW_8225_ANAPARAM2_OFF); - urtw_write32_m(sc, URTW_ANAPARAM, URTW_8225_ANAPARAM_OFF); - } - - urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - -fail: - return (error); -} - -static usb_error_t -urtw_8225v2_rf_init(struct urtw_softc *sc) -{ - int i; - uint16_t data; - uint32_t data32; - usb_error_t error; - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - - error = urtw_8225_usb_init(sc); - if (error) - goto fail; - - urtw_write32_m(sc, URTW_RF_TIMING, 0x000a8008); - urtw_read16_m(sc, URTW_BRSR, &data); /* XXX ??? */ - urtw_write16_m(sc, URTW_BRSR, 0xffff); - urtw_write32_m(sc, URTW_RF_PARA, 0x100044); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - urtw_write8_m(sc, URTW_CONFIG3, 0x44); - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - error = urtw_8185_rf_pins_enable(sc); - if (error) - goto fail; - - usb_pause_mtx(&sc->sc_mtx, 500); - - for (i = 0; i < nitems(urtw_8225v2_rf_part1); i++) { - urtw_8225_write(sc, urtw_8225v2_rf_part1[i].reg, - urtw_8225v2_rf_part1[i].val); - } - usb_pause_mtx(&sc->sc_mtx, 50); - - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC1); - - for (i = 0; i < 95; i++) { - urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, - urtw_8225v2_rxgain[i]); - } - - urtw_8225_write(sc, - URTW_8225_ADDR_3_MAGIC, URTW_8225_ADDR_3_DATA_MAGIC1); - urtw_8225_write(sc, - URTW_8225_ADDR_5_MAGIC, URTW_8225_ADDR_5_DATA_MAGIC1); - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC2); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); - usb_pause_mtx(&sc->sc_mtx, 100); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); - usb_pause_mtx(&sc->sc_mtx, 100); - - error = urtw_8225_read(sc, URTW_8225_ADDR_6_MAGIC, &data32); - if (error != 0) - goto fail; - if (data32 != URTW_8225_ADDR_6_DATA_MAGIC1) - device_printf(sc->sc_dev, "expect 0xe6!! (0x%x)\n", data32); - if (!(data32 & URTW_8225_ADDR_6_DATA_MAGIC2)) { - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC1); - usb_pause_mtx(&sc->sc_mtx, 100); - urtw_8225_write(sc, - URTW_8225_ADDR_2_MAGIC, URTW_8225_ADDR_2_DATA_MAGIC2); - usb_pause_mtx(&sc->sc_mtx, 50); - error = urtw_8225_read(sc, URTW_8225_ADDR_6_MAGIC, &data32); - if (error != 0) - goto fail; - if (!(data32 & URTW_8225_ADDR_6_DATA_MAGIC2)) - device_printf(sc->sc_dev, "RF calibration failed\n"); - } - usb_pause_mtx(&sc->sc_mtx, 100); - - urtw_8225_write(sc, - URTW_8225_ADDR_0_MAGIC, URTW_8225_ADDR_0_DATA_MAGIC6); - for (i = 0; i < 128; i++) { - urtw_8187_write_phy_ofdm(sc, 0xb, urtw_8225_agc[i]); - urtw_8187_write_phy_ofdm(sc, 0xa, (uint8_t)i + 0x80); - } - - for (i = 0; i < nitems(urtw_8225v2_rf_part2); i++) { - urtw_8187_write_phy_ofdm(sc, urtw_8225v2_rf_part2[i].reg, - urtw_8225v2_rf_part2[i].val); - } - - error = urtw_8225v2_setgain(sc, 4); - if (error) - goto fail; - - for (i = 0; i < nitems(urtw_8225v2_rf_part3); i++) { - urtw_8187_write_phy_cck(sc, urtw_8225v2_rf_part3[i].reg, - urtw_8225v2_rf_part3[i].val); - } - - urtw_write8_m(sc, URTW_TESTR, 0x0d); - - error = urtw_8225v2_set_txpwrlvl(sc, 1); - if (error) - goto fail; - - urtw_8187_write_phy_cck(sc, 0x10, 0x9b); - urtw_8187_write_phy_ofdm(sc, 0x26, 0x90); - - /* TX ant A, 0x0 for B */ - error = urtw_8185_tx_antenna(sc, 0x3); - if (error) - goto fail; - urtw_write32_m(sc, URTW_HSSI_PARA, 0x3dc00002); - - error = urtw_8225_rf_set_chan(sc, 1); -fail: - return (error); -} - -static usb_error_t -urtw_8225v2_rf_set_chan(struct urtw_softc *sc, int chan) -{ - usb_error_t error; - - error = urtw_8225v2_set_txpwrlvl(sc, chan); - if (error) - goto fail; - - urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); - usb_pause_mtx(&sc->sc_mtx, 10); -fail: - return (error); -} - -static usb_error_t -urtw_8225_read(struct urtw_softc *sc, uint8_t addr, uint32_t *data) -{ - int i; - int16_t bit; - uint8_t rlen = 12, wlen = 6; - uint16_t o1, o2, o3, tmp; - uint32_t d2w = ((uint32_t)(addr & 0x1f)) << 27; - uint32_t mask = 0x80000000, value = 0; - usb_error_t error; - - urtw_read16_m(sc, URTW_RF_PINS_OUTPUT, &o1); - urtw_read16_m(sc, URTW_RF_PINS_ENABLE, &o2); - urtw_read16_m(sc, URTW_RF_PINS_SELECT, &o3); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, o2 | URTW_RF_PINS_MAGIC4); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, o3 | URTW_RF_PINS_MAGIC4); - o1 &= ~URTW_RF_PINS_MAGIC4; - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_EN); - DELAY(5); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1); - DELAY(5); - - for (i = 0; i < (wlen / 2); i++, mask = mask >> 1) { - bit = ((d2w & mask) != 0) ? 1 : 0; - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - mask = mask >> 1; - if (i == 2) - break; - bit = ((d2w & mask) != 0) ? 1 : 0; - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1); - DELAY(1); - } - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | URTW_BB_HOST_BANG_RW | - URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, bit | o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - - mask = 0x800; - for (i = 0; i < rlen; i++, mask = mask >> 1) { - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); - DELAY(2); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW | URTW_BB_HOST_BANG_CLK); - DELAY(2); - - urtw_read16_m(sc, URTW_RF_PINS_INPUT, &tmp); - value |= ((tmp & URTW_BB_HOST_BANG_CLK) ? mask : 0); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, - o1 | URTW_BB_HOST_BANG_RW); - DELAY(2); - } - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, o1 | URTW_BB_HOST_BANG_EN | - URTW_BB_HOST_BANG_RW); - DELAY(2); - - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, o2); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, o3); - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, URTW_RF_PINS_OUTPUT_MAGIC1); - - if (data != NULL) - *data = value; -fail: - return (error); -} - - -static usb_error_t -urtw_8225v2_set_txpwrlvl(struct urtw_softc *sc, int chan) -{ - int i; - uint8_t *cck_pwrtable; - uint8_t cck_pwrlvl_max = 15, ofdm_pwrlvl_max = 25, ofdm_pwrlvl_min = 10; - uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; - uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; - usb_error_t error; - - /* CCK power setting */ - cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? cck_pwrlvl_max : cck_pwrlvl; - cck_pwrlvl += sc->sc_txpwr_cck_base; - cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; - cck_pwrtable = (chan == 14) ? urtw_8225v2_txpwr_cck_ch14 : - urtw_8225v2_txpwr_cck; - - for (i = 0; i < 8; i++) - urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]); - - urtw_write8_m(sc, URTW_TX_GAIN_CCK, - urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl]); - usb_pause_mtx(&sc->sc_mtx, 1); - - /* OFDM power setting */ - ofdm_pwrlvl = (ofdm_pwrlvl > (ofdm_pwrlvl_max - ofdm_pwrlvl_min)) ? - ofdm_pwrlvl_max : ofdm_pwrlvl + ofdm_pwrlvl_min; - ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; - ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; - - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; - - urtw_8187_write_phy_ofdm(sc, 2, 0x42); - urtw_8187_write_phy_ofdm(sc, 5, 0x0); - urtw_8187_write_phy_ofdm(sc, 6, 0x40); - urtw_8187_write_phy_ofdm(sc, 7, 0x0); - urtw_8187_write_phy_ofdm(sc, 8, 0x40); - - urtw_write8_m(sc, URTW_TX_GAIN_OFDM, - urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl]); - usb_pause_mtx(&sc->sc_mtx, 1); -fail: - return (error); -} - -static usb_error_t -urtw_8225v2_setgain(struct urtw_softc *sc, int16_t gain) -{ - uint8_t *gainp; - usb_error_t error; - - /* XXX for A? */ - gainp = urtw_8225v2_gain_bg; - urtw_8187_write_phy_ofdm(sc, 0x0d, gainp[gain * 3]); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8187_write_phy_ofdm(sc, 0x1b, gainp[gain * 3 + 1]); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8187_write_phy_ofdm(sc, 0x1d, gainp[gain * 3 + 2]); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8187_write_phy_ofdm(sc, 0x21, 0x17); - usb_pause_mtx(&sc->sc_mtx, 1); -fail: - return (error); -} - -static usb_error_t -urtw_8225_isv2(struct urtw_softc *sc, int *ret) -{ - uint32_t data; - usb_error_t error; - - *ret = 1; - - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, URTW_RF_PINS_MAGIC5); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, URTW_RF_PINS_MAGIC5); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, URTW_RF_PINS_MAGIC5); - usb_pause_mtx(&sc->sc_mtx, 500); - - urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, - URTW_8225_ADDR_0_DATA_MAGIC1); - - error = urtw_8225_read(sc, URTW_8225_ADDR_8_MAGIC, &data); - if (error != 0) - goto fail; - if (data != URTW_8225_ADDR_8_DATA_MAGIC1) - *ret = 0; - else { - error = urtw_8225_read(sc, URTW_8225_ADDR_9_MAGIC, &data); - if (error != 0) - goto fail; - if (data != URTW_8225_ADDR_9_DATA_MAGIC1) - *ret = 0; - } - - urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, - URTW_8225_ADDR_0_DATA_MAGIC2); -fail: - return (error); -} - -static usb_error_t -urtw_8225v2b_rf_init(struct urtw_softc *sc) -{ - int i; - uint8_t data8; - usb_error_t error; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - /* - * initialize extra registers on 8187 - */ - urtw_write16_m(sc, URTW_BRSR_8187B, 0xfff); - - /* retry limit */ - urtw_read8_m(sc, URTW_CW_CONF, &data8); - data8 |= URTW_CW_CONF_PERPACKET_RETRY; - urtw_write8_m(sc, URTW_CW_CONF, data8); - - /* TX AGC */ - urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); - data8 |= URTW_TX_AGC_CTL_PERPACKET_GAIN; - urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); - - /* Auto Rate Fallback Control */ -#define URTW_ARFR 0x1e0 - urtw_write16_m(sc, URTW_ARFR, 0xfff); - urtw_read8_m(sc, URTW_RATE_FALLBACK, &data8); - urtw_write8_m(sc, URTW_RATE_FALLBACK, - data8 | URTW_RATE_FALLBACK_ENABLE); - - urtw_read8_m(sc, URTW_MSR, &data8); - urtw_write8_m(sc, URTW_MSR, data8 & 0xf3); - urtw_read8_m(sc, URTW_MSR, &data8); - urtw_write8_m(sc, URTW_MSR, data8 | URTW_MSR_LINK_ENEDCA); - urtw_write8_m(sc, URTW_ACM_CONTROL, sc->sc_acmctl); - - urtw_write16_m(sc, URTW_ATIM_WND, 2); - urtw_write16_m(sc, URTW_BEACON_INTERVAL, 100); -#define URTW_FEMR_FOR_8187B 0x1d4 - urtw_write16_m(sc, URTW_FEMR_FOR_8187B, 0xffff); - - /* led type */ - urtw_read8_m(sc, URTW_CONFIG1, &data8); - data8 = (data8 & 0x3f) | 0x80; - urtw_write8_m(sc, URTW_CONFIG1, data8); - - /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - urtw_write8_m(sc, URTW_WPA_CONFIG, 0); - - /* - * MAC configuration - */ - for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++) - urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg, - urtw_8225v2b_rf_part1[i].val); - urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50); - urtw_write16_m(sc, URTW_INT_MIG, 0x0000); - urtw_write32_m(sc, 0x1f0, 0); - urtw_write32_m(sc, 0x1f4, 0); - urtw_write8_m(sc, 0x1f8, 0); - urtw_write32_m(sc, URTW_RF_TIMING, 0x4001); - -#define URTW_RFSW_CTRL 0x272 - urtw_write16_m(sc, URTW_RFSW_CTRL, 0x569a); - - /* - * initialize PHY - */ - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - urtw_read8_m(sc, URTW_CONFIG3, &data8); - urtw_write8_m(sc, URTW_CONFIG3, - data8 | URTW_CONFIG3_ANAPARAM_WRITE); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; - - /* setup RFE initial timing */ - urtw_write16_m(sc, URTW_RF_PINS_OUTPUT, 0x0480); - urtw_write16_m(sc, URTW_RF_PINS_SELECT, 0x2488); - urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff); - usb_pause_mtx(&sc->sc_mtx, 1100); - - for (i = 0; i < nitems(urtw_8225v2b_rf_part0); i++) { - urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg, - urtw_8225v2b_rf_part0[i].val); - usb_pause_mtx(&sc->sc_mtx, 1); - } - urtw_8225_write(sc, 0x00, 0x01b7); - - for (i = 0; i < 95; i++) { - urtw_8225_write(sc, URTW_8225_ADDR_1_MAGIC, (uint8_t)(i + 1)); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, - urtw_8225v2b_rxgain[i]); - usb_pause_mtx(&sc->sc_mtx, 1); - } - - urtw_8225_write(sc, URTW_8225_ADDR_3_MAGIC, 0x080); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8225_write(sc, URTW_8225_ADDR_5_MAGIC, 0x004); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x0b7); - usb_pause_mtx(&sc->sc_mtx, 1); - usb_pause_mtx(&sc->sc_mtx, 3000); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0xc4d); - usb_pause_mtx(&sc->sc_mtx, 2000); - urtw_8225_write(sc, URTW_8225_ADDR_2_MAGIC, 0x44d); - usb_pause_mtx(&sc->sc_mtx, 1); - urtw_8225_write(sc, URTW_8225_ADDR_0_MAGIC, 0x2bf); - usb_pause_mtx(&sc->sc_mtx, 1); - - urtw_write8_m(sc, URTW_TX_GAIN_CCK, 0x03); - urtw_write8_m(sc, URTW_TX_GAIN_OFDM, 0x07); - urtw_write8_m(sc, URTW_TX_ANTENNA, 0x03); - - urtw_8187_write_phy_ofdm(sc, 0x80, 0x12); - for (i = 0; i < 128; i++) { - uint32_t addr, data; - - data = (urtw_8225z2_agc[i] << 8) | 0x0000008f; - addr = ((i + 0x80) << 8) | 0x0000008e; - - urtw_8187_write_phy_ofdm(sc, data & 0x7f, (data >> 8) & 0xff); - urtw_8187_write_phy_ofdm(sc, addr & 0x7f, (addr >> 8) & 0xff); - urtw_8187_write_phy_ofdm(sc, 0x0e, 0x00); - } - urtw_8187_write_phy_ofdm(sc, 0x80, 0x10); - - for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++) - urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val); - - urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c); - urtw_write32_m(sc, URTW_8187B_AC_VI, (7 << 12) | (3 << 8) | 0x1c); - urtw_write32_m(sc, URTW_8187B_AC_BE, (7 << 12) | (3 << 8) | 0x1c); - urtw_write32_m(sc, URTW_8187B_AC_BK, (7 << 12) | (3 << 8) | 0x1c); - - urtw_8187_write_phy_ofdm(sc, 0x97, 0x46); - urtw_8187_write_phy_ofdm(sc, 0xa4, 0xb6); - urtw_8187_write_phy_ofdm(sc, 0x85, 0xfc); - urtw_8187_write_phy_cck(sc, 0xc1, 0x88); - -fail: - return (error); -} - -static usb_error_t -urtw_8225v2b_rf_set_chan(struct urtw_softc *sc, int chan) -{ - usb_error_t error; - - error = urtw_8225v2b_set_txpwrlvl(sc, chan); - if (error) - goto fail; - - urtw_8225_write(sc, URTW_8225_ADDR_7_MAGIC, urtw_8225_channel[chan]); - usb_pause_mtx(&sc->sc_mtx, 10); -fail: - return (error); -} - -static usb_error_t -urtw_8225v2b_set_txpwrlvl(struct urtw_softc *sc, int chan) -{ - int i; - uint8_t *cck_pwrtable; - uint8_t cck_pwrlvl_max = 15; - uint8_t cck_pwrlvl = sc->sc_txpwr_cck[chan] & 0xff; - uint8_t ofdm_pwrlvl = sc->sc_txpwr_ofdm[chan] & 0xff; - usb_error_t error; - - /* CCK power setting */ - cck_pwrlvl = (cck_pwrlvl > cck_pwrlvl_max) ? - ((sc->sc_flags & URTW_RTL8187B_REV_B) ? cck_pwrlvl_max : 22) : - (cck_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 0 : 7)); - cck_pwrlvl += sc->sc_txpwr_cck_base; - cck_pwrlvl = (cck_pwrlvl > 35) ? 35 : cck_pwrlvl; - cck_pwrtable = (chan == 14) ? urtw_8225v2b_txpwr_cck_ch14 : - urtw_8225v2b_txpwr_cck; - - if (sc->sc_flags & URTW_RTL8187B_REV_B) - cck_pwrtable += (cck_pwrlvl <= 6) ? 0 : - ((cck_pwrlvl <= 11) ? 8 : 16); - else - cck_pwrtable += (cck_pwrlvl <= 5) ? 0 : - ((cck_pwrlvl <= 11) ? 8 : ((cck_pwrlvl <= 17) ? 16 : 24)); - - for (i = 0; i < 8; i++) - urtw_8187_write_phy_cck(sc, 0x44 + i, cck_pwrtable[i]); - - urtw_write8_m(sc, URTW_TX_GAIN_CCK, - urtw_8225v2_tx_gain_cck_ofdm[cck_pwrlvl] << 1); - usb_pause_mtx(&sc->sc_mtx, 1); - - /* OFDM power setting */ - ofdm_pwrlvl = (ofdm_pwrlvl > 15) ? - ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 17 : 25) : - (ofdm_pwrlvl + ((sc->sc_flags & URTW_RTL8187B_REV_B) ? 2 : 10)); - ofdm_pwrlvl += sc->sc_txpwr_ofdm_base; - ofdm_pwrlvl = (ofdm_pwrlvl > 35) ? 35 : ofdm_pwrlvl; - - urtw_write8_m(sc, URTW_TX_GAIN_OFDM, - urtw_8225v2_tx_gain_cck_ofdm[ofdm_pwrlvl] << 1); - - if (sc->sc_flags & URTW_RTL8187B_REV_B) { - if (ofdm_pwrlvl <= 11) { - urtw_8187_write_phy_ofdm(sc, 0x87, 0x60); - urtw_8187_write_phy_ofdm(sc, 0x89, 0x60); - } else { - urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c); - urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c); - } - } else { - if (ofdm_pwrlvl <= 11) { - urtw_8187_write_phy_ofdm(sc, 0x87, 0x5c); - urtw_8187_write_phy_ofdm(sc, 0x89, 0x5c); - } else if (ofdm_pwrlvl <= 17) { - urtw_8187_write_phy_ofdm(sc, 0x87, 0x54); - urtw_8187_write_phy_ofdm(sc, 0x89, 0x54); - } else { - urtw_8187_write_phy_ofdm(sc, 0x87, 0x50); - urtw_8187_write_phy_ofdm(sc, 0x89, 0x50); - } - } - usb_pause_mtx(&sc->sc_mtx, 1); -fail: - return (error); -} - -static usb_error_t -urtw_read8e(struct urtw_softc *sc, int val, uint8_t *data) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = URTW_8187_GETREGS_REQ; - USETW(req.wValue, val | 0xfe00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint8_t)); - - error = urtw_do_request(sc, &req, data); - return (error); -} - -static usb_error_t -urtw_write8e(struct urtw_softc *sc, int val, uint8_t data) -{ - struct usb_device_request req; - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = URTW_8187_SETREGS_REQ; - USETW(req.wValue, val | 0xfe00); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(uint8_t)); - - return (urtw_do_request(sc, &req, &data)); -} - -static usb_error_t -urtw_8180_set_anaparam(struct urtw_softc *sc, uint32_t val) -{ - uint8_t data; - usb_error_t error; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); - urtw_write32_m(sc, URTW_ANAPARAM, val); - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; -fail: - return (error); -} - -static usb_error_t -urtw_8185_set_anaparam2(struct urtw_softc *sc, uint32_t val) -{ - uint8_t data; - usb_error_t error; - - error = urtw_set_mode(sc, URTW_EPROM_CMD_CONFIG); - if (error) - goto fail; - - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data | URTW_CONFIG3_ANAPARAM_WRITE); - urtw_write32_m(sc, URTW_ANAPARAM2, val); - urtw_read8_m(sc, URTW_CONFIG3, &data); - urtw_write8_m(sc, URTW_CONFIG3, data & ~URTW_CONFIG3_ANAPARAM_WRITE); - - error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); - if (error) - goto fail; -fail: - return (error); -} - -static usb_error_t -urtw_intr_enable(struct urtw_softc *sc) -{ - usb_error_t error; - - urtw_write16_m(sc, URTW_INTR_MASK, 0xffff); -fail: - return (error); -} - -static usb_error_t -urtw_intr_disable(struct urtw_softc *sc) -{ - usb_error_t error; - - urtw_write16_m(sc, URTW_INTR_MASK, 0); -fail: - return (error); -} - -static usb_error_t -urtw_reset(struct urtw_softc *sc) -{ - uint8_t data; - usb_error_t error; - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; - - error = urtw_intr_disable(sc); - if (error) - goto fail; - usb_pause_mtx(&sc->sc_mtx, 100); - - error = urtw_write8e(sc, 0x18, 0x10); - if (error != 0) - goto fail; - error = urtw_write8e(sc, 0x18, 0x11); - if (error != 0) - goto fail; - error = urtw_write8e(sc, 0x18, 0x00); - if (error != 0) - goto fail; - usb_pause_mtx(&sc->sc_mtx, 100); - - urtw_read8_m(sc, URTW_CMD, &data); - data = (data & 0x2) | URTW_CMD_RST; - urtw_write8_m(sc, URTW_CMD, data); - usb_pause_mtx(&sc->sc_mtx, 100); - - urtw_read8_m(sc, URTW_CMD, &data); - if (data & URTW_CMD_RST) { - device_printf(sc->sc_dev, "reset timeout\n"); - goto fail; - } - - error = urtw_set_mode(sc, URTW_EPROM_CMD_LOAD); - if (error) - goto fail; - usb_pause_mtx(&sc->sc_mtx, 100); - - error = urtw_8180_set_anaparam(sc, URTW_8225_ANAPARAM_ON); - if (error) - goto fail; - error = urtw_8185_set_anaparam2(sc, URTW_8225_ANAPARAM2_ON); - if (error) - goto fail; -fail: - return (error); -} - -static usb_error_t -urtw_led_ctl(struct urtw_softc *sc, int mode) -{ - usb_error_t error = 0; - - switch (sc->sc_strategy) { - case URTW_SW_LED_MODE0: - error = urtw_led_mode0(sc, mode); - break; - case URTW_SW_LED_MODE1: - error = urtw_led_mode1(sc, mode); - break; - case URTW_SW_LED_MODE2: - error = urtw_led_mode2(sc, mode); - break; - case URTW_SW_LED_MODE3: - error = urtw_led_mode3(sc, mode); - break; - default: - panic("unsupported LED mode %d\n", sc->sc_strategy); - /* never reach */ - } - - return (error); -} - -static usb_error_t -urtw_led_mode0(struct urtw_softc *sc, int mode) -{ - - switch (mode) { - case URTW_LED_CTL_POWER_ON: - sc->sc_gpio_ledstate = URTW_LED_POWER_ON_BLINK; - break; - case URTW_LED_CTL_TX: - if (sc->sc_gpio_ledinprogress == 1) - return (0); - - sc->sc_gpio_ledstate = URTW_LED_BLINK_NORMAL; - sc->sc_gpio_blinktime = 2; - break; - case URTW_LED_CTL_LINK: - sc->sc_gpio_ledstate = URTW_LED_ON; - break; - default: - panic("unsupported LED mode 0x%x", mode); - /* never reach */ - } - - switch (sc->sc_gpio_ledstate) { - case URTW_LED_ON: - if (sc->sc_gpio_ledinprogress != 0) - break; - urtw_led_on(sc, URTW_LED_GPIO); - break; - case URTW_LED_BLINK_NORMAL: - if (sc->sc_gpio_ledinprogress != 0) - break; - sc->sc_gpio_ledinprogress = 1; - sc->sc_gpio_blinkstate = (sc->sc_gpio_ledon != 0) ? - URTW_LED_OFF : URTW_LED_ON; - usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc); - break; - case URTW_LED_POWER_ON_BLINK: - urtw_led_on(sc, URTW_LED_GPIO); - usb_pause_mtx(&sc->sc_mtx, 100); - urtw_led_off(sc, URTW_LED_GPIO); - break; - default: - panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); - /* never reach */ - } - return (0); -} - -static usb_error_t -urtw_led_mode1(struct urtw_softc *sc, int mode) -{ - return (USB_ERR_INVAL); -} - -static usb_error_t -urtw_led_mode2(struct urtw_softc *sc, int mode) -{ - return (USB_ERR_INVAL); -} - -static usb_error_t -urtw_led_mode3(struct urtw_softc *sc, int mode) -{ - return (USB_ERR_INVAL); -} - -static usb_error_t -urtw_led_on(struct urtw_softc *sc, int type) -{ - usb_error_t error; - - if (type == URTW_LED_GPIO) { - switch (sc->sc_gpio_ledpin) { - case URTW_LED_PIN_GPIO0: - urtw_write8_m(sc, URTW_GPIO, 0x01); - urtw_write8_m(sc, URTW_GP_ENABLE, 0x00); - break; - default: - panic("unsupported LED PIN type 0x%x", - sc->sc_gpio_ledpin); - /* never reach */ - } - } else { - panic("unsupported LED type 0x%x", type); - /* never reach */ - } - - sc->sc_gpio_ledon = 1; -fail: - return (error); -} - -static usb_error_t -urtw_led_off(struct urtw_softc *sc, int type) -{ - usb_error_t error; - - if (type == URTW_LED_GPIO) { - switch (sc->sc_gpio_ledpin) { - case URTW_LED_PIN_GPIO0: - urtw_write8_m(sc, URTW_GPIO, URTW_GPIO_DATA_MAGIC1); - urtw_write8_m(sc, - URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1); - break; - default: - panic("unsupported LED PIN type 0x%x", - sc->sc_gpio_ledpin); - /* never reach */ - } - } else { - panic("unsupported LED type 0x%x", type); - /* never reach */ - } - - sc->sc_gpio_ledon = 0; - -fail: - return (error); -} - -static void -urtw_led_ch(void *arg) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ieee80211_runtask(ic, &sc->sc_led_task); -} - -static void -urtw_ledtask(void *arg, int pending) -{ - struct urtw_softc *sc = arg; - - if (sc->sc_strategy != URTW_SW_LED_MODE0) - panic("could not process a LED strategy 0x%x", sc->sc_strategy); - - URTW_LOCK(sc); - urtw_led_blink(sc); - URTW_UNLOCK(sc); -} - -static usb_error_t -urtw_led_blink(struct urtw_softc *sc) -{ - uint8_t ing = 0; - usb_error_t error; - - if (sc->sc_gpio_blinkstate == URTW_LED_ON) - error = urtw_led_on(sc, URTW_LED_GPIO); - else - error = urtw_led_off(sc, URTW_LED_GPIO); - sc->sc_gpio_blinktime--; - if (sc->sc_gpio_blinktime == 0) - ing = 1; - else { - if (sc->sc_gpio_ledstate != URTW_LED_BLINK_NORMAL && - sc->sc_gpio_ledstate != URTW_LED_BLINK_SLOWLY && - sc->sc_gpio_ledstate != URTW_LED_BLINK_CM3) - ing = 1; - } - if (ing == 1) { - if (sc->sc_gpio_ledstate == URTW_LED_ON && - sc->sc_gpio_ledon == 0) - error = urtw_led_on(sc, URTW_LED_GPIO); - else if (sc->sc_gpio_ledstate == URTW_LED_OFF && - sc->sc_gpio_ledon == 1) - error = urtw_led_off(sc, URTW_LED_GPIO); - - sc->sc_gpio_blinktime = 0; - sc->sc_gpio_ledinprogress = 0; - return (0); - } - - sc->sc_gpio_blinkstate = (sc->sc_gpio_blinkstate != URTW_LED_ON) ? - URTW_LED_ON : URTW_LED_OFF; - - switch (sc->sc_gpio_ledstate) { - case URTW_LED_BLINK_NORMAL: - usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc); - break; - default: - panic("unknown LED status 0x%x", sc->sc_gpio_ledstate); - /* never reach */ - } - return (0); -} - -static usb_error_t -urtw_rx_enable(struct urtw_softc *sc) -{ - uint8_t data; - usb_error_t error; - - usbd_transfer_start((sc->sc_flags & URTW_RTL8187B) ? - sc->sc_xfer[URTW_8187B_BULK_RX] : sc->sc_xfer[URTW_8187L_BULK_RX]); - - error = urtw_rx_setconf(sc); - if (error != 0) - goto fail; - - if ((sc->sc_flags & URTW_RTL8187B) == 0) { - urtw_read8_m(sc, URTW_CMD, &data); - urtw_write8_m(sc, URTW_CMD, data | URTW_CMD_RX_ENABLE); - } -fail: - return (error); -} - -static usb_error_t -urtw_tx_enable(struct urtw_softc *sc) -{ - uint8_t data8; - uint32_t data; - usb_error_t error; - - if (sc->sc_flags & URTW_RTL8187B) { - urtw_read32_m(sc, URTW_TX_CONF, &data); - data &= ~URTW_TX_LOOPBACK_MASK; - data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); - data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); - data &= ~URTW_TX_SWPLCPLEN; - data |= URTW_TX_HW_SEQNUM | URTW_TX_DISREQQSIZE | - (7 << 8) | /* short retry limit */ - (7 << 0) | /* long retry limit */ - (7 << 21); /* MAX TX DMA */ - urtw_write32_m(sc, URTW_TX_CONF, data); - - urtw_read8_m(sc, URTW_MSR, &data8); - data8 |= URTW_MSR_LINK_ENEDCA; - urtw_write8_m(sc, URTW_MSR, data8); - return (error); - } - - urtw_read8_m(sc, URTW_CW_CONF, &data8); - data8 &= ~(URTW_CW_CONF_PERPACKET_CW | URTW_CW_CONF_PERPACKET_RETRY); - urtw_write8_m(sc, URTW_CW_CONF, data8); - - urtw_read8_m(sc, URTW_TX_AGC_CTL, &data8); - data8 &= ~URTW_TX_AGC_CTL_PERPACKET_GAIN; - data8 &= ~URTW_TX_AGC_CTL_PERPACKET_ANTSEL; - data8 &= ~URTW_TX_AGC_CTL_FEEDBACK_ANT; - urtw_write8_m(sc, URTW_TX_AGC_CTL, data8); - - urtw_read32_m(sc, URTW_TX_CONF, &data); - data &= ~URTW_TX_LOOPBACK_MASK; - data |= URTW_TX_LOOPBACK_NONE; - data &= ~(URTW_TX_DPRETRY_MASK | URTW_TX_RTSRETRY_MASK); - data |= sc->sc_tx_retry << URTW_TX_DPRETRY_SHIFT; - data |= sc->sc_rts_retry << URTW_TX_RTSRETRY_SHIFT; - data &= ~(URTW_TX_NOCRC | URTW_TX_MXDMA_MASK); - data |= URTW_TX_MXDMA_2048 | URTW_TX_CWMIN | URTW_TX_DISCW; - data &= ~URTW_TX_SWPLCPLEN; - data |= URTW_TX_NOICV; - urtw_write32_m(sc, URTW_TX_CONF, data); - - urtw_read8_m(sc, URTW_CMD, &data8); - urtw_write8_m(sc, URTW_CMD, data8 | URTW_CMD_TX_ENABLE); -fail: - return (error); -} - -static usb_error_t -urtw_rx_setconf(struct urtw_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t data; - usb_error_t error; - - urtw_read32_m(sc, URTW_RX, &data); - data = data &~ URTW_RX_FILTER_MASK; - if (sc->sc_flags & URTW_RTL8187B) { - data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA | - URTW_RX_FILTER_MCAST | URTW_RX_FILTER_BCAST | - URTW_RX_FILTER_NICMAC | URTW_RX_CHECK_BSSID | - URTW_RX_FIFO_THRESHOLD_NONE | - URTW_MAX_RX_DMA_2048 | - URTW_RX_AUTORESETPHY | URTW_RCR_ONLYERLPKT; - } else { - data = data | URTW_RX_FILTER_MNG | URTW_RX_FILTER_DATA; - data = data | URTW_RX_FILTER_BCAST | URTW_RX_FILTER_MCAST; - - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - data = data | URTW_RX_FILTER_ICVERR; - data = data | URTW_RX_FILTER_PWR; - } - if (sc->sc_crcmon == 1 && ic->ic_opmode == IEEE80211_M_MONITOR) - data = data | URTW_RX_FILTER_CRCERR; - - if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { - data = data | URTW_RX_FILTER_ALLMAC; - } else { - data = data | URTW_RX_FILTER_NICMAC; - data = data | URTW_RX_CHECK_BSSID; - } - - data = data &~ URTW_RX_FIFO_THRESHOLD_MASK; - data = data | URTW_RX_FIFO_THRESHOLD_NONE | - URTW_RX_AUTORESETPHY; - data = data &~ URTW_MAX_RX_DMA_MASK; - data = data | URTW_MAX_RX_DMA_2048 | URTW_RCR_ONLYERLPKT; - } - - urtw_write32_m(sc, URTW_RX, data); -fail: - return (error); -} - -static struct mbuf * -urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, - int8_t *nf_p) -{ - int actlen, flen, rssi; - struct ieee80211_frame *wh; - struct mbuf *m, *mnew; - struct urtw_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint8_t noise = 0, rate; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - if (actlen < URTW_MIN_RXBUFSZ) { - ifp->if_ierrors++; - return (NULL); - } - - if (sc->sc_flags & URTW_RTL8187B) { - struct urtw_8187b_rxhdr *rx; - - rx = (struct urtw_8187b_rxhdr *)(data->buf + - (actlen - (sizeof(struct urtw_8187b_rxhdr)))); - flen = le32toh(rx->flag) & 0xfff; - if (flen > actlen) { - ifp->if_ierrors++; - return (NULL); - } - rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; - /* XXX correct? */ - rssi = rx->rssi & URTW_RX_RSSI_MASK; - noise = rx->noise; - } else { - struct urtw_8187l_rxhdr *rx; - - rx = (struct urtw_8187l_rxhdr *)(data->buf + - (actlen - (sizeof(struct urtw_8187l_rxhdr)))); - flen = le32toh(rx->flag) & 0xfff; - if (flen > actlen) { - ifp->if_ierrors++; - return (NULL); - } - - rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; - /* XXX correct? */ - rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK; - noise = rx->noise; - } - - mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - if (mnew == NULL) { - ifp->if_ierrors++; - return (NULL); - } - - m = data->m; - data->m = mnew; - data->buf = mtod(mnew, uint8_t *); - - /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN; - - if (ieee80211_radiotap_active(ic)) { - struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap; - - /* XXX Are variables correct? */ - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); - tap->wr_dbm_antsignal = (int8_t)rssi; - } - - wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_DATA) - sc->sc_currate = (rate > 0) ? rate : sc->sc_currate; - - *rssi_p = rssi; - *nf_p = noise; /* XXX correct? */ - - return (m); -} - -static void -urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_frame *wh; - struct ieee80211_node *ni; - struct mbuf *m = NULL; - struct urtw_data *data; - int8_t nf = -95; - int rssi = 1; - - URTW_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - data = STAILQ_FIRST(&sc->sc_rx_active); - if (data == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); - m = urtw_rxeof(xfer, data, &rssi, &nf); - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - data = STAILQ_FIRST(&sc->sc_rx_inactive); - if (data == NULL) { - KASSERT(m == NULL, ("mbuf isn't NULL")); - return; - } - STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next); - STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next); - usbd_xfer_set_frame_data(xfer, 0, data->buf, - usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - - /* - * To avoid LOR we should unlock our private mutex here to call - * ieee80211_input() because here is at the end of a USB - * callback and safe to unlock. - */ - URTW_UNLOCK(sc); - if (m != NULL) { - wh = mtod(m, struct ieee80211_frame *); - ni = ieee80211_find_rxnode(ic, - (struct ieee80211_frame_min *)wh); - if (ni != NULL) { - (void) ieee80211_input(ni, m, rssi, nf); - /* node is no longer needed */ - ieee80211_free_node(ni); - } else - (void) ieee80211_input_all(ic, m, rssi, nf); - m = NULL; - } - URTW_LOCK(sc); - break; - default: - /* needs it to the inactive queue due to a error. */ - data = STAILQ_FIRST(&sc->sc_rx_active); - if (data != NULL) { - STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next); - STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next); - } - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - ifp->if_ierrors++; - goto setup; - } - break; - } -} - -#define URTW_STATUS_TYPE_TXCLOSE 1 -#define URTW_STATUS_TYPE_BEACON_INTR 0 - -static void -urtw_txstatus_eof(struct usb_xfer *xfer) -{ - struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - int actlen, type, pktretry, seq; - uint64_t val; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - if (actlen != sizeof(uint64_t)) - return; - - val = le64toh(sc->sc_txstatus); - type = (val >> 30) & 0x3; - if (type == URTW_STATUS_TYPE_TXCLOSE) { - pktretry = val & 0xff; - seq = (val >> 16) & 0xff; - if (pktretry == URTW_TX_MAXRETRY) - ifp->if_oerrors++; - DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n", - pktretry, seq); - } -} - -static void -urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - - URTW_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - urtw_txstatus_eof(xfer); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - usbd_xfer_set_frame_data(xfer, 0, &sc->sc_txstatus, - sizeof(int64_t)); - usbd_transfer_submit(xfer); - break; - default: - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - ifp->if_ierrors++; - goto setup; - } - break; - } -} - -static void -urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data) -{ - struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct mbuf *m; - - URTW_ASSERT_LOCKED(sc); - - /* - * Do any tx complete callback. Note this must be done before releasing - * the node reference. - */ - if (data->m) { - m = data->m; - if (m->m_flags & M_TXCB) { - /* XXX status? */ - ieee80211_process_callback(data->ni, m, 0); - } - m_freem(m); - data->m = NULL; - } - if (data->ni) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - sc->sc_txtimer = 0; - ifp->if_opackets++; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; -} - -static void -urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct urtw_data *data; - - URTW_ASSERT_LOCKED(sc); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - data = STAILQ_FIRST(&sc->sc_tx_active); - if (data == NULL) - goto setup; - STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next); - urtw_txeof(xfer, data); - STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); - /* FALLTHROUGH */ - case USB_ST_SETUP: -setup: - data = STAILQ_FIRST(&sc->sc_tx_pending); - if (data == NULL) { - DPRINTF(sc, URTW_DEBUG_XMIT, - "%s: empty pending queue\n", __func__); - return; - } - STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next); - STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next); - - usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); - usbd_transfer_submit(xfer); - - URTW_UNLOCK(sc); - urtw_start(ifp); - URTW_LOCK(sc); - break; - default: - data = STAILQ_FIRST(&sc->sc_tx_active); - if (data == NULL) - goto setup; - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - ifp->if_oerrors++; - } - if (error != USB_ERR_CANCELLED) { - usbd_xfer_set_stall(xfer); - goto setup; - } - break; - } -} - -static struct urtw_data * -_urtw_getbuf(struct urtw_softc *sc) -{ - struct urtw_data *bf; - - bf = STAILQ_FIRST(&sc->sc_tx_inactive); - if (bf != NULL) - STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next); - else - bf = NULL; - if (bf == NULL) - DPRINTF(sc, URTW_DEBUG_XMIT, "%s: %s\n", __func__, - "out of xmit buffers"); - return (bf); -} - -static struct urtw_data * -urtw_getbuf(struct urtw_softc *sc) -{ - struct urtw_data *bf; - - URTW_ASSERT_LOCKED(sc); - - bf = _urtw_getbuf(sc); - if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - } - return (bf); -} - -static int -urtw_isbmode(uint16_t rate) -{ - - return ((rate <= 22 && rate != 12 && rate != 18) || - rate == 44) ? (1) : (0); -} - -static uint16_t -urtw_rate2dbps(uint16_t rate) -{ - - switch(rate) { - case 12: - case 18: - case 24: - case 36: - case 48: - case 72: - case 96: - case 108: - return (rate * 2); - default: - break; - } - return (24); -} - -static int -urtw_compute_txtime(uint16_t framelen, uint16_t rate, - uint8_t ismgt, uint8_t isshort) -{ - uint16_t ceiling, frametime, n_dbps; - - if (urtw_isbmode(rate)) { - if (ismgt || !isshort || rate == 2) - frametime = (uint16_t)(144 + 48 + - (framelen * 8 / (rate / 2))); - else - frametime = (uint16_t)(72 + 24 + - (framelen * 8 / (rate / 2))); - if ((framelen * 8 % (rate / 2)) != 0) - frametime++; - } else { - n_dbps = urtw_rate2dbps(rate); - ceiling = (16 + 8 * framelen + 6) / n_dbps - + (((16 + 8 * framelen + 6) % n_dbps) ? 1 : 0); - frametime = (uint16_t)(16 + 4 + 4 * ceiling + 6); - } - return (frametime); -} - -/* - * Callback from the 802.11 layer to update the - * slot time based on the current setting. - */ -static void -urtw_updateslot(struct ieee80211com *ic) -{ - struct urtw_softc *sc = ic->ic_softc; - - ieee80211_runtask(ic, &sc->sc_updateslot_task); -} - -static void -urtw_updateslottask(void *arg, int pending) -{ - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - int error; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - URTW_LOCK(sc); - if (sc->sc_flags & URTW_RTL8187B) { - urtw_write8_m(sc, URTW_SIFS, 0x22); - if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) - urtw_write8_m(sc, URTW_SLOT, 0x9); - else - urtw_write8_m(sc, URTW_SLOT, 0x14); - urtw_write8_m(sc, URTW_8187B_EIFS, 0x5b); - urtw_write8_m(sc, URTW_CARRIER_SCOUNT, 0x5b); - } else { - urtw_write8_m(sc, URTW_SIFS, 0x22); - if (sc->sc_state == IEEE80211_S_ASSOC && - ic->ic_flags & IEEE80211_F_SHSLOT) - urtw_write8_m(sc, URTW_SLOT, 0x9); - else - urtw_write8_m(sc, URTW_SLOT, 0x14); - if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) { - urtw_write8_m(sc, URTW_DIFS, 0x14); - urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x14); - urtw_write8_m(sc, URTW_CW_VAL, 0x73); - } else { - urtw_write8_m(sc, URTW_DIFS, 0x24); - urtw_write8_m(sc, URTW_EIFS, 0x5b - 0x24); - urtw_write8_m(sc, URTW_CW_VAL, 0xa5); - } - } -fail: - URTW_UNLOCK(sc); -} - -static void -urtw_sysctl_node(struct urtw_softc *sc) -{ -#define URTW_SYSCTL_STAT_ADD32(c, h, n, p, d) \ - SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) - struct sysctl_ctx_list *ctx; - struct sysctl_oid_list *child, *parent; - struct sysctl_oid *tree; - struct urtw_stats *stats = &sc->sc_stats; - - ctx = device_get_sysctl_ctx(sc->sc_dev); - child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev)); - - tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD, - NULL, "URTW statistics"); - parent = SYSCTL_CHILDREN(tree); - - /* Tx statistics. */ - tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD, - NULL, "Tx MAC statistics"); - child = SYSCTL_CHILDREN(tree); - URTW_SYSCTL_STAT_ADD32(ctx, child, "1m", &stats->txrates[0], - "1 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "2m", &stats->txrates[1], - "2 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "5.5m", &stats->txrates[2], - "5.5 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "6m", &stats->txrates[4], - "6 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "9m", &stats->txrates[5], - "9 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "11m", &stats->txrates[3], - "11 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "12m", &stats->txrates[6], - "12 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "18m", &stats->txrates[7], - "18 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "24m", &stats->txrates[8], - "24 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "36m", &stats->txrates[9], - "36 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "48m", &stats->txrates[10], - "48 Mbit/s"); - URTW_SYSCTL_STAT_ADD32(ctx, child, "54m", &stats->txrates[11], - "54 Mbit/s"); -#undef URTW_SYSCTL_STAT_ADD32 -} - -static device_method_t urtw_methods[] = { - DEVMETHOD(device_probe, urtw_match), - DEVMETHOD(device_attach, urtw_attach), - DEVMETHOD(device_detach, urtw_detach), - DEVMETHOD_END -}; -static driver_t urtw_driver = { - "urtw", - urtw_methods, - sizeof(struct urtw_softc) -}; -static devclass_t urtw_devclass; - -DRIVER_MODULE(urtw, uhub, urtw_driver, urtw_devclass, NULL, NULL); -MODULE_DEPEND(urtw, wlan, 1, 1, 1); -MODULE_DEPEND(urtw, usb, 1, 1, 1); -MODULE_VERSION(urtw, 1); diff --git a/sys/bus/u4b/wlan/if_urtwreg.h b/sys/bus/u4b/wlan/if_urtwreg.h deleted file mode 100644 index a0fe5ffd71..0000000000 --- a/sys/bus/u4b/wlan/if_urtwreg.h +++ /dev/null @@ -1,432 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2008 Weongyo Jeong - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define URTW_CONFIG_INDEX 0 -#define URTW_IFACE_INDEX 0 - -/* for 8187 */ -#define URTW_MAC0 0x0000 /* 1 byte */ -#define URTW_MAC1 0x0001 /* 1 byte */ -#define URTW_MAC2 0x0002 /* 1 byte */ -#define URTW_MAC3 0x0003 /* 1 byte */ -#define URTW_MAC4 0x0004 /* 1 byte */ -#define URTW_MAC5 0x0005 /* 1 byte */ -#define URTW_MAR 0x0008 /* 6 byte */ -#define URTW_RXFIFO_CNT 0x0010 /* 1 byte */ -#define URTW_TXFIFO_CNT 0x0012 /* 1 byte */ -#define URTW_BQREQ 0x0013 /* 1 byte */ -#define URTW_TSFT 0x0018 /* 6 byte */ -#define URTW_TLPDA 0x0020 /* 4 byte */ -#define URTW_TNPDA 0x0024 /* 4 byte */ -#define URTW_THPDA 0x0028 /* 4 byte */ -#define URTW_BRSR 0x002c /* 2 byte */ -#define URTW_BRSR_MBR_8185 (0x0fff) -#define URTW_8187B_EIFS 0x002d /* 1 byte for 8187B */ -#define URTW_BSSID 0x002e /* 6 byte */ -#define URTW_BRSR_8187B 0x0034 /* 2 byte for 8187B */ -#define URTW_RESP_RATE 0x0034 /* 1 byte for 8187L */ -#define URTW_RESP_MAX_RATE_SHIFT (4) -#define URTW_RESP_MIN_RATE_SHIFT (0) -#define URTW_EIFS 0x0035 /* 1 byte */ -#define URTW_CMD 0x0037 /* 1 byte */ -#define URTW_CMD_TX_ENABLE (0x4) -#define URTW_CMD_RX_ENABLE (0x8) -#define URTW_CMD_RST (0x10) -#define URTW_INTR_MASK 0x003c /* 2 byte */ -#define URTW_INTR_STATUS 0x003e /* 2 byte */ -#define URTW_TX_CONF 0x0040 /* 4 byte */ -#define URTW_TX_LOOPBACK_SHIFT (17) -#define URTW_TX_LOOPBACK_NONE (0 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_MAC (1 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_BASEBAND (2 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_CONTINUE (3 << URTW_TX_LOOPBACK_SHIFT) -#define URTW_TX_LOOPBACK_MASK (0x60000) -#define URTW_TX_DPRETRY_MASK (0xff00) -#define URTW_TX_RTSRETRY_MASK (0xff) -#define URTW_TX_DPRETRY_SHIFT (0) -#define URTW_TX_RTSRETRY_SHIFT (8) -#define URTW_TX_NOCRC (0x10000) -#define URTW_TX_MXDMA_MASK (0xe00000) -#define URTW_TX_MXDMA_1024 (6 << URTW_TX_MXDMA_SHIFT) -#define URTW_TX_MXDMA_2048 (7 << URTW_TX_MXDMA_SHIFT) -#define URTW_TX_MXDMA_SHIFT (21) -#define URTW_TX_DISCW (1 << 20) -#define URTW_TX_SWPLCPLEN (1 << 24) -#define URTW_TX_R8187vD (5 << 25) -#define URTW_TX_R8187vD_B (6 << 25) -#define URTW_TX_HWMASK (7 << 25) -#define URTW_TX_DISREQQSIZE (1 << 28) -#define URTW_TX_HW_SEQNUM (1 << 30) -#define URTW_TX_CWMIN (1 << 31) -#define URTW_TX_NOICV (0x80000) -#define URTW_RX 0x0044 /* 4 byte */ -#define URTW_RX_9356SEL (1 << 6) -#define URTW_RX_FILTER_MASK \ - (URTW_RX_FILTER_ALLMAC | URTW_RX_FILTER_NICMAC | URTW_RX_FILTER_MCAST | \ - URTW_RX_FILTER_BCAST | URTW_RX_FILTER_CRCERR | URTW_RX_FILTER_ICVERR | \ - URTW_RX_FILTER_DATA | URTW_RX_FILTER_CTL | URTW_RX_FILTER_MNG | \ - (1 << 21) | \ - URTW_RX_FILTER_PWR | URTW_RX_CHECK_BSSID) -#define URTW_RX_FILTER_ALLMAC (0x00000001) -#define URTW_RX_FILTER_NICMAC (0x00000002) -#define URTW_RX_FILTER_MCAST (0x00000004) -#define URTW_RX_FILTER_BCAST (0x00000008) -#define URTW_RX_FILTER_CRCERR (0x00000020) -#define URTW_RX_FILTER_ICVERR (0x00001000) -#define URTW_RX_FILTER_DATA (0x00040000) -#define URTW_RX_FILTER_CTL (0x00080000) -#define URTW_RX_FILTER_MNG (0x00100000) -#define URTW_RX_FILTER_PWR (0x00400000) -#define URTW_RX_CHECK_BSSID (0x00800000) -#define URTW_RX_FIFO_THRESHOLD_MASK ((1 << 13) | (1 << 14) | (1 << 15)) -#define URTW_RX_FIFO_THRESHOLD_SHIFT (13) -#define URTW_RX_FIFO_THRESHOLD_128 (3) -#define URTW_RX_FIFO_THRESHOLD_256 (4) -#define URTW_RX_FIFO_THRESHOLD_512 (5) -#define URTW_RX_FIFO_THRESHOLD_1024 (6) -#define URTW_RX_FIFO_THRESHOLD_NONE (7 << URTW_RX_FIFO_THRESHOLD_SHIFT) -#define URTW_RX_AUTORESETPHY (1 << URTW_RX_AUTORESETPHY_SHIFT) -#define URTW_RX_AUTORESETPHY_SHIFT (28) -#define URTW_MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10)) -#define URTW_MAX_RX_DMA_2048 (7 << URTW_MAX_RX_DMA_SHIFT) -#define URTW_MAX_RX_DMA_1024 (6) -#define URTW_MAX_RX_DMA_SHIFT (10) -#define URTW_RCR_ONLYERLPKT (1 << 31) -#define URTW_INT_TIMEOUT 0x0048 /* 4 byte */ -#define URTW_INT_TBDA 0x004c /* 4 byte */ -#define URTW_EPROM_CMD 0x0050 /* 1 byte */ -#define URTW_EPROM_CMD_NORMAL (0x0) -#define URTW_EPROM_CMD_NORMAL_MODE \ - (URTW_EPROM_CMD_NORMAL << URTW_EPROM_CMD_SHIFT) -#define URTW_EPROM_CMD_LOAD (0x1) -#define URTW_EPROM_CMD_PROGRAM (0x2) -#define URTW_EPROM_CMD_PROGRAM_MODE \ - (URTW_EPROM_CMD_PROGRAM << URTW_EPROM_CMD_SHIFT) -#define URTW_EPROM_CMD_CONFIG (0x3) -#define URTW_EPROM_CMD_SHIFT (6) -#define URTW_EPROM_CMD_MASK ((1 << 7) | (1 << 6)) -#define URTW_EPROM_READBIT (0x1) -#define URTW_EPROM_WRITEBIT (0x2) -#define URTW_EPROM_CK (0x4) -#define URTW_EPROM_CS (0x8) -#define URTW_CONFIG0 0x0051 /* 1 byte */ -#define URTW_CONFIG1 0x0052 /* 1 byte */ -#define URTW_CONFIG2 0x0053 /* 1 byte */ -#define URTW_ANAPARAM 0x0054 /* 4 byte */ -#define URTW_8225_ANAPARAM_ON (0xa0000a59) -#define URTW_8225_ANAPARAM_OFF (0xa00beb59) -#define URTW_8187B_8225_ANAPARAM_ON (0x45090658) -#define URTW_8187B_8225_ANAPARAM_OFF (0x55480658) -#define URTW_MSR 0x0058 /* 1 byte */ -#define URTW_MSR_LINK_MASK ((1 << 2) | (1 << 3)) -#define URTW_MSR_LINK_SHIFT (2) -#define URTW_MSR_LINK_NONE (0 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_ADHOC (1 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_STA (2 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_HOSTAP (3 << URTW_MSR_LINK_SHIFT) -#define URTW_MSR_LINK_ENEDCA (1 << 4) -#define URTW_CONFIG3 0x0059 /* 1 byte */ -#define URTW_CONFIG3_ANAPARAM_WRITE (0x40) -#define URTW_CONFIG3_GNT_SELECT (0x80) -#define URTW_CONFIG3_ANAPARAM_W_SHIFT (6) -#define URTW_CONFIG4 0x005a /* 1 byte */ -#define URTW_CONFIG4_VCOOFF (1 << 7) -#define URTW_TESTR 0x005b /* 1 byte */ -#define URTW_PSR 0x005e /* 1 byte */ -#define URTW_SECURITY 0x005f /* 1 byte */ -#define URTW_ANAPARAM2 0x0060 /* 4 byte */ -#define URTW_8225_ANAPARAM2_ON (0x860c7312) -#define URTW_8225_ANAPARAM2_OFF (0x840dec11) -#define URTW_8187B_8225_ANAPARAM2_ON (0x727f3f52) -#define URTW_8187B_8225_ANAPARAM2_OFF (0x72003f50) -#define URTW_BEACON_INTERVAL 0x0070 /* 2 byte */ -#define URTW_ATIM_WND 0x0072 /* 2 byte */ -#define URTW_BEACON_INTERVAL_TIME 0x0074 /* 2 byte */ -#define URTW_ATIM_TR_ITV 0x0076 /* 2 byte */ -#define URTW_PHY_DELAY 0x0078 /* 1 byte */ -#define URTW_CARRIER_SCOUNT 0x0079 /* 1 byte */ -#define URTW_PHY_MAGIC1 0x007c /* 1 byte */ -#define URTW_PHY_MAGIC2 0x007d /* 1 byte */ -#define URTW_PHY_MAGIC3 0x007e /* 1 byte */ -#define URTW_PHY_MAGIC4 0x007f /* 1 byte */ -#define URTW_RF_PINS_OUTPUT 0x0080 /* 2 byte */ -#define URTW_RF_PINS_OUTPUT_MAGIC1 (0x3a0) -#define URTW_BB_HOST_BANG_CLK (1 << 1) -#define URTW_BB_HOST_BANG_EN (1 << 2) -#define URTW_BB_HOST_BANG_RW (1 << 3) -#define URTW_RF_PINS_ENABLE 0x0082 /* 2 byte */ -#define URTW_RF_PINS_SELECT 0x0084 /* 2 byte */ -#define URTW_ADDR_MAGIC1 0x0085 /* broken? */ -#define URTW_RF_PINS_INPUT 0x0086 /* 2 byte */ -#define URTW_RF_PINS_MAGIC1 (0xfff3) -#define URTW_RF_PINS_MAGIC2 (0xfff0) -#define URTW_RF_PINS_MAGIC3 (0x0007) -#define URTW_RF_PINS_MAGIC4 (0xf) -#define URTW_RF_PINS_MAGIC5 (0x0080) -#define URTW_RF_PARA 0x0088 /* 4 byte */ -#define URTW_RF_TIMING 0x008c /* 4 byte */ -#define URTW_GP_ENABLE 0x0090 /* 1 byte */ -#define URTW_GP_ENABLE_DATA_MAGIC1 (0x1) -#define URTW_GPIO 0x0091 /* 1 byte */ -#define URTW_GPIO_DATA_MAGIC1 (0x1) -#define URTW_HSSI_PARA 0x0094 /* 4 byte */ -#define URTW_TX_AGC_CTL 0x009c /* 1 byte */ -#define URTW_TX_AGC_CTL_PERPACKET_GAIN (0x1) -#define URTW_TX_AGC_CTL_PERPACKET_ANTSEL (0x2) -#define URTW_TX_AGC_CTL_FEEDBACK_ANT (0x4) -#define URTW_TX_GAIN_CCK 0x009d /* 1 byte */ -#define URTW_TX_GAIN_OFDM 0x009e /* 1 byte */ -#define URTW_TX_ANTENNA 0x009f /* 1 byte */ -#define URTW_WPA_CONFIG 0x00b0 /* 1 byte */ -#define URTW_SIFS 0x00b4 /* 1 byte */ -#define URTW_DIFS 0x00b5 /* 1 byte */ -#define URTW_SLOT 0x00b6 /* 1 byte */ -#define URTW_CW_CONF 0x00bc /* 1 byte */ -#define URTW_CW_CONF_PERPACKET_RETRY (0x2) -#define URTW_CW_CONF_PERPACKET_CW (0x1) -#define URTW_CW_VAL 0x00bd /* 1 byte */ -#define URTW_RATE_FALLBACK 0x00be /* 1 byte */ -#define URTW_RATE_FALLBACK_ENABLE (0x80) -#define URTW_ACM_CONTROL 0x00bf /* 1 byte */ -#define URTW_CONFIG5 0x00d8 /* 1 byte */ -#define URTW_TXDMA_POLLING 0x00d9 /* 1 byte */ -#define URTW_CWR 0x00dc /* 2 byte */ -#define URTW_RETRY_CTR 0x00de /* 1 byte */ -#define URTW_INT_MIG 0x00e2 /* 2 byte */ -#define URTW_RDSAR 0x00e4 /* 4 byte */ -#define URTW_TID_AC_MAP 0x00e8 /* 2 byte */ -#define URTW_ANAPARAM3 0x00ee /* 1 byte */ -#define URTW_8187B_8225_ANAPARAM3_ON (0x0) -#define URTW_8187B_8225_ANAPARAM3_OFF (0x0) -#define URTW_8187B_AC_VO 0x00f0 /* 4 byte for 8187B */ -#define URTW_FEMR 0x00f4 /* 2 byte */ -#define URTW_8187B_AC_VI 0x00f4 /* 4 byte for 8187B */ -#define URTW_8187B_AC_BE 0x00f8 /* 4 byte for 8187B */ -#define URTW_TALLY_CNT 0x00fa /* 2 byte */ -#define URTW_TALLY_SEL 0x00fc /* 1 byte */ -#define URTW_8187B_AC_BK 0x00fc /* 4 byte for 8187B */ -#define URTW_ADDR_MAGIC2 0x00fe /* 2 byte */ -#define URTW_ADDR_MAGIC3 0x00ff /* 1 byte */ - -/* for 8225 */ -#define URTW_8225_ADDR_0_MAGIC 0x0 -#define URTW_8225_ADDR_0_DATA_MAGIC1 (0x1b7) -#define URTW_8225_ADDR_0_DATA_MAGIC2 (0x0b7) -#define URTW_8225_ADDR_0_DATA_MAGIC3 (0x127) -#define URTW_8225_ADDR_0_DATA_MAGIC4 (0x027) -#define URTW_8225_ADDR_0_DATA_MAGIC5 (0x22f) -#define URTW_8225_ADDR_0_DATA_MAGIC6 (0x2bf) -#define URTW_8225_ADDR_1_MAGIC 0x1 -#define URTW_8225_ADDR_2_MAGIC 0x2 -#define URTW_8225_ADDR_2_DATA_MAGIC1 (0xc4d) -#define URTW_8225_ADDR_2_DATA_MAGIC2 (0x44d) -#define URTW_8225_ADDR_3_MAGIC 0x3 -#define URTW_8225_ADDR_3_DATA_MAGIC1 (0x2) -#define URTW_8225_ADDR_5_MAGIC 0x5 -#define URTW_8225_ADDR_5_DATA_MAGIC1 (0x4) -#define URTW_8225_ADDR_6_MAGIC 0x6 -#define URTW_8225_ADDR_6_DATA_MAGIC1 (0xe6) -#define URTW_8225_ADDR_6_DATA_MAGIC2 (0x80) -#define URTW_8225_ADDR_7_MAGIC 0x7 -#define URTW_8225_ADDR_8_MAGIC 0x8 -#define URTW_8225_ADDR_8_DATA_MAGIC1 (0x588) -#define URTW_8225_ADDR_9_MAGIC 0x9 -#define URTW_8225_ADDR_9_DATA_MAGIC1 (0x700) -#define URTW_8225_ADDR_C_MAGIC 0xc -#define URTW_8225_ADDR_C_DATA_MAGIC1 (0x850) -#define URTW_8225_ADDR_C_DATA_MAGIC2 (0x050) - -/* for EEPROM */ -#define URTW_EPROM_CHANPLAN 0x03 -#define URTW_EPROM_TXPW_BASE 0x05 -#define URTW_EPROM_RFCHIPID 0x06 -#define URTW_EPROM_RFCHIPID_RTL8225U (5) -#define URTW_EPROM_RFCHIPID_RTL8225Z2 (6) -#define URTW_EPROM_MACADDR 0x07 -#define URTW_EPROM_TXPW0 0x16 -#define URTW_EPROM_TXPW2 0x1b -#define URTW_EPROM_TXPW1 0x3d -#define URTW_EPROM_SWREV 0x3f -#define URTW_EPROM_CID_MASK (0xff) -#define URTW_EPROM_CID_RSVD0 (0x00) -#define URTW_EPROM_CID_RSVD1 (0xff) -#define URTW_EPROM_CID_ALPHA0 (0x01) -#define URTW_EPROM_CID_SERCOMM_PS (0x02) -#define URTW_EPROM_CID_HW_LED (0x03) - -/* LED */ -#define URTW_CID_DEFAULT 0 -#define URTW_CID_8187_ALPHA0 1 -#define URTW_CID_8187_SERCOMM_PS 2 -#define URTW_CID_8187_HW_LED 3 -#define URTW_SW_LED_MODE0 0 -#define URTW_SW_LED_MODE1 1 -#define URTW_SW_LED_MODE2 2 -#define URTW_SW_LED_MODE3 3 -#define URTW_HW_LED 4 -#define URTW_LED_CTL_POWER_ON 0 -#define URTW_LED_CTL_LINK 2 -#define URTW_LED_CTL_TX 4 -#define URTW_LED_PIN_GPIO0 0 -#define URTW_LED_PIN_LED0 1 -#define URTW_LED_PIN_LED1 2 -#define URTW_LED_UNKNOWN 0 -#define URTW_LED_ON 1 -#define URTW_LED_OFF 2 -#define URTW_LED_BLINK_NORMAL 3 -#define URTW_LED_BLINK_SLOWLY 4 -#define URTW_LED_POWER_ON_BLINK 5 -#define URTW_LED_SCAN_BLINK 6 -#define URTW_LED_NO_LINK_BLINK 7 -#define URTW_LED_BLINK_CM3 8 - -/* for extra area */ -#define URTW_EPROM_DISABLE 0 -#define URTW_EPROM_ENABLE 1 -#define URTW_EPROM_DELAY 10 -#define URTW_8187_GETREGS_REQ 5 -#define URTW_8187_SETREGS_REQ 5 -#define URTW_8225_RF_MAX_SENS 6 -#define URTW_8225_RF_DEF_SENS 4 -#define URTW_DEFAULT_RTS_RETRY 7 -#define URTW_DEFAULT_TX_RETRY 7 -#define URTW_DEFAULT_RTS_THRESHOLD 2342U - -#define URTW_ASIFS_TIME 10 -#define URTW_ACKCTS_LEN 14 /* len for ACK and CTS */ - -struct urtw_8187b_rxhdr { - uint32_t flag; -#define URTW_RX_FLAG_LEN /* 0 ~ 11 bits */ -#define URTW_RX_FLAG_ICV_ERR (1 << 12) -#define URTW_RX_FLAG_CRC32_ERR (1 << 13) -#define URTW_RX_FLAG_PM (1 << 14) -#define URTW_RX_FLAG_RX_ERR (1 << 15) -#define URTW_RX_FLAG_BCAST (1 << 16) -#define URTW_RX_FLAG_PAM (1 << 17) -#define URTW_RX_FLAG_MCAST (1 << 18) -#define URTW_RX_FLAG_QOS (1 << 19) /* only for RTL8187B */ -#define URTW_RX_FLAG_RXRATE /* 20 ~ 23 bits */ -#define URTW_RX_FLAG_RXRATE_SHIFT 20 -#define URTW_RX_FLAG_TRSW (1 << 24) /* only for RTL8187B */ -#define URTW_RX_FLAG_SPLCP (1 << 25) -#define URTW_RX_FLAG_FOF (1 << 26) -#define URTW_RX_FLAG_DMA_FAIL (1 << 27) -#define URTW_RX_FLAG_LAST (1 << 28) -#define URTW_RX_FLAG_FIRST (1 << 29) -#define URTW_RX_FLAG_EOR (1 << 30) -#define URTW_RX_FLAG_OWN (1 << 31) - uint64_t mactime; - uint8_t noise; - uint8_t rssi; -#define URTW_RX_RSSI /* 0 ~ 6 bits */ -#define URTW_RX_RSSI_MASK 0x3f -#define URTW_RX_ANTENNA (1 << 7) - uint8_t agc; - uint8_t flag2; -#define URTW_RX_FLAG2_DECRYPTED (1 << 0) -#define URTW_RX_FLAG2_WAKUP (1 << 1) -#define URTW_RX_FLAG2_SHIFT (1 << 2) -#define URTW_RX_FLAG2_RSVD0 /* 3 ~ 7 bits */ - uint16_t flag3; -#define URTW_RX_FLAG3_NUMMCSI /* 0 ~ 3 bits */ -#define URTW_RX_FLAG3_SNR_L2E /* 4 ~ 9 bits */ -#define URTW_RX_FLAG3_CFO_BIAS /* 10 ~ 15 bits */ - int8_t pwdb; - uint8_t fot; -} __packed; - -struct urtw_8187b_txhdr { - uint32_t flag; -#define URTW_TX_FLAG_PKTLEN /* 0 ~ 11 bits */ -#define URTW_TX_FLAG_RSVD0 /* 12 ~ 14 bits */ -#define URTW_TX_FLAG_NO_ENC (1 << 15) -#define URTW_TX_FLAG_SPLCP (1 << 16) -#define URTW_TX_FLAG_MOREFRAG (1 << 17) -#define URTW_TX_FLAG_CTS (1 << 18) -#define URTW_TX_FLAG_RTSRATE /* 19 ~ 22 bits */ -#define URTW_TX_FLAG_RTSRATE_SHIFT 19 -#define URTW_TX_FLAG_RTS (1 << 23) -#define URTW_TX_FLAG_TXRATE /* 24 ~ 27 bits */ -#define URTW_TX_FLAG_TXRATE_SHIFT 24 -#define URTW_TX_FLAG_LAST (1 << 28) -#define URTW_TX_FLAG_FIRST (1 << 29) -#define URTW_TX_FLAG_DMA (1 << 30) -#define URTW_TX_FLAG_OWN (1 << 31) - uint16_t rtsdur; - uint16_t len; -#define URTW_TX_LEN /* 0 ~ 14 bits */ -#define URTW_TX_LEN_EXT (1 << 15) - uint32_t bufaddr; - uint16_t flag1; -#define URTW_TX_FLAG1_RXLEN /* 0 ~ 11 bits */ -#define URTW_TX_FLAG1_RSVD0 /* 12 ~ 14 bits */ -#define URTW_TX_FLAG1_MICCAL (1 << 15) - uint16_t txdur; - uint32_t nextdescaddr; - uint8_t rtsagc; - uint8_t retry; - uint16_t flag2; -#define URTW_TX_FLAG2_RTDB (1 << 0) -#define URTW_TX_FLAG2_NOACM (1 << 1) -#define URTW_TX_FLAG2_PIFS (1 << 2) -#define URTW_TX_FLAG2_RSVD0 /* 3 ~ 6 bits */ -#define URTW_TX_FLAG2_RTSRATEFALLBACK /* 7 ~ 10 bits */ -#define URTW_TX_FLAG2_RATEFALLBACK /* 11 ~ 15 bits */ - uint16_t delaybound; - uint16_t flag3; -#define URTW_TX_FLAG3_RSVD0 /* 0 ~ 3 bits */ -#define URTW_TX_FLAG3_AGC /* 4 ~ 11 bits */ -#define URTW_TX_FLAG3_ANTENNA (1 << 12) -#define URTW_TX_FLAG3_SPC /* 13 ~ 14 bits */ -#define URTW_TX_FLAG3_RSVD1 (1 << 15) - uint32_t flag4; -#define URTW_TX_FLAG4_LENADJUST /* 0 ~ 1 bits */ -#define URTW_TX_FLAG4_RSVD0 (1 << 2) -#define URTW_TX_FLAG4_TPCDESEN (1 << 3) -#define URTW_TX_FLAG4_TPCPOLARITY /* 4 ~ 5 bits */ -#define URTW_TX_FLAG4_TPCEN (1 << 6) -#define URTW_TX_FLAG4_PTEN (1 << 7) -#define URTW_TX_FLAG4_BCKEY /* 8 ~ 13 bits */ -#define URTW_TX_FLAG4_ENBCKEY (1 << 14) -#define URTW_TX_FLAG4_ENPMPD (1 << 15) -#define URTW_TX_FLAG4_FRAGQSZ /* 16 ~ 31 bits */ -} __packed; - -struct urtw_8187l_rxhdr { - uint32_t flag; - uint8_t noise; - uint8_t rssi; -#define URTW_RX_8187L_RSSI /* 0 ~ 6 bits */ -#define URTW_RX_8187L_RSSI_MASK 0x3f -#define URTW_RX_8187L_ANTENNA (1 << 7) - uint8_t agc; - uint8_t flag2; -#define URTW_RX_8187L_DECRYPTED (1 << 0) -#define URTW_RX_8187L_WAKEUP (1 << 1) -#define URTW_RX_8187L_SHIFT (1 << 2) -#define URTW_RX_8187L_RSVD0 /* 3 ~ 7 bits */ - uint64_t mactime; -} __packed; - -struct urtw_8187l_txhdr { - uint32_t flag; - uint16_t rtsdur; - uint16_t len; - uint32_t retry; -} __packed; diff --git a/sys/bus/u4b/wlan/if_urtwvar.h b/sys/bus/u4b/wlan/if_urtwvar.h deleted file mode 100644 index e4a872147f..0000000000 --- a/sys/bus/u4b/wlan/if_urtwvar.h +++ /dev/null @@ -1,186 +0,0 @@ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2008 Weongyo Jeong - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -enum { - URTW_8187B_BULK_RX, - URTW_8187B_BULK_TX_STATUS, - URTW_8187B_BULK_TX_BE, - URTW_8187B_BULK_TX_BK, - URTW_8187B_BULK_TX_VI, - URTW_8187B_BULK_TX_VO, - URTW_8187B_BULK_TX_EP12, - URTW_8187B_N_XFERS = 7 -}; - -enum { - URTW_8187L_BULK_RX, - URTW_8187L_BULK_TX_LOW, - URTW_8187L_BULK_TX_NORMAL, - URTW_8187L_N_XFERS = 3 -}; - -/* XXX no definition at net80211? */ -#define URTW_MAX_CHANNELS 15 - -struct urtw_data { - struct urtw_softc *sc; - uint8_t *buf; - uint16_t buflen; - struct mbuf *m; - struct ieee80211_node *ni; /* NB: tx only */ - STAILQ_ENTRY(urtw_data) next; -}; -typedef STAILQ_HEAD(, urtw_data) urtw_datahead; - -/* XXX not correct.. */ -#define URTW_MIN_RXBUFSZ \ - (sizeof(struct ieee80211_frame_min)) - -#define URTW_RX_DATA_LIST_COUNT 4 -#define URTW_TX_DATA_LIST_COUNT 16 -#define URTW_RX_MAXSIZE 0x9c4 -#define URTW_TX_MAXSIZE 0x9c4 -#define URTW_TX_MAXRETRY 11 - -struct urtw_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_dbm_antsignal; -} __packed; - -#define URTW_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)) - -struct urtw_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define URTW_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct urtw_stats { - unsigned int txrates[12]; -}; - -struct urtw_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define URTW_VAP(vap) ((struct urtw_vap *)(vap)) - -struct urtw_softc { - struct ifnet *sc_ifp; - device_t sc_dev; - struct usb_device *sc_udev; - struct mtx sc_mtx; - - int sc_debug; - int sc_if_flags; - int sc_flags; -#define URTW_INIT_ONCE (1 << 1) -#define URTW_RTL8187B (1 << 2) -#define URTW_RTL8187B_REV_B (1 << 3) -#define URTW_RTL8187B_REV_D (1 << 4) -#define URTW_RTL8187B_REV_E (1 << 5) - enum ieee80211_state sc_state; - - int sc_epromtype; -#define URTW_EEPROM_93C46 0 -#define URTW_EEPROM_93C56 1 - uint8_t sc_crcmon; - uint8_t sc_bssid[IEEE80211_ADDR_LEN]; - - struct ieee80211_channel *sc_curchan; - - /* for RF */ - usb_error_t (*sc_rf_init)(struct urtw_softc *); - usb_error_t (*sc_rf_set_chan)(struct urtw_softc *, - int); - usb_error_t (*sc_rf_set_sens)(struct urtw_softc *, - int); - usb_error_t (*sc_rf_stop)(struct urtw_softc *); - uint8_t sc_rfchip; - uint32_t sc_max_sens; - uint32_t sc_sens; - /* for LED */ - struct usb_callout sc_led_ch; - struct task sc_led_task; - uint8_t sc_psr; - uint8_t sc_strategy; -#define URTW_LED_GPIO 1 - uint8_t sc_gpio_ledon; - uint8_t sc_gpio_ledinprogress; - uint8_t sc_gpio_ledstate; - uint8_t sc_gpio_ledpin; - uint8_t sc_gpio_blinktime; - uint8_t sc_gpio_blinkstate; - /* RX/TX */ - struct usb_xfer *sc_xfer[URTW_8187B_N_XFERS]; -#define URTW_PRIORITY_LOW 0 -#define URTW_PRIORITY_NORMAL 1 -#define URTW_DATA_TIMEOUT 10000 /* 10 sec */ -#define URTW_8187B_TXPIPE_BE 0x6 /* best effort */ -#define URTW_8187B_TXPIPE_BK 0x7 /* background */ -#define URTW_8187B_TXPIPE_VI 0x5 /* video */ -#define URTW_8187B_TXPIPE_VO 0x4 /* voice */ -#define URTW_8187B_TXPIPE_MAX 4 - struct urtw_data sc_rx[URTW_RX_DATA_LIST_COUNT]; - urtw_datahead sc_rx_active; - urtw_datahead sc_rx_inactive; - struct urtw_data sc_tx[URTW_TX_DATA_LIST_COUNT]; - urtw_datahead sc_tx_active; - urtw_datahead sc_tx_inactive; - urtw_datahead sc_tx_pending; - uint8_t sc_rts_retry; - uint8_t sc_tx_retry; - uint8_t sc_preamble_mode; -#define URTW_PREAMBLE_MODE_SHORT 1 -#define URTW_PREAMBLE_MODE_LONG 2 - struct callout sc_watchdog_ch; - int sc_txtimer; - int sc_currate; - /* TX power */ - uint8_t sc_txpwr_cck[URTW_MAX_CHANNELS]; - uint8_t sc_txpwr_cck_base; - uint8_t sc_txpwr_ofdm[URTW_MAX_CHANNELS]; - uint8_t sc_txpwr_ofdm_base; - - uint8_t sc_acmctl; - uint64_t sc_txstatus; /* only for 8187B */ - struct task sc_updateslot_task; - - struct urtw_stats sc_stats; - - struct urtw_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct urtw_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define URTW_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define URTW_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define URTW_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) diff --git a/sys/bus/u4b/wlan/if_zyd.c b/sys/bus/u4b/wlan/if_zyd.c deleted file mode 100644 index edf221772c..0000000000 --- a/sys/bus/u4b/wlan/if_zyd.c +++ /dev/null @@ -1,2920 +0,0 @@ -/* $OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $ */ -/* $NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2006 by Damien Bergamini - * Copyright (c) 2006 by Florian Stoehr - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * ZyDAS ZD1211/ZD1211B USB WLAN driver. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include -#include "usbdevs.h" - -#include -#include - -#ifdef USB_DEBUG -static int zyd_debug = 0; - -static SYSCTL_NODE(_hw_usb, OID_AUTO, zyd, CTLFLAG_RW, 0, "USB zyd"); -SYSCTL_INT(_hw_usb_zyd, OID_AUTO, debug, CTLFLAG_RWTUN, &zyd_debug, 0, - "zyd debug level"); - -enum { - ZYD_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ - ZYD_DEBUG_RECV = 0x00000002, /* basic recv operation */ - ZYD_DEBUG_RESET = 0x00000004, /* reset processing */ - ZYD_DEBUG_INIT = 0x00000008, /* device init */ - ZYD_DEBUG_TX_PROC = 0x00000010, /* tx ISR proc */ - ZYD_DEBUG_RX_PROC = 0x00000020, /* rx ISR proc */ - ZYD_DEBUG_STATE = 0x00000040, /* 802.11 state transitions */ - ZYD_DEBUG_STAT = 0x00000080, /* statistic */ - ZYD_DEBUG_FW = 0x00000100, /* firmware */ - ZYD_DEBUG_CMD = 0x00000200, /* fw commands */ - ZYD_DEBUG_ANY = 0xffffffff -}; -#define DPRINTF(sc, m, fmt, ...) do { \ - if (zyd_debug & (m)) \ - printf("%s: " fmt, __func__, ## __VA_ARGS__); \ -} while (0) -#else -#define DPRINTF(sc, m, fmt, ...) do { \ - (void) sc; \ -} while (0) -#endif - -#define zyd_do_request(sc,req,data) \ - usbd_do_request_flags((sc)->sc_udev, &(sc)->sc_mtx, req, data, 0, NULL, 5000) - -static device_probe_t zyd_match; -static device_attach_t zyd_attach; -static device_detach_t zyd_detach; - -static usb_callback_t zyd_intr_read_callback; -static usb_callback_t zyd_intr_write_callback; -static usb_callback_t zyd_bulk_read_callback; -static usb_callback_t zyd_bulk_write_callback; - -static struct ieee80211vap *zyd_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void zyd_vap_delete(struct ieee80211vap *); -static void zyd_tx_free(struct zyd_tx_data *, int); -static void zyd_setup_tx_list(struct zyd_softc *); -static void zyd_unsetup_tx_list(struct zyd_softc *); -static int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static int zyd_cmd(struct zyd_softc *, uint16_t, const void *, int, - void *, int, int); -static int zyd_read16(struct zyd_softc *, uint16_t, uint16_t *); -static int zyd_read32(struct zyd_softc *, uint16_t, uint32_t *); -static int zyd_write16(struct zyd_softc *, uint16_t, uint16_t); -static int zyd_write32(struct zyd_softc *, uint16_t, uint32_t); -static int zyd_rfwrite(struct zyd_softc *, uint32_t); -static int zyd_lock_phy(struct zyd_softc *); -static int zyd_unlock_phy(struct zyd_softc *); -static int zyd_rf_attach(struct zyd_softc *, uint8_t); -static const char *zyd_rf_name(uint8_t); -static int zyd_hw_init(struct zyd_softc *); -static int zyd_read_pod(struct zyd_softc *); -static int zyd_read_eeprom(struct zyd_softc *); -static int zyd_get_macaddr(struct zyd_softc *); -static int zyd_set_macaddr(struct zyd_softc *, const uint8_t *); -static int zyd_set_bssid(struct zyd_softc *, const uint8_t *); -static int zyd_switch_radio(struct zyd_softc *, int); -static int zyd_set_led(struct zyd_softc *, int, int); -static void zyd_set_multi(struct zyd_softc *); -static void zyd_update_mcast(struct ieee80211com *); -static int zyd_set_rxfilter(struct zyd_softc *); -static void zyd_set_chan(struct zyd_softc *, struct ieee80211_channel *); -static int zyd_set_beacon_interval(struct zyd_softc *, int); -static void zyd_rx_data(struct usb_xfer *, int, uint16_t); -static int zyd_tx_start(struct zyd_softc *, struct mbuf *, - struct ieee80211_node *); -static void zyd_start(struct ifnet *); -static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static int zyd_ioctl(struct ifnet *, u_long, caddr_t); -static void zyd_init_locked(struct zyd_softc *); -static void zyd_init(void *); -static void zyd_stop(struct zyd_softc *); -static int zyd_loadfirmware(struct zyd_softc *); -static void zyd_scan_start(struct ieee80211com *); -static void zyd_scan_end(struct ieee80211com *); -static void zyd_set_channel(struct ieee80211com *); -static int zyd_rfmd_init(struct zyd_rf *); -static int zyd_rfmd_switch_radio(struct zyd_rf *, int); -static int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t); -static int zyd_al2230_init(struct zyd_rf *); -static int zyd_al2230_switch_radio(struct zyd_rf *, int); -static int zyd_al2230_set_channel(struct zyd_rf *, uint8_t); -static int zyd_al2230_set_channel_b(struct zyd_rf *, uint8_t); -static int zyd_al2230_init_b(struct zyd_rf *); -static int zyd_al7230B_init(struct zyd_rf *); -static int zyd_al7230B_switch_radio(struct zyd_rf *, int); -static int zyd_al7230B_set_channel(struct zyd_rf *, uint8_t); -static int zyd_al2210_init(struct zyd_rf *); -static int zyd_al2210_switch_radio(struct zyd_rf *, int); -static int zyd_al2210_set_channel(struct zyd_rf *, uint8_t); -static int zyd_gct_init(struct zyd_rf *); -static int zyd_gct_switch_radio(struct zyd_rf *, int); -static int zyd_gct_set_channel(struct zyd_rf *, uint8_t); -static int zyd_gct_mode(struct zyd_rf *); -static int zyd_gct_set_channel_synth(struct zyd_rf *, int, int); -static int zyd_gct_write(struct zyd_rf *, uint16_t); -static int zyd_gct_txgain(struct zyd_rf *, uint8_t); -static int zyd_maxim2_init(struct zyd_rf *); -static int zyd_maxim2_switch_radio(struct zyd_rf *, int); -static int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t); - -static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY; -static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB; - -/* various supported device vendors/products */ -#define ZYD_ZD1211 0 -#define ZYD_ZD1211B 1 - -#define ZYD_ZD1211_DEV(v,p) \ - { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, ZYD_ZD1211) } -#define ZYD_ZD1211B_DEV(v,p) \ - { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, ZYD_ZD1211B) } -static const STRUCT_USB_HOST_ID zyd_devs[] = { - /* ZYD_ZD1211 */ - ZYD_ZD1211_DEV(3COM2, 3CRUSB10075), - ZYD_ZD1211_DEV(ABOCOM, WL54), - ZYD_ZD1211_DEV(ASUS, WL159G), - ZYD_ZD1211_DEV(CYBERTAN, TG54USB), - ZYD_ZD1211_DEV(DRAYTEK, VIGOR550), - ZYD_ZD1211_DEV(PLANEX2, GWUS54GD), - ZYD_ZD1211_DEV(PLANEX2, GWUS54GZL), - ZYD_ZD1211_DEV(PLANEX3, GWUS54GZ), - ZYD_ZD1211_DEV(PLANEX3, GWUS54MINI), - ZYD_ZD1211_DEV(SAGEM, XG760A), - ZYD_ZD1211_DEV(SENAO, NUB8301), - ZYD_ZD1211_DEV(SITECOMEU, WL113), - ZYD_ZD1211_DEV(SWEEX, ZD1211), - ZYD_ZD1211_DEV(TEKRAM, QUICKWLAN), - ZYD_ZD1211_DEV(TEKRAM, ZD1211_1), - ZYD_ZD1211_DEV(TEKRAM, ZD1211_2), - ZYD_ZD1211_DEV(TWINMOS, G240), - ZYD_ZD1211_DEV(UMEDIA, ALL0298V2), - ZYD_ZD1211_DEV(UMEDIA, TEW429UB_A), - ZYD_ZD1211_DEV(UMEDIA, TEW429UB), - ZYD_ZD1211_DEV(WISTRONNEWEB, UR055G), - ZYD_ZD1211_DEV(ZCOM, ZD1211), - ZYD_ZD1211_DEV(ZYDAS, ZD1211), - ZYD_ZD1211_DEV(ZYXEL, AG225H), - ZYD_ZD1211_DEV(ZYXEL, ZYAIRG220), - ZYD_ZD1211_DEV(ZYXEL, G200V2), - /* ZYD_ZD1211B */ - ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG_NF), - ZYD_ZD1211B_DEV(ACCTON, SMCWUSBG), - ZYD_ZD1211B_DEV(ACCTON, ZD1211B), - ZYD_ZD1211B_DEV(ASUS, A9T_WIFI), - ZYD_ZD1211B_DEV(BELKIN, F5D7050_V4000), - ZYD_ZD1211B_DEV(BELKIN, ZD1211B), - ZYD_ZD1211B_DEV(CISCOLINKSYS, WUSBF54G), - ZYD_ZD1211B_DEV(FIBERLINE, WL430U), - ZYD_ZD1211B_DEV(MELCO, KG54L), - ZYD_ZD1211B_DEV(PHILIPS, SNU5600), - ZYD_ZD1211B_DEV(PLANEX2, GW_US54GXS), - ZYD_ZD1211B_DEV(SAGEM, XG76NA), - ZYD_ZD1211B_DEV(SITECOMEU, ZD1211B), - ZYD_ZD1211B_DEV(UMEDIA, TEW429UBC1), - ZYD_ZD1211B_DEV(USR, USR5423), - ZYD_ZD1211B_DEV(VTECH, ZD1211B), - ZYD_ZD1211B_DEV(ZCOM, ZD1211B), - ZYD_ZD1211B_DEV(ZYDAS, ZD1211B), - ZYD_ZD1211B_DEV(ZYXEL, M202), - ZYD_ZD1211B_DEV(ZYXEL, G202), - ZYD_ZD1211B_DEV(ZYXEL, G220V2) -}; - -static const struct usb_config zyd_config[ZYD_N_TRANSFER] = { - [ZYD_BULK_WR] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = ZYD_MAX_TXBUFSZ, - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = zyd_bulk_write_callback, - .ep_index = 0, - .timeout = 10000, /* 10 seconds */ - }, - [ZYD_BULK_RD] = { - .type = UE_BULK, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = ZYX_MAX_RXBUFSZ, - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = zyd_bulk_read_callback, - .ep_index = 0, - }, - [ZYD_INTR_WR] = { - .type = UE_BULK_INTR, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_OUT, - .bufsize = sizeof(struct zyd_cmd), - .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, - .callback = zyd_intr_write_callback, - .timeout = 1000, /* 1 second */ - .ep_index = 1, - }, - [ZYD_INTR_RD] = { - .type = UE_INTERRUPT, - .endpoint = UE_ADDR_ANY, - .direction = UE_DIR_IN, - .bufsize = sizeof(struct zyd_cmd), - .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, - .callback = zyd_intr_read_callback, - }, -}; -#define zyd_read16_m(sc, val, data) do { \ - error = zyd_read16(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define zyd_write16_m(sc, val, data) do { \ - error = zyd_write16(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define zyd_read32_m(sc, val, data) do { \ - error = zyd_read32(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) -#define zyd_write32_m(sc, val, data) do { \ - error = zyd_write32(sc, val, data); \ - if (error != 0) \ - goto fail; \ -} while (0) - -static int -zyd_match(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - - if (uaa->usb_mode != USB_MODE_HOST) - return (ENXIO); - if (uaa->info.bConfigIndex != ZYD_CONFIG_INDEX) - return (ENXIO); - if (uaa->info.bIfaceIndex != ZYD_IFACE_INDEX) - return (ENXIO); - - return (usbd_lookup_id_by_uaa(zyd_devs, sizeof(zyd_devs), uaa)); -} - -static int -zyd_attach(device_t dev) -{ - struct usb_attach_arg *uaa = device_get_ivars(dev); - struct zyd_softc *sc = device_get_softc(dev); - struct ifnet *ifp; - struct ieee80211com *ic; - uint8_t iface_index, bands; - int error; - - if (uaa->info.bcdDevice < 0x4330) { - device_printf(dev, "device version mismatch: 0x%X " - "(only >= 43.30 supported)\n", - uaa->info.bcdDevice); - return (EINVAL); - } - - device_set_usb_desc(dev); - sc->sc_dev = dev; - sc->sc_udev = uaa->device; - sc->sc_macrev = USB_GET_DRIVER_INFO(uaa); - - mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), - MTX_NETWORK_LOCK, MTX_DEF); - STAILQ_INIT(&sc->sc_rqh); - - iface_index = ZYD_IFACE_INDEX; - error = usbd_transfer_setup(uaa->device, - &iface_index, sc->sc_xfer, zyd_config, - ZYD_N_TRANSFER, sc, &sc->sc_mtx); - if (error) { - device_printf(dev, "could not allocate USB transfers, " - "err=%s\n", usbd_errstr(error)); - goto detach; - } - - ZYD_LOCK(sc); - if ((error = zyd_get_macaddr(sc)) != 0) { - device_printf(sc->sc_dev, "could not read EEPROM\n"); - ZYD_UNLOCK(sc); - goto detach; - } - ZYD_UNLOCK(sc); - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - goto detach; - } - ifp->if_softc = sc; - if_initname(ifp, "zyd", device_get_unit(sc->sc_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = zyd_init; - ifp->if_ioctl = zyd_ioctl; - ifp->if_start = zyd_start; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - IFQ_SET_READY(&ifp->if_snd); - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; - ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(dev); - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; - - /* set device capabilities */ - ic->ic_caps = - IEEE80211_C_STA /* station mode */ - | IEEE80211_C_MONITOR /* monitor mode */ - | IEEE80211_C_SHPREAMBLE /* short preamble supported */ - | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_BGSCAN /* capable of bg scanning */ - | IEEE80211_C_WPA /* 802.11i */ - ; - - bands = 0; - setbit(&bands, IEEE80211_MODE_11B); - setbit(&bands, IEEE80211_MODE_11G); - ieee80211_init_channels(ic, NULL, &bands); - - ieee80211_ifattach(ic, sc->sc_bssid); - ic->ic_raw_xmit = zyd_raw_xmit; - ic->ic_scan_start = zyd_scan_start; - ic->ic_scan_end = zyd_scan_end; - ic->ic_set_channel = zyd_set_channel; - ic->ic_vap_create = zyd_vap_create; - ic->ic_vap_delete = zyd_vap_delete; - ic->ic_update_mcast = zyd_update_mcast; - ic->ic_update_promisc = zyd_update_mcast; - - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - ZYD_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - ZYD_RX_RADIOTAP_PRESENT); - - if (bootverbose) - ieee80211_announce(ic); - - return (0); - -detach: - zyd_detach(dev); - return (ENXIO); /* failure */ -} - -static int -zyd_detach(device_t dev) -{ - struct zyd_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; - - /* stop all USB transfers */ - usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); - - /* free TX list, if any */ - zyd_unsetup_tx_list(sc); - - if (ifp) { - ic = ifp->if_l2com; - ieee80211_ifdetach(ic); - if_free(ifp); - } - mtx_destroy(&sc->sc_mtx); - - return (0); -} - -static struct ieee80211vap * -zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, - enum ieee80211_opmode opmode, int flags, - const uint8_t bssid[IEEE80211_ADDR_LEN], - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct zyd_vap *zvp; - struct ieee80211vap *vap; - - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ - return (NULL); - zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap), - M_80211_VAP, M_WAITOK | M_ZERO); - if (zvp == NULL) - return (NULL); - vap = &zvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); - - /* override state transition machine */ - zvp->newstate = vap->iv_newstate; - vap->iv_newstate = zyd_newstate; - - ieee80211_ratectl_init(vap); - ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); - - /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); - ic->ic_opmode = opmode; - return (vap); -} - -static void -zyd_vap_delete(struct ieee80211vap *vap) -{ - struct zyd_vap *zvp = ZYD_VAP(vap); - - ieee80211_ratectl_deinit(vap); - ieee80211_vap_detach(vap); - free(zvp, M_80211_VAP); -} - -static void -zyd_tx_free(struct zyd_tx_data *data, int txerr) -{ - struct zyd_softc *sc = data->sc; - - if (data->m != NULL) { - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, - txerr ? ETIMEDOUT : 0); - m_freem(data->m); - data->m = NULL; - - ieee80211_free_node(data->ni); - data->ni = NULL; - } - STAILQ_INSERT_TAIL(&sc->tx_free, data, next); - sc->tx_nfree++; -} - -static void -zyd_setup_tx_list(struct zyd_softc *sc) -{ - struct zyd_tx_data *data; - int i; - - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); - - for (i = 0; i < ZYD_TX_LIST_CNT; i++) { - data = &sc->tx_data[i]; - - data->sc = sc; - STAILQ_INSERT_TAIL(&sc->tx_free, data, next); - sc->tx_nfree++; - } -} - -static void -zyd_unsetup_tx_list(struct zyd_softc *sc) -{ - struct zyd_tx_data *data; - int i; - - /* make sure any subsequent use of the queues will fail */ - sc->tx_nfree = 0; - STAILQ_INIT(&sc->tx_q); - STAILQ_INIT(&sc->tx_free); - - /* free up all node references and mbufs */ - for (i = 0; i < ZYD_TX_LIST_CNT; i++) { - data = &sc->tx_data[i]; - - if (data->m != NULL) { - m_freem(data->m); - data->m = NULL; - } - if (data->ni != NULL) { - ieee80211_free_node(data->ni); - data->ni = NULL; - } - } -} - -static int -zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) -{ - struct zyd_vap *zvp = ZYD_VAP(vap); - struct ieee80211com *ic = vap->iv_ic; - struct zyd_softc *sc = ic->ic_ifp->if_softc; - int error; - - DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[vap->iv_state], - ieee80211_state_name[nstate]); - - IEEE80211_UNLOCK(ic); - ZYD_LOCK(sc); - switch (nstate) { - case IEEE80211_S_AUTH: - zyd_set_chan(sc, ic->ic_curchan); - break; - case IEEE80211_S_RUN: - if (vap->iv_opmode == IEEE80211_M_MONITOR) - break; - - /* turn link LED on */ - error = zyd_set_led(sc, ZYD_LED1, 1); - if (error != 0) - break; - - /* make data LED blink upon Tx */ - zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1); - - IEEE80211_ADDR_COPY(sc->sc_bssid, vap->iv_bss->ni_bssid); - zyd_set_bssid(sc, sc->sc_bssid); - break; - default: - break; - } -fail: - ZYD_UNLOCK(sc); - IEEE80211_LOCK(ic); - return (zvp->newstate(vap, nstate, arg)); -} - -/* - * Callback handler for interrupt transfer - */ -static void -zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni; - struct zyd_cmd *cmd = &sc->sc_ibuf; - struct usb_page_cache *pc; - int datalen; - int actlen; - char hexstr[HEX_NCPYLEN(64)]; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, 0, cmd, sizeof(*cmd)); - - switch (le16toh(cmd->code)) { - case ZYD_NOTIF_RETRYSTATUS: - { - struct zyd_notif_retry *retry = - (struct zyd_notif_retry *)cmd->data; - - DPRINTF(sc, ZYD_DEBUG_TX_PROC, - "retry intr: rate=0x%x addr=%s count=%d (0x%x)\n", - le16toh(retry->rate), ether_sprintf(retry->macaddr), - le16toh(retry->count)&0xff, le16toh(retry->count)); - - /* - * Find the node to which the packet was sent and - * update its retry statistics. In BSS mode, this node - * is the AP we're associated to so no lookup is - * actually needed. - */ - ni = ieee80211_find_txnode(vap, retry->macaddr); - if (ni != NULL) { - int retrycnt = - (int)(le16toh(retry->count) & 0xff); - - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, NULL); - ieee80211_free_node(ni); - } - if (le16toh(retry->count) & 0x100) - ifp->if_oerrors++; /* too many retries */ - break; - } - case ZYD_NOTIF_IORD: - { - struct zyd_rq *rqp; - - if (le16toh(*(uint16_t *)cmd->data) == ZYD_CR_INTERRUPT) - break; /* HMAC interrupt */ - - datalen = actlen - sizeof(cmd->code); - datalen -= 2; /* XXX: padding? */ - - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { - int i, cnt; - - if (rqp->olen != datalen) - continue; - cnt = rqp->olen / sizeof(struct zyd_pair); - for (i = 0; i < cnt; i++) { - if (*(((const uint16_t *)rqp->idata) + i) != - (((struct zyd_pair *)cmd->data) + i)->reg) - break; - } - if (i != cnt) - continue; - /* copy answer into caller-supplied buffer */ - memcpy(rqp->odata, cmd->data, rqp->olen); - DPRINTF(sc, ZYD_DEBUG_CMD, - "command %p complete, data = %s \n", - rqp, hexncpy(rqp->odata, rqp->olen, hexstr, - HEX_NCPYLEN(rqp->olen), ":")); - wakeup(rqp); /* wakeup caller */ - break; - } - if (rqp == NULL) { - device_printf(sc->sc_dev, - "unexpected IORD notification %s\n", - hexncpy(cmd->data, datalen, hexstr, - HEX_NCPYLEN(datalen), ":")); - } - break; - } - default: - device_printf(sc->sc_dev, "unknown notification %x\n", - le16toh(cmd->code)); - } - - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - break; - - default: /* Error */ - DPRINTF(sc, ZYD_DEBUG_CMD, "error = %s\n", - usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static void -zyd_intr_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct zyd_rq *rqp, *cmd; - struct usb_page_cache *pc; - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - cmd = usbd_xfer_get_priv(xfer); - DPRINTF(sc, ZYD_DEBUG_CMD, "command %p transferred\n", cmd); - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { - /* Ensure the cached rq pointer is still valid */ - if (rqp == cmd && - (rqp->flags & ZYD_CMD_FLAG_READ) == 0) - wakeup(rqp); /* wakeup caller */ - } - - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - STAILQ_FOREACH(rqp, &sc->sc_rqh, rq) { - if (rqp->flags & ZYD_CMD_FLAG_SENT) - continue; - - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, rqp->cmd, rqp->ilen); - - usbd_xfer_set_frame_len(xfer, 0, rqp->ilen); - usbd_xfer_set_priv(xfer, rqp); - rqp->flags |= ZYD_CMD_FLAG_SENT; - usbd_transfer_submit(xfer); - break; - } - break; - - default: /* Error */ - DPRINTF(sc, ZYD_DEBUG_ANY, "error = %s\n", - usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static int -zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen, - void *odata, int olen, int flags) -{ - struct zyd_cmd cmd; - struct zyd_rq rq; - int error; -#ifdef USB_DEBUG - char hexstr[HEX_NCPYLEN(64)]; -#endif - - if (ilen > sizeof(cmd.data)) - return (EINVAL); - - cmd.code = htole16(code); - memcpy(cmd.data, idata, ilen); - DPRINTF(sc, ZYD_DEBUG_CMD, "sending cmd %p = %s\n", &rq, - hexncpy(idata, ilen, hexstr, HEX_NCPYLEN(ilen), ":")); - - rq.cmd = &cmd; - rq.idata = idata; - rq.odata = odata; - rq.ilen = sizeof(uint16_t) + ilen; - rq.olen = olen; - rq.flags = flags; - STAILQ_INSERT_TAIL(&sc->sc_rqh, &rq, rq); - usbd_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); - usbd_transfer_start(sc->sc_xfer[ZYD_INTR_WR]); - - /* wait at most one second for command reply */ - error = mtx_sleep(&rq, &sc->sc_mtx, 0 , "zydcmd", hz); - if (error) - device_printf(sc->sc_dev, "command timeout\n"); - STAILQ_REMOVE(&sc->sc_rqh, &rq, zyd_rq, rq); - DPRINTF(sc, ZYD_DEBUG_CMD, "finsihed cmd %p, error = %d \n", - &rq, error); - - return (error); -} - -static int -zyd_read16(struct zyd_softc *sc, uint16_t reg, uint16_t *val) -{ - struct zyd_pair tmp; - int error; - - reg = htole16(reg); - error = zyd_cmd(sc, ZYD_CMD_IORD, ®, sizeof(reg), &tmp, sizeof(tmp), - ZYD_CMD_FLAG_READ); - if (error == 0) - *val = le16toh(tmp.val); - return (error); -} - -static int -zyd_read32(struct zyd_softc *sc, uint16_t reg, uint32_t *val) -{ - struct zyd_pair tmp[2]; - uint16_t regs[2]; - int error; - - regs[0] = htole16(ZYD_REG32_HI(reg)); - regs[1] = htole16(ZYD_REG32_LO(reg)); - error = zyd_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), tmp, sizeof(tmp), - ZYD_CMD_FLAG_READ); - if (error == 0) - *val = le16toh(tmp[0].val) << 16 | le16toh(tmp[1].val); - return (error); -} - -static int -zyd_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val) -{ - struct zyd_pair pair; - - pair.reg = htole16(reg); - pair.val = htole16(val); - - return zyd_cmd(sc, ZYD_CMD_IOWR, &pair, sizeof(pair), NULL, 0, 0); -} - -static int -zyd_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val) -{ - struct zyd_pair pair[2]; - - pair[0].reg = htole16(ZYD_REG32_HI(reg)); - pair[0].val = htole16(val >> 16); - pair[1].reg = htole16(ZYD_REG32_LO(reg)); - pair[1].val = htole16(val & 0xffff); - - return zyd_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0); -} - -static int -zyd_rfwrite(struct zyd_softc *sc, uint32_t val) -{ - struct zyd_rf *rf = &sc->sc_rf; - struct zyd_rfwrite_cmd req; - uint16_t cr203; - int error, i; - - zyd_read16_m(sc, ZYD_CR203, &cr203); - cr203 &= ~(ZYD_RF_IF_LE | ZYD_RF_CLK | ZYD_RF_DATA); - - req.code = htole16(2); - req.width = htole16(rf->width); - for (i = 0; i < rf->width; i++) { - req.bit[i] = htole16(cr203); - if (val & (1 << (rf->width - 1 - i))) - req.bit[i] |= htole16(ZYD_RF_DATA); - } - error = zyd_cmd(sc, ZYD_CMD_RFCFG, &req, 4 + 2 * rf->width, NULL, 0, 0); -fail: - return (error); -} - -static int -zyd_rfwrite_cr(struct zyd_softc *sc, uint32_t val) -{ - int error; - - zyd_write16_m(sc, ZYD_CR244, (val >> 16) & 0xff); - zyd_write16_m(sc, ZYD_CR243, (val >> 8) & 0xff); - zyd_write16_m(sc, ZYD_CR242, (val >> 0) & 0xff); -fail: - return (error); -} - -static int -zyd_lock_phy(struct zyd_softc *sc) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); - tmp &= ~ZYD_UNLOCK_PHY_REGS; - zyd_write32_m(sc, ZYD_MAC_MISC, tmp); -fail: - return (error); -} - -static int -zyd_unlock_phy(struct zyd_softc *sc) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_MAC_MISC, &tmp); - tmp |= ZYD_UNLOCK_PHY_REGS; - zyd_write32_m(sc, ZYD_MAC_MISC, tmp); -fail: - return (error); -} - -/* - * RFMD RF methods. - */ -static int -zyd_rfmd_init(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_RFMD_PHY; - static const uint32_t rfini[] = ZYD_RFMD_RF; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) { - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - } - - /* init RFMD radio */ - for (i = 0; i < nitems(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } -fail: - return (error); -} - -static int -zyd_rfmd_switch_radio(struct zyd_rf *rf, int on) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - - zyd_write16_m(sc, ZYD_CR10, on ? 0x89 : 0x15); - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x81); -fail: - return (error); -} - -static int -zyd_rfmd_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_RFMD_CHANTABLE; - - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - -fail: - return (error); -} - -/* - * AL2230 RF methods. - */ -static int -zyd_al2230_init(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY; - static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; - static const struct zyd_phy_pair phypll[] = { - { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x3f }, - { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 } - }; - static const uint32_t rfini1[] = ZYD_AL2230_RF_PART1; - static const uint32_t rfini2[] = ZYD_AL2230_RF_PART2; - static const uint32_t rfini3[] = ZYD_AL2230_RF_PART3; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { - for (i = 0; i < nitems(phy2230s); i++) - zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); - } - - /* init AL2230 radio */ - for (i = 0; i < nitems(rfini1); i++) { - error = zyd_rfwrite(sc, rfini1[i]); - if (error != 0) - goto fail; - } - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) - error = zyd_rfwrite(sc, 0x000824); - else - error = zyd_rfwrite(sc, 0x0005a4); - if (error != 0) - goto fail; - - for (i = 0; i < nitems(rfini2); i++) { - error = zyd_rfwrite(sc, rfini2[i]); - if (error != 0) - goto fail; - } - - for (i = 0; i < nitems(phypll); i++) - zyd_write16_m(sc, phypll[i].reg, phypll[i].val); - - for (i = 0; i < nitems(rfini3); i++) { - error = zyd_rfwrite(sc, rfini3[i]); - if (error != 0) - goto fail; - } -fail: - return (error); -} - -static int -zyd_al2230_fini(struct zyd_rf *rf) -{ - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy[] = ZYD_AL2230_PHY_FINI_PART1; - - for (i = 0; i < nitems(phy); i++) - zyd_write16_m(sc, phy[i].reg, phy[i].val); - - if (sc->sc_newphy != 0) - zyd_write16_m(sc, ZYD_CR9, 0xe1); - - zyd_write16_m(sc, ZYD_CR203, 0x6); -fail: - return (error); -} - -static int -zyd_al2230_init_b(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; - static const struct zyd_phy_pair phy2[] = ZYD_AL2230_PHY_PART2; - static const struct zyd_phy_pair phy3[] = ZYD_AL2230_PHY_PART3; - static const struct zyd_phy_pair phy2230s[] = ZYD_AL2230S_PHY_INIT; - static const struct zyd_phy_pair phyini[] = ZYD_AL2230_PHY_B; - static const uint32_t rfini_part1[] = ZYD_AL2230_RF_B_PART1; - static const uint32_t rfini_part2[] = ZYD_AL2230_RF_B_PART2; - static const uint32_t rfini_part3[] = ZYD_AL2230_RF_B_PART3; - static const uint32_t zyd_al2230_chtable[][3] = ZYD_AL2230_CHANTABLE; - int i, error; - - for (i = 0; i < nitems(phy1); i++) - zyd_write16_m(sc, phy1[i].reg, phy1[i].val); - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) { - for (i = 0; i < nitems(phy2230s); i++) - zyd_write16_m(sc, phy2230s[i].reg, phy2230s[i].val); - } - - for (i = 0; i < 3; i++) { - error = zyd_rfwrite_cr(sc, zyd_al2230_chtable[0][i]); - if (error != 0) - return (error); - } - - for (i = 0; i < nitems(rfini_part1); i++) { - error = zyd_rfwrite_cr(sc, rfini_part1[i]); - if (error != 0) - return (error); - } - - if (sc->sc_rfrev == ZYD_RF_AL2230S || sc->sc_al2230s != 0) - error = zyd_rfwrite(sc, 0x241000); - else - error = zyd_rfwrite(sc, 0x25a000); - if (error != 0) - goto fail; - - for (i = 0; i < nitems(rfini_part2); i++) { - error = zyd_rfwrite_cr(sc, rfini_part2[i]); - if (error != 0) - return (error); - } - - for (i = 0; i < nitems(phy2); i++) - zyd_write16_m(sc, phy2[i].reg, phy2[i].val); - - for (i = 0; i < nitems(rfini_part3); i++) { - error = zyd_rfwrite_cr(sc, rfini_part3[i]); - if (error != 0) - return (error); - } - - for (i = 0; i < nitems(phy3); i++) - zyd_write16_m(sc, phy3[i].reg, phy3[i].val); - - error = zyd_al2230_fini(rf); -fail: - return (error); -} - -static int -zyd_al2230_switch_radio(struct zyd_rf *rf, int on) -{ - struct zyd_softc *sc = rf->rf_sc; - int error, on251 = (sc->sc_macrev == ZYD_ZD1211) ? 0x3f : 0x7f; - - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); - zyd_write16_m(sc, ZYD_CR251, on ? on251 : 0x2f); -fail: - return (error); -} - -static int -zyd_al2230_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy1[] = { - { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 }, - }; - static const struct { - uint32_t r1, r2, r3; - } rfprog[] = ZYD_AL2230_CHANTABLE; - - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r3); - if (error != 0) - goto fail; - - for (i = 0; i < nitems(phy1); i++) - zyd_write16_m(sc, phy1[i].reg, phy1[i].val); -fail: - return (error); -} - -static int -zyd_al2230_set_channel_b(struct zyd_rf *rf, uint8_t chan) -{ - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phy1[] = ZYD_AL2230_PHY_PART1; - static const struct { - uint32_t r1, r2, r3; - } rfprog[] = ZYD_AL2230_CHANTABLE_B; - - for (i = 0; i < nitems(phy1); i++) - zyd_write16_m(sc, phy1[i].reg, phy1[i].val); - - error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - error = zyd_rfwrite_cr(sc, rfprog[chan - 1].r3); - if (error != 0) - goto fail; - error = zyd_al2230_fini(rf); -fail: - return (error); -} - -#define ZYD_AL2230_PHY_BANDEDGE6 \ -{ \ - { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \ - { ZYD_CR47, 0x1e } \ -} - -static int -zyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c) -{ - int error = 0, i; - struct zyd_softc *sc = rf->rf_sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6; - int chan = ieee80211_chan2ieee(ic, c); - - if (chan == 1 || chan == 11) - r[0].val = 0x12; - - for (i = 0; i < nitems(r); i++) - zyd_write16_m(sc, r[i].reg, r[i].val); -fail: - return (error); -} - -/* - * AL7230B RF methods. - */ -static int -zyd_al7230B_init(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini_1[] = ZYD_AL7230B_PHY_1; - static const struct zyd_phy_pair phyini_2[] = ZYD_AL7230B_PHY_2; - static const struct zyd_phy_pair phyini_3[] = ZYD_AL7230B_PHY_3; - static const uint32_t rfini_1[] = ZYD_AL7230B_RF_1; - static const uint32_t rfini_2[] = ZYD_AL7230B_RF_2; - int i, error; - - /* for AL7230B, PHY and RF need to be initialized in "phases" */ - - /* init RF-dependent PHY registers, part one */ - for (i = 0; i < nitems(phyini_1); i++) - zyd_write16_m(sc, phyini_1[i].reg, phyini_1[i].val); - - /* init AL7230B radio, part one */ - for (i = 0; i < nitems(rfini_1); i++) { - if ((error = zyd_rfwrite(sc, rfini_1[i])) != 0) - return (error); - } - /* init RF-dependent PHY registers, part two */ - for (i = 0; i < nitems(phyini_2); i++) - zyd_write16_m(sc, phyini_2[i].reg, phyini_2[i].val); - - /* init AL7230B radio, part two */ - for (i = 0; i < nitems(rfini_2); i++) { - if ((error = zyd_rfwrite(sc, rfini_2[i])) != 0) - return (error); - } - /* init RF-dependent PHY registers, part three */ - for (i = 0; i < nitems(phyini_3); i++) - zyd_write16_m(sc, phyini_3[i].reg, phyini_3[i].val); -fail: - return (error); -} - -static int -zyd_al7230B_switch_radio(struct zyd_rf *rf, int on) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); - zyd_write16_m(sc, ZYD_CR251, on ? 0x3f : 0x2f); -fail: - return (error); -} - -static int -zyd_al7230B_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_AL7230B_CHANTABLE; - static const uint32_t rfsc[] = ZYD_AL7230B_RF_SETCHANNEL; - int i, error; - - zyd_write16_m(sc, ZYD_CR240, 0x57); - zyd_write16_m(sc, ZYD_CR251, 0x2f); - - for (i = 0; i < nitems(rfsc); i++) { - if ((error = zyd_rfwrite(sc, rfsc[i])) != 0) - return (error); - } - - zyd_write16_m(sc, ZYD_CR128, 0x14); - zyd_write16_m(sc, ZYD_CR129, 0x12); - zyd_write16_m(sc, ZYD_CR130, 0x10); - zyd_write16_m(sc, ZYD_CR38, 0x38); - zyd_write16_m(sc, ZYD_CR136, 0xdf); - - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, 0x3c9000); - if (error != 0) - goto fail; - - zyd_write16_m(sc, ZYD_CR251, 0x3f); - zyd_write16_m(sc, ZYD_CR203, 0x06); - zyd_write16_m(sc, ZYD_CR240, 0x08); -fail: - return (error); -} - -/* - * AL2210 RF methods. - */ -static int -zyd_al2210_init(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_AL2210_PHY; - static const uint32_t rfini[] = ZYD_AL2210_RF; - uint32_t tmp; - int i, error; - - zyd_write32_m(sc, ZYD_CR18, 2); - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - /* init AL2210 radio */ - for (i = 0; i < nitems(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_write16_m(sc, ZYD_CR47, 0x1e); - zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); - zyd_write16_m(sc, ZYD_CR47, 0x1e); - zyd_write32_m(sc, ZYD_CR18, 3); -fail: - return (error); -} - -static int -zyd_al2210_switch_radio(struct zyd_rf *rf, int on) -{ - /* vendor driver does nothing for this RF chip */ - - return (0); -} - -static int -zyd_al2210_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - static const uint32_t rfprog[] = ZYD_AL2210_CHANTABLE; - uint32_t tmp; - - zyd_write32_m(sc, ZYD_CR18, 2); - zyd_write16_m(sc, ZYD_CR47, 0x1e); - zyd_read32_m(sc, ZYD_CR_RADIO_PD, &tmp); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp & ~1); - zyd_write32_m(sc, ZYD_CR_RADIO_PD, tmp | 1); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x05); - zyd_write32_m(sc, ZYD_CR_RFCFG, 0x00); - zyd_write16_m(sc, ZYD_CR47, 0x1e); - - /* actually set the channel */ - error = zyd_rfwrite(sc, rfprog[chan - 1]); - if (error != 0) - goto fail; - - zyd_write32_m(sc, ZYD_CR18, 3); -fail: - return (error); -} - -/* - * GCT RF methods. - */ -static int -zyd_gct_init(struct zyd_rf *rf) -{ -#define ZYD_GCT_INTR_REG 0x85c1 - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_GCT_PHY; - static const uint32_t rfini[] = ZYD_GCT_RF; - static const uint16_t vco[11][7] = ZYD_GCT_VCO; - int i, idx = -1, error; - uint16_t data; - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - /* init cgt radio */ - for (i = 0; i < nitems(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - - error = zyd_gct_mode(rf); - if (error != 0) - return (error); - - for (i = 0; i < nitems(vco) - 1; i++) { - error = zyd_gct_set_channel_synth(rf, 1, 0); - if (error != 0) - goto fail; - error = zyd_gct_write(rf, vco[i][0]); - if (error != 0) - goto fail; - zyd_write16_m(sc, ZYD_GCT_INTR_REG, 0xf); - zyd_read16_m(sc, ZYD_GCT_INTR_REG, &data); - if ((data & 0xf) == 0) { - idx = i; - break; - } - } - if (idx == -1) { - error = zyd_gct_set_channel_synth(rf, 1, 1); - if (error != 0) - goto fail; - error = zyd_gct_write(rf, 0x6662); - if (error != 0) - goto fail; - } - - rf->idx = idx; - zyd_write16_m(sc, ZYD_CR203, 0x6); -fail: - return (error); -#undef ZYD_GCT_INTR_REG -} - -static int -zyd_gct_mode(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const uint32_t mode[] = { - 0x25f98, 0x25f9a, 0x25f94, 0x27fd4 - }; - int i, error; - - for (i = 0; i < nitems(mode); i++) { - if ((error = zyd_rfwrite(sc, mode[i])) != 0) - break; - } - return (error); -} - -static int -zyd_gct_set_channel_synth(struct zyd_rf *rf, int chan, int acal) -{ - int error, idx = chan - 1; - struct zyd_softc *sc = rf->rf_sc; - static uint32_t acal_synth[] = ZYD_GCT_CHANNEL_ACAL; - static uint32_t std_synth[] = ZYD_GCT_CHANNEL_STD; - static uint32_t div_synth[] = ZYD_GCT_CHANNEL_DIV; - - error = zyd_rfwrite(sc, - (acal == 1) ? acal_synth[idx] : std_synth[idx]); - if (error != 0) - return (error); - return zyd_rfwrite(sc, div_synth[idx]); -} - -static int -zyd_gct_write(struct zyd_rf *rf, uint16_t value) -{ - struct zyd_softc *sc = rf->rf_sc; - - return zyd_rfwrite(sc, 0x300000 | 0x40000 | value); -} - -static int -zyd_gct_switch_radio(struct zyd_rf *rf, int on) -{ - int error; - struct zyd_softc *sc = rf->rf_sc; - - error = zyd_rfwrite(sc, on ? 0x25f94 : 0x25f90); - if (error != 0) - return (error); - - zyd_write16_m(sc, ZYD_CR11, on ? 0x00 : 0x04); - zyd_write16_m(sc, ZYD_CR251, - on ? ((sc->sc_macrev == ZYD_ZD1211B) ? 0x7f : 0x3f) : 0x2f); -fail: - return (error); -} - -static int -zyd_gct_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - int error, i; - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair cmd[] = { - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR79, 0x58 }, - { ZYD_CR12, 0xf0 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x58 }, - }; - static const uint16_t vco[11][7] = ZYD_GCT_VCO; - - error = zyd_gct_set_channel_synth(rf, chan, 0); - if (error != 0) - goto fail; - error = zyd_gct_write(rf, (rf->idx == -1) ? 0x6662 : - vco[rf->idx][((chan - 1) / 2)]); - if (error != 0) - goto fail; - error = zyd_gct_mode(rf); - if (error != 0) - return (error); - for (i = 0; i < nitems(cmd); i++) - zyd_write16_m(sc, cmd[i].reg, cmd[i].val); - error = zyd_gct_txgain(rf, chan); - if (error != 0) - return (error); - zyd_write16_m(sc, ZYD_CR203, 0x6); -fail: - return (error); -} - -static int -zyd_gct_txgain(struct zyd_rf *rf, uint8_t chan) -{ - struct zyd_softc *sc = rf->rf_sc; - static uint32_t txgain[] = ZYD_GCT_TXGAIN; - uint8_t idx = sc->sc_pwrint[chan - 1]; - - if (idx >= nitems(txgain)) { - device_printf(sc->sc_dev, "could not set TX gain (%d %#x)\n", - chan, idx); - return 0; - } - - return zyd_rfwrite(sc, 0x700000 | txgain[idx]); -} - -/* - * Maxim2 RF methods. - */ -static int -zyd_maxim2_init(struct zyd_rf *rf) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; - static const uint32_t rfini[] = ZYD_MAXIM2_RF; - uint16_t tmp; - int i, error; - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* init maxim2 radio */ - for (i = 0; i < nitems(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -} - -static int -zyd_maxim2_switch_radio(struct zyd_rf *rf, int on) -{ - - /* vendor driver does nothing for this RF chip */ - return (0); -} - -static int -zyd_maxim2_set_channel(struct zyd_rf *rf, uint8_t chan) -{ - struct zyd_softc *sc = rf->rf_sc; - static const struct zyd_phy_pair phyini[] = ZYD_MAXIM2_PHY; - static const uint32_t rfini[] = ZYD_MAXIM2_RF; - static const struct { - uint32_t r1, r2; - } rfprog[] = ZYD_MAXIM2_CHANTABLE; - uint16_t tmp; - int i, error; - - /* - * Do the same as we do when initializing it, except for the channel - * values coming from the two channel tables. - */ - - /* init RF-dependent PHY registers */ - for (i = 0; i < nitems(phyini); i++) - zyd_write16_m(sc, phyini[i].reg, phyini[i].val); - - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp & ~(1 << 4)); - - /* first two values taken from the chantables */ - error = zyd_rfwrite(sc, rfprog[chan - 1].r1); - if (error != 0) - goto fail; - error = zyd_rfwrite(sc, rfprog[chan - 1].r2); - if (error != 0) - goto fail; - - /* init maxim2 radio - skipping the two first values */ - for (i = 2; i < nitems(rfini); i++) { - if ((error = zyd_rfwrite(sc, rfini[i])) != 0) - return (error); - } - zyd_read16_m(sc, ZYD_CR203, &tmp); - zyd_write16_m(sc, ZYD_CR203, tmp | (1 << 4)); -fail: - return (error); -} - -static int -zyd_rf_attach(struct zyd_softc *sc, uint8_t type) -{ - struct zyd_rf *rf = &sc->sc_rf; - - rf->rf_sc = sc; - rf->update_pwr = 1; - - switch (type) { - case ZYD_RF_RFMD: - rf->init = zyd_rfmd_init; - rf->switch_radio = zyd_rfmd_switch_radio; - rf->set_channel = zyd_rfmd_set_channel; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_AL2230: - case ZYD_RF_AL2230S: - if (sc->sc_macrev == ZYD_ZD1211B) { - rf->init = zyd_al2230_init_b; - rf->set_channel = zyd_al2230_set_channel_b; - } else { - rf->init = zyd_al2230_init; - rf->set_channel = zyd_al2230_set_channel; - } - rf->switch_radio = zyd_al2230_switch_radio; - rf->bandedge6 = zyd_al2230_bandedge6; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_AL7230B: - rf->init = zyd_al7230B_init; - rf->switch_radio = zyd_al7230B_switch_radio; - rf->set_channel = zyd_al7230B_set_channel; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_AL2210: - rf->init = zyd_al2210_init; - rf->switch_radio = zyd_al2210_switch_radio; - rf->set_channel = zyd_al2210_set_channel; - rf->width = 24; /* 24-bit RF values */ - break; - case ZYD_RF_MAXIM_NEW: - case ZYD_RF_GCT: - rf->init = zyd_gct_init; - rf->switch_radio = zyd_gct_switch_radio; - rf->set_channel = zyd_gct_set_channel; - rf->width = 24; /* 24-bit RF values */ - rf->update_pwr = 0; - break; - case ZYD_RF_MAXIM_NEW2: - rf->init = zyd_maxim2_init; - rf->switch_radio = zyd_maxim2_switch_radio; - rf->set_channel = zyd_maxim2_set_channel; - rf->width = 18; /* 18-bit RF values */ - break; - default: - device_printf(sc->sc_dev, - "sorry, radio \"%s\" is not supported yet\n", - zyd_rf_name(type)); - return (EINVAL); - } - return (0); -} - -static const char * -zyd_rf_name(uint8_t type) -{ - static const char * const zyd_rfs[] = { - "unknown", "unknown", "UW2451", "UCHIP", "AL2230", - "AL7230B", "THETA", "AL2210", "MAXIM_NEW", "GCT", - "AL2230S", "RALINK", "INTERSIL", "RFMD", "MAXIM_NEW2", - "PHILIPS" - }; - - return zyd_rfs[(type > 15) ? 0 : type]; -} - -static int -zyd_hw_init(struct zyd_softc *sc) -{ - int error; - const struct zyd_phy_pair *phyp; - struct zyd_rf *rf = &sc->sc_rf; - uint16_t val; - - /* specify that the plug and play is finished */ - zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); - zyd_read16_m(sc, ZYD_FIRMWARE_BASE_ADDR, &sc->sc_fwbase); - DPRINTF(sc, ZYD_DEBUG_FW, "firmware base address=0x%04x\n", - sc->sc_fwbase); - - /* retrieve firmware revision number */ - zyd_read16_m(sc, sc->sc_fwbase + ZYD_FW_FIRMWARE_REV, &sc->sc_fwrev); - zyd_write32_m(sc, ZYD_CR_GPI_EN, 0); - zyd_write32_m(sc, ZYD_MAC_CONT_WIN_LIMIT, 0x7f043f); - /* set mandatory rates - XXX assumes 802.11b/g */ - zyd_write32_m(sc, ZYD_MAC_MAN_RATE, 0x150f); - - /* disable interrupts */ - zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); - - if ((error = zyd_read_pod(sc)) != 0) { - device_printf(sc->sc_dev, "could not read EEPROM\n"); - goto fail; - } - - /* PHY init (resetting) */ - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - phyp = (sc->sc_macrev == ZYD_ZD1211B) ? zyd_def_phyB : zyd_def_phy; - for (; phyp->reg != 0; phyp++) - zyd_write16_m(sc, phyp->reg, phyp->val); - if (sc->sc_macrev == ZYD_ZD1211 && sc->sc_fix_cr157 != 0) { - zyd_read16_m(sc, ZYD_EEPROM_PHY_REG, &val); - zyd_write32_m(sc, ZYD_CR157, val >> 8); - } - error = zyd_unlock_phy(sc); - if (error != 0) - goto fail; - - /* HMAC init */ - zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000020); - zyd_write32_m(sc, ZYD_CR_ADDA_MBIAS_WT, 0x30000808); - zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_GHTBL, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_GHTBH, 0x80000000); - zyd_write32_m(sc, ZYD_MAC_MISC, 0x000000a4); - zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x0000007f); - zyd_write32_m(sc, ZYD_MAC_BCNCFG, 0x00f00401); - zyd_write32_m(sc, ZYD_MAC_PHY_DELAY2, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_ACK_EXT, 0x00000080); - zyd_write32_m(sc, ZYD_CR_ADDA_PWR_DWN, 0x00000000); - zyd_write32_m(sc, ZYD_MAC_SIFS_ACK_TIME, 0x00000100); - zyd_write32_m(sc, ZYD_CR_RX_PE_DELAY, 0x00000070); - zyd_write32_m(sc, ZYD_CR_PS_CTRL, 0x10000000); - zyd_write32_m(sc, ZYD_MAC_RTSCTSRATE, 0x02030203); - zyd_write32_m(sc, ZYD_MAC_AFTER_PNP, 1); - zyd_write32_m(sc, ZYD_MAC_BACKOFF_PROTECT, 0x00000114); - zyd_write32_m(sc, ZYD_MAC_DIFS_EIFS_SIFS, 0x0a47c032); - zyd_write32_m(sc, ZYD_MAC_CAM_MODE, 0x3); - - if (sc->sc_macrev == ZYD_ZD1211) { - zyd_write32_m(sc, ZYD_MAC_RETRY, 0x00000002); - zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0640); - } else { - zyd_write32_m(sc, ZYD_MACB_MAX_RETRY, 0x02020202); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL4, 0x007f003f); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL3, 0x007f003f); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL2, 0x003f001f); - zyd_write32_m(sc, ZYD_MACB_TXPWR_CTL1, 0x001f000f); - zyd_write32_m(sc, ZYD_MACB_AIFS_CTL1, 0x00280028); - zyd_write32_m(sc, ZYD_MACB_AIFS_CTL2, 0x008C003C); - zyd_write32_m(sc, ZYD_MACB_TXOP, 0x01800824); - zyd_write32_m(sc, ZYD_MAC_RX_THRESHOLD, 0x000c0eff); - } - - /* init beacon interval to 100ms */ - if ((error = zyd_set_beacon_interval(sc, 100)) != 0) - goto fail; - - if ((error = zyd_rf_attach(sc, sc->sc_rfrev)) != 0) { - device_printf(sc->sc_dev, "could not attach RF, rev 0x%x\n", - sc->sc_rfrev); - goto fail; - } - - /* RF chip init */ - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - error = (*rf->init)(rf); - if (error != 0) { - device_printf(sc->sc_dev, - "radio initialization failed, error %d\n", error); - goto fail; - } - error = zyd_unlock_phy(sc); - if (error != 0) - goto fail; - - if ((error = zyd_read_eeprom(sc)) != 0) { - device_printf(sc->sc_dev, "could not read EEPROM\n"); - goto fail; - } - -fail: return (error); -} - -static int -zyd_read_pod(struct zyd_softc *sc) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_EEPROM_POD, &tmp); - sc->sc_rfrev = tmp & 0x0f; - sc->sc_ledtype = (tmp >> 4) & 0x01; - sc->sc_al2230s = (tmp >> 7) & 0x01; - sc->sc_cckgain = (tmp >> 8) & 0x01; - sc->sc_fix_cr157 = (tmp >> 13) & 0x01; - sc->sc_parev = (tmp >> 16) & 0x0f; - sc->sc_bandedge6 = (tmp >> 21) & 0x01; - sc->sc_newphy = (tmp >> 31) & 0x01; - sc->sc_txled = ((tmp & (1 << 24)) && (tmp & (1 << 29))) ? 0 : 1; -fail: - return (error); -} - -static int -zyd_read_eeprom(struct zyd_softc *sc) -{ - uint16_t val; - int error, i; - - /* read Tx power calibration tables */ - for (i = 0; i < 7; i++) { - zyd_read16_m(sc, ZYD_EEPROM_PWR_CAL + i, &val); - sc->sc_pwrcal[i * 2] = val >> 8; - sc->sc_pwrcal[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_PWR_INT + i, &val); - sc->sc_pwrint[i * 2] = val >> 8; - sc->sc_pwrint[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_36M_CAL + i, &val); - sc->sc_ofdm36_cal[i * 2] = val >> 8; - sc->sc_ofdm36_cal[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_48M_CAL + i, &val); - sc->sc_ofdm48_cal[i * 2] = val >> 8; - sc->sc_ofdm48_cal[i * 2 + 1] = val & 0xff; - zyd_read16_m(sc, ZYD_EEPROM_54M_CAL + i, &val); - sc->sc_ofdm54_cal[i * 2] = val >> 8; - sc->sc_ofdm54_cal[i * 2 + 1] = val & 0xff; - } -fail: - return (error); -} - -static int -zyd_get_macaddr(struct zyd_softc *sc) -{ - struct usb_device_request req; - usb_error_t error; - - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = ZYD_READFWDATAREQ; - USETW(req.wValue, ZYD_EEPROM_MAC_ADDR_P1); - USETW(req.wIndex, 0); - USETW(req.wLength, IEEE80211_ADDR_LEN); - - error = zyd_do_request(sc, &req, sc->sc_bssid); - if (error != 0) { - device_printf(sc->sc_dev, "could not read EEPROM: %s\n", - usbd_errstr(error)); - } - - return (error); -} - -static int -zyd_set_macaddr(struct zyd_softc *sc, const uint8_t *addr) -{ - int error; - uint32_t tmp; - - tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; - zyd_write32_m(sc, ZYD_MAC_MACADRL, tmp); - tmp = addr[5] << 8 | addr[4]; - zyd_write32_m(sc, ZYD_MAC_MACADRH, tmp); -fail: - return (error); -} - -static int -zyd_set_bssid(struct zyd_softc *sc, const uint8_t *addr) -{ - int error; - uint32_t tmp; - - tmp = addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]; - zyd_write32_m(sc, ZYD_MAC_BSSADRL, tmp); - tmp = addr[5] << 8 | addr[4]; - zyd_write32_m(sc, ZYD_MAC_BSSADRH, tmp); -fail: - return (error); -} - -static int -zyd_switch_radio(struct zyd_softc *sc, int on) -{ - struct zyd_rf *rf = &sc->sc_rf; - int error; - - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - error = (*rf->switch_radio)(rf, on); - if (error != 0) - goto fail; - error = zyd_unlock_phy(sc); -fail: - return (error); -} - -static int -zyd_set_led(struct zyd_softc *sc, int which, int on) -{ - int error; - uint32_t tmp; - - zyd_read32_m(sc, ZYD_MAC_TX_PE_CONTROL, &tmp); - tmp &= ~which; - if (on) - tmp |= which; - zyd_write32_m(sc, ZYD_MAC_TX_PE_CONTROL, tmp); -fail: - return (error); -} - -static void -zyd_set_multi(struct zyd_softc *sc) -{ - int error; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ifmultiaddr *ifma; - uint32_t low, high; - uint8_t v; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - low = 0x00000000; - high = 0x80000000; - - if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { - low = 0xffffffff; - high = 0xffffffff; - } else { - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - v = ((uint8_t *)LLADDR((struct sockaddr_dl *) - ifma->ifma_addr))[5] >> 2; - if (v < 32) - low |= 1 << v; - else - high |= 1 << (v - 32); - } - if_maddr_runlock(ifp); - } - - /* reprogram multicast global hash table */ - zyd_write32_m(sc, ZYD_MAC_GHTBL, low); - zyd_write32_m(sc, ZYD_MAC_GHTBH, high); -fail: - if (error != 0) - device_printf(sc->sc_dev, - "could not set multicast hash table\n"); -} - -static void -zyd_update_mcast(struct ieee80211com *ic) -{ - struct zyd_softc *sc = ic->ic_softc; - - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - ZYD_LOCK(sc); - zyd_set_multi(sc); - ZYD_UNLOCK(sc); -} - -static int -zyd_set_rxfilter(struct zyd_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - uint32_t rxfilter; - - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - rxfilter = ZYD_FILTER_BSS; - break; - case IEEE80211_M_IBSS: - case IEEE80211_M_HOSTAP: - rxfilter = ZYD_FILTER_HOSTAP; - break; - case IEEE80211_M_MONITOR: - rxfilter = ZYD_FILTER_MONITOR; - break; - default: - /* should not get there */ - return (EINVAL); - } - return zyd_write32(sc, ZYD_MAC_RXFILTER, rxfilter); -} - -static void -zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c) -{ - int error; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct zyd_rf *rf = &sc->sc_rf; - uint32_t tmp; - int chan; - - chan = ieee80211_chan2ieee(ic, c); - if (chan == 0 || chan == IEEE80211_CHAN_ANY) { - /* XXX should NEVER happen */ - device_printf(sc->sc_dev, - "%s: invalid channel %x\n", __func__, chan); - return; - } - - error = zyd_lock_phy(sc); - if (error != 0) - goto fail; - - error = (*rf->set_channel)(rf, chan); - if (error != 0) - goto fail; - - if (rf->update_pwr) { - /* update Tx power */ - zyd_write16_m(sc, ZYD_CR31, sc->sc_pwrint[chan - 1]); - - if (sc->sc_macrev == ZYD_ZD1211B) { - zyd_write16_m(sc, ZYD_CR67, - sc->sc_ofdm36_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR66, - sc->sc_ofdm48_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR65, - sc->sc_ofdm54_cal[chan - 1]); - zyd_write16_m(sc, ZYD_CR68, sc->sc_pwrcal[chan - 1]); - zyd_write16_m(sc, ZYD_CR69, 0x28); - zyd_write16_m(sc, ZYD_CR69, 0x2a); - } - } - if (sc->sc_cckgain) { - /* set CCK baseband gain from EEPROM */ - if (zyd_read32(sc, ZYD_EEPROM_PHY_REG, &tmp) == 0) - zyd_write16_m(sc, ZYD_CR47, tmp & 0xff); - } - if (sc->sc_bandedge6 && rf->bandedge6 != NULL) { - error = (*rf->bandedge6)(rf, c); - if (error != 0) - goto fail; - } - zyd_write32_m(sc, ZYD_CR_CONFIG_PHILIPS, 0); - - error = zyd_unlock_phy(sc); - if (error != 0) - goto fail; - - sc->sc_rxtap.wr_chan_freq = sc->sc_txtap.wt_chan_freq = - htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = sc->sc_txtap.wt_chan_flags = - htole16(c->ic_flags); -fail: - return; -} - -static int -zyd_set_beacon_interval(struct zyd_softc *sc, int bintval) -{ - int error; - uint32_t val; - - zyd_read32_m(sc, ZYD_CR_ATIM_WND_PERIOD, &val); - sc->sc_atim_wnd = val; - zyd_read32_m(sc, ZYD_CR_PRE_TBTT, &val); - sc->sc_pre_tbtt = val; - sc->sc_bcn_int = bintval; - - if (sc->sc_bcn_int <= 5) - sc->sc_bcn_int = 5; - if (sc->sc_pre_tbtt < 4 || sc->sc_pre_tbtt >= sc->sc_bcn_int) - sc->sc_pre_tbtt = sc->sc_bcn_int - 1; - if (sc->sc_atim_wnd >= sc->sc_pre_tbtt) - sc->sc_atim_wnd = sc->sc_pre_tbtt - 1; - - zyd_write32_m(sc, ZYD_CR_ATIM_WND_PERIOD, sc->sc_atim_wnd); - zyd_write32_m(sc, ZYD_CR_PRE_TBTT, sc->sc_pre_tbtt); - zyd_write32_m(sc, ZYD_CR_BCN_INTERVAL, sc->sc_bcn_int); -fail: - return (error); -} - -static void -zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) -{ - struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct zyd_plcphdr plcp; - struct zyd_rx_stat stat; - struct usb_page_cache *pc; - struct mbuf *m; - int rlen, rssi; - - if (len < ZYD_MIN_FRAGSZ) { - DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n", - device_get_nameunit(sc->sc_dev), len); - ifp->if_ierrors++; - return; - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, offset, &plcp, sizeof(plcp)); - usbd_copy_out(pc, offset + len - sizeof(stat), &stat, sizeof(stat)); - - if (stat.flags & ZYD_RX_ERROR) { - DPRINTF(sc, ZYD_DEBUG_RECV, - "%s: RX status indicated error (%x)\n", - device_get_nameunit(sc->sc_dev), stat.flags); - ifp->if_ierrors++; - return; - } - - /* compute actual frame length */ - rlen = len - sizeof(struct zyd_plcphdr) - - sizeof(struct zyd_rx_stat) - IEEE80211_CRC_LEN; - - /* allocate a mbuf to store the frame */ - if (rlen > MCLBYTES) { - DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n", - device_get_nameunit(sc->sc_dev), rlen); - ifp->if_ierrors++; - return; - } else if (rlen > MHLEN) - m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); - else - m = m_gethdr(M_DONTWAIT, MT_DATA); - if (m == NULL) { - DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n", - device_get_nameunit(sc->sc_dev)); - ifp->if_ierrors++; - return; - } - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = rlen; - usbd_copy_out(pc, offset + sizeof(plcp), mtod(m, uint8_t *), rlen); - - if (ieee80211_radiotap_active(ic)) { - struct zyd_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = 0; - if (stat.flags & (ZYD_RX_BADCRC16 | ZYD_RX_BADCRC32)) - tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; - /* XXX toss, no way to express errors */ - if (stat.flags & ZYD_RX_DECRYPTERR) - tap->wr_flags |= IEEE80211_RADIOTAP_F_BADFCS; - tap->wr_rate = ieee80211_plcp2rate(plcp.signal, - (stat.flags & ZYD_RX_OFDM) ? - IEEE80211_T_OFDM : IEEE80211_T_CCK); - tap->wr_antsignal = stat.rssi + -95; - tap->wr_antnoise = -95; /* XXX */ - } - rssi = (stat.rssi > 63) ? 127 : 2 * stat.rssi; - - sc->sc_rx_data[sc->sc_rx_count].rssi = rssi; - sc->sc_rx_data[sc->sc_rx_count].m = m; - sc->sc_rx_count++; -} - -static void -zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ieee80211_node *ni; - struct zyd_rx_desc desc; - struct mbuf *m; - struct usb_page_cache *pc; - uint32_t offset; - uint8_t rssi; - int8_t nf; - int i; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - sc->sc_rx_count = 0; - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_out(pc, actlen - sizeof(desc), &desc, sizeof(desc)); - - offset = 0; - if (UGETW(desc.tag) == ZYD_TAG_MULTIFRAME) { - DPRINTF(sc, ZYD_DEBUG_RECV, - "%s: received multi-frame transfer\n", __func__); - - for (i = 0; i < ZYD_MAX_RXFRAMECNT; i++) { - uint16_t len16 = UGETW(desc.len[i]); - - if (len16 == 0 || len16 > actlen) - break; - - zyd_rx_data(xfer, offset, len16); - - /* next frame is aligned on a 32-bit boundary */ - len16 = (len16 + 3) & ~3; - offset += len16; - if (len16 > actlen) - break; - actlen -= len16; - } - } else { - DPRINTF(sc, ZYD_DEBUG_RECV, - "%s: received single-frame transfer\n", __func__); - - zyd_rx_data(xfer, 0, actlen); - } - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); - usbd_transfer_submit(xfer); - - /* - * At the end of a USB callback it is always safe to unlock - * the private mutex of a device! That is why we do the - * "ieee80211_input" here, and not some lines up! - */ - ZYD_UNLOCK(sc); - for (i = 0; i < sc->sc_rx_count; i++) { - rssi = sc->sc_rx_data[i].rssi; - m = sc->sc_rx_data[i].m; - sc->sc_rx_data[i].m = NULL; - - nf = -95; /* XXX */ - - ni = ieee80211_find_rxnode(ic, - mtod(m, struct ieee80211_frame_min *)); - if (ni != NULL) { - (void)ieee80211_input(ni, m, rssi, nf); - ieee80211_free_node(ni); - } else - (void)ieee80211_input_all(ic, m, rssi, nf); - } - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && - !IFQ_IS_EMPTY(&ifp->if_snd)) - zyd_start(ifp); - ZYD_LOCK(sc); - break; - - default: /* Error */ - DPRINTF(sc, ZYD_DEBUG_ANY, "frame error: %s\n", usbd_errstr(error)); - - if (error != USB_ERR_CANCELLED) { - /* try to clear stall first */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static uint8_t -zyd_plcp_signal(struct zyd_softc *sc, int rate) -{ - switch (rate) { - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: - return (0xb); - case 18: - return (0xf); - case 24: - return (0xa); - case 36: - return (0xe); - case 48: - return (0x9); - case 72: - return (0xd); - case 96: - return (0x8); - case 108: - return (0xc); - /* CCK rates (NB: not IEEE std, device-specific) */ - case 2: - return (0x0); - case 4: - return (0x1); - case 11: - return (0x2); - case 22: - return (0x3); - } - - device_printf(sc->sc_dev, "unsupported rate %d\n", rate); - return (0x0); -} - -static void -zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) -{ - struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211vap *vap; - struct zyd_tx_data *data; - struct mbuf *m; - struct usb_page_cache *pc; - int actlen; - - usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); - - switch (USB_GET_STATE(xfer)) { - case USB_ST_TRANSFERRED: - DPRINTF(sc, ZYD_DEBUG_ANY, "transfer complete, %u bytes\n", - actlen); - - /* free resources */ - data = usbd_xfer_get_priv(xfer); - zyd_tx_free(data, 0); - usbd_xfer_set_priv(xfer, NULL); - - ifp->if_opackets++; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - - /* FALLTHROUGH */ - case USB_ST_SETUP: -tr_setup: - data = STAILQ_FIRST(&sc->tx_q); - if (data) { - STAILQ_REMOVE_HEAD(&sc->tx_q, next); - m = data->m; - - if (m->m_pkthdr.len > ZYD_MAX_TXBUFSZ) { - DPRINTF(sc, ZYD_DEBUG_ANY, "data overflow, %u bytes\n", - m->m_pkthdr.len); - m->m_pkthdr.len = ZYD_MAX_TXBUFSZ; - } - pc = usbd_xfer_get_frame(xfer, 0); - usbd_copy_in(pc, 0, &data->desc, ZYD_TX_DESC_SIZE); - usbd_m_copy_in(pc, ZYD_TX_DESC_SIZE, m, 0, - m->m_pkthdr.len); - - vap = data->ni->ni_vap; - if (ieee80211_radiotap_active_vap(vap)) { - struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = data->rate; - - ieee80211_radiotap_tx(vap, m); - } - - usbd_xfer_set_frame_len(xfer, 0, ZYD_TX_DESC_SIZE + m->m_pkthdr.len); - usbd_xfer_set_priv(xfer, data); - usbd_transfer_submit(xfer); - } - ZYD_UNLOCK(sc); - zyd_start(ifp); - ZYD_LOCK(sc); - break; - - default: /* Error */ - DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n", - usbd_errstr(error)); - - ifp->if_oerrors++; - data = usbd_xfer_get_priv(xfer); - usbd_xfer_set_priv(xfer, NULL); - if (data != NULL) - zyd_tx_free(data, error); - - if (error != USB_ERR_CANCELLED) { - if (error == USB_ERR_TIMEOUT) - device_printf(sc->sc_dev, "device timeout\n"); - - /* - * Try to clear stall first, also if other - * errors occur, hence clearing stall - * introduces a 50 ms delay: - */ - usbd_xfer_set_stall(xfer); - goto tr_setup; - } - break; - } -} - -static int -zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211com *ic = ni->ni_ic; - struct zyd_tx_desc *desc; - struct zyd_tx_data *data; - struct ieee80211_frame *wh; - const struct ieee80211_txparam *tp; - struct ieee80211_key *k; - int rate, totlen; - static uint8_t ratediv[] = ZYD_TX_RATEDIV; - uint8_t phy; - uint16_t pktlen; - uint32_t bits; - - wh = mtod(m0, struct ieee80211_frame *); - data = STAILQ_FIRST(&sc->tx_free); - STAILQ_REMOVE_HEAD(&sc->tx_free, next); - sc->tx_nfree--; - - if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT || - (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) { - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - rate = tp->mgmtrate; - } else { - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - /* for data frames */ - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else { - (void) ieee80211_ratectl_rate(ni, NULL, 0); - rate = ni->ni_txrate; - } - } - - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m0); - if (k == NULL) { - m_freem(m0); - return (ENOBUFS); - } - /* packet header may have moved, reset our local pointer */ - wh = mtod(m0, struct ieee80211_frame *); - } - - data->ni = ni; - data->m = m0; - data->rate = rate; - - /* fill Tx descriptor */ - desc = &data->desc; - phy = zyd_plcp_signal(sc, rate); - desc->phy = phy; - if (ZYD_RATE_IS_OFDM(rate)) { - desc->phy |= ZYD_TX_PHY_OFDM; - if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) - desc->phy |= ZYD_TX_PHY_5GHZ; - } else if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) - desc->phy |= ZYD_TX_PHY_SHPREAMBLE; - - totlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN; - desc->len = htole16(totlen); - - desc->flags = ZYD_TX_FLAG_BACKOFF; - if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { - /* multicast frames are not sent at OFDM rates in 802.11b/g */ - if (totlen > vap->iv_rtsthreshold) { - desc->flags |= ZYD_TX_FLAG_RTS; - } else if (ZYD_RATE_IS_OFDM(rate) && - (ic->ic_flags & IEEE80211_F_USEPROT)) { - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) - desc->flags |= ZYD_TX_FLAG_CTS_TO_SELF; - else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) - desc->flags |= ZYD_TX_FLAG_RTS; - } - } else - desc->flags |= ZYD_TX_FLAG_MULTICAST; - if ((wh->i_fc[0] & - (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == - (IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_PS_POLL)) - desc->flags |= ZYD_TX_FLAG_TYPE(ZYD_TX_TYPE_PS_POLL); - - /* actual transmit length (XXX why +10?) */ - pktlen = ZYD_TX_DESC_SIZE + 10; - if (sc->sc_macrev == ZYD_ZD1211) - pktlen += totlen; - desc->pktlen = htole16(pktlen); - - bits = (rate == 11) ? (totlen * 16) + 10 : - ((rate == 22) ? (totlen * 8) + 10 : (totlen * 8)); - desc->plcp_length = htole16(bits / ratediv[phy]); - desc->plcp_service = 0; - if (rate == 22 && (bits % 11) > 0 && (bits % 11) <= 3) - desc->plcp_service |= ZYD_PLCP_LENGEXT; - desc->nextlen = 0; - - if (ieee80211_radiotap_active_vap(vap)) { - struct zyd_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - - ieee80211_radiotap_tx(vap, m0); - } - - DPRINTF(sc, ZYD_DEBUG_XMIT, - "%s: sending data frame len=%zu rate=%u\n", - device_get_nameunit(sc->sc_dev), (size_t)m0->m_pkthdr.len, - rate); - - STAILQ_INSERT_TAIL(&sc->tx_q, data, next); - usbd_transfer_start(sc->sc_xfer[ZYD_BULK_WR]); - - return (0); -} - -static void -zyd_start(struct ifnet *ifp) -{ - struct zyd_softc *sc = ifp->if_softc; - struct ieee80211_node *ni; - struct mbuf *m; - - ZYD_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - if (sc->tx_nfree == 0) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - if (zyd_tx_start(sc, m, ni) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } - } - ZYD_UNLOCK(sc); -} - -static int -zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct zyd_softc *sc = ifp->if_softc; - - ZYD_LOCK(sc); - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - ZYD_UNLOCK(sc); - m_freem(m); - ieee80211_free_node(ni); - return (ENETDOWN); - } - if (sc->tx_nfree == 0) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - ZYD_UNLOCK(sc); - m_freem(m); - ieee80211_free_node(ni); - return (ENOBUFS); /* XXX */ - } - - /* - * Legacy path; interpret frame contents to decide - * precisely how to send the frame. - * XXX raw path - */ - if (zyd_tx_start(sc, m, ni) != 0) { - ZYD_UNLOCK(sc); - ifp->if_oerrors++; - ieee80211_free_node(ni); - return (EIO); - } - ZYD_UNLOCK(sc); - return (0); -} - -static int -zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct zyd_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - ZYD_LOCK(sc); - if (ifp->if_flags & IFF_UP) { - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - zyd_init_locked(sc); - startall = 1; - } else - zyd_set_multi(sc); - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - zyd_stop(sc); - } - ZYD_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - default: - error = EINVAL; - break; - } - return (error); -} - -static void -zyd_init_locked(struct zyd_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct usb_config_descriptor *cd; - int error; - uint32_t val; -#ifdef USB_DEBUG - char ethstr[ETHER_ADDRSTRLEN + 1]; -#endif - - ZYD_LOCK_ASSERT(sc, MA_OWNED); - - if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) { - error = zyd_loadfirmware(sc); - if (error != 0) { - device_printf(sc->sc_dev, - "could not load firmware (error=%d)\n", error); - goto fail; - } - - /* reset device */ - cd = usbd_get_config_descriptor(sc->sc_udev); - error = usbd_req_set_config(sc->sc_udev, &sc->sc_mtx, - cd->bConfigurationValue); - if (error) - device_printf(sc->sc_dev, "reset failed, continuing\n"); - - error = zyd_hw_init(sc); - if (error) { - device_printf(sc->sc_dev, - "hardware initialization failed\n"); - goto fail; - } - - device_printf(sc->sc_dev, - "HMAC ZD1211%s, FW %02x.%02x, RF %s S%x, PA%x LED %x " - "BE%x NP%x Gain%x F%x\n", - (sc->sc_macrev == ZYD_ZD1211) ? "": "B", - sc->sc_fwrev >> 8, sc->sc_fwrev & 0xff, - zyd_rf_name(sc->sc_rfrev), sc->sc_al2230s, sc->sc_parev, - sc->sc_ledtype, sc->sc_bandedge6, sc->sc_newphy, - sc->sc_cckgain, sc->sc_fix_cr157); - - /* read regulatory domain (currently unused) */ - zyd_read32_m(sc, ZYD_EEPROM_SUBID, &val); - sc->sc_regdomain = val >> 16; - DPRINTF(sc, ZYD_DEBUG_INIT, "regulatory domain %x\n", - sc->sc_regdomain); - - /* we'll do software WEP decryption for now */ - DPRINTF(sc, ZYD_DEBUG_INIT, "%s: setting encryption type\n", - __func__); - zyd_write32_m(sc, ZYD_MAC_ENCRYPTION_TYPE, ZYD_ENC_SNIFFER); - - sc->sc_flags |= ZYD_FLAG_INITONCE; - } - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - zyd_stop(sc); - - DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %s\n", - kether_ntoa(IF_LLADDR(ifp), ethstr)); - error = zyd_set_macaddr(sc, IF_LLADDR(ifp)); - if (error != 0) - return; - - /* set basic rates */ - if (ic->ic_curmode == IEEE80211_MODE_11B) - zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x0003); - else if (ic->ic_curmode == IEEE80211_MODE_11A) - zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0x1500); - else /* assumes 802.11b/g */ - zyd_write32_m(sc, ZYD_MAC_BAS_RATE, 0xff0f); - - /* promiscuous mode */ - zyd_write32_m(sc, ZYD_MAC_SNIFFER, 0); - /* multicast setup */ - zyd_set_multi(sc); - /* set RX filter */ - error = zyd_set_rxfilter(sc); - if (error != 0) - goto fail; - - /* switch radio transmitter ON */ - error = zyd_switch_radio(sc, 1); - if (error != 0) - goto fail; - /* set default BSS channel */ - zyd_set_chan(sc, ic->ic_curchan); - - /* - * Allocate Tx and Rx xfer queues. - */ - zyd_setup_tx_list(sc); - - /* enable interrupts */ - zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); - - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - usbd_xfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]); - usbd_transfer_start(sc->sc_xfer[ZYD_BULK_RD]); - usbd_transfer_start(sc->sc_xfer[ZYD_INTR_RD]); - - return; - -fail: zyd_stop(sc); - return; -} - -static void -zyd_init(void *priv) -{ - struct zyd_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ZYD_LOCK(sc); - zyd_init_locked(sc); - ZYD_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -zyd_stop(struct zyd_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - int error; - - ZYD_LOCK_ASSERT(sc, MA_OWNED); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - - /* - * Drain all the transfers, if not already drained: - */ - ZYD_UNLOCK(sc); - usbd_transfer_drain(sc->sc_xfer[ZYD_BULK_WR]); - usbd_transfer_drain(sc->sc_xfer[ZYD_BULK_RD]); - ZYD_LOCK(sc); - - zyd_unsetup_tx_list(sc); - - /* Stop now if the device was never set up */ - if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) - return; - - /* switch radio transmitter OFF */ - error = zyd_switch_radio(sc, 0); - if (error != 0) - goto fail; - /* disable Rx */ - zyd_write32_m(sc, ZYD_MAC_RXFILTER, 0); - /* disable interrupts */ - zyd_write32_m(sc, ZYD_CR_INTERRUPT, 0); - -fail: - return; -} - -static int -zyd_loadfirmware(struct zyd_softc *sc) -{ - struct usb_device_request req; - size_t size; - u_char *fw; - uint8_t stat; - uint16_t addr; - - if (sc->sc_flags & ZYD_FLAG_FWLOADED) - return (0); - - if (sc->sc_macrev == ZYD_ZD1211) { - fw = (u_char *)zd1211_firmware; - size = sizeof(zd1211_firmware); - } else { - fw = (u_char *)zd1211b_firmware; - size = sizeof(zd1211b_firmware); - } - - req.bmRequestType = UT_WRITE_VENDOR_DEVICE; - req.bRequest = ZYD_DOWNLOADREQ; - USETW(req.wIndex, 0); - - addr = ZYD_FIRMWARE_START_ADDR; - while (size > 0) { - /* - * When the transfer size is 4096 bytes, it is not - * likely to be able to transfer it. - * The cause is port or machine or chip? - */ - const int mlen = min(size, 64); - - DPRINTF(sc, ZYD_DEBUG_FW, - "loading firmware block: len=%d, addr=0x%x\n", mlen, addr); - - USETW(req.wValue, addr); - USETW(req.wLength, mlen); - if (zyd_do_request(sc, &req, fw) != 0) - return (EIO); - - addr += mlen / 2; - fw += mlen; - size -= mlen; - } - - /* check whether the upload succeeded */ - req.bmRequestType = UT_READ_VENDOR_DEVICE; - req.bRequest = ZYD_DOWNLOADSTS; - USETW(req.wValue, 0); - USETW(req.wIndex, 0); - USETW(req.wLength, sizeof(stat)); - if (zyd_do_request(sc, &req, &stat) != 0) - return (EIO); - - sc->sc_flags |= ZYD_FLAG_FWLOADED; - - return (stat & 0x80) ? (EIO) : (0); -} - -static void -zyd_scan_start(struct ieee80211com *ic) -{ - struct ifnet *ifp = ic->ic_ifp; - struct zyd_softc *sc = ifp->if_softc; - - ZYD_LOCK(sc); - /* want broadcast address while scanning */ - zyd_set_bssid(sc, ifp->if_broadcastaddr); - ZYD_UNLOCK(sc); -} - -static void -zyd_scan_end(struct ieee80211com *ic) -{ - struct zyd_softc *sc = ic->ic_ifp->if_softc; - - ZYD_LOCK(sc); - /* restore previous bssid */ - zyd_set_bssid(sc, sc->sc_bssid); - ZYD_UNLOCK(sc); -} - -static void -zyd_set_channel(struct ieee80211com *ic) -{ - struct zyd_softc *sc = ic->ic_ifp->if_softc; - - ZYD_LOCK(sc); - zyd_set_chan(sc, ic->ic_curchan); - ZYD_UNLOCK(sc); -} - -static device_method_t zyd_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, zyd_match), - DEVMETHOD(device_attach, zyd_attach), - DEVMETHOD(device_detach, zyd_detach), - - DEVMETHOD_END -}; - -static driver_t zyd_driver = { - "zyd", - zyd_methods, - sizeof(struct zyd_softc) -}; - -static devclass_t zyd_devclass; - -DRIVER_MODULE(zyd, uhub, zyd_driver, zyd_devclass, NULL, NULL); -MODULE_DEPEND(zyd, usb, 1, 1, 1); -MODULE_DEPEND(zyd, wlan, 1, 1, 1); -MODULE_VERSION(zyd, 1); diff --git a/sys/bus/u4b/wlan/if_zydfw.h b/sys/bus/u4b/wlan/if_zydfw.h deleted file mode 100644 index 46f5c2aba7..0000000000 --- a/sys/bus/u4b/wlan/if_zydfw.h +++ /dev/null @@ -1,1144 +0,0 @@ -/* - * Copyright (C) 2001, 2002, 2003,2004 ZyDAS Technology Corporation. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted provided - * that the following conditions are met: - * 1. Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* $FreeBSD$ */ - -uint8_t zd1211_firmware[] = { - 0x08, 0x91, 0xFF, 0xED, 0x09, 0x93, 0x1E, 0xEE, - 0xD1, 0x94, 0x11, 0xEE, 0x88, 0xD4, 0xD1, 0x96, - 0xD1, 0x98, 0x5C, 0x99, 0x5C, 0x99, 0x4C, 0x99, - 0x04, 0x9D, 0xD1, 0x98, 0xD1, 0x9A, 0x03, 0xEE, - 0xF4, 0x94, 0xD3, 0xD4, 0x41, 0x2A, 0x40, 0x4A, - 0x45, 0xBE, 0x88, 0x92, 0x41, 0x24, 0x40, 0x44, - 0x53, 0xBE, 0x40, 0xF0, 0x93, 0xEE, 0x41, 0xEE, - 0x98, 0x9A, 0xD4, 0xF7, 0x02, 0x00, 0x1F, 0xEC, - 0x00, 0x00, 0xB2, 0xF8, 0x4D, 0x00, 0xA1, 0xEC, - 0x00, 0x00, 0xA6, 0xF7, 0x21, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xD8, - 0xA0, 0x90, 0x98, 0x9A, 0x98, 0x9A, 0xA0, 0xD8, - 0x40, 0xF0, 0xB4, 0xF0, 0xA0, 0x90, 0x98, 0x9A, - 0xA0, 0xD8, 0x40, 0xF0, 0x64, 0xEF, 0xA0, 0x90, - 0x98, 0x9A, 0xA0, 0xD8, 0x40, 0xF0, 0xF6, 0xF0, - 0xA0, 0x90, 0x98, 0x9A, 0xA0, 0xD8, 0x40, 0xF0, - 0xF7, 0xF6, 0xA0, 0x90, 0x98, 0x9A, 0xA0, 0xD8, - 0x40, 0xF0, 0xF8, 0xF5, 0xA0, 0x90, 0x98, 0x9A, - 0xA0, 0xD8, 0x40, 0xF0, 0xF1, 0xF0, 0xA0, 0x90, - 0x98, 0x9A, 0x98, 0x9A, 0xA0, 0xD8, 0x40, 0xF0, - 0x97, 0xF7, 0xA0, 0x90, 0x98, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x0D, 0x03, 0x03, 0x00, - 0x09, 0x05, 0x01, 0x00, 0xC2, 0x94, 0x42, 0x02, - 0xC1, 0x92, 0x03, 0x96, 0x1B, 0xD7, 0x2A, 0x86, - 0x1A, 0xD5, 0x2B, 0x86, 0x09, 0xA3, 0x00, 0x80, - 0x19, 0xD3, 0x2C, 0x86, 0x00, 0xEE, 0x0A, 0x65, - 0xC0, 0x7A, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, - 0xFE, 0xFF, 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x42, 0x20, 0x08, 0x0B, 0x01, 0x00, - 0x0D, 0x03, 0x05, 0x00, 0x05, 0x94, 0xC5, 0xD4, - 0x09, 0x05, 0x01, 0x00, 0xC2, 0x94, 0x01, 0xD4, - 0x42, 0x02, 0xC1, 0x96, 0x0A, 0x65, 0xC0, 0x7A, - 0x02, 0x99, 0xC4, 0x92, 0x41, 0xA2, 0xC4, 0xD2, - 0xC5, 0x98, 0x1C, 0xD9, 0x2A, 0x86, 0x01, 0x98, - 0x1C, 0xD9, 0x2B, 0x86, 0x1B, 0xD7, 0x2C, 0x86, - 0x00, 0xEE, 0x09, 0xB3, 0xFE, 0xFF, 0xC2, 0xD2, - 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x41, 0x20, 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, - 0xE5, 0xEE, 0x11, 0x93, 0xD8, 0xF7, 0x41, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xAE, 0xEE, 0x40, 0xF1, - 0x40, 0x92, 0x19, 0xD3, 0xD8, 0xF7, 0xC5, 0x92, - 0x41, 0x92, 0x19, 0xD3, 0x00, 0x83, 0x40, 0x92, - 0x19, 0xD3, 0x00, 0x83, 0x0F, 0x9F, 0x95, 0xF8, - 0x0F, 0x9F, 0x99, 0xEE, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x99, 0xEE, 0x40, 0x92, 0x19, 0xD3, - 0xD8, 0xF7, 0x09, 0x93, 0xC7, 0xF7, 0x19, 0xD3, - 0x91, 0xEC, 0x40, 0xF0, 0x5F, 0xF2, 0x09, 0x63, - 0x00, 0x80, 0x19, 0xD3, 0xF2, 0xBD, 0x0F, 0x9F, - 0x99, 0xEE, 0x41, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0x92, - 0x19, 0xD3, 0x12, 0x95, 0x19, 0xD3, 0x10, 0x95, - 0x19, 0xD3, 0x02, 0x80, 0x19, 0xD3, 0x03, 0x82, - 0x09, 0x93, 0xC7, 0xF7, 0x19, 0xD3, 0x91, 0xEC, - 0x40, 0xF0, 0x5F, 0xF2, 0x40, 0xF0, 0xDE, 0xF3, - 0x11, 0x93, 0x04, 0xEC, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xE3, 0xEE, 0x40, 0x92, 0x19, 0xD3, - 0x04, 0xEC, 0x40, 0xF0, 0x38, 0xF2, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x11, 0x93, 0x44, 0x96, 0x09, 0xB3, 0xFF, 0xFD, - 0x19, 0xD3, 0x44, 0x96, 0x40, 0xF0, 0x90, 0xF7, - 0x6E, 0x92, 0x19, 0xD3, 0x05, 0x84, 0x40, 0xF0, - 0xC4, 0xEE, 0x4B, 0x62, 0x0A, 0x95, 0x2E, 0xEE, - 0xD1, 0xD4, 0x0B, 0x97, 0x2B, 0xEE, 0xD1, 0xD6, - 0x0A, 0x95, 0x00, 0xEE, 0xD1, 0xD4, 0x0B, 0x97, - 0x2F, 0xEE, 0xD1, 0xD6, 0x0A, 0x95, 0x34, 0xEE, - 0xD1, 0xD4, 0x0B, 0x97, 0x39, 0xEE, 0xD1, 0xD6, - 0x0A, 0x95, 0x3E, 0xEE, 0xD1, 0xD4, 0x0B, 0x97, - 0x43, 0xEE, 0xD1, 0xD6, 0x0A, 0x95, 0x48, 0xEE, - 0xD1, 0xD4, 0x0B, 0x97, 0x4D, 0xEE, 0xD1, 0xD6, - 0x0A, 0x95, 0x4E, 0xEE, 0xC1, 0xD4, 0x0A, 0x65, - 0x00, 0x44, 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, - 0xC2, 0xD2, 0x43, 0xF1, 0x09, 0x93, 0x01, 0x3F, - 0x19, 0xD3, 0xC0, 0x85, 0x11, 0x93, 0x44, 0x96, - 0x09, 0xB3, 0xFF, 0xFC, 0x19, 0xD3, 0x44, 0x96, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x0D, 0x03, 0x03, 0x00, 0x03, 0x96, - 0x41, 0x02, 0x03, 0x99, 0xC4, 0x94, 0x42, 0x04, - 0xC1, 0x04, 0xC2, 0x94, 0xC3, 0xD4, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x40, 0x92, 0x19, 0xD3, 0x94, 0xEC, 0x13, 0x97, - 0x95, 0xEC, 0x1B, 0xD7, 0x02, 0x80, 0x11, 0x93, - 0x99, 0xEC, 0x19, 0xD3, 0x7C, 0x96, 0x0B, 0x97, - 0xA0, 0x00, 0x1B, 0xD7, 0x6E, 0xEC, 0x0A, 0x65, - 0x0E, 0x42, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, - 0xFF, 0xBF, 0x11, 0xA3, 0x9A, 0xEC, 0xC2, 0xD2, - 0x0A, 0x65, 0xEB, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xA3, 0xC0, 0x00, 0xC2, 0xD2, 0x0A, 0x65, - 0xE9, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, - 0xBF, 0xFF, 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x47, 0x20, 0x08, 0x0B, 0x01, 0x00, - 0x14, 0x99, 0x03, 0x80, 0x0C, 0xB3, 0x00, 0x10, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x97, 0xF0, - 0x11, 0x93, 0x9F, 0xEC, 0x41, 0x02, 0x19, 0xD3, - 0x9F, 0xEC, 0x11, 0x93, 0xD6, 0xF7, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x84, 0xEF, 0x0A, 0x65, - 0xFE, 0x7F, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0x00, 0x04, 0xC2, 0xD2, 0x0F, 0x9F, 0xB1, 0xF0, - 0x11, 0x93, 0x94, 0xEC, 0x02, 0xD2, 0x40, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xD0, 0xEF, 0x41, 0x92, - 0x19, 0xD3, 0x94, 0xEC, 0x19, 0xD3, 0x9F, 0xEC, - 0x12, 0x95, 0x02, 0x80, 0x1A, 0xD5, 0x95, 0xEC, - 0x13, 0x97, 0x7C, 0x96, 0x1B, 0xD7, 0x99, 0xEC, - 0x0A, 0x65, 0x0E, 0x42, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0x00, 0x40, 0x19, 0xD3, 0x9A, 0xEC, - 0x09, 0x63, 0x00, 0x40, 0xC2, 0xD2, 0x02, 0x94, - 0x1A, 0xD5, 0x7C, 0x96, 0x0C, 0xB3, 0x00, 0x08, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0xB0, 0xEF, - 0x0C, 0xB3, 0xFF, 0x07, 0x0F, 0x9F, 0xB4, 0xEF, - 0x11, 0x93, 0x06, 0x80, 0x09, 0xB3, 0xFF, 0x07, - 0x09, 0x03, 0x00, 0xA0, 0x19, 0xD3, 0x97, 0xEC, - 0x40, 0x98, 0x0B, 0x97, 0x9C, 0xEC, 0x04, 0x95, - 0x03, 0x05, 0x14, 0x03, 0x97, 0xEC, 0x46, 0x02, - 0xC1, 0x92, 0xC2, 0xD2, 0x41, 0x08, 0x42, 0x48, - 0x02, 0x9E, 0x0F, 0x9F, 0xBB, 0xEF, 0x11, 0x93, - 0x97, 0xEC, 0xC1, 0x92, 0xC5, 0xD2, 0x5F, 0xB2, - 0x19, 0xD3, 0x9B, 0xEC, 0x0F, 0x9F, 0xD3, 0xEF, - 0x13, 0x97, 0x98, 0xEC, 0xC5, 0xD6, 0x11, 0x93, - 0x03, 0x80, 0x09, 0xB3, 0x00, 0x08, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xE9, 0xEF, 0x11, 0x93, - 0xDC, 0xF7, 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, - 0x11, 0x93, 0xDB, 0xF7, 0x09, 0xA3, 0x00, 0x10, - 0x19, 0xD3, 0xDB, 0xF7, 0x40, 0x98, 0x1C, 0xD9, - 0x9B, 0xEC, 0x12, 0x95, 0x9B, 0xEC, 0x40, 0x44, - 0x02, 0x4E, 0x0F, 0x9F, 0x86, 0xF0, 0x0A, 0xB3, - 0x08, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x07, 0xF0, 0x0A, 0xB3, 0x07, 0x00, 0x09, 0x05, - 0xA9, 0xEC, 0xC2, 0x94, 0x01, 0xD4, 0x09, 0x03, - 0xA1, 0xEC, 0xC1, 0x92, 0x19, 0xD3, 0x9B, 0xEC, - 0xC5, 0x94, 0x0A, 0xB5, 0x00, 0xFF, 0x01, 0xA5, - 0xC5, 0xD4, 0x0F, 0x9F, 0x13, 0xF0, 0x0A, 0x05, - 0xFF, 0xFF, 0x0A, 0x03, 0xB1, 0xEC, 0xC1, 0x92, - 0x01, 0xD2, 0x1A, 0xD5, 0x9B, 0xEC, 0xC5, 0x96, - 0x0B, 0x07, 0xFF, 0xFF, 0xC5, 0xD6, 0x11, 0x93, - 0x97, 0xEC, 0xC5, 0x98, 0xC1, 0xD8, 0x11, 0x93, - 0x97, 0xEC, 0x09, 0x05, 0x0B, 0x00, 0x03, 0xD4, - 0xC2, 0x96, 0x06, 0xD6, 0x7B, 0x95, 0x7A, 0x95, - 0x4C, 0x02, 0xC1, 0x92, 0x59, 0x93, 0x59, 0x93, - 0x01, 0xA5, 0x01, 0x98, 0x0C, 0xF5, 0x7B, 0x93, - 0x09, 0x09, 0x01, 0x00, 0x06, 0x92, 0x09, 0xB3, - 0xFF, 0x00, 0x04, 0xD2, 0x5C, 0x93, 0x59, 0x93, - 0x04, 0x94, 0x01, 0xA5, 0x03, 0x96, 0xC3, 0xD4, - 0x11, 0x93, 0x97, 0xEC, 0x4C, 0x02, 0x05, 0xD2, - 0xC1, 0x92, 0x09, 0xB3, 0x00, 0xFF, 0x7C, 0x95, - 0x7A, 0x95, 0x02, 0xA3, 0x05, 0x98, 0xC4, 0xD2, - 0x12, 0x95, 0x97, 0xEC, 0x45, 0x04, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xA3, 0x00, 0x01, 0xC2, 0xD2, - 0x12, 0x95, 0x9B, 0xEC, 0x0A, 0xB3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x5B, 0xF0, - 0x12, 0x95, 0x97, 0xEC, 0x4A, 0x04, 0x02, 0x99, - 0xC4, 0x92, 0x01, 0x98, 0x0C, 0xF3, 0x7B, 0x93, - 0x41, 0x02, 0x0F, 0x9F, 0x7C, 0xF0, 0x43, 0x44, - 0x02, 0x8E, 0x0F, 0x9F, 0x7D, 0xF0, 0x11, 0x93, - 0x97, 0xEC, 0x42, 0x02, 0x0A, 0x05, 0xFF, 0xFF, - 0xC1, 0xD4, 0x11, 0x93, 0x97, 0xEC, 0x4A, 0x02, - 0x12, 0x95, 0x60, 0x96, 0xC1, 0xD4, 0x12, 0x95, - 0x97, 0xEC, 0x4B, 0x04, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0x1F, 0xFF, 0xC2, 0xD2, 0x12, 0x95, - 0x97, 0xEC, 0x4B, 0x04, 0x11, 0x93, 0x62, 0x96, - 0x41, 0x93, 0x59, 0x93, 0x02, 0x99, 0xC4, 0xA2, - 0xC2, 0xD2, 0xC5, 0x92, 0x19, 0xD3, 0x98, 0xEC, - 0x0A, 0x95, 0x0C, 0x02, 0x1A, 0xD5, 0x02, 0x80, - 0x0F, 0x9F, 0xB1, 0xF0, 0x09, 0x63, 0xFE, 0x7F, - 0x01, 0x97, 0xC3, 0x94, 0x0A, 0xA5, 0x00, 0x04, - 0xC1, 0xD4, 0x11, 0x93, 0x9F, 0xEC, 0x09, 0xA3, - 0x00, 0x01, 0x19, 0xD3, 0x9F, 0xEC, 0x40, 0xF0, - 0x39, 0xEF, 0x0F, 0x9F, 0xB1, 0xF0, 0x11, 0x93, - 0x94, 0xEC, 0x41, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0xA6, 0xF0, 0x40, 0xF0, 0x39, 0xEF, 0x11, 0x93, - 0x95, 0xEC, 0x44, 0xB2, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xB1, 0xF0, 0x48, 0x98, 0x1C, 0xD9, - 0x02, 0x80, 0x11, 0x93, 0x91, 0xEC, 0x41, 0x22, - 0x0A, 0x95, 0xB1, 0xF0, 0x88, 0xD4, 0x88, 0xDC, - 0x91, 0x9A, 0x47, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0x04, 0x82, 0x48, 0xB2, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xC8, 0xF0, 0x0A, 0x65, 0xFD, 0x7D, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xFF, 0xFE, - 0xC2, 0xD2, 0x41, 0x92, 0x19, 0xD3, 0xBF, 0xEC, - 0x11, 0x93, 0x04, 0x82, 0x43, 0xB2, 0x12, 0x95, - 0x03, 0x82, 0x02, 0xB3, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xEF, 0xF0, 0x0A, 0xB3, 0x00, 0xFF, - 0x48, 0xA2, 0x19, 0xD3, 0x03, 0x82, 0x40, 0xF0, - 0xEB, 0xF3, 0x11, 0x93, 0xBF, 0xEC, 0x41, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xEF, 0xF0, 0x11, 0x93, - 0x07, 0x82, 0x11, 0x43, 0x03, 0xEC, 0x02, 0x0E, - 0x0F, 0x9F, 0xEF, 0xF0, 0x11, 0x93, 0x03, 0x82, - 0x09, 0xA3, 0x00, 0x01, 0x19, 0xD3, 0x03, 0x82, - 0x40, 0x96, 0x1B, 0xD7, 0xBF, 0xEC, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x11, 0x93, 0x20, 0xBC, 0xC8, 0xD2, - 0x40, 0xF0, 0x48, 0xF1, 0x41, 0x00, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x42, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x0D, 0x03, 0x05, 0x00, 0x05, 0x94, - 0x41, 0x02, 0xC1, 0x92, 0x01, 0x97, 0xC3, 0x96, - 0xC2, 0xD6, 0x0A, 0x45, 0x00, 0x95, 0x02, 0x5E, - 0x0F, 0x9F, 0x45, 0xF1, 0xC1, 0x92, 0x41, 0xB2, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x45, 0xF1, - 0x11, 0x93, 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x45, 0xF1, 0x41, 0x98, 0x1C, 0xD9, - 0xC0, 0xEC, 0x12, 0x95, 0x02, 0x80, 0x01, 0xD4, - 0x40, 0xF0, 0x56, 0xF2, 0x0B, 0x67, 0xFD, 0x7D, - 0x03, 0x99, 0xC4, 0x92, 0x0C, 0x99, 0x96, 0x03, - 0x1C, 0xD9, 0x06, 0x82, 0x41, 0x98, 0x1C, 0xD9, - 0x02, 0x82, 0x42, 0x98, 0x1C, 0xD9, 0x05, 0x82, - 0x0C, 0x69, 0x80, 0x7F, 0x1C, 0xD9, 0x00, 0xB0, - 0x09, 0xA3, 0x00, 0x01, 0xC3, 0xD2, 0x01, 0x94, - 0x0A, 0xB3, 0x04, 0x00, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x43, 0xF1, 0x42, 0xA4, 0x1A, 0xD5, - 0x02, 0x80, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x42, 0x20, 0x08, 0x0B, 0x01, 0x00, - 0x05, 0x92, 0xC5, 0xD2, 0x60, 0xB2, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x55, 0xF1, 0x40, 0xF0, - 0x35, 0xF7, 0xC5, 0x94, 0x0A, 0xB3, 0x10, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x5E, 0xF1, - 0x40, 0xF0, 0x23, 0xF6, 0xC5, 0x96, 0x0B, 0xB3, - 0x40, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x67, 0xF1, 0x40, 0xF0, 0x5D, 0xF5, 0xC5, 0x94, - 0x0A, 0xB3, 0x01, 0x00, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xC8, 0xF1, 0x13, 0x97, 0x21, 0xBC, - 0x01, 0xD6, 0x0B, 0xB3, 0x02, 0x00, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x79, 0xF1, 0x40, 0xF0, - 0x62, 0xFB, 0x01, 0x94, 0x0A, 0xB3, 0x04, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x82, 0xF1, - 0x40, 0xF0, 0x6C, 0xFB, 0x01, 0x96, 0x0B, 0xB3, - 0x01, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xA2, 0xF1, 0x40, 0xF0, 0xB0, 0xFA, 0x41, 0x92, - 0x19, 0xD3, 0xD5, 0xF7, 0x11, 0x93, 0x03, 0xEC, - 0x09, 0x43, 0x40, 0x00, 0x02, 0x5E, 0x0F, 0x9F, - 0x98, 0xF1, 0x40, 0x94, 0x1A, 0xD5, 0xD5, 0xF7, - 0x11, 0x93, 0x00, 0xEC, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xAB, 0xF1, 0x40, 0xF0, 0x38, 0xF2, - 0x0F, 0x9F, 0xAB, 0xF1, 0x01, 0x96, 0x0B, 0xB3, - 0x08, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xAB, 0xF1, 0x40, 0xF0, 0x7C, 0xFB, 0x01, 0x94, - 0x0A, 0xB3, 0x10, 0x00, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0xB4, 0xF1, 0x40, 0xF0, 0x87, 0xFB, - 0x11, 0x93, 0x10, 0xEC, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xBF, 0xF1, 0x44, 0x96, 0x1B, 0xD7, - 0x0B, 0xBC, 0x0F, 0x9F, 0xC5, 0xF1, 0x41, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0xC5, 0xF1, 0x19, 0xD3, - 0x0B, 0xBC, 0x40, 0x92, 0x19, 0xD3, 0x10, 0xEC, - 0xC5, 0x94, 0x0A, 0xB3, 0x80, 0x00, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x12, 0xF2, 0x13, 0x97, - 0x28, 0xBC, 0x01, 0xD6, 0x0B, 0xB3, 0x40, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0xDA, 0xF1, - 0x40, 0xF0, 0x18, 0xF7, 0x01, 0x94, 0x0A, 0xB3, - 0x02, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xED, 0xF1, 0x40, 0xF0, 0xC4, 0xEE, 0x40, 0xF0, - 0x8F, 0xFB, 0x40, 0xF0, 0x1B, 0xF2, 0x40, 0x96, - 0x1B, 0xD7, 0x00, 0xEC, 0x41, 0x92, 0x19, 0xD3, - 0xD8, 0xF7, 0x01, 0x94, 0x0A, 0xB3, 0x04, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x09, 0xF2, - 0x40, 0xF0, 0x9E, 0xFB, 0x09, 0x63, 0x00, 0x44, - 0x01, 0x97, 0xC3, 0x94, 0x48, 0xA4, 0xC1, 0xD4, - 0x00, 0xEE, 0x40, 0x92, 0x19, 0xD3, 0x12, 0x95, - 0x19, 0xD3, 0x10, 0x95, 0x19, 0xD3, 0x02, 0x80, - 0x19, 0xD3, 0x03, 0x82, 0x41, 0x92, 0x19, 0xD3, - 0xD8, 0xF7, 0x01, 0x94, 0x0A, 0xB3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x12, 0xF2, - 0x40, 0xF0, 0xAE, 0xFB, 0x0A, 0x65, 0x00, 0x44, - 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, 0xC2, 0xD2, - 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x09, 0x63, 0x00, 0x40, - 0x19, 0xD3, 0xF2, 0xBD, 0x0A, 0x65, 0xEA, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, 0xC2, 0xD2, - 0x0A, 0x65, 0xE9, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xA3, 0x40, 0x00, 0xC2, 0xD2, 0x0A, 0x65, - 0xEB, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0xC0, 0x00, 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x09, 0x63, - 0x00, 0x80, 0x19, 0xD3, 0xF2, 0xBD, 0x0A, 0x65, - 0xE8, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0xC0, 0x00, 0xC2, 0xD2, 0x0A, 0x65, 0xEB, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xBF, 0xFF, - 0xC2, 0xD2, 0x0A, 0x65, 0xEA, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xB3, 0xFB, 0xFF, 0xC2, 0xD2, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x09, 0x93, 0x00, 0x01, 0x19, 0xD3, - 0x02, 0x80, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x09, 0x93, 0x00, 0x09, - 0x19, 0xD3, 0x02, 0x80, 0x40, 0xF0, 0x56, 0xF2, - 0x40, 0x92, 0x19, 0xD3, 0x94, 0xEC, 0xC8, 0xD2, - 0x09, 0x93, 0x91, 0xEC, 0xC8, 0xD2, 0x40, 0xF0, - 0x2A, 0xEF, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, - 0x3B, 0xF5, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x85, 0xF2, 0x0A, 0x65, 0xFE, 0x7F, 0x02, 0x97, - 0xC3, 0x92, 0x44, 0xA2, 0xC2, 0xD2, 0x0F, 0x9F, - 0x92, 0xF2, 0x40, 0xF0, 0x94, 0xF2, 0x40, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0x92, 0xF2, 0xC8, 0xD2, - 0x09, 0x93, 0x91, 0xEC, 0xC8, 0xD2, 0x40, 0xF0, - 0x2A, 0xEF, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0xF1, 0xBD, 0x19, 0xD3, 0xB6, 0xEC, 0x11, 0x93, - 0xB4, 0xEC, 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0xAC, 0xF2, 0x09, 0x63, 0x00, 0x80, 0x01, 0x97, - 0xC3, 0x94, 0x0A, 0x07, 0x07, 0x00, 0xC1, 0xD6, - 0x0A, 0x05, 0x00, 0xA0, 0x1A, 0xD5, 0x96, 0xEC, - 0x11, 0x93, 0xB6, 0xEC, 0x19, 0xD3, 0x01, 0x80, - 0x0A, 0x65, 0xFE, 0x7F, 0x02, 0x97, 0xC3, 0x92, - 0x41, 0xA2, 0xC2, 0xD2, 0x40, 0x92, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x41, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x13, 0x97, 0xB4, 0xEC, 0x40, 0x46, - 0x02, 0x5E, 0x0F, 0x9F, 0x2C, 0xF3, 0x12, 0x95, - 0x96, 0xEC, 0x0A, 0x03, 0x07, 0x00, 0xC1, 0x92, - 0xC2, 0xD2, 0x11, 0x93, 0x96, 0xEC, 0x09, 0x05, - 0x01, 0x00, 0x48, 0x02, 0xC1, 0x92, 0xC2, 0xD2, - 0x11, 0x93, 0x96, 0xEC, 0x4E, 0x02, 0xC1, 0x94, - 0xC5, 0xD6, 0xC5, 0x92, 0x11, 0x07, 0x96, 0xEC, - 0x0B, 0x03, 0x0F, 0x00, 0xC1, 0x98, 0x46, 0x06, - 0x7A, 0x93, 0x79, 0x93, 0x5C, 0x95, 0x5A, 0x95, - 0x02, 0xA3, 0xC3, 0xD2, 0x04, 0x95, 0xC5, 0x96, - 0x41, 0x06, 0xC5, 0xD6, 0x42, 0x46, 0x02, 0x9E, - 0x0F, 0x9F, 0xD5, 0xF2, 0x11, 0x93, 0x96, 0xEC, - 0x09, 0x05, 0x05, 0x00, 0x41, 0x02, 0xC1, 0x92, - 0xC2, 0xD2, 0x11, 0x93, 0x96, 0xEC, 0xC1, 0x92, - 0x09, 0xB5, 0x1F, 0x00, 0x43, 0x44, 0x02, 0x8E, - 0x0F, 0x9F, 0x02, 0xF3, 0x40, 0x44, 0x02, 0x4E, - 0x0F, 0x9F, 0x03, 0xF3, 0x0A, 0x05, 0xFF, 0xFF, - 0x0F, 0x9F, 0x03, 0xF3, 0x43, 0x94, 0x11, 0x93, - 0x96, 0xEC, 0x42, 0x02, 0xC1, 0xD4, 0x11, 0x93, - 0x96, 0xEC, 0x49, 0x02, 0xC1, 0x92, 0x19, 0xD3, - 0xB4, 0xEC, 0x09, 0x05, 0xF2, 0xFF, 0x1A, 0xD5, - 0x92, 0xEC, 0x09, 0x43, 0xD0, 0x07, 0x02, 0x9E, - 0x0F, 0x9F, 0x2C, 0xF3, 0x11, 0x93, 0xDC, 0xF7, - 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, 0x11, 0x93, - 0xDB, 0xF7, 0x09, 0xA3, 0x40, 0x00, 0x19, 0xD3, - 0xDB, 0xF7, 0x09, 0x63, 0x00, 0x80, 0x01, 0x95, - 0xC2, 0x94, 0x1A, 0xD5, 0xB5, 0xEC, 0x40, 0x96, - 0x1B, 0xD7, 0xB4, 0xEC, 0x0F, 0x9F, 0x92, 0xF3, - 0x11, 0x93, 0x92, 0xEC, 0x12, 0x95, 0xB6, 0xEC, - 0x02, 0x43, 0x02, 0x8E, 0x0F, 0x9F, 0x7A, 0xF3, - 0x02, 0x0E, 0x0F, 0x9F, 0x4D, 0xF3, 0x11, 0x93, - 0xDC, 0xF7, 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, - 0x11, 0x93, 0xDB, 0xF7, 0x09, 0xA3, 0x80, 0x00, - 0x19, 0xD3, 0xDB, 0xF7, 0x09, 0x63, 0x00, 0x80, - 0x01, 0x95, 0xC2, 0x94, 0x1A, 0xD5, 0xB5, 0xEC, - 0x40, 0x96, 0x1B, 0xD7, 0xB4, 0xEC, 0x0F, 0x9F, - 0x92, 0xF3, 0x11, 0x93, 0x03, 0x80, 0x09, 0xB3, - 0x00, 0x40, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x5F, 0xF3, 0x11, 0x93, 0xC0, 0xEC, 0x40, 0x42, - 0x02, 0x5E, 0x0F, 0x9F, 0x5F, 0xF3, 0x40, 0xF0, - 0xA6, 0xF3, 0x0F, 0x9F, 0x94, 0xF3, 0x41, 0x92, - 0xC8, 0xD2, 0x0A, 0x95, 0x91, 0xEC, 0xC8, 0xD4, - 0x40, 0xF0, 0x2A, 0xEF, 0x42, 0x00, 0x11, 0x93, - 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x72, 0xF3, 0x42, 0x96, 0x1B, 0xD7, 0xC0, 0xEC, - 0x0F, 0x9F, 0x94, 0xF3, 0x0A, 0x65, 0xFE, 0x7F, - 0x02, 0x97, 0xC3, 0x92, 0x42, 0xA2, 0xC2, 0xD2, - 0x0F, 0x9F, 0x94, 0xF3, 0x12, 0x45, 0x03, 0xEC, - 0x02, 0x4E, 0x0F, 0x9F, 0x8C, 0xF3, 0x11, 0x93, - 0xDC, 0xF7, 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, - 0x11, 0x93, 0xDB, 0xF7, 0x09, 0xA3, 0x00, 0x08, - 0x19, 0xD3, 0xDB, 0xF7, 0x1A, 0xD5, 0x92, 0xEC, - 0x11, 0x93, 0x92, 0xEC, 0x19, 0x25, 0x92, 0xEC, - 0x09, 0x63, 0x00, 0x80, 0x19, 0xD3, 0xF2, 0xBD, - 0x41, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, 0xA6, 0xF3, - 0x40, 0x92, 0xC8, 0xD2, 0x09, 0x93, 0x91, 0xEC, - 0xC8, 0xD2, 0x40, 0xF0, 0x2A, 0xEF, 0x42, 0x00, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x11, 0x93, 0xD7, 0xF7, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xB6, 0xF3, 0x0A, 0x65, - 0xBC, 0x69, 0x02, 0x97, 0xC3, 0x92, 0x09, 0x83, - 0x00, 0x02, 0xC2, 0xD2, 0x11, 0x93, 0x03, 0x80, - 0x09, 0xB3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xC9, 0xF3, 0x11, 0x93, 0xDC, 0xF7, - 0x41, 0x02, 0x19, 0xD3, 0xDC, 0xF7, 0x11, 0x93, - 0xDB, 0xF7, 0x09, 0xA3, 0x00, 0x20, 0x19, 0xD3, - 0xDB, 0xF7, 0x11, 0x93, 0xB5, 0xEC, 0x19, 0xD3, - 0x04, 0x80, 0x12, 0x95, 0xB4, 0xEC, 0x1A, 0xD5, - 0x05, 0x80, 0x09, 0x63, 0x00, 0x80, 0x01, 0x97, - 0xC3, 0x96, 0x1B, 0xD7, 0xB5, 0xEC, 0x40, 0x94, - 0x1A, 0xD5, 0xB4, 0xEC, 0x19, 0xD3, 0xF2, 0xBD, - 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, - 0x01, 0x00, 0x09, 0x93, 0x96, 0x03, 0x19, 0xD3, - 0x06, 0x82, 0x09, 0x93, 0x00, 0x01, 0x19, 0xD3, - 0x03, 0x82, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x47, 0x20, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0x01, 0x82, 0xC5, 0xD2, 0x40, 0x94, 0x01, 0xD4, - 0x13, 0x97, 0xB8, 0xEC, 0x02, 0xD6, 0x03, 0x95, - 0x0C, 0x99, 0xBB, 0xEC, 0x04, 0x05, 0x13, 0x97, - 0x03, 0xEC, 0x01, 0x27, 0x02, 0x99, 0xC4, 0x92, - 0x03, 0x03, 0xC2, 0xD2, 0x14, 0x99, 0xBA, 0xEC, - 0x03, 0x09, 0x1C, 0xD9, 0xBA, 0xEC, 0x12, 0x95, - 0x04, 0x82, 0x0A, 0xB3, 0x02, 0x00, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0x29, 0xF5, 0x01, 0x92, - 0x03, 0xD2, 0x0A, 0xA3, 0x02, 0x00, 0x19, 0xD3, - 0x04, 0x82, 0x02, 0x96, 0x0B, 0x05, 0x01, 0x00, - 0x1A, 0xD5, 0xB8, 0xEC, 0xC5, 0x92, 0x43, 0x42, - 0x02, 0x9E, 0x0F, 0x9F, 0x37, 0xF4, 0x42, 0x44, - 0x02, 0x8E, 0x0F, 0x9F, 0x37, 0xF4, 0x11, 0x93, - 0xBF, 0xEC, 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0x37, 0xF4, 0x0C, 0x49, 0xD3, 0x08, 0x02, 0x8E, - 0x0F, 0x9F, 0x37, 0xF4, 0x11, 0x63, 0x07, 0x82, - 0x11, 0xA3, 0x07, 0x82, 0x71, 0x93, 0x79, 0x93, - 0x79, 0x93, 0x79, 0x93, 0x03, 0xD2, 0xC5, 0x94, - 0x0A, 0xB5, 0xFC, 0xFF, 0x04, 0xD4, 0x03, 0x96, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0x46, 0xF4, - 0x11, 0x93, 0xB8, 0xEC, 0x41, 0x42, 0x02, 0x8E, - 0x0F, 0x9F, 0x4D, 0xF4, 0xC5, 0x98, 0x0C, 0x03, - 0xFF, 0xFF, 0x42, 0x42, 0x02, 0x8E, 0x0F, 0x9F, - 0x74, 0xF4, 0x0A, 0x95, 0xBB, 0xEC, 0x42, 0x92, - 0x19, 0xD3, 0xB9, 0xEC, 0xC5, 0x96, 0x43, 0x46, - 0x02, 0x9E, 0x0F, 0x9F, 0x66, 0xF4, 0x0B, 0x07, - 0xFC, 0xFF, 0xC5, 0xD6, 0xD2, 0x98, 0x1C, 0xD9, - 0xC8, 0xBC, 0xD2, 0x96, 0x1B, 0xD7, 0xCA, 0xBC, - 0x09, 0x03, 0xFF, 0xFF, 0x40, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x52, 0xF4, 0x19, 0xD3, 0xB9, 0xEC, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0x72, 0xF4, - 0x0A, 0x05, 0xFE, 0xFF, 0xCA, 0xD2, 0xC2, 0xD2, - 0x0F, 0x9F, 0x74, 0xF4, 0x1A, 0xD5, 0x93, 0xEC, - 0x03, 0x98, 0x40, 0x48, 0x02, 0x5E, 0x0F, 0x9F, - 0xA1, 0xF4, 0x11, 0x93, 0xB8, 0xEC, 0x41, 0x42, - 0x02, 0x9E, 0x0F, 0x9F, 0x84, 0xF4, 0x04, 0x94, - 0x48, 0x44, 0x02, 0x4E, 0x0F, 0x9F, 0x8F, 0xF4, - 0x41, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0xA1, 0xF4, - 0x11, 0x93, 0x04, 0x82, 0x41, 0xB2, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xA1, 0xF4, 0x41, 0x96, - 0x01, 0xD6, 0x0A, 0x65, 0xBD, 0x43, 0x02, 0x99, - 0xC4, 0x92, 0x09, 0xA3, 0x80, 0x00, 0xC2, 0xD2, - 0x0A, 0x65, 0xE8, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0xBF, 0xFF, 0xC2, 0xD2, 0x0F, 0x9F, - 0xFA, 0xF4, 0xC5, 0x98, 0x43, 0x48, 0x02, 0x9E, - 0x0F, 0x9F, 0xFA, 0xF4, 0x4F, 0x96, 0x0C, 0xB3, - 0x01, 0x00, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xAE, 0xF4, 0x47, 0x96, 0x11, 0x93, 0xB7, 0xEC, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0xD6, 0xF4, - 0x11, 0x93, 0xB8, 0xEC, 0x41, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0xD6, 0xF4, 0x12, 0x95, 0x00, 0x82, - 0x0A, 0x05, 0xFF, 0xAF, 0x05, 0xD4, 0xC8, 0xD6, - 0xC8, 0xD2, 0x40, 0xF0, 0x7B, 0xF7, 0x42, 0x00, - 0x05, 0x96, 0xC3, 0x94, 0x01, 0xB5, 0x40, 0x44, - 0x02, 0x4E, 0x0F, 0x9F, 0xD6, 0xF4, 0x06, 0x98, - 0x50, 0x98, 0x1C, 0xD9, 0xA2, 0xBC, 0x40, 0x98, - 0x1C, 0xD9, 0xA2, 0xBC, 0x40, 0x92, 0x03, 0xD2, - 0x0F, 0x9F, 0xFF, 0xF4, 0x03, 0x94, 0x40, 0x44, - 0x02, 0x5E, 0x0F, 0x9F, 0xE3, 0xF4, 0x0A, 0x65, - 0x5E, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x48, 0xA2, - 0xC2, 0xD2, 0x0F, 0x9F, 0xFF, 0xF4, 0x11, 0x93, - 0xB8, 0xEC, 0x0C, 0x99, 0xBB, 0xEC, 0x04, 0x03, - 0x04, 0x96, 0x13, 0x25, 0x03, 0xEC, 0xC1, 0xD4, - 0x11, 0x93, 0xBA, 0xEC, 0x19, 0x05, 0xBA, 0xEC, - 0x1B, 0xD7, 0x01, 0x82, 0x0A, 0x65, 0xFD, 0x7D, - 0x02, 0x99, 0xC4, 0x92, 0x43, 0xA2, 0xC2, 0xD2, - 0x41, 0x92, 0x01, 0xD2, 0x03, 0x94, 0x40, 0x44, - 0x02, 0x5E, 0x0F, 0x9F, 0x13, 0xF5, 0x11, 0x93, - 0xB9, 0xEC, 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0x0B, 0xF5, 0x19, 0xD3, 0xB8, 0xEC, 0x19, 0xD3, - 0xBA, 0xEC, 0x19, 0xD3, 0xBB, 0xEC, 0x03, 0x96, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0x13, 0xF5, - 0x41, 0x98, 0x1C, 0xD9, 0xB7, 0xEC, 0x11, 0x93, - 0xBF, 0xEC, 0x41, 0x42, 0x02, 0x5E, 0x0F, 0x9F, - 0x24, 0xF5, 0x11, 0x93, 0x00, 0x82, 0x19, 0xD3, - 0x02, 0x82, 0x0A, 0x65, 0xFD, 0x7D, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xA3, 0x00, 0x01, 0xC2, 0xD2, - 0x40, 0x98, 0x1C, 0xD9, 0xBF, 0xEC, 0x0F, 0x9F, - 0x2C, 0xF5, 0x01, 0x92, 0x19, 0xD3, 0xB7, 0xEC, - 0x01, 0x94, 0x40, 0x44, 0x02, 0x5E, 0x0F, 0x9F, - 0x38, 0xF5, 0x0A, 0x65, 0xEA, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xB3, 0xFB, 0xFF, 0xC2, 0xD2, - 0x47, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x12, 0x95, 0x03, 0x80, - 0x0A, 0xB3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x57, 0xF5, 0x0A, 0xB7, 0x00, 0x08, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0x5A, 0xF5, - 0x11, 0x93, 0x03, 0xEC, 0x41, 0x02, 0x09, 0xB3, - 0xFE, 0xFF, 0x12, 0x95, 0x07, 0x80, 0x01, 0x45, - 0x02, 0x8E, 0x0F, 0x9F, 0x5A, 0xF5, 0x41, 0x92, - 0x0F, 0x9F, 0x5B, 0xF5, 0x40, 0x92, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x41, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x0A, 0x65, 0xE9, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x09, 0xA3, 0x40, 0x00, 0xC2, 0xD2, - 0x13, 0x97, 0x6E, 0xEC, 0x0B, 0x47, 0xA0, 0x00, - 0x02, 0x5E, 0x0F, 0x9F, 0x86, 0xF5, 0x09, 0x63, - 0x08, 0x43, 0x0A, 0x65, 0xFF, 0x5F, 0x01, 0x99, - 0xC4, 0xD4, 0x0A, 0x95, 0x9B, 0xEC, 0xD2, 0x96, - 0x1B, 0xD7, 0xFA, 0xBC, 0xD2, 0x96, 0xC4, 0xD6, - 0xD2, 0x98, 0x1C, 0xD9, 0xFA, 0xBC, 0xD2, 0x96, - 0xC1, 0xD6, 0xC2, 0x94, 0x1A, 0xD5, 0xFA, 0xBC, - 0x0F, 0x9F, 0xC4, 0xF5, 0x0C, 0x69, 0xFF, 0x6F, - 0x1C, 0xD9, 0xF8, 0xBC, 0x0B, 0x47, 0x10, 0x95, - 0x02, 0x5E, 0x0F, 0x9F, 0x9E, 0xF5, 0x0A, 0x95, - 0x6F, 0xEC, 0x09, 0x63, 0x06, 0x43, 0x01, 0x99, - 0xC4, 0xD6, 0xD2, 0x96, 0x1B, 0xD7, 0xF8, 0xBC, - 0x0C, 0x69, 0xEE, 0x6A, 0xC1, 0xD8, 0xC2, 0x94, - 0x1A, 0xD5, 0xF8, 0xBC, 0x40, 0x92, 0xC5, 0xD2, - 0x11, 0x43, 0xC1, 0xEC, 0x02, 0x0E, 0x0F, 0x9F, - 0xC1, 0xF5, 0xC5, 0x94, 0x0A, 0x03, 0x71, 0xEC, - 0xC1, 0x94, 0x1A, 0xD5, 0xFA, 0xBC, 0x11, 0x93, - 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0xB3, 0xF5, 0x0A, 0x95, 0x6F, 0xEC, 0xC8, 0xD4, - 0x40, 0xF0, 0x9C, 0xF7, 0x19, 0xD3, 0xF8, 0xBC, - 0x41, 0x00, 0xC5, 0x96, 0x41, 0x06, 0xC5, 0xD6, - 0x13, 0x47, 0xC1, 0xEC, 0x02, 0x1E, 0x0F, 0x9F, - 0xA5, 0xF5, 0x40, 0x98, 0x1C, 0xD9, 0xFA, 0xBC, - 0x40, 0x92, 0x19, 0xD3, 0x6E, 0xEC, 0x19, 0xD3, - 0xC1, 0xEC, 0x0A, 0x65, 0x52, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x48, 0xA2, 0xC2, 0xD2, 0x0A, 0x65, - 0xEB, 0x43, 0x02, 0x99, 0xC4, 0x92, 0x09, 0xB3, - 0xBF, 0xFF, 0xC2, 0xD2, 0x41, 0x00, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x43, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x06, 0x92, 0x01, 0xD2, 0x0A, 0x65, - 0xF0, 0x6A, 0x0B, 0x97, 0x6F, 0xEC, 0x02, 0x99, - 0xC4, 0x98, 0xD3, 0xD8, 0x02, 0xD6, 0x0A, 0x03, - 0x02, 0x00, 0x01, 0x97, 0xC3, 0x98, 0x02, 0x96, - 0xC3, 0xD8, 0x01, 0x96, 0xC1, 0xD6, 0x1A, 0xD5, - 0x6E, 0xEC, 0xC5, 0x98, 0x14, 0x99, 0x6F, 0xEC, - 0xC2, 0xD8, 0x43, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0x92, - 0xC8, 0xD2, 0x40, 0xF0, 0xD9, 0xF5, 0x41, 0x00, - 0x11, 0x93, 0xC0, 0xEC, 0x40, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x13, 0xF6, 0x42, 0x42, 0x02, 0x5E, - 0x0F, 0x9F, 0x10, 0xF6, 0x0A, 0x65, 0xFE, 0x7F, - 0x02, 0x97, 0xC3, 0x92, 0x42, 0xA2, 0xC2, 0xD2, - 0x40, 0x92, 0x19, 0xD3, 0xC0, 0xEC, 0x0A, 0x65, - 0xEB, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0xC0, 0x00, 0xC2, 0xD2, 0x0A, 0x65, 0xE9, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xBF, 0xFF, - 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x63, 0x20, 0x08, 0x0B, 0x01, 0x00, 0x11, 0x93, - 0xAF, 0xBC, 0x47, 0xB2, 0x59, 0x95, 0x5A, 0x95, - 0x12, 0xA5, 0xBF, 0xBC, 0x0A, 0xB3, 0x01, 0x00, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x35, 0xF6, - 0x41, 0x04, 0x05, 0x93, 0x40, 0x96, 0x20, 0xD6, - 0x62, 0x97, 0x0F, 0x9F, 0x44, 0xF6, 0x14, 0x99, - 0xFC, 0xBC, 0xD1, 0xD8, 0x14, 0x99, 0xFE, 0xBC, - 0xD1, 0xD8, 0x20, 0x98, 0x42, 0x08, 0x20, 0xD8, - 0x20, 0x98, 0x03, 0x49, 0x02, 0x1E, 0x0F, 0x9F, - 0x3B, 0xF6, 0xC5, 0x92, 0x62, 0x42, 0x02, 0x4E, - 0x0F, 0x9F, 0x5D, 0xF6, 0x02, 0x8E, 0x0F, 0x9F, - 0x57, 0xF6, 0x61, 0x42, 0x02, 0x4E, 0x0F, 0x9F, - 0x81, 0xF6, 0x0F, 0x9F, 0xAE, 0xF6, 0x63, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xA4, 0xF6, 0x0F, 0x9F, - 0xAE, 0xF6, 0x0D, 0x03, 0x01, 0x00, 0x0C, 0x99, - 0x71, 0xEC, 0x0B, 0x05, 0xFF, 0xFF, 0x40, 0x96, - 0x0F, 0x9F, 0x6A, 0xF6, 0xD1, 0x96, 0xD4, 0xD6, - 0x20, 0x96, 0x41, 0x06, 0x20, 0xD6, 0x02, 0x47, - 0x02, 0x1E, 0x0F, 0x9F, 0x66, 0xF6, 0x1A, 0xD5, - 0xC1, 0xEC, 0x0A, 0x65, 0xEB, 0x43, 0x02, 0x99, - 0xC4, 0x92, 0x09, 0xA3, 0xC0, 0x00, 0xC2, 0xD2, - 0x0A, 0x65, 0xE9, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0xBF, 0xFF, 0xC2, 0xD2, 0x0F, 0x9F, - 0xAE, 0xF6, 0x0A, 0x03, 0xFE, 0xFF, 0x61, 0x95, - 0x40, 0x98, 0x20, 0xD8, 0x02, 0x49, 0x02, 0x0E, - 0x0F, 0x9F, 0xAE, 0xF6, 0x0D, 0x03, 0x01, 0x00, - 0x21, 0xD2, 0x20, 0x92, 0x05, 0x03, 0x42, 0x02, - 0xC8, 0xD2, 0x21, 0x96, 0xC3, 0x92, 0x42, 0x06, - 0x21, 0xD6, 0xC8, 0xD2, 0x22, 0xD4, 0x40, 0xF0, - 0x01, 0xF1, 0x42, 0x00, 0x20, 0x98, 0x42, 0x08, - 0x20, 0xD8, 0x22, 0x94, 0x02, 0x49, 0x02, 0x1E, - 0x0F, 0x9F, 0x8D, 0xF6, 0x0F, 0x9F, 0xAE, 0xF6, - 0x0D, 0x03, 0x03, 0x00, 0xC8, 0xD2, 0x02, 0x92, - 0xC8, 0xD2, 0x01, 0x96, 0xC8, 0xD6, 0x40, 0xF0, - 0xB1, 0xF6, 0x43, 0x00, 0x63, 0x00, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x45, 0x20, 0x08, 0x0B, - 0x01, 0x00, 0x0D, 0x03, 0x08, 0x00, 0x08, 0x94, - 0xC5, 0xD4, 0x09, 0x05, 0x01, 0x00, 0xC2, 0x94, - 0x03, 0xD4, 0x42, 0x02, 0xC1, 0x92, 0x01, 0xD2, - 0x02, 0x97, 0xC5, 0x94, 0x0A, 0x83, 0xFF, 0xFF, - 0x11, 0xB3, 0x2C, 0x93, 0x09, 0xB3, 0xFB, 0xFF, - 0x19, 0xD3, 0x2C, 0x93, 0x03, 0x92, 0x40, 0x42, - 0x02, 0x4E, 0x0F, 0x9F, 0xE4, 0xF6, 0x01, 0x94, - 0xD2, 0x92, 0x19, 0xD3, 0x2C, 0x93, 0x01, 0xD4, - 0x02, 0x94, 0x12, 0x95, 0x2C, 0x93, 0x44, 0xA4, - 0x1A, 0xD5, 0x2C, 0x93, 0x0A, 0xB5, 0xFB, 0xFF, - 0x1A, 0xD5, 0x2C, 0x93, 0x0B, 0x07, 0xFF, 0xFF, - 0x40, 0x46, 0x02, 0x5E, 0x0F, 0x9F, 0xCF, 0xF6, - 0x09, 0x63, 0xD4, 0x6C, 0x01, 0x95, 0xC2, 0x96, - 0xC5, 0x94, 0x02, 0xA7, 0xC1, 0xD6, 0x03, 0x92, - 0x54, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0xF4, 0xF6, - 0x0A, 0x83, 0xFF, 0xFF, 0x1B, 0xB3, 0x2C, 0x93, - 0x45, 0x00, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x09, 0x63, 0x00, 0x40, - 0x19, 0xD3, 0xF2, 0xBD, 0x40, 0xF0, 0x3B, 0xF5, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0x08, 0xF7, - 0x40, 0xF0, 0x94, 0xF2, 0x0F, 0x9F, 0x16, 0xF7, - 0x40, 0x96, 0xC8, 0xD6, 0x09, 0x93, 0x91, 0xEC, - 0xC8, 0xD2, 0x40, 0xF0, 0x2A, 0xEF, 0x0A, 0x65, - 0xFE, 0x7F, 0x02, 0x97, 0xC3, 0x92, 0x44, 0xA2, - 0xC2, 0xD2, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x0A, 0x65, - 0xE8, 0x43, 0x02, 0x97, 0xC3, 0x92, 0x09, 0xA3, - 0x40, 0x00, 0xC2, 0xD2, 0x0A, 0x65, 0xEA, 0x43, - 0x02, 0x97, 0xC3, 0x92, 0x09, 0xB3, 0xFB, 0xFF, - 0xC2, 0xD2, 0x40, 0x92, 0x19, 0xD3, 0x2D, 0xBC, - 0x0A, 0x65, 0xD8, 0x43, 0x02, 0x97, 0xC3, 0x92, - 0x09, 0xB3, 0xBF, 0xFF, 0xC2, 0xD2, 0x88, 0x98, - 0x90, 0x9A, 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, - 0x09, 0x63, 0xEA, 0x43, 0x01, 0x97, 0xC3, 0x94, - 0x44, 0xA4, 0xC1, 0xD4, 0x11, 0x93, 0xB9, 0xEC, - 0x40, 0x42, 0x02, 0x4E, 0x0F, 0x9F, 0x6F, 0xF7, - 0x12, 0x95, 0x93, 0xEC, 0x0B, 0x67, 0x36, 0x43, - 0xD2, 0x98, 0x1C, 0xD9, 0xC8, 0xBC, 0xD2, 0x98, - 0x03, 0x93, 0xC1, 0xD8, 0x11, 0x93, 0xB9, 0xEC, - 0x09, 0x03, 0xFF, 0xFF, 0x19, 0xD3, 0xB9, 0xEC, - 0x40, 0x42, 0x02, 0x5E, 0x0F, 0x9F, 0x48, 0xF7, - 0x19, 0xD3, 0xB8, 0xEC, 0x19, 0xD3, 0xBA, 0xEC, - 0x0A, 0x05, 0xFE, 0xFF, 0xCA, 0xD2, 0xCA, 0xD2, - 0xC2, 0xD2, 0x0A, 0x65, 0x5E, 0x43, 0x02, 0x97, - 0xC3, 0x92, 0x48, 0xA2, 0xC2, 0xD2, 0x0A, 0x65, - 0xEA, 0x43, 0x02, 0x99, 0xC4, 0x92, 0x09, 0xB3, - 0xFB, 0xFF, 0x0F, 0x9F, 0x78, 0xF7, 0x11, 0x93, - 0x03, 0xEC, 0x19, 0xD3, 0x01, 0x82, 0x0A, 0x65, - 0xFD, 0x7D, 0x02, 0x97, 0xC3, 0x92, 0x43, 0xA2, - 0xC2, 0xD2, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x03, 0x92, 0x04, 0x96, - 0x0D, 0x5E, 0x50, 0x46, 0x02, 0x0E, 0x40, 0x92, - 0x09, 0xEE, 0x44, 0x46, 0x04, 0x0E, 0x59, 0x93, - 0x44, 0x26, 0x04, 0x5E, 0x46, 0xEE, 0x41, 0x93, - 0x41, 0x26, 0x43, 0x4E, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x40, 0xF0, - 0xB1, 0xFE, 0x88, 0x98, 0x90, 0x9A, 0x88, 0xDA, - 0x08, 0x0B, 0x01, 0x00, 0x88, 0x98, 0x90, 0x9A, - 0x88, 0xDA, 0x08, 0x0B, 0x01, 0x00, 0x03, 0x94, - 0x1A, 0xD5, 0xA3, 0xF7, 0x11, 0x93, 0x00, 0x90, - 0x88, 0x98, 0x90, 0x9A, 0x1D, 0x00, 0x1A, 0x00, - 0x03, 0x00, 0x03, 0x00, 0x18, 0x00, 0x19, 0x00, - 0x1A, 0x00, 0x1B, 0x00, 0x16, 0x00, 0x21, 0x00, - 0x12, 0x00, 0x09, 0x00, 0x13, 0x00, 0x19, 0x00, - 0x19, 0x00, 0x19, 0x00, 0x21, 0x00, 0x2D, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x69, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5F, 0xF2, 0xCD, 0xF7, 0x00, 0x00, 0x74, 0xF2, - 0xCD, 0xF7, 0x00, 0x00, 0xB9, 0xF2, 0xCA, 0xF7, - 0xD1, 0xF7, 0x00, 0x00, 0x97, 0xF3, 0xCD, 0xF7, - 0x05, 0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* - * current zd1211b firmware version. - */ -#define ZD1211B_FIRMWARE_VER 4705 - -uint8_t zd1211b_firmware[] = { - 0x08, 0x91, 0xff, 0xed, 0x09, 0x93, 0x1e, 0xee, 0xd1, 0x94, 0x11, - 0xee, 0x88, 0xd4, 0xd1, 0x96, 0xd1, 0x98, 0x5c, 0x99, 0x5c, 0x99, - 0x4c, 0x99, 0x04, 0x9d, 0xd1, 0x98, 0xd1, 0x9a, 0x03, 0xee, 0xf4, - 0x94, 0xd3, 0xd4, 0x41, 0x2a, 0x40, 0x4a, 0x45, 0xbe, 0x88, 0x92, - 0x41, 0x24, 0x40, 0x44, 0x53, 0xbe, 0x40, 0xf0, 0x4e, 0xee, 0x41, - 0xee, 0x98, 0x9a, 0x72, 0xf7, 0x02, 0x00, 0x1f, 0xec, 0x00, 0x00, - 0xb2, 0xf8, 0x4d, 0x00, 0xa1, 0xec, 0x00, 0x00, 0x43, 0xf7, 0x22, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xd8, - 0xa0, 0x90, 0x98, 0x9a, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x5a, - 0xf0, 0xa0, 0x90, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x0a, 0xef, - 0xa0, 0x90, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x97, 0xf0, 0xa0, - 0x90, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x94, 0xf6, 0xa0, 0x90, - 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x95, 0xf5, 0xa0, 0x90, 0x98, - 0x9a, 0x98, 0x9a, 0xa0, 0xd8, 0x40, 0xf0, 0x34, 0xf7, 0xa0, 0x90, - 0x98, 0x9a, 0x88, 0xda, 0x41, 0x20, 0x08, 0x0b, 0x01, 0x00, 0x40, - 0xf0, 0x8e, 0xee, 0x40, 0x96, 0x0a, 0x65, 0x00, 0x7d, 0x11, 0x93, - 0x76, 0xf7, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x57, 0xee, 0x40, - 0xf1, 0x1b, 0xd7, 0x76, 0xf7, 0xc5, 0x92, 0x02, 0x99, 0x41, 0x92, - 0xc4, 0xd2, 0x40, 0x92, 0xc4, 0xd2, 0x0f, 0x9f, 0x95, 0xf8, 0x0f, - 0x9f, 0x57, 0xee, 0x41, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x40, 0x92, 0x19, 0xd3, 0x12, 0x95, 0x19, - 0xd3, 0x10, 0x95, 0x19, 0xd3, 0x02, 0x80, 0x19, 0xd3, 0x03, 0x82, - 0x09, 0x93, 0x65, 0xf7, 0x19, 0xd3, 0x91, 0xec, 0x40, 0xf0, 0x07, - 0xf2, 0x40, 0xf0, 0x75, 0xf3, 0x11, 0x93, 0x04, 0xec, 0x42, 0x42, - 0x02, 0x5e, 0x0f, 0x9f, 0x8c, 0xee, 0x40, 0x92, 0x19, 0xd3, 0x04, - 0xec, 0x40, 0xf0, 0xe0, 0xf1, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0x44, 0x96, 0x09, 0xb3, 0xff, - 0xfd, 0x19, 0xd3, 0x44, 0x96, 0x40, 0xf0, 0x2d, 0xf7, 0x40, 0xf0, - 0x6d, 0xee, 0x4b, 0x62, 0x0a, 0x95, 0x2e, 0xee, 0xd1, 0xd4, 0x0b, - 0x97, 0x2b, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x00, 0xee, 0xd1, 0xd4, - 0x0b, 0x97, 0x2f, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x34, 0xee, 0xd1, - 0xd4, 0x0b, 0x97, 0x39, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x3e, 0xee, - 0xd1, 0xd4, 0x0b, 0x97, 0x43, 0xee, 0xd1, 0xd6, 0x0a, 0x95, 0x2e, - 0xee, 0xd1, 0xd4, 0x0b, 0x97, 0x48, 0xee, 0xd1, 0xd6, 0x0a, 0x95, - 0x49, 0xee, 0xc1, 0xd4, 0x0a, 0x65, 0x00, 0x44, 0x02, 0x97, 0xc3, - 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x43, 0xf1, 0x09, 0x93, 0x01, 0x3f, - 0x19, 0xd3, 0xc0, 0x85, 0x11, 0x93, 0x44, 0x96, 0x09, 0xb3, 0xff, - 0xfc, 0x19, 0xd3, 0x44, 0x96, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x0d, 0x03, 0x03, 0x00, 0x03, 0x96, 0x41, - 0x02, 0x03, 0x99, 0xc4, 0x94, 0x42, 0x04, 0xc1, 0x04, 0xc2, 0x94, - 0xc3, 0xd4, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x40, 0x92, 0x19, 0xd3, 0x94, 0xec, 0x13, 0x97, 0x95, 0xec, - 0x1b, 0xd7, 0x02, 0x80, 0x11, 0x93, 0x99, 0xec, 0x19, 0xd3, 0x7c, - 0x96, 0x0b, 0x97, 0xa0, 0x00, 0x1b, 0xd7, 0x6e, 0xec, 0x0a, 0x65, - 0x0e, 0x42, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xff, 0xbf, 0x11, - 0xa3, 0x9a, 0xec, 0xc2, 0xd2, 0x0a, 0x65, 0xeb, 0x43, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, 0xd2, 0x0a, 0x65, 0xe9, - 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, 0xc2, 0xd2, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x47, 0x20, 0x08, 0x0b, 0x01, - 0x00, 0x14, 0x99, 0x03, 0x80, 0x0c, 0xb3, 0x00, 0x10, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0x3d, 0xf0, 0x11, 0x93, 0x9f, 0xec, 0x41, - 0x02, 0x19, 0xd3, 0x9f, 0xec, 0x11, 0x93, 0x74, 0xf7, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0x2a, 0xef, 0x0a, 0x65, 0xfe, 0x7f, 0x02, - 0x97, 0xc3, 0x92, 0x09, 0xa3, 0x00, 0x04, 0xc2, 0xd2, 0x0f, 0x9f, - 0x57, 0xf0, 0x11, 0x93, 0x94, 0xec, 0x02, 0xd2, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x76, 0xef, 0x41, 0x92, 0x19, 0xd3, 0x94, 0xec, - 0x19, 0xd3, 0x9f, 0xec, 0x12, 0x95, 0x02, 0x80, 0x1a, 0xd5, 0x95, - 0xec, 0x13, 0x97, 0x7c, 0x96, 0x1b, 0xd7, 0x99, 0xec, 0x0a, 0x65, - 0x0e, 0x42, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0x00, 0x40, 0x19, - 0xd3, 0x9a, 0xec, 0x09, 0x63, 0x00, 0x40, 0xc2, 0xd2, 0x02, 0x94, - 0x1a, 0xd5, 0x7c, 0x96, 0x0c, 0xb3, 0x00, 0x08, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x56, 0xef, 0x0c, 0xb3, 0xff, 0x07, 0x0f, 0x9f, - 0x5a, 0xef, 0x11, 0x93, 0x06, 0x80, 0x09, 0xb3, 0xff, 0x07, 0x09, - 0x03, 0x00, 0xa0, 0x19, 0xd3, 0x97, 0xec, 0x40, 0x98, 0x0b, 0x97, - 0x9c, 0xec, 0x04, 0x95, 0x03, 0x05, 0x14, 0x03, 0x97, 0xec, 0x46, - 0x02, 0xc1, 0x92, 0xc2, 0xd2, 0x41, 0x08, 0x42, 0x48, 0x02, 0x9e, - 0x0f, 0x9f, 0x61, 0xef, 0x11, 0x93, 0x97, 0xec, 0xc1, 0x92, 0xc5, - 0xd2, 0x5f, 0xb2, 0x19, 0xd3, 0x9b, 0xec, 0x0f, 0x9f, 0x79, 0xef, - 0x13, 0x97, 0x98, 0xec, 0xc5, 0xd6, 0x11, 0x93, 0x03, 0x80, 0x09, - 0xb3, 0x00, 0x08, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x8f, 0xef, - 0x11, 0x93, 0x7a, 0xf7, 0x41, 0x02, 0x19, 0xd3, 0x7a, 0xf7, 0x11, - 0x93, 0x79, 0xf7, 0x09, 0xa3, 0x00, 0x10, 0x19, 0xd3, 0x79, 0xf7, - 0x40, 0x98, 0x1c, 0xd9, 0x9b, 0xec, 0x12, 0x95, 0x9b, 0xec, 0x40, - 0x44, 0x02, 0x4e, 0x0f, 0x9f, 0x2c, 0xf0, 0x0a, 0xb3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xad, 0xef, 0x0a, 0xb3, 0x07, - 0x00, 0x09, 0x05, 0xa9, 0xec, 0xc2, 0x94, 0x01, 0xd4, 0x09, 0x03, - 0xa1, 0xec, 0xc1, 0x92, 0x19, 0xd3, 0x9b, 0xec, 0xc5, 0x94, 0x0a, - 0xb5, 0x00, 0xff, 0x01, 0xa5, 0xc5, 0xd4, 0x0f, 0x9f, 0xb9, 0xef, - 0x0a, 0x05, 0xff, 0xff, 0x0a, 0x03, 0xb1, 0xec, 0xc1, 0x92, 0x01, - 0xd2, 0x1a, 0xd5, 0x9b, 0xec, 0xc5, 0x96, 0x0b, 0x07, 0xff, 0xff, - 0xc5, 0xd6, 0x11, 0x93, 0x97, 0xec, 0xc5, 0x98, 0xc1, 0xd8, 0x11, - 0x93, 0x97, 0xec, 0x09, 0x05, 0x0b, 0x00, 0x03, 0xd4, 0xc2, 0x96, - 0x06, 0xd6, 0x7b, 0x95, 0x7a, 0x95, 0x4c, 0x02, 0xc1, 0x92, 0x59, - 0x93, 0x59, 0x93, 0x01, 0xa5, 0x01, 0x98, 0x0c, 0xf5, 0x7b, 0x93, - 0x09, 0x09, 0x01, 0x00, 0x06, 0x92, 0x09, 0xb3, 0xff, 0x00, 0x04, - 0xd2, 0x5c, 0x93, 0x59, 0x93, 0x04, 0x94, 0x01, 0xa5, 0x03, 0x96, - 0xc3, 0xd4, 0x11, 0x93, 0x97, 0xec, 0x4c, 0x02, 0x05, 0xd2, 0xc1, - 0x92, 0x09, 0xb3, 0x00, 0xff, 0x7c, 0x95, 0x7a, 0x95, 0x02, 0xa3, - 0x05, 0x98, 0xc4, 0xd2, 0x12, 0x95, 0x97, 0xec, 0x45, 0x04, 0x02, - 0x97, 0xc3, 0x92, 0x09, 0xa3, 0x00, 0x01, 0xc2, 0xd2, 0x12, 0x95, - 0x9b, 0xec, 0x0a, 0xb3, 0x08, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x01, 0xf0, 0x12, 0x95, 0x97, 0xec, 0x4a, 0x04, 0x02, 0x99, - 0xc4, 0x92, 0x01, 0x98, 0x0c, 0xf3, 0x7b, 0x93, 0x41, 0x02, 0x0f, - 0x9f, 0x22, 0xf0, 0x43, 0x44, 0x02, 0x8e, 0x0f, 0x9f, 0x23, 0xf0, - 0x11, 0x93, 0x97, 0xec, 0x42, 0x02, 0x0a, 0x05, 0xff, 0xff, 0xc1, - 0xd4, 0x11, 0x93, 0x97, 0xec, 0x4a, 0x02, 0x12, 0x95, 0x60, 0x96, - 0xc1, 0xd4, 0x12, 0x95, 0x97, 0xec, 0x4b, 0x04, 0x02, 0x97, 0xc3, - 0x92, 0x09, 0xb3, 0x1f, 0xff, 0xc2, 0xd2, 0x12, 0x95, 0x97, 0xec, - 0x4b, 0x04, 0x11, 0x93, 0x62, 0x96, 0x41, 0x93, 0x59, 0x93, 0x02, - 0x99, 0xc4, 0xa2, 0xc2, 0xd2, 0xc5, 0x92, 0x19, 0xd3, 0x98, 0xec, - 0x0a, 0x95, 0x0c, 0x02, 0x1a, 0xd5, 0x02, 0x80, 0x0f, 0x9f, 0x57, - 0xf0, 0x09, 0x63, 0xfe, 0x7f, 0x01, 0x97, 0xc3, 0x94, 0x0a, 0xa5, - 0x00, 0x04, 0xc1, 0xd4, 0x11, 0x93, 0x9f, 0xec, 0x09, 0xa3, 0x00, - 0x01, 0x19, 0xd3, 0x9f, 0xec, 0x40, 0xf0, 0xdf, 0xee, 0x0f, 0x9f, - 0x57, 0xf0, 0x11, 0x93, 0x94, 0xec, 0x41, 0x42, 0x02, 0x5e, 0x0f, - 0x9f, 0x4c, 0xf0, 0x40, 0xf0, 0xdf, 0xee, 0x11, 0x93, 0x95, 0xec, - 0x44, 0xb2, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x57, 0xf0, 0x48, - 0x98, 0x1c, 0xd9, 0x02, 0x80, 0x11, 0x93, 0x91, 0xec, 0x41, 0x22, - 0x0a, 0x95, 0x57, 0xf0, 0x88, 0xd4, 0x88, 0xdc, 0x91, 0x9a, 0x47, - 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, - 0x11, 0x93, 0x04, 0x82, 0x48, 0xb2, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x6e, 0xf0, 0x0a, 0x65, 0xfd, 0x7d, 0x02, 0x97, 0xc3, 0x92, - 0x09, 0xb3, 0xff, 0xfe, 0xc2, 0xd2, 0x41, 0x92, 0x19, 0xd3, 0xbf, - 0xec, 0x11, 0x93, 0x04, 0x82, 0x43, 0xb2, 0x12, 0x95, 0x03, 0x82, - 0x02, 0xb3, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x95, 0xf0, 0x0a, - 0xb3, 0x00, 0xff, 0x48, 0xa2, 0x19, 0xd3, 0x03, 0x82, 0x40, 0xf0, - 0x82, 0xf3, 0x11, 0x93, 0xbf, 0xec, 0x41, 0x42, 0x02, 0x5e, 0x0f, - 0x9f, 0x95, 0xf0, 0x11, 0x93, 0x07, 0x82, 0x11, 0x43, 0x03, 0xec, - 0x02, 0x0e, 0x0f, 0x9f, 0x95, 0xf0, 0x11, 0x93, 0x03, 0x82, 0x09, - 0xa3, 0x00, 0x01, 0x19, 0xd3, 0x03, 0x82, 0x40, 0x96, 0x1b, 0xd7, - 0xbf, 0xec, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x11, 0x93, 0x20, 0xbc, 0xc8, 0xd2, 0x40, 0xf0, 0xe9, 0xf0, - 0x41, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x42, 0x20, 0x08, - 0x0b, 0x01, 0x00, 0x0d, 0x03, 0x05, 0x00, 0x05, 0x94, 0x41, 0x02, - 0xc1, 0x92, 0x01, 0x97, 0xc3, 0x96, 0xc2, 0xd6, 0x0a, 0x45, 0x00, - 0x95, 0x02, 0x5e, 0x0f, 0x9f, 0xe6, 0xf0, 0xc1, 0x92, 0x41, 0xb2, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xe6, 0xf0, 0x11, 0x93, 0xc0, - 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xe6, 0xf0, 0x41, 0x98, - 0x1c, 0xd9, 0xc0, 0xec, 0x12, 0x95, 0x02, 0x80, 0x01, 0xd4, 0x40, - 0xf0, 0xfe, 0xf1, 0x0b, 0x67, 0xfd, 0x7d, 0x03, 0x99, 0xc4, 0x92, - 0x0c, 0x99, 0x96, 0x03, 0x1c, 0xd9, 0x06, 0x82, 0x41, 0x98, 0x1c, - 0xd9, 0x02, 0x82, 0x42, 0x98, 0x1c, 0xd9, 0x05, 0x82, 0x0c, 0x69, - 0x80, 0x7f, 0x1c, 0xd9, 0x00, 0xb0, 0x09, 0xa3, 0x00, 0x01, 0xc3, - 0xd2, 0x01, 0x94, 0x0a, 0xb3, 0x04, 0x00, 0x40, 0x42, 0x02, 0x4e, - 0x0f, 0x9f, 0xe4, 0xf0, 0x42, 0xa4, 0x1a, 0xd5, 0x02, 0x80, 0x42, - 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x42, 0x20, 0x08, 0x0b, - 0x01, 0x00, 0x05, 0x92, 0xc5, 0xd2, 0x60, 0xb2, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0xf6, 0xf0, 0x40, 0xf0, 0xd2, 0xf6, 0xc5, 0x94, - 0x0a, 0xb3, 0x10, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xff, - 0xf0, 0x40, 0xf0, 0xc0, 0xf5, 0xc5, 0x96, 0x0b, 0xb3, 0x40, 0x00, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x08, 0xf1, 0x40, 0xf0, 0xfa, - 0xf4, 0xc5, 0x94, 0x0a, 0xb3, 0x01, 0x00, 0x40, 0x42, 0x02, 0x4e, - 0x0f, 0x9f, 0x70, 0xf1, 0x13, 0x97, 0x21, 0xbc, 0x01, 0xd6, 0x0b, - 0xb3, 0x02, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x1a, 0xf1, - 0x40, 0xf0, 0x62, 0xfb, 0x01, 0x94, 0x0a, 0xb3, 0x04, 0x00, 0x40, - 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x23, 0xf1, 0x40, 0xf0, 0x6c, 0xfb, - 0x01, 0x96, 0x0b, 0xb3, 0x01, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x4c, 0xf1, 0x40, 0xf0, 0xb0, 0xfa, 0x41, 0x92, 0x19, 0xd3, - 0x73, 0xf7, 0x11, 0x93, 0x03, 0xec, 0x09, 0x43, 0x40, 0x00, 0x02, - 0x5e, 0x0f, 0x9f, 0x39, 0xf1, 0x40, 0x94, 0x1a, 0xd5, 0x73, 0xf7, - 0x11, 0x93, 0x00, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x55, - 0xf1, 0x11, 0x93, 0xc1, 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0x55, 0xf1, 0x40, 0xf0, 0xe0, 0xf1, 0x41, 0x96, 0x1b, 0xd7, 0xc1, - 0xec, 0x0f, 0x9f, 0x55, 0xf1, 0x01, 0x94, 0x0a, 0xb3, 0x08, 0x00, - 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x55, 0xf1, 0x40, 0xf0, 0x7c, - 0xfb, 0x01, 0x96, 0x0b, 0xb3, 0x10, 0x00, 0x40, 0x42, 0x02, 0x4e, - 0x0f, 0x9f, 0x5e, 0xf1, 0x40, 0xf0, 0x87, 0xfb, 0x11, 0x93, 0x10, - 0xec, 0x42, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x67, 0xf1, 0x44, 0x92, - 0x0f, 0x9f, 0x6b, 0xf1, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x6d, - 0xf1, 0x19, 0xd3, 0x0b, 0xbc, 0x40, 0x94, 0x1a, 0xd5, 0x10, 0xec, - 0xc5, 0x96, 0x0b, 0xb3, 0x80, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0xba, 0xf1, 0x11, 0x93, 0x28, 0xbc, 0x01, 0xd2, 0x09, 0xb3, - 0x40, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x82, 0xf1, 0x40, - 0xf0, 0xb5, 0xf6, 0x01, 0x94, 0x0a, 0xb3, 0x02, 0x00, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0x95, 0xf1, 0x40, 0xf0, 0x6d, 0xee, 0x40, - 0xf0, 0x8f, 0xfb, 0x40, 0xf0, 0xc3, 0xf1, 0x40, 0x96, 0x1b, 0xd7, - 0x00, 0xec, 0x41, 0x92, 0x19, 0xd3, 0x76, 0xf7, 0x01, 0x94, 0x0a, - 0xb3, 0x04, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xb1, 0xf1, - 0x40, 0xf0, 0x9e, 0xfb, 0x09, 0x63, 0x00, 0x44, 0x01, 0x97, 0xc3, - 0x94, 0x48, 0xa4, 0xc1, 0xd4, 0x00, 0xee, 0x40, 0x92, 0x19, 0xd3, - 0x12, 0x95, 0x19, 0xd3, 0x10, 0x95, 0x19, 0xd3, 0x02, 0x80, 0x19, - 0xd3, 0x03, 0x82, 0x41, 0x92, 0x19, 0xd3, 0x76, 0xf7, 0x01, 0x94, - 0x0a, 0xb3, 0x08, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xba, - 0xf1, 0x40, 0xf0, 0xae, 0xfb, 0x0a, 0x65, 0x00, 0x44, 0x02, 0x97, - 0xc3, 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x42, 0x00, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, 0x63, 0x00, 0x40, - 0x19, 0xd3, 0xf2, 0xbd, 0x0a, 0x65, 0xea, 0x43, 0x02, 0x97, 0xc3, - 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0xa3, 0x40, 0x00, 0xc2, 0xd2, 0x0a, 0x65, 0xeb, - 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, 0xd2, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, - 0x63, 0x00, 0x80, 0x19, 0xd3, 0xf2, 0xbd, 0x0a, 0x65, 0xe8, 0x43, - 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, 0xd2, 0x0a, - 0x65, 0xeb, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, - 0xc2, 0xd2, 0x0a, 0x65, 0xea, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, - 0xb3, 0xfb, 0xff, 0xc2, 0xd2, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x09, 0x93, 0x00, 0x01, 0x19, 0xd3, 0x02, - 0x80, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, - 0x09, 0x93, 0x00, 0x09, 0x19, 0xd3, 0x02, 0x80, 0x40, 0xf0, 0xfe, - 0xf1, 0x40, 0x92, 0x19, 0xd3, 0x94, 0xec, 0xc8, 0xd2, 0x09, 0x93, - 0x91, 0xec, 0xc8, 0xd2, 0x40, 0xf0, 0xd0, 0xee, 0x42, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0xf0, - 0xd8, 0xf4, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x2d, 0xf2, 0x0a, - 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, 0x92, 0x44, 0xa2, 0xc2, 0xd2, - 0x0f, 0x9f, 0x3a, 0xf2, 0x40, 0xf0, 0x3c, 0xf2, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x3a, 0xf2, 0xc8, 0xd2, 0x09, 0x93, 0x91, 0xec, - 0xc8, 0xd2, 0x40, 0xf0, 0xd0, 0xee, 0x42, 0x00, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0xf1, 0xbd, - 0x19, 0xd3, 0xb6, 0xec, 0x11, 0x93, 0xb4, 0xec, 0x40, 0x42, 0x02, - 0x5e, 0x0f, 0x9f, 0x54, 0xf2, 0x09, 0x63, 0x00, 0x80, 0x01, 0x97, - 0xc3, 0x94, 0x0a, 0x07, 0x07, 0x00, 0xc1, 0xd6, 0x0a, 0x05, 0x00, - 0xa0, 0x1a, 0xd5, 0x96, 0xec, 0x11, 0x93, 0xb6, 0xec, 0x19, 0xd3, - 0x01, 0x80, 0x0a, 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, 0x92, 0x41, - 0xa2, 0xc2, 0xd2, 0x40, 0x92, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x41, 0x20, 0x08, 0x0b, 0x01, 0x00, 0x13, 0x97, 0xb4, 0xec, 0x40, - 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xc3, 0xf2, 0x12, 0x95, 0x96, 0xec, - 0x0a, 0x03, 0x07, 0x00, 0xc1, 0x92, 0xc2, 0xd2, 0x11, 0x93, 0x96, - 0xec, 0x09, 0x05, 0x01, 0x00, 0x48, 0x02, 0xc1, 0x92, 0xc2, 0xd2, - 0x11, 0x93, 0x96, 0xec, 0x4e, 0x02, 0xc1, 0x94, 0xc5, 0xd6, 0xc5, - 0x92, 0x11, 0x07, 0x96, 0xec, 0x0b, 0x03, 0x0f, 0x00, 0xc1, 0x98, - 0x46, 0x06, 0x7a, 0x93, 0x79, 0x93, 0x5c, 0x95, 0x5a, 0x95, 0x02, - 0xa3, 0xc3, 0xd2, 0x04, 0x95, 0xc5, 0x96, 0x41, 0x06, 0xc5, 0xd6, - 0x42, 0x46, 0x02, 0x9e, 0x0f, 0x9f, 0x7d, 0xf2, 0x11, 0x93, 0x96, - 0xec, 0x09, 0x05, 0x05, 0x00, 0x41, 0x02, 0xc1, 0x92, 0xc2, 0xd2, - 0x11, 0x93, 0x96, 0xec, 0xc1, 0x92, 0x09, 0xb5, 0x1f, 0x00, 0x43, - 0x44, 0x02, 0x8e, 0x0f, 0x9f, 0xaa, 0xf2, 0x40, 0x44, 0x02, 0x4e, - 0x0f, 0x9f, 0xab, 0xf2, 0x0a, 0x05, 0xff, 0xff, 0x0f, 0x9f, 0xab, - 0xf2, 0x43, 0x94, 0x11, 0x93, 0x96, 0xec, 0x42, 0x02, 0xc1, 0xd4, - 0x13, 0x97, 0x96, 0xec, 0x03, 0x93, 0xd1, 0x94, 0x7a, 0x95, 0x7a, - 0x95, 0xc1, 0x92, 0x59, 0x93, 0x59, 0x93, 0x01, 0x05, 0x49, 0x06, - 0xc3, 0x92, 0x7f, 0xb2, 0x01, 0x05, 0x1a, 0xd5, 0xb4, 0xec, 0x0a, - 0x05, 0xf2, 0xff, 0x1a, 0xd5, 0x92, 0xec, 0x11, 0x93, 0x92, 0xec, - 0x12, 0x95, 0xb6, 0xec, 0x02, 0x43, 0x02, 0x8e, 0x0f, 0x9f, 0x11, - 0xf3, 0x02, 0x0e, 0x0f, 0x9f, 0xe4, 0xf2, 0x11, 0x93, 0x7a, 0xf7, - 0x41, 0x02, 0x19, 0xd3, 0x7a, 0xf7, 0x11, 0x93, 0x79, 0xf7, 0x09, - 0xa3, 0x80, 0x00, 0x19, 0xd3, 0x79, 0xf7, 0x09, 0x63, 0x00, 0x80, - 0x01, 0x95, 0xc2, 0x94, 0x1a, 0xd5, 0xb5, 0xec, 0x40, 0x96, 0x1b, - 0xd7, 0xb4, 0xec, 0x0f, 0x9f, 0x29, 0xf3, 0x11, 0x93, 0x03, 0x80, - 0x09, 0xb3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xf6, - 0xf2, 0x11, 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0xf6, 0xf2, 0x40, 0xf0, 0x3d, 0xf3, 0x0f, 0x9f, 0x2b, 0xf3, 0x41, - 0x92, 0xc8, 0xd2, 0x0a, 0x95, 0x91, 0xec, 0xc8, 0xd4, 0x40, 0xf0, - 0xd0, 0xee, 0x42, 0x00, 0x11, 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0x09, 0xf3, 0x42, 0x96, 0x1b, 0xd7, 0xc0, 0xec, - 0x0f, 0x9f, 0x2b, 0xf3, 0x0a, 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, - 0x92, 0x42, 0xa2, 0xc2, 0xd2, 0x0f, 0x9f, 0x2b, 0xf3, 0x12, 0x45, - 0x03, 0xec, 0x02, 0x4e, 0x0f, 0x9f, 0x23, 0xf3, 0x11, 0x93, 0x7a, - 0xf7, 0x41, 0x02, 0x19, 0xd3, 0x7a, 0xf7, 0x11, 0x93, 0x79, 0xf7, - 0x09, 0xa3, 0x00, 0x08, 0x19, 0xd3, 0x79, 0xf7, 0x1a, 0xd5, 0x92, - 0xec, 0x11, 0x93, 0x92, 0xec, 0x19, 0x25, 0x92, 0xec, 0x09, 0x63, - 0x00, 0x80, 0x19, 0xd3, 0xf2, 0xbd, 0x41, 0x00, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0xf0, 0x3d, 0xf3, - 0x40, 0x92, 0xc8, 0xd2, 0x09, 0x93, 0x91, 0xec, 0xc8, 0xd2, 0x40, - 0xf0, 0xd0, 0xee, 0x42, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, - 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0x75, 0xf7, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0x4d, 0xf3, 0x0a, 0x65, 0xbc, 0x69, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0x83, 0x00, 0x02, 0xc2, 0xd2, 0x11, 0x93, 0x03, - 0x80, 0x09, 0xb3, 0x00, 0x40, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0x60, 0xf3, 0x11, 0x93, 0x7a, 0xf7, 0x41, 0x02, 0x19, 0xd3, 0x7a, - 0xf7, 0x11, 0x93, 0x79, 0xf7, 0x09, 0xa3, 0x00, 0x20, 0x19, 0xd3, - 0x79, 0xf7, 0x11, 0x93, 0xb5, 0xec, 0x19, 0xd3, 0x04, 0x80, 0x12, - 0x95, 0xb4, 0xec, 0x1a, 0xd5, 0x05, 0x80, 0x09, 0x63, 0x00, 0x80, - 0x01, 0x97, 0xc3, 0x96, 0x1b, 0xd7, 0xb5, 0xec, 0x40, 0x94, 0x1a, - 0xd5, 0xb4, 0xec, 0x19, 0xd3, 0xf2, 0xbd, 0x88, 0x98, 0x90, 0x9a, - 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, 0x93, 0x96, 0x03, 0x19, - 0xd3, 0x06, 0x82, 0x09, 0x93, 0x00, 0x01, 0x19, 0xd3, 0x03, 0x82, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x47, 0x20, 0x08, 0x0b, 0x01, - 0x00, 0x11, 0x93, 0x01, 0x82, 0xc5, 0xd2, 0x40, 0x94, 0x01, 0xd4, - 0x13, 0x97, 0xb8, 0xec, 0x02, 0xd6, 0x03, 0x95, 0x0c, 0x99, 0xbb, - 0xec, 0x04, 0x05, 0x13, 0x97, 0x03, 0xec, 0x01, 0x27, 0x02, 0x99, - 0xc4, 0x92, 0x03, 0x03, 0xc2, 0xd2, 0x14, 0x99, 0xba, 0xec, 0x03, - 0x09, 0x1c, 0xd9, 0xba, 0xec, 0x12, 0x95, 0x04, 0x82, 0x0a, 0xb3, - 0x02, 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xc6, 0xf4, 0x01, - 0x92, 0x03, 0xd2, 0x0a, 0xa3, 0x02, 0x00, 0x19, 0xd3, 0x04, 0x82, - 0x02, 0x96, 0x0b, 0x05, 0x01, 0x00, 0x1a, 0xd5, 0xb8, 0xec, 0xc5, - 0x92, 0x43, 0x42, 0x02, 0x9e, 0x0f, 0x9f, 0xce, 0xf3, 0x42, 0x44, - 0x02, 0x8e, 0x0f, 0x9f, 0xce, 0xf3, 0x11, 0x93, 0xbf, 0xec, 0x40, - 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xce, 0xf3, 0x0c, 0x49, 0xd3, 0x08, - 0x02, 0x8e, 0x0f, 0x9f, 0xce, 0xf3, 0x11, 0x63, 0x07, 0x82, 0x11, - 0xa3, 0x07, 0x82, 0x71, 0x93, 0x79, 0x93, 0x79, 0x93, 0x79, 0x93, - 0x03, 0xd2, 0xc5, 0x94, 0x0a, 0xb5, 0xfc, 0xff, 0x04, 0xd4, 0x03, - 0x96, 0x40, 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xdd, 0xf3, 0x11, 0x93, - 0xb8, 0xec, 0x41, 0x42, 0x02, 0x8e, 0x0f, 0x9f, 0xe4, 0xf3, 0xc5, - 0x98, 0x0c, 0x03, 0xff, 0xff, 0x42, 0x42, 0x02, 0x8e, 0x0f, 0x9f, - 0x0b, 0xf4, 0x0a, 0x95, 0xbb, 0xec, 0x42, 0x92, 0x19, 0xd3, 0xb9, - 0xec, 0xc5, 0x96, 0x43, 0x46, 0x02, 0x9e, 0x0f, 0x9f, 0xfd, 0xf3, - 0x0b, 0x07, 0xfc, 0xff, 0xc5, 0xd6, 0xd2, 0x98, 0x1c, 0xd9, 0xc8, - 0xbc, 0xd2, 0x96, 0x1b, 0xd7, 0xca, 0xbc, 0x09, 0x03, 0xff, 0xff, - 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xe9, 0xf3, 0x19, 0xd3, 0xb9, - 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x09, 0xf4, 0x0a, 0x05, - 0xfe, 0xff, 0xca, 0xd2, 0xc2, 0xd2, 0x0f, 0x9f, 0x0b, 0xf4, 0x1a, - 0xd5, 0x93, 0xec, 0x03, 0x98, 0x40, 0x48, 0x02, 0x5e, 0x0f, 0x9f, - 0x38, 0xf4, 0x11, 0x93, 0xb8, 0xec, 0x41, 0x42, 0x02, 0x9e, 0x0f, - 0x9f, 0x1b, 0xf4, 0x04, 0x94, 0x48, 0x44, 0x02, 0x4e, 0x0f, 0x9f, - 0x26, 0xf4, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x38, 0xf4, 0x11, - 0x93, 0x04, 0x82, 0x41, 0xb2, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, - 0x38, 0xf4, 0x41, 0x96, 0x01, 0xd6, 0x0a, 0x65, 0xbd, 0x43, 0x02, - 0x99, 0xc4, 0x92, 0x09, 0xa3, 0x80, 0x00, 0xc2, 0xd2, 0x0a, 0x65, - 0xe8, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, 0xc2, - 0xd2, 0x0f, 0x9f, 0x97, 0xf4, 0xc5, 0x98, 0x43, 0x48, 0x02, 0x9e, - 0x0f, 0x9f, 0x97, 0xf4, 0x4f, 0x96, 0x0c, 0xb3, 0x01, 0x00, 0x40, - 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x45, 0xf4, 0x47, 0x96, 0x11, 0x93, - 0xb7, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x73, 0xf4, 0x11, - 0x93, 0xb8, 0xec, 0x41, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x73, 0xf4, - 0x12, 0x95, 0x00, 0x82, 0x0a, 0x05, 0xff, 0xaf, 0x05, 0xd4, 0xc8, - 0xd6, 0xc8, 0xd2, 0x40, 0xf0, 0x18, 0xf7, 0x42, 0x00, 0x05, 0x96, - 0xc3, 0x94, 0x01, 0xb5, 0x40, 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0x68, - 0xf4, 0x11, 0x93, 0xba, 0xec, 0x4d, 0x42, 0x02, 0x8e, 0x0f, 0x9f, - 0x73, 0xf4, 0x06, 0x98, 0x50, 0x98, 0x1c, 0xd9, 0xa2, 0xbc, 0x40, - 0x98, 0x1c, 0xd9, 0xa2, 0xbc, 0x40, 0x92, 0x03, 0xd2, 0x0f, 0x9f, - 0x9c, 0xf4, 0x03, 0x94, 0x40, 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0x80, - 0xf4, 0x0a, 0x65, 0x5e, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x48, 0xa2, - 0xc2, 0xd2, 0x0f, 0x9f, 0x9c, 0xf4, 0x11, 0x93, 0xb8, 0xec, 0x0c, - 0x99, 0xbb, 0xec, 0x04, 0x03, 0x04, 0x96, 0x13, 0x25, 0x03, 0xec, - 0xc1, 0xd4, 0x11, 0x93, 0xba, 0xec, 0x19, 0x05, 0xba, 0xec, 0x1b, - 0xd7, 0x01, 0x82, 0x0a, 0x65, 0xfd, 0x7d, 0x02, 0x99, 0xc4, 0x92, - 0x43, 0xa2, 0xc2, 0xd2, 0x41, 0x92, 0x01, 0xd2, 0x03, 0x94, 0x40, - 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0xb0, 0xf4, 0x11, 0x93, 0xb9, 0xec, - 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xa8, 0xf4, 0x19, 0xd3, 0xb8, - 0xec, 0x19, 0xd3, 0xba, 0xec, 0x19, 0xd3, 0xbb, 0xec, 0x03, 0x96, - 0x40, 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xb0, 0xf4, 0x41, 0x98, 0x1c, - 0xd9, 0xb7, 0xec, 0x11, 0x93, 0xbf, 0xec, 0x41, 0x42, 0x02, 0x5e, - 0x0f, 0x9f, 0xc1, 0xf4, 0x11, 0x93, 0x00, 0x82, 0x19, 0xd3, 0x02, - 0x82, 0x0a, 0x65, 0xfd, 0x7d, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, - 0x00, 0x01, 0xc2, 0xd2, 0x40, 0x98, 0x1c, 0xd9, 0xbf, 0xec, 0x0f, - 0x9f, 0xc9, 0xf4, 0x01, 0x92, 0x19, 0xd3, 0xb7, 0xec, 0x01, 0x94, - 0x40, 0x44, 0x02, 0x5e, 0x0f, 0x9f, 0xd5, 0xf4, 0x0a, 0x65, 0xea, - 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xfb, 0xff, 0xc2, 0xd2, - 0x47, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x12, 0x95, 0x03, 0x80, 0x0a, 0xb3, 0x00, 0x40, 0x40, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0xf4, 0xf4, 0x0a, 0xb7, 0x00, 0x08, 0x40, - 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0xf7, 0xf4, 0x11, 0x93, 0x03, 0xec, - 0x41, 0x02, 0x09, 0xb3, 0xfe, 0xff, 0x12, 0x95, 0x07, 0x80, 0x01, - 0x45, 0x02, 0x8e, 0x0f, 0x9f, 0xf7, 0xf4, 0x41, 0x92, 0x0f, 0x9f, - 0xf8, 0xf4, 0x40, 0x92, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x41, - 0x20, 0x08, 0x0b, 0x01, 0x00, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, - 0xc3, 0x92, 0x09, 0xa3, 0x40, 0x00, 0xc2, 0xd2, 0x13, 0x97, 0x6e, - 0xec, 0x0b, 0x47, 0xa0, 0x00, 0x02, 0x5e, 0x0f, 0x9f, 0x23, 0xf5, - 0x09, 0x63, 0x08, 0x43, 0x0a, 0x65, 0xff, 0x5f, 0x01, 0x99, 0xc4, - 0xd4, 0x0a, 0x95, 0x9b, 0xec, 0xd2, 0x96, 0x1b, 0xd7, 0xfa, 0xbc, - 0xd2, 0x96, 0xc4, 0xd6, 0xd2, 0x98, 0x1c, 0xd9, 0xfa, 0xbc, 0xd2, - 0x96, 0xc1, 0xd6, 0xc2, 0x94, 0x1a, 0xd5, 0xfa, 0xbc, 0x0f, 0x9f, - 0x61, 0xf5, 0x0c, 0x69, 0xff, 0x6f, 0x1c, 0xd9, 0xf8, 0xbc, 0x0b, - 0x47, 0x10, 0x95, 0x02, 0x5e, 0x0f, 0x9f, 0x3b, 0xf5, 0x0a, 0x95, - 0x6f, 0xec, 0x09, 0x63, 0x06, 0x43, 0x01, 0x99, 0xc4, 0xd6, 0xd2, - 0x96, 0x1b, 0xd7, 0xf8, 0xbc, 0x0c, 0x69, 0xee, 0x6a, 0xc1, 0xd8, - 0xc2, 0x94, 0x1a, 0xd5, 0xf8, 0xbc, 0x40, 0x92, 0xc5, 0xd2, 0x11, - 0x43, 0xc2, 0xec, 0x02, 0x0e, 0x0f, 0x9f, 0x5e, 0xf5, 0xc5, 0x94, - 0x0a, 0x03, 0x71, 0xec, 0xc1, 0x94, 0x1a, 0xd5, 0xfa, 0xbc, 0x11, - 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x50, 0xf5, - 0x0a, 0x95, 0x6f, 0xec, 0xc8, 0xd4, 0x40, 0xf0, 0x39, 0xf7, 0x19, - 0xd3, 0xf8, 0xbc, 0x41, 0x00, 0xc5, 0x96, 0x41, 0x06, 0xc5, 0xd6, - 0x13, 0x47, 0xc2, 0xec, 0x02, 0x1e, 0x0f, 0x9f, 0x42, 0xf5, 0x40, - 0x98, 0x1c, 0xd9, 0xfa, 0xbc, 0x40, 0x92, 0x19, 0xd3, 0x6e, 0xec, - 0x19, 0xd3, 0xc2, 0xec, 0x0a, 0x65, 0x52, 0x43, 0x02, 0x97, 0xc3, - 0x92, 0x48, 0xa2, 0xc2, 0xd2, 0x0a, 0x65, 0xeb, 0x43, 0x02, 0x99, - 0xc4, 0x92, 0x09, 0xb3, 0xbf, 0xff, 0xc2, 0xd2, 0x41, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x43, 0x20, 0x08, 0x0b, 0x01, 0x00, - 0x06, 0x92, 0x01, 0xd2, 0x0a, 0x65, 0xf0, 0x6a, 0x0b, 0x97, 0x6f, - 0xec, 0x02, 0x99, 0xc4, 0x98, 0xd3, 0xd8, 0x02, 0xd6, 0x0a, 0x03, - 0x02, 0x00, 0x01, 0x97, 0xc3, 0x98, 0x02, 0x96, 0xc3, 0xd8, 0x01, - 0x96, 0xc1, 0xd6, 0x1a, 0xd5, 0x6e, 0xec, 0xc5, 0x98, 0x14, 0x99, - 0x6f, 0xec, 0xc2, 0xd8, 0x43, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, - 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0x92, 0xc8, 0xd2, 0x40, 0xf0, - 0x76, 0xf5, 0x41, 0x00, 0x11, 0x93, 0xc0, 0xec, 0x40, 0x42, 0x02, - 0x4e, 0x0f, 0x9f, 0xb0, 0xf5, 0x42, 0x42, 0x02, 0x5e, 0x0f, 0x9f, - 0xad, 0xf5, 0x0a, 0x65, 0xfe, 0x7f, 0x02, 0x97, 0xc3, 0x92, 0x42, - 0xa2, 0xc2, 0xd2, 0x40, 0x92, 0x19, 0xd3, 0xc0, 0xec, 0x0a, 0x65, - 0xeb, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0xc0, 0x00, 0xc2, - 0xd2, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, - 0xbf, 0xff, 0xc2, 0xd2, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x63, - 0x20, 0x08, 0x0b, 0x01, 0x00, 0x11, 0x93, 0xaf, 0xbc, 0x47, 0xb2, - 0x59, 0x95, 0x5a, 0x95, 0x12, 0xa5, 0xbf, 0xbc, 0x0a, 0xb3, 0x01, - 0x00, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0xd2, 0xf5, 0x41, 0x04, - 0x05, 0x93, 0x40, 0x96, 0x20, 0xd6, 0x62, 0x97, 0x0f, 0x9f, 0xe1, - 0xf5, 0x14, 0x99, 0xfc, 0xbc, 0xd1, 0xd8, 0x14, 0x99, 0xfe, 0xbc, - 0xd1, 0xd8, 0x20, 0x98, 0x42, 0x08, 0x20, 0xd8, 0x20, 0x98, 0x03, - 0x49, 0x02, 0x1e, 0x0f, 0x9f, 0xd8, 0xf5, 0xc5, 0x92, 0x62, 0x42, - 0x02, 0x4e, 0x0f, 0x9f, 0xfa, 0xf5, 0x02, 0x8e, 0x0f, 0x9f, 0xf4, - 0xf5, 0x61, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x1e, 0xf6, 0x0f, 0x9f, - 0x4b, 0xf6, 0x63, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x41, 0xf6, 0x0f, - 0x9f, 0x4b, 0xf6, 0x0d, 0x03, 0x01, 0x00, 0x0c, 0x99, 0x71, 0xec, - 0x0b, 0x05, 0xff, 0xff, 0x40, 0x96, 0x0f, 0x9f, 0x07, 0xf6, 0xd1, - 0x96, 0xd4, 0xd6, 0x20, 0x96, 0x41, 0x06, 0x20, 0xd6, 0x02, 0x47, - 0x02, 0x1e, 0x0f, 0x9f, 0x03, 0xf6, 0x1a, 0xd5, 0xc2, 0xec, 0x0a, - 0x65, 0xeb, 0x43, 0x02, 0x99, 0xc4, 0x92, 0x09, 0xa3, 0xc0, 0x00, - 0xc2, 0xd2, 0x0a, 0x65, 0xe9, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, - 0xb3, 0xbf, 0xff, 0xc2, 0xd2, 0x0f, 0x9f, 0x4b, 0xf6, 0x0a, 0x03, - 0xfe, 0xff, 0x61, 0x95, 0x40, 0x98, 0x20, 0xd8, 0x02, 0x49, 0x02, - 0x0e, 0x0f, 0x9f, 0x4b, 0xf6, 0x0d, 0x03, 0x01, 0x00, 0x21, 0xd2, - 0x20, 0x92, 0x05, 0x03, 0x42, 0x02, 0xc8, 0xd2, 0x21, 0x96, 0xc3, - 0x92, 0x42, 0x06, 0x21, 0xd6, 0xc8, 0xd2, 0x22, 0xd4, 0x40, 0xf0, - 0xa2, 0xf0, 0x42, 0x00, 0x20, 0x98, 0x42, 0x08, 0x20, 0xd8, 0x22, - 0x94, 0x02, 0x49, 0x02, 0x1e, 0x0f, 0x9f, 0x2a, 0xf6, 0x0f, 0x9f, - 0x4b, 0xf6, 0x0d, 0x03, 0x03, 0x00, 0xc8, 0xd2, 0x02, 0x92, 0xc8, - 0xd2, 0x01, 0x96, 0xc8, 0xd6, 0x40, 0xf0, 0x4e, 0xf6, 0x43, 0x00, - 0x63, 0x00, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x45, 0x20, 0x08, - 0x0b, 0x01, 0x00, 0x0d, 0x03, 0x08, 0x00, 0x08, 0x94, 0xc5, 0xd4, - 0x09, 0x05, 0x01, 0x00, 0xc2, 0x94, 0x03, 0xd4, 0x42, 0x02, 0xc1, - 0x92, 0x01, 0xd2, 0x02, 0x97, 0xc5, 0x94, 0x0a, 0x83, 0xff, 0xff, - 0x11, 0xb3, 0x2c, 0x93, 0x09, 0xb3, 0xfb, 0xff, 0x19, 0xd3, 0x2c, - 0x93, 0x03, 0x92, 0x40, 0x42, 0x02, 0x4e, 0x0f, 0x9f, 0x81, 0xf6, - 0x01, 0x94, 0xd2, 0x92, 0x19, 0xd3, 0x2c, 0x93, 0x01, 0xd4, 0x02, - 0x94, 0x12, 0x95, 0x2c, 0x93, 0x44, 0xa4, 0x1a, 0xd5, 0x2c, 0x93, - 0x0a, 0xb5, 0xfb, 0xff, 0x1a, 0xd5, 0x2c, 0x93, 0x0b, 0x07, 0xff, - 0xff, 0x40, 0x46, 0x02, 0x5e, 0x0f, 0x9f, 0x6c, 0xf6, 0x09, 0x63, - 0xd4, 0x6c, 0x01, 0x95, 0xc2, 0x96, 0xc5, 0x94, 0x02, 0xa7, 0xc1, - 0xd6, 0x03, 0x92, 0x54, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0x91, 0xf6, - 0x0a, 0x83, 0xff, 0xff, 0x1b, 0xb3, 0x2c, 0x93, 0x45, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x09, 0x63, - 0x00, 0x40, 0x19, 0xd3, 0xf2, 0xbd, 0x40, 0xf0, 0xd8, 0xf4, 0x40, - 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xa5, 0xf6, 0x40, 0xf0, 0x3c, 0xf2, - 0x0f, 0x9f, 0xb3, 0xf6, 0x40, 0x96, 0xc8, 0xd6, 0x09, 0x93, 0x91, - 0xec, 0xc8, 0xd2, 0x40, 0xf0, 0xd0, 0xee, 0x0a, 0x65, 0xfe, 0x7f, - 0x02, 0x97, 0xc3, 0x92, 0x44, 0xa2, 0xc2, 0xd2, 0x42, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x0a, 0x65, - 0xe8, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xa3, 0x40, 0x00, 0xc2, - 0xd2, 0x0a, 0x65, 0xea, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, - 0xfb, 0xff, 0xc2, 0xd2, 0x40, 0x92, 0x19, 0xd3, 0x2d, 0xbc, 0x0a, - 0x65, 0xd8, 0x43, 0x02, 0x97, 0xc3, 0x92, 0x09, 0xb3, 0xbf, 0xff, - 0xc2, 0xd2, 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, - 0x00, 0x09, 0x63, 0xea, 0x43, 0x01, 0x97, 0xc3, 0x94, 0x44, 0xa4, - 0xc1, 0xd4, 0x11, 0x93, 0xb9, 0xec, 0x40, 0x42, 0x02, 0x4e, 0x0f, - 0x9f, 0x0c, 0xf7, 0x12, 0x95, 0x93, 0xec, 0x0b, 0x67, 0x36, 0x43, - 0xd2, 0x98, 0x1c, 0xd9, 0xc8, 0xbc, 0xd2, 0x98, 0x03, 0x93, 0xc1, - 0xd8, 0x11, 0x93, 0xb9, 0xec, 0x09, 0x03, 0xff, 0xff, 0x19, 0xd3, - 0xb9, 0xec, 0x40, 0x42, 0x02, 0x5e, 0x0f, 0x9f, 0xe5, 0xf6, 0x19, - 0xd3, 0xb8, 0xec, 0x19, 0xd3, 0xba, 0xec, 0x0a, 0x05, 0xfe, 0xff, - 0xca, 0xd2, 0xca, 0xd2, 0xc2, 0xd2, 0x0a, 0x65, 0x5e, 0x43, 0x02, - 0x97, 0xc3, 0x92, 0x48, 0xa2, 0xc2, 0xd2, 0x0a, 0x65, 0xea, 0x43, - 0x02, 0x99, 0xc4, 0x92, 0x09, 0xb3, 0xfb, 0xff, 0x0f, 0x9f, 0x15, - 0xf7, 0x11, 0x93, 0x03, 0xec, 0x19, 0xd3, 0x01, 0x82, 0x0a, 0x65, - 0xfd, 0x7d, 0x02, 0x97, 0xc3, 0x92, 0x43, 0xa2, 0xc2, 0xd2, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x03, 0x92, - 0x04, 0x96, 0x0d, 0x5e, 0x50, 0x46, 0x02, 0x0e, 0x40, 0x92, 0x09, - 0xee, 0x44, 0x46, 0x04, 0x0e, 0x59, 0x93, 0x44, 0x26, 0x04, 0x5e, - 0x46, 0xee, 0x41, 0x93, 0x41, 0x26, 0x43, 0x4e, 0x88, 0x98, 0x90, - 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x40, 0xf0, 0xb1, 0xfe, - 0x88, 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x88, - 0x98, 0x90, 0x9a, 0x88, 0xda, 0x08, 0x0b, 0x01, 0x00, 0x03, 0x94, - 0x1a, 0xd5, 0x40, 0xf7, 0x11, 0x93, 0x00, 0x90, 0x88, 0x98, 0x90, - 0x9a, 0x1d, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x03, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x1a, 0x00, 0x1b, 0x00, 0x16, 0x00, 0x21, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x13, 0x00, 0x19, 0x00, 0x19, 0x00, 0x19, 0x00, - 0x21, 0x00, 0x2d, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf2, 0x6b, 0xf7, 0x00, 0x00, - 0x1c, 0xf2, 0x6b, 0xf7, 0x00, 0x00, 0x61, 0xf2, 0x68, 0xf7, 0x6f, - 0xf7, 0x00, 0x00, 0x2e, 0xf3, 0x6b, 0xf7, 0x25, 0x47, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00 -}; diff --git a/sys/bus/u4b/wlan/if_zydreg.h b/sys/bus/u4b/wlan/if_zydreg.h deleted file mode 100644 index d91cc0c186..0000000000 --- a/sys/bus/u4b/wlan/if_zydreg.h +++ /dev/null @@ -1,1313 +0,0 @@ -/* $OpenBSD: if_zydreg.h,v 1.19 2006/11/30 19:28:07 damien Exp $ */ -/* $NetBSD: if_zydreg.h,v 1.2 2007/06/16 11:18:45 kiyohara Exp $ */ -/* $FreeBSD$ */ - -/*- - * Copyright (c) 2006 by Damien Bergamini - * Copyright (c) 2006 by Florian Stoehr - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * ZyDAS ZD1211/ZD1211B USB WLAN driver. - */ - -#define ZYD_CR_GPI_EN 0x9418 -#define ZYD_CR_RADIO_PD 0x942c -#define ZYD_CR_RF2948_PD 0x942c -#define ZYD_CR_EN_PS_MANUAL_AGC 0x943c -#define ZYD_CR_CONFIG_PHILIPS 0x9440 -#define ZYD_CR_I2C_WRITE 0x9444 -#define ZYD_CR_SA2400_SER_RP 0x9448 -#define ZYD_CR_RADIO_PE 0x9458 -#define ZYD_CR_RST_BUS_MASTER 0x945c -#define ZYD_CR_RFCFG 0x9464 -#define ZYD_CR_HSTSCHG 0x946c -#define ZYD_CR_PHY_ON 0x9474 -#define ZYD_CR_RX_DELAY 0x9478 -#define ZYD_CR_RX_PE_DELAY 0x947c -#define ZYD_CR_GPIO_1 0x9490 -#define ZYD_CR_GPIO_2 0x9494 -#define ZYD_CR_EnZYD_CRyBufMux 0x94a8 -#define ZYD_CR_PS_CTRL 0x9500 -#define ZYD_CR_ADDA_PWR_DWN 0x9504 -#define ZYD_CR_ADDA_MBIAS_WT 0x9508 -#define ZYD_CR_INTERRUPT 0x9510 -#define ZYD_CR_MAC_PS_STATE 0x950c -#define ZYD_CR_ATIM_WND_PERIOD 0x951c -#define ZYD_CR_BCN_INTERVAL 0x9520 -#define ZYD_CR_PRE_TBTT 0x9524 - -/* - * MAC registers. - */ -#define ZYD_MAC_MACADRL 0x9610 /* MAC address (low) */ -#define ZYD_MAC_MACADRH 0x9614 /* MAC address (high) */ -#define ZYD_MAC_BSSADRL 0x9618 /* BSS address (low) */ -#define ZYD_MAC_BSSADRH 0x961c /* BSS address (high) */ -#define ZYD_MAC_BCNCFG 0x9620 /* BCN configuration */ -#define ZYD_MAC_GHTBL 0x9624 /* Group hash table (low) */ -#define ZYD_MAC_GHTBH 0x9628 /* Group hash table (high) */ -#define ZYD_MAC_RX_TIMEOUT 0x962c /* Rx timeout value */ -#define ZYD_MAC_BAS_RATE 0x9630 /* Basic rate setting */ -#define ZYD_MAC_MAN_RATE 0x9634 /* Mandatory rate setting */ -#define ZYD_MAC_RTSCTSRATE 0x9638 /* RTS CTS rate */ -#define ZYD_MAC_BACKOFF_PROTECT 0x963c /* Backoff protection */ -#define ZYD_MAC_RX_THRESHOLD 0x9640 /* Rx threshold */ -#define ZYD_MAC_TX_PE_CONTROL 0x9644 /* Tx_PE control */ -#define ZYD_MAC_AFTER_PNP 0x9648 /* After PnP */ -#define ZYD_MAC_RX_PE_DELAY 0x964c /* Rx_pe delay */ -#define ZYD_MAC_RX_ADDR2_L 0x9650 /* RX address2 (low) */ -#define ZYD_MAC_RX_ADDR2_H 0x9654 /* RX address2 (high) */ -#define ZYD_MAC_SIFS_ACK_TIME 0x9658 /* Dynamic SIFS ack time */ -#define ZYD_MAC_PHY_DELAY 0x9660 /* PHY delay */ -#define ZYD_MAC_PHY_DELAY2 0x966c /* PHY delay */ -#define ZYD_MAC_BCNFIFO 0x9670 /* Beacon FIFO I/O port */ -#define ZYD_MAC_SNIFFER 0x9674 /* Sniffer on/off */ -#define ZYD_MAC_ENCRYPTION_TYPE 0x9678 /* Encryption type */ -#define ZYD_MAC_RETRY 0x967c /* Retry time */ -#define ZYD_MAC_MISC 0x9680 /* Misc */ -#define ZYD_MAC_STMACHINESTAT 0x9684 /* State machine status */ -#define ZYD_MAC_TX_UNDERRUN_CNT 0x9688 /* TX underrun counter */ -#define ZYD_MAC_RXFILTER 0x968c /* Send to host settings */ -#define ZYD_MAC_ACK_EXT 0x9690 /* Acknowledge extension */ -#define ZYD_MAC_BCNFIFOST 0x9694 /* BCN FIFO set and status */ -#define ZYD_MAC_DIFS_EIFS_SIFS 0x9698 /* DIFS, EIFS & SIFS settings */ -#define ZYD_MAC_RX_TIMEOUT_CNT 0x969c /* RX timeout count */ -#define ZYD_MAC_RX_TOTAL_FRAME 0x96a0 /* RX total frame count */ -#define ZYD_MAC_RX_CRC32_CNT 0x96a4 /* RX CRC32 frame count */ -#define ZYD_MAC_RX_CRC16_CNT 0x96a8 /* RX CRC16 frame count */ -#define ZYD_MAC_RX_UDEC 0x96ac /* RX unicast decr. error count */ -#define ZYD_MAC_RX_OVERRUN_CNT 0x96b0 /* RX FIFO overrun count */ -#define ZYD_MAC_RX_MDEC 0x96bc /* RX multicast decr. err. cnt. */ -#define ZYD_MAC_NAV_TCR 0x96c4 /* NAV timer count read */ -#define ZYD_MAC_BACKOFF_ST_RD 0x96c8 /* Backoff status read */ -#define ZYD_MAC_DM_RETRY_CNT_RD 0x96cc /* DM retry count read */ -#define ZYD_MAC_RX_ACR 0x96d0 /* RX arbitration count read */ -#define ZYD_MAC_TX_CCR 0x96d4 /* Tx complete count read */ -#define ZYD_MAC_TCB_ADDR 0x96e8 /* Current PCI process TCP addr */ -#define ZYD_MAC_RCB_ADDR 0x96ec /* Next RCB address */ -#define ZYD_MAC_CONT_WIN_LIMIT 0x96f0 /* Contention window limit */ -#define ZYD_MAC_TX_PKT 0x96f4 /* Tx total packet count read */ -#define ZYD_MAC_DL_CTRL 0x96f8 /* Download control */ -#define ZYD_MAC_CAM_MODE 0x9700 /* CAM: Continuous Access Mode */ -#define ZYD_MACB_TXPWR_CTL1 0x9b00 -#define ZYD_MACB_TXPWR_CTL2 0x9b04 -#define ZYD_MACB_TXPWR_CTL3 0x9b08 -#define ZYD_MACB_TXPWR_CTL4 0x9b0c -#define ZYD_MACB_AIFS_CTL1 0x9b10 -#define ZYD_MACB_AIFS_CTL2 0x9b14 -#define ZYD_MACB_TXOP 0x9b20 -#define ZYD_MACB_MAX_RETRY 0x9b28 - -/* - * Miscellaneous registers. - */ -#define ZYD_FIRMWARE_START_ADDR 0xee00 -#define ZYD_FIRMWARE_BASE_ADDR 0xee1d /* Firmware base address */ - -/* - * EEPROM registers. - */ -#define ZYD_EEPROM_START_HEAD 0xf800 /* EEPROM start */ -#define ZYD_EEPROM_SUBID 0xf817 -#define ZYD_EEPROM_POD 0xf819 -#define ZYD_EEPROM_MAC_ADDR_P1 0xf81b /* Part 1 of the MAC address */ -#define ZYD_EEPROM_MAC_ADDR_P2 0xf81d /* Part 2 of the MAC address */ -#define ZYD_EEPROM_PWR_CAL 0xf81f /* Calibration */ -#define ZYD_EEPROM_PWR_INT 0xf827 /* Calibration */ -#define ZYD_EEPROM_ALLOWEDCHAN 0xf82f /* Allowed CH mask, 1 bit each */ -#define ZYD_EEPROM_DEVICE_VER 0xf837 /* Device version */ -#define ZYD_EEPROM_PHY_REG 0xf83c /* PHY registers */ -#define ZYD_EEPROM_36M_CAL 0xf83f /* Calibration */ -#define ZYD_EEPROM_11A_INT 0xf847 /* Interpolation */ -#define ZYD_EEPROM_48M_CAL 0xf84f /* Calibration */ -#define ZYD_EEPROM_48M_INT 0xf857 /* Interpolation */ -#define ZYD_EEPROM_54M_CAL 0xf85f /* Calibration */ -#define ZYD_EEPROM_54M_INT 0xf867 /* Interpolation */ - -/* - * Firmware registers offsets (relative to fwbase). - */ -#define ZYD_FW_FIRMWARE_REV 0x0000 /* Firmware version */ -#define ZYD_FW_USB_SPEED 0x0001 /* USB speed (!=0 if highspeed) */ -#define ZYD_FW_FIX_TX_RATE 0x0002 /* Fixed TX rate */ -#define ZYD_FW_LINK_STATUS 0x0003 -#define ZYD_FW_SOFT_RESET 0x0004 -#define ZYD_FW_FLASH_CHK 0x0005 - -/* possible flags for register ZYD_FW_LINK_STATUS */ -#define ZYD_LED1 (1 << 8) -#define ZYD_LED2 (1 << 9) - -/* - * RF IDs. - */ -#define ZYD_RF_UW2451 0x2 /* not supported yet */ -#define ZYD_RF_UCHIP 0x3 /* not supported yet */ -#define ZYD_RF_AL2230 0x4 -#define ZYD_RF_AL7230B 0x5 -#define ZYD_RF_THETA 0x6 /* not supported yet */ -#define ZYD_RF_AL2210 0x7 -#define ZYD_RF_MAXIM_NEW 0x8 -#define ZYD_RF_GCT 0x9 -#define ZYD_RF_AL2230S 0xa /* not supported yet */ -#define ZYD_RF_RALINK 0xb /* not supported yet */ -#define ZYD_RF_INTERSIL 0xc /* not supported yet */ -#define ZYD_RF_RFMD 0xd -#define ZYD_RF_MAXIM_NEW2 0xe -#define ZYD_RF_PHILIPS 0xf /* not supported yet */ - -/* - * PHY registers (8 bits, not documented). - */ -#define ZYD_CR0 0x9000 -#define ZYD_CR1 0x9004 -#define ZYD_CR2 0x9008 -#define ZYD_CR3 0x900c -#define ZYD_CR5 0x9010 -#define ZYD_CR6 0x9014 -#define ZYD_CR7 0x9018 -#define ZYD_CR8 0x901c -#define ZYD_CR4 0x9020 -#define ZYD_CR9 0x9024 -#define ZYD_CR10 0x9028 -#define ZYD_CR11 0x902c -#define ZYD_CR12 0x9030 -#define ZYD_CR13 0x9034 -#define ZYD_CR14 0x9038 -#define ZYD_CR15 0x903c -#define ZYD_CR16 0x9040 -#define ZYD_CR17 0x9044 -#define ZYD_CR18 0x9048 -#define ZYD_CR19 0x904c -#define ZYD_CR20 0x9050 -#define ZYD_CR21 0x9054 -#define ZYD_CR22 0x9058 -#define ZYD_CR23 0x905c -#define ZYD_CR24 0x9060 -#define ZYD_CR25 0x9064 -#define ZYD_CR26 0x9068 -#define ZYD_CR27 0x906c -#define ZYD_CR28 0x9070 -#define ZYD_CR29 0x9074 -#define ZYD_CR30 0x9078 -#define ZYD_CR31 0x907c -#define ZYD_CR32 0x9080 -#define ZYD_CR33 0x9084 -#define ZYD_CR34 0x9088 -#define ZYD_CR35 0x908c -#define ZYD_CR36 0x9090 -#define ZYD_CR37 0x9094 -#define ZYD_CR38 0x9098 -#define ZYD_CR39 0x909c -#define ZYD_CR40 0x90a0 -#define ZYD_CR41 0x90a4 -#define ZYD_CR42 0x90a8 -#define ZYD_CR43 0x90ac -#define ZYD_CR44 0x90b0 -#define ZYD_CR45 0x90b4 -#define ZYD_CR46 0x90b8 -#define ZYD_CR47 0x90bc -#define ZYD_CR48 0x90c0 -#define ZYD_CR49 0x90c4 -#define ZYD_CR50 0x90c8 -#define ZYD_CR51 0x90cc -#define ZYD_CR52 0x90d0 -#define ZYD_CR53 0x90d4 -#define ZYD_CR54 0x90d8 -#define ZYD_CR55 0x90dc -#define ZYD_CR56 0x90e0 -#define ZYD_CR57 0x90e4 -#define ZYD_CR58 0x90e8 -#define ZYD_CR59 0x90ec -#define ZYD_CR60 0x90f0 -#define ZYD_CR61 0x90f4 -#define ZYD_CR62 0x90f8 -#define ZYD_CR63 0x90fc -#define ZYD_CR64 0x9100 -#define ZYD_CR65 0x9104 -#define ZYD_CR66 0x9108 -#define ZYD_CR67 0x910c -#define ZYD_CR68 0x9110 -#define ZYD_CR69 0x9114 -#define ZYD_CR70 0x9118 -#define ZYD_CR71 0x911c -#define ZYD_CR72 0x9120 -#define ZYD_CR73 0x9124 -#define ZYD_CR74 0x9128 -#define ZYD_CR75 0x912c -#define ZYD_CR76 0x9130 -#define ZYD_CR77 0x9134 -#define ZYD_CR78 0x9138 -#define ZYD_CR79 0x913c -#define ZYD_CR80 0x9140 -#define ZYD_CR81 0x9144 -#define ZYD_CR82 0x9148 -#define ZYD_CR83 0x914c -#define ZYD_CR84 0x9150 -#define ZYD_CR85 0x9154 -#define ZYD_CR86 0x9158 -#define ZYD_CR87 0x915c -#define ZYD_CR88 0x9160 -#define ZYD_CR89 0x9164 -#define ZYD_CR90 0x9168 -#define ZYD_CR91 0x916c -#define ZYD_CR92 0x9170 -#define ZYD_CR93 0x9174 -#define ZYD_CR94 0x9178 -#define ZYD_CR95 0x917c -#define ZYD_CR96 0x9180 -#define ZYD_CR97 0x9184 -#define ZYD_CR98 0x9188 -#define ZYD_CR99 0x918c -#define ZYD_CR100 0x9190 -#define ZYD_CR101 0x9194 -#define ZYD_CR102 0x9198 -#define ZYD_CR103 0x919c -#define ZYD_CR104 0x91a0 -#define ZYD_CR105 0x91a4 -#define ZYD_CR106 0x91a8 -#define ZYD_CR107 0x91ac -#define ZYD_CR108 0x91b0 -#define ZYD_CR109 0x91b4 -#define ZYD_CR110 0x91b8 -#define ZYD_CR111 0x91bc -#define ZYD_CR112 0x91c0 -#define ZYD_CR113 0x91c4 -#define ZYD_CR114 0x91c8 -#define ZYD_CR115 0x91cc -#define ZYD_CR116 0x91d0 -#define ZYD_CR117 0x91d4 -#define ZYD_CR118 0x91d8 -#define ZYD_CR119 0x91dc -#define ZYD_CR120 0x91e0 -#define ZYD_CR121 0x91e4 -#define ZYD_CR122 0x91e8 -#define ZYD_CR123 0x91ec -#define ZYD_CR124 0x91f0 -#define ZYD_CR125 0x91f4 -#define ZYD_CR126 0x91f8 -#define ZYD_CR127 0x91fc -#define ZYD_CR128 0x9200 -#define ZYD_CR129 0x9204 -#define ZYD_CR130 0x9208 -#define ZYD_CR131 0x920c -#define ZYD_CR132 0x9210 -#define ZYD_CR133 0x9214 -#define ZYD_CR134 0x9218 -#define ZYD_CR135 0x921c -#define ZYD_CR136 0x9220 -#define ZYD_CR137 0x9224 -#define ZYD_CR138 0x9228 -#define ZYD_CR139 0x922c -#define ZYD_CR140 0x9230 -#define ZYD_CR141 0x9234 -#define ZYD_CR142 0x9238 -#define ZYD_CR143 0x923c -#define ZYD_CR144 0x9240 -#define ZYD_CR145 0x9244 -#define ZYD_CR146 0x9248 -#define ZYD_CR147 0x924c -#define ZYD_CR148 0x9250 -#define ZYD_CR149 0x9254 -#define ZYD_CR150 0x9258 -#define ZYD_CR151 0x925c -#define ZYD_CR152 0x9260 -#define ZYD_CR153 0x9264 -#define ZYD_CR154 0x9268 -#define ZYD_CR155 0x926c -#define ZYD_CR156 0x9270 -#define ZYD_CR157 0x9274 -#define ZYD_CR158 0x9278 -#define ZYD_CR159 0x927c -#define ZYD_CR160 0x9280 -#define ZYD_CR161 0x9284 -#define ZYD_CR162 0x9288 -#define ZYD_CR163 0x928c -#define ZYD_CR164 0x9290 -#define ZYD_CR165 0x9294 -#define ZYD_CR166 0x9298 -#define ZYD_CR167 0x929c -#define ZYD_CR168 0x92a0 -#define ZYD_CR169 0x92a4 -#define ZYD_CR170 0x92a8 -#define ZYD_CR171 0x92ac -#define ZYD_CR172 0x92b0 -#define ZYD_CR173 0x92b4 -#define ZYD_CR174 0x92b8 -#define ZYD_CR175 0x92bc -#define ZYD_CR176 0x92c0 -#define ZYD_CR177 0x92c4 -#define ZYD_CR178 0x92c8 -#define ZYD_CR179 0x92cc -#define ZYD_CR180 0x92d0 -#define ZYD_CR181 0x92d4 -#define ZYD_CR182 0x92d8 -#define ZYD_CR183 0x92dc -#define ZYD_CR184 0x92e0 -#define ZYD_CR185 0x92e4 -#define ZYD_CR186 0x92e8 -#define ZYD_CR187 0x92ec -#define ZYD_CR188 0x92f0 -#define ZYD_CR189 0x92f4 -#define ZYD_CR190 0x92f8 -#define ZYD_CR191 0x92fc -#define ZYD_CR192 0x9300 -#define ZYD_CR193 0x9304 -#define ZYD_CR194 0x9308 -#define ZYD_CR195 0x930c -#define ZYD_CR196 0x9310 -#define ZYD_CR197 0x9314 -#define ZYD_CR198 0x9318 -#define ZYD_CR199 0x931c -#define ZYD_CR200 0x9320 -#define ZYD_CR201 0x9324 -#define ZYD_CR202 0x9328 -#define ZYD_CR203 0x932c -#define ZYD_CR204 0x9330 -#define ZYD_CR205 0x9334 -#define ZYD_CR206 0x9338 -#define ZYD_CR207 0x933c -#define ZYD_CR208 0x9340 -#define ZYD_CR209 0x9344 -#define ZYD_CR210 0x9348 -#define ZYD_CR211 0x934c -#define ZYD_CR212 0x9350 -#define ZYD_CR213 0x9354 -#define ZYD_CR214 0x9358 -#define ZYD_CR215 0x935c -#define ZYD_CR216 0x9360 -#define ZYD_CR217 0x9364 -#define ZYD_CR218 0x9368 -#define ZYD_CR219 0x936c -#define ZYD_CR220 0x9370 -#define ZYD_CR221 0x9374 -#define ZYD_CR222 0x9378 -#define ZYD_CR223 0x937c -#define ZYD_CR224 0x9380 -#define ZYD_CR225 0x9384 -#define ZYD_CR226 0x9388 -#define ZYD_CR227 0x938c -#define ZYD_CR228 0x9390 -#define ZYD_CR229 0x9394 -#define ZYD_CR230 0x9398 -#define ZYD_CR231 0x939c -#define ZYD_CR232 0x93a0 -#define ZYD_CR233 0x93a4 -#define ZYD_CR234 0x93a8 -#define ZYD_CR235 0x93ac -#define ZYD_CR236 0x93b0 -#define ZYD_CR240 0x93c0 -#define ZYD_CR241 0x93c4 -#define ZYD_CR242 0x93c8 -#define ZYD_CR243 0x93cc -#define ZYD_CR244 0x93d0 -#define ZYD_CR245 0x93d4 -#define ZYD_CR251 0x93ec -#define ZYD_CR252 0x93f0 -#define ZYD_CR253 0x93f4 -#define ZYD_CR254 0x93f8 -#define ZYD_CR255 0x93fc - -/* copied nearly verbatim from the Linux driver rewrite */ -#define ZYD_DEF_PHY \ -{ \ - { ZYD_CR0, 0x0a }, { ZYD_CR1, 0x06 }, { ZYD_CR2, 0x26 }, \ - { ZYD_CR3, 0x38 }, { ZYD_CR4, 0x80 }, { ZYD_CR9, 0xa0 }, \ - { ZYD_CR10, 0x81 }, { ZYD_CR11, 0x00 }, { ZYD_CR12, 0x7f }, \ - { ZYD_CR13, 0x8c }, { ZYD_CR14, 0x80 }, { ZYD_CR15, 0x3d }, \ - { ZYD_CR16, 0x20 }, { ZYD_CR17, 0x1e }, { ZYD_CR18, 0x0a }, \ - { ZYD_CR19, 0x48 }, { ZYD_CR20, 0x0c }, { ZYD_CR21, 0x0c }, \ - { ZYD_CR22, 0x23 }, { ZYD_CR23, 0x90 }, { ZYD_CR24, 0x14 }, \ - { ZYD_CR25, 0x40 }, { ZYD_CR26, 0x10 }, { ZYD_CR27, 0x19 }, \ - { ZYD_CR28, 0x7f }, { ZYD_CR29, 0x80 }, { ZYD_CR30, 0x4b }, \ - { ZYD_CR31, 0x60 }, { ZYD_CR32, 0x43 }, { ZYD_CR33, 0x08 }, \ - { ZYD_CR34, 0x06 }, { ZYD_CR35, 0x0a }, { ZYD_CR36, 0x00 }, \ - { ZYD_CR37, 0x00 }, { ZYD_CR38, 0x38 }, { ZYD_CR39, 0x0c }, \ - { ZYD_CR40, 0x84 }, { ZYD_CR41, 0x2a }, { ZYD_CR42, 0x80 }, \ - { ZYD_CR43, 0x10 }, { ZYD_CR44, 0x12 }, { ZYD_CR46, 0xff }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR48, 0x26 }, { ZYD_CR49, 0x5b }, \ - { ZYD_CR64, 0xd0 }, { ZYD_CR65, 0x04 }, { ZYD_CR66, 0x58 }, \ - { ZYD_CR67, 0xc9 }, { ZYD_CR68, 0x88 }, { ZYD_CR69, 0x41 }, \ - { ZYD_CR70, 0x23 }, { ZYD_CR71, 0x10 }, { ZYD_CR72, 0xff }, \ - { ZYD_CR73, 0x32 }, { ZYD_CR74, 0x30 }, { ZYD_CR75, 0x65 }, \ - { ZYD_CR76, 0x41 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x30 }, \ - { ZYD_CR79, 0x68 }, { ZYD_CR80, 0x64 }, { ZYD_CR81, 0x64 }, \ - { ZYD_CR82, 0x00 }, { ZYD_CR83, 0x00 }, { ZYD_CR84, 0x00 }, \ - { ZYD_CR85, 0x02 }, { ZYD_CR86, 0x00 }, { ZYD_CR87, 0x00 }, \ - { ZYD_CR88, 0xff }, { ZYD_CR89, 0xfc }, { ZYD_CR90, 0x00 }, \ - { ZYD_CR91, 0x00 }, { ZYD_CR92, 0x00 }, { ZYD_CR93, 0x08 }, \ - { ZYD_CR94, 0x00 }, { ZYD_CR95, 0x00 }, { ZYD_CR96, 0xff }, \ - { ZYD_CR97, 0xe7 }, { ZYD_CR98, 0x00 }, { ZYD_CR99, 0x00 }, \ - { ZYD_CR100, 0x00 }, { ZYD_CR101, 0xae }, { ZYD_CR102, 0x02 }, \ - { ZYD_CR103, 0x00 }, { ZYD_CR104, 0x03 }, { ZYD_CR105, 0x65 }, \ - { ZYD_CR106, 0x04 }, { ZYD_CR107, 0x00 }, { ZYD_CR108, 0x0a }, \ - { ZYD_CR109, 0xaa }, { ZYD_CR110, 0xaa }, { ZYD_CR111, 0x25 }, \ - { ZYD_CR112, 0x25 }, { ZYD_CR113, 0x00 }, { ZYD_CR119, 0x1e }, \ - { ZYD_CR125, 0x90 }, { ZYD_CR126, 0x00 }, { ZYD_CR127, 0x00 }, \ - { ZYD_CR5, 0x00 }, { ZYD_CR6, 0x00 }, { ZYD_CR7, 0x00 }, \ - { ZYD_CR8, 0x00 }, { ZYD_CR9, 0x20 }, { ZYD_CR12, 0xf0 }, \ - { ZYD_CR20, 0x0e }, { ZYD_CR21, 0x0e }, { ZYD_CR27, 0x10 }, \ - { ZYD_CR44, 0x33 }, { ZYD_CR47, 0x1E }, { ZYD_CR83, 0x24 }, \ - { ZYD_CR84, 0x04 }, { ZYD_CR85, 0x00 }, { ZYD_CR86, 0x0C }, \ - { ZYD_CR87, 0x12 }, { ZYD_CR88, 0x0C }, { ZYD_CR89, 0x00 }, \ - { ZYD_CR90, 0x10 }, { ZYD_CR91, 0x08 }, { ZYD_CR93, 0x00 }, \ - { ZYD_CR94, 0x01 }, { ZYD_CR95, 0x00 }, { ZYD_CR96, 0x50 }, \ - { ZYD_CR97, 0x37 }, { ZYD_CR98, 0x35 }, { ZYD_CR101, 0x13 }, \ - { ZYD_CR102, 0x27 }, { ZYD_CR103, 0x27 }, { ZYD_CR104, 0x18 }, \ - { ZYD_CR105, 0x12 }, { ZYD_CR109, 0x27 }, { ZYD_CR110, 0x27 }, \ - { ZYD_CR111, 0x27 }, { ZYD_CR112, 0x27 }, { ZYD_CR113, 0x27 }, \ - { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, { ZYD_CR116, 0x24 }, \ - { ZYD_CR117, 0xfc }, { ZYD_CR118, 0xfa }, { ZYD_CR120, 0x4f }, \ - { ZYD_CR125, 0xaa }, { ZYD_CR127, 0x03 }, { ZYD_CR128, 0x14 }, \ - { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR131, 0x0C }, \ - { ZYD_CR136, 0xdf }, { ZYD_CR137, 0x40 }, { ZYD_CR138, 0xa0 }, \ - { ZYD_CR139, 0xb0 }, { ZYD_CR140, 0x99 }, { ZYD_CR141, 0x82 }, \ - { ZYD_CR142, 0x54 }, { ZYD_CR143, 0x1c }, { ZYD_CR144, 0x6c }, \ - { ZYD_CR147, 0x07 }, { ZYD_CR148, 0x4c }, { ZYD_CR149, 0x50 }, \ - { ZYD_CR150, 0x0e }, { ZYD_CR151, 0x18 }, { ZYD_CR160, 0xfe }, \ - { ZYD_CR161, 0xee }, { ZYD_CR162, 0xaa }, { ZYD_CR163, 0xfa }, \ - { ZYD_CR164, 0xfa }, { ZYD_CR165, 0xea }, { ZYD_CR166, 0xbe }, \ - { ZYD_CR167, 0xbe }, { ZYD_CR168, 0x6a }, { ZYD_CR169, 0xba }, \ - { ZYD_CR170, 0xba }, { ZYD_CR171, 0xba }, { ZYD_CR204, 0x7d }, \ - { ZYD_CR203, 0x30 }, { 0, 0} \ -} - -#define ZYD_DEF_PHYB \ -{ \ - { ZYD_CR0, 0x14 }, { ZYD_CR1, 0x06 }, { ZYD_CR2, 0x26 }, \ - { ZYD_CR3, 0x38 }, { ZYD_CR4, 0x80 }, { ZYD_CR9, 0xe0 }, \ - { ZYD_CR10, 0x81 }, { ZYD_CR11, 0x00 }, { ZYD_CR12, 0xf0 }, \ - { ZYD_CR13, 0x8c }, { ZYD_CR14, 0x80 }, { ZYD_CR15, 0x3d }, \ - { ZYD_CR16, 0x20 }, { ZYD_CR17, 0x1e }, { ZYD_CR18, 0x0a }, \ - { ZYD_CR19, 0x48 }, { ZYD_CR20, 0x10 }, { ZYD_CR21, 0x0e }, \ - { ZYD_CR22, 0x23 }, { ZYD_CR23, 0x90 }, { ZYD_CR24, 0x14 }, \ - { ZYD_CR25, 0x40 }, { ZYD_CR26, 0x10 }, { ZYD_CR27, 0x10 }, \ - { ZYD_CR28, 0x7f }, { ZYD_CR29, 0x80 }, { ZYD_CR30, 0x4b }, \ - { ZYD_CR31, 0x60 }, { ZYD_CR32, 0x43 }, { ZYD_CR33, 0x08 }, \ - { ZYD_CR34, 0x06 }, { ZYD_CR35, 0x0a }, { ZYD_CR36, 0x00 }, \ - { ZYD_CR37, 0x00 }, { ZYD_CR38, 0x38 }, { ZYD_CR39, 0x0c }, \ - { ZYD_CR40, 0x84 }, { ZYD_CR41, 0x2a }, { ZYD_CR42, 0x80 }, \ - { ZYD_CR43, 0x10 }, { ZYD_CR44, 0x33 }, { ZYD_CR46, 0xff }, \ - { ZYD_CR47, 0x1E }, { ZYD_CR48, 0x26 }, { ZYD_CR49, 0x5b }, \ - { ZYD_CR64, 0xd0 }, { ZYD_CR65, 0x04 }, { ZYD_CR66, 0x58 }, \ - { ZYD_CR67, 0xc9 }, { ZYD_CR68, 0x88 }, { ZYD_CR69, 0x41 }, \ - { ZYD_CR70, 0x23 }, { ZYD_CR71, 0x10 }, { ZYD_CR72, 0xff }, \ - { ZYD_CR73, 0x32 }, { ZYD_CR74, 0x30 }, { ZYD_CR75, 0x65 }, \ - { ZYD_CR76, 0x41 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x30 }, \ - { ZYD_CR79, 0xf0 }, { ZYD_CR80, 0x64 }, { ZYD_CR81, 0x64 }, \ - { ZYD_CR82, 0x00 }, { ZYD_CR83, 0x24 }, { ZYD_CR84, 0x04 }, \ - { ZYD_CR85, 0x00 }, { ZYD_CR86, 0x0c }, { ZYD_CR87, 0x12 }, \ - { ZYD_CR88, 0x0c }, { ZYD_CR89, 0x00 }, { ZYD_CR90, 0x58 }, \ - { ZYD_CR91, 0x04 }, { ZYD_CR92, 0x00 }, { ZYD_CR93, 0x00 }, \ - { ZYD_CR94, 0x01 }, { ZYD_CR95, 0x20 }, { ZYD_CR96, 0x50 }, \ - { ZYD_CR97, 0x37 }, { ZYD_CR98, 0x35 }, { ZYD_CR99, 0x00 }, \ - { ZYD_CR100, 0x01 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR103, 0x27 }, { ZYD_CR104, 0x18 }, { ZYD_CR105, 0x12 }, \ - { ZYD_CR106, 0x04 }, { ZYD_CR107, 0x00 }, { ZYD_CR108, 0x0a }, \ - { ZYD_CR109, 0x27 }, { ZYD_CR110, 0x27 }, { ZYD_CR111, 0x27 }, \ - { ZYD_CR112, 0x27 }, { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, \ - { ZYD_CR115, 0x26 }, { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfc }, \ - { ZYD_CR118, 0xfa }, { ZYD_CR119, 0x1e }, { ZYD_CR125, 0x90 }, \ - { ZYD_CR126, 0x00 }, { ZYD_CR127, 0x00 }, { ZYD_CR128, 0x14 }, \ - { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR131, 0x0c }, \ - { ZYD_CR136, 0xdf }, { ZYD_CR137, 0xa0 }, { ZYD_CR138, 0xa8 }, \ - { ZYD_CR139, 0xb4 }, { ZYD_CR140, 0x98 }, { ZYD_CR141, 0x82 }, \ - { ZYD_CR142, 0x53 }, { ZYD_CR143, 0x1c }, { ZYD_CR144, 0x6c }, \ - { ZYD_CR147, 0x07 }, { ZYD_CR148, 0x40 }, { ZYD_CR149, 0x40 }, \ - { ZYD_CR150, 0x14 }, { ZYD_CR151, 0x18 }, { ZYD_CR159, 0x70 }, \ - { ZYD_CR160, 0xfe }, { ZYD_CR161, 0xee }, { ZYD_CR162, 0xaa }, \ - { ZYD_CR163, 0xfa }, { ZYD_CR164, 0xfa }, { ZYD_CR165, 0xea }, \ - { ZYD_CR166, 0xbe }, { ZYD_CR167, 0xbe }, { ZYD_CR168, 0x6a }, \ - { ZYD_CR169, 0xba }, { ZYD_CR170, 0xba }, { ZYD_CR171, 0xba }, \ - { ZYD_CR204, 0x7d }, { ZYD_CR203, 0x30 }, \ - { 0, 0 } \ -} - -#define ZYD_RFMD_PHY \ -{ \ - { ZYD_CR2, 0x1e }, { ZYD_CR9, 0x20 }, { ZYD_CR10, 0x89 }, \ - { ZYD_CR11, 0x00 }, { ZYD_CR15, 0xd0 }, { ZYD_CR17, 0x68 }, \ - { ZYD_CR19, 0x4a }, { ZYD_CR20, 0x0c }, { ZYD_CR21, 0x0e }, \ - { ZYD_CR23, 0x48 }, { ZYD_CR24, 0x14 }, { ZYD_CR26, 0x90 }, \ - { ZYD_CR27, 0x30 }, { ZYD_CR29, 0x20 }, { ZYD_CR31, 0xb2 }, \ - { ZYD_CR32, 0x43 }, { ZYD_CR33, 0x28 }, { ZYD_CR38, 0x30 }, \ - { ZYD_CR34, 0x0f }, { ZYD_CR35, 0xf0 }, { ZYD_CR41, 0x2a }, \ - { ZYD_CR46, 0x7f }, { ZYD_CR47, 0x1e }, { ZYD_CR51, 0xc5 }, \ - { ZYD_CR52, 0xc5 }, { ZYD_CR53, 0xc5 }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR82, 0x00 }, \ - { ZYD_CR83, 0x24 }, { ZYD_CR84, 0x04 }, { ZYD_CR85, 0x00 }, \ - { ZYD_CR86, 0x10 }, { ZYD_CR87, 0x2a }, { ZYD_CR88, 0x10 }, \ - { ZYD_CR89, 0x24 }, { ZYD_CR90, 0x18 }, { ZYD_CR91, 0x00 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR93, 0x00 }, { ZYD_CR94, 0x01 }, \ - { ZYD_CR95, 0x00 }, { ZYD_CR96, 0x40 }, { ZYD_CR97, 0x37 }, \ - { ZYD_CR98, 0x05 }, { ZYD_CR99, 0x28 }, { ZYD_CR100, 0x00 }, \ - { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, { ZYD_CR103, 0x27 }, \ - { ZYD_CR104, 0x18 }, { ZYD_CR105, 0x12 }, { ZYD_CR106, 0x1a }, \ - { ZYD_CR107, 0x24 }, { ZYD_CR108, 0x0a }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x2f }, { ZYD_CR111, 0x27 }, { ZYD_CR112, 0x27 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x40 }, \ - { ZYD_CR116, 0x40 }, { ZYD_CR117, 0xf0 }, { ZYD_CR118, 0xf0 }, \ - { ZYD_CR119, 0x16 }, { ZYD_CR122, 0x00 }, { ZYD_CR127, 0x03 }, \ - { ZYD_CR131, 0x08 }, { ZYD_CR138, 0x28 }, { ZYD_CR148, 0x44 }, \ - { ZYD_CR150, 0x10 }, { ZYD_CR169, 0xbb }, { ZYD_CR170, 0xbb } \ -} - -#define ZYD_RFMD_RF \ -{ \ - 0x000007, 0x07dd43, 0x080959, 0x0e6666, 0x116a57, 0x17dd43, \ - 0x1819f9, 0x1e6666, 0x214554, 0x25e7fa, 0x27fffa, 0x294128, \ - 0x2c0000, 0x300000, 0x340000, 0x381e0f, 0x6c180f \ -} - -#define ZYD_RFMD_CHANTABLE \ -{ \ - { 0x181979, 0x1e6666 }, \ - { 0x181989, 0x1e6666 }, \ - { 0x181999, 0x1e6666 }, \ - { 0x1819a9, 0x1e6666 }, \ - { 0x1819b9, 0x1e6666 }, \ - { 0x1819c9, 0x1e6666 }, \ - { 0x1819d9, 0x1e6666 }, \ - { 0x1819e9, 0x1e6666 }, \ - { 0x1819f9, 0x1e6666 }, \ - { 0x181a09, 0x1e6666 }, \ - { 0x181a19, 0x1e6666 }, \ - { 0x181a29, 0x1e6666 }, \ - { 0x181a39, 0x1e6666 }, \ - { 0x181a60, 0x1c0000 } \ -} - -#define ZYD_AL2230_PHY \ -{ \ - { ZYD_CR15, 0x20 }, { ZYD_CR23, 0x40 }, { ZYD_CR24, 0x20 }, \ - { ZYD_CR26, 0x11 }, { ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, \ - { ZYD_CR44, 0x33 }, { ZYD_CR106, 0x2a }, { ZYD_CR107, 0x1a }, \ - { ZYD_CR109, 0x09 }, { ZYD_CR110, 0x27 }, { ZYD_CR111, 0x2b }, \ - { ZYD_CR112, 0x2b }, { ZYD_CR119, 0x0a }, { ZYD_CR10, 0x89 }, \ - { ZYD_CR17, 0x28 }, { ZYD_CR26, 0x93 }, { ZYD_CR34, 0x30 }, \ - { ZYD_CR35, 0x3e }, { ZYD_CR41, 0x24 }, { ZYD_CR44, 0x32 }, \ - { ZYD_CR46, 0x96 }, { ZYD_CR47, 0x1e }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, \ - { ZYD_CR89, 0x04 }, { ZYD_CR92, 0x0a }, { ZYD_CR99, 0x28 }, \ - { ZYD_CR100, 0x00 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x24 }, { ZYD_CR107, 0x2a }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0xfc }, \ - { ZYD_CR119, 0x10 }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, \ - { ZYD_CR122, 0xe0 }, { ZYD_CR137, 0x88 }, { ZYD_CR252, 0xff }, \ - { ZYD_CR253, 0xff }, { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x3f }, \ - { ZYD_CR138, 0x28 }, { ZYD_CR203, 0x06 } \ -} - -#define ZYD_AL2230_PHY_B \ -{ \ - { ZYD_CR10, 0x89 }, { ZYD_CR15, 0x20 }, { ZYD_CR17, 0x2B }, \ - { ZYD_CR23, 0x40 }, { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, { ZYD_CR33, 0x28 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x3e }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x99 }, { ZYD_CR47, 0x1e }, \ - { ZYD_CR48, 0x06 }, { ZYD_CR49, 0xf9 }, { ZYD_CR51, 0x01 }, \ - { ZYD_CR52, 0x80 }, { ZYD_CR53, 0x7e }, { ZYD_CR65, 0x00 }, \ - { ZYD_CR66, 0x00 }, { ZYD_CR67, 0x00 }, { ZYD_CR68, 0x00 }, \ - { ZYD_CR69, 0x28 }, { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, \ - { ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, \ - { ZYD_CR91, 0x00 }, { ZYD_CR92, 0x0a }, { ZYD_CR98, 0x8d }, \ - { ZYD_CR99, 0x00 }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x24 }, { ZYD_CR107, 0x2a }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x1f }, { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x26 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xfa }, \ - { ZYD_CR119, 0x10 }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x6c }, \ - { ZYD_CR122, 0xfc }, { ZYD_CR123, 0x57 }, { ZYD_CR125, 0xad }, \ - { ZYD_CR126, 0x6c }, { ZYD_CR127, 0x03 }, { ZYD_CR137, 0x50 }, \ - { ZYD_CR138, 0xa8 }, { ZYD_CR144, 0xac }, { ZYD_CR150, 0x0d }, \ - { ZYD_CR252, 0x34 }, { ZYD_CR253, 0x34 } \ -} - -#define ZYD_AL2230_PHY_PART1 \ -{ \ - { ZYD_CR240, 0x57 }, { ZYD_CR9, 0xe0 } \ -} - -#define ZYD_AL2230_PHY_PART2 \ -{ \ - { ZYD_CR251, 0x2f }, { ZYD_CR251, 0x7f }, \ -} - -#define ZYD_AL2230_PHY_PART3 \ -{ \ - { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, \ -} - -#define ZYD_AL2230S_PHY_INIT \ -{ \ - { ZYD_CR47, 0x1e }, { ZYD_CR106, 0x22 }, { ZYD_CR107, 0x2a }, \ - { ZYD_CR109, 0x13 }, { ZYD_CR118, 0xf8 }, { ZYD_CR119, 0x12 }, \ - { ZYD_CR122, 0xe0 }, { ZYD_CR128, 0x10 }, { ZYD_CR129, 0x0e }, \ - { ZYD_CR130, 0x10 } \ -} - -#define ZYD_AL2230_PHY_FINI_PART1 \ -{ \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR12, 0xf0 }, { ZYD_CR77, 0x1b }, { ZYD_CR78, 0x58 }, \ - { ZYD_CR203, 0x06 }, { ZYD_CR240, 0x80 }, \ -} - -#define ZYD_AL2230_RF_PART1 \ -{ \ - 0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3 \ -} - -#define ZYD_AL2230_RF_PART2 \ -{ \ - 0x000da4, 0x0f4dc5, 0x0805b6, 0x011687, 0x000688, 0x0403b9, \ - 0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00500f \ -} - -#define ZYD_AL2230_RF_PART3 \ -{ \ - 0x00d00f, 0x004c0f, 0x00540f, 0x00700f, 0x00500f \ -} - -#define ZYD_AL2230_RF_B \ -{ \ - 0x03f790, 0x033331, 0x00000d, 0x0b3331, 0x03b812, 0x00fff3, \ - 0x0005a4, 0x0f4dc5, 0x0805b6, 0x0146c7, 0x000688, 0x0403b9, \ - 0x00dbba, 0x00099b, 0x0bdffc, 0x00000d, 0x00580f \ -} - -#define ZYD_AL2230_RF_B_PART1 \ -{ \ - 0x8cccd0, 0x481dc0, 0xcfff00, 0x25a000 \ -} - -#define ZYD_AL2230_RF_B_PART2 \ -{ \ - 0x25a000, 0xa3b2f0, 0x6da010, 0xe36280, 0x116000, 0x9dc020, \ - 0x5ddb00, 0xd99000, 0x3ffbd0, 0xb00000, 0xf01a00 \ -} - -#define ZYD_AL2230_RF_B_PART3 \ -{ \ - 0xf01b00, 0xf01e00, 0xf01a00 \ -} - -#define ZYD_AL2230_CHANTABLE \ -{ \ - { 0x03f790, 0x033331, 0x00000d }, \ - { 0x03f790, 0x0b3331, 0x00000d }, \ - { 0x03e790, 0x033331, 0x00000d }, \ - { 0x03e790, 0x0b3331, 0x00000d }, \ - { 0x03f7a0, 0x033331, 0x00000d }, \ - { 0x03f7a0, 0x0b3331, 0x00000d }, \ - { 0x03e7a0, 0x033331, 0x00000d }, \ - { 0x03e7a0, 0x0b3331, 0x00000d }, \ - { 0x03f7b0, 0x033331, 0x00000d }, \ - { 0x03f7b0, 0x0b3331, 0x00000d }, \ - { 0x03e7b0, 0x033331, 0x00000d }, \ - { 0x03e7b0, 0x0b3331, 0x00000d }, \ - { 0x03f7c0, 0x033331, 0x00000d }, \ - { 0x03e7c0, 0x066661, 0x00000d } \ -} - -#define ZYD_AL2230_CHANTABLE_B \ -{ \ - { 0x09efc0, 0x8cccc0, 0xb00000 }, \ - { 0x09efc0, 0x8cccd0, 0xb00000 }, \ - { 0x09e7c0, 0x8cccc0, 0xb00000 }, \ - { 0x09e7c0, 0x8cccd0, 0xb00000 }, \ - { 0x05efc0, 0x8cccc0, 0xb00000 }, \ - { 0x05efc0, 0x8cccd0, 0xb00000 }, \ - { 0x05e7c0, 0x8cccc0, 0xb00000 }, \ - { 0x05e7c0, 0x8cccd0, 0xb00000 }, \ - { 0x0defc0, 0x8cccc0, 0xb00000 }, \ - { 0x0defc0, 0x8cccd0, 0xb00000 }, \ - { 0x0de7c0, 0x8cccc0, 0xb00000 }, \ - { 0x0de7c0, 0x8cccd0, 0xb00000 }, \ - { 0x03efc0, 0x8cccc0, 0xb00000 }, \ - { 0x03e7c0, 0x866660, 0xb00000 } \ -} - -#define ZYD_AL7230B_PHY_1 \ -{ \ - { ZYD_CR240, 0x57 }, { ZYD_CR15, 0x20 }, { ZYD_CR23, 0x40 }, \ - { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x11 }, { ZYD_CR28, 0x3e }, \ - { ZYD_CR29, 0x00 }, { ZYD_CR44, 0x33 }, { ZYD_CR106, 0x22 }, \ - { ZYD_CR107, 0x1a }, { ZYD_CR109, 0x09 }, { ZYD_CR110, 0x27 }, \ - { ZYD_CR111, 0x2b }, { ZYD_CR112, 0x2b }, { ZYD_CR119, 0x0a }, \ - { ZYD_CR122, 0xfc }, { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x28 }, \ - { ZYD_CR26, 0x93 }, { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x3e }, \ - { ZYD_CR41, 0x24 }, { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x96 }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, \ - { ZYD_CR81, 0x30 }, { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR99, 0x28 }, { ZYD_CR100, 0x02 }, \ - { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, { ZYD_CR106, 0x22 }, \ - { ZYD_CR107, 0x3f }, { ZYD_CR109, 0x09 }, { ZYD_CR110, 0x1f }, \ - { ZYD_CR111, 0x1f }, { ZYD_CR112, 0x1f }, { ZYD_CR113, 0x27 }, \ - { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, { ZYD_CR116, 0x3f }, \ - { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xfc }, { ZYD_CR119, 0x10 }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, { ZYD_CR137, 0x88 }, \ - { ZYD_CR138, 0xa8 }, { ZYD_CR252, 0x34 }, { ZYD_CR253, 0x34 }, \ - { ZYD_CR251, 0x2f } \ -} - -#define ZYD_AL7230B_PHY_2 \ -{ \ - { ZYD_CR251, 0x3f }, { ZYD_CR128, 0x14 }, { ZYD_CR129, 0x12 }, \ - { ZYD_CR130, 0x10 }, { ZYD_CR38, 0x38 }, { ZYD_CR136, 0xdf } \ -} - -#define ZYD_AL7230B_PHY_3 \ -{ \ - { ZYD_CR203, 0x06 }, { ZYD_CR240, 0x80 } \ -} - -#define ZYD_AL7230B_RF_1 \ -{ \ - 0x09ec04, 0x8cccc8, 0x4ff821, 0xc5fbfc, 0x21ebfe, 0xafd401, \ - 0x6cf56a, 0xe04073, 0x193d76, 0x9dd844, 0x500007, 0xd8c010, \ - 0x3c9000, 0xbfffff, 0x700000, 0xf15d58 \ -} - -#define ZYD_AL7230B_RF_2 \ -{ \ - 0xf15d59, 0xf15d5c, 0xf15d58 \ -} - -#define ZYD_AL7230B_RF_SETCHANNEL \ -{ \ - 0x4ff821, 0xc5fbfc, 0x21ebfe, 0xafd401, 0x6cf56a, 0xe04073, \ - 0x193d76, 0x9dd844, 0x500007, 0xd8c010, 0x3c9000, 0xf15d58 \ -} - -#define ZYD_AL7230B_CHANTABLE \ -{ \ - { 0x09ec00, 0x8cccc8 }, \ - { 0x09ec00, 0x8cccd8 }, \ - { 0x09ec00, 0x8cccc0 }, \ - { 0x09ec00, 0x8cccd0 }, \ - { 0x05ec00, 0x8cccc8 }, \ - { 0x05ec00, 0x8cccd8 }, \ - { 0x05ec00, 0x8cccc0 }, \ - { 0x05ec00, 0x8cccd0 }, \ - { 0x0dec00, 0x8cccc8 }, \ - { 0x0dec00, 0x8cccd8 }, \ - { 0x0dec00, 0x8cccc0 }, \ - { 0x0dec00, 0x8cccd0 }, \ - { 0x03ec00, 0x8cccc8 }, \ - { 0x03ec00, 0x866660 } \ -} - -#define ZYD_AL2210_PHY \ -{ \ - { ZYD_CR9, 0xe0 }, { ZYD_CR10, 0x91 }, { ZYD_CR12, 0x90 }, \ - { ZYD_CR15, 0xd0 }, { ZYD_CR16, 0x40 }, { ZYD_CR17, 0x58 }, \ - { ZYD_CR18, 0x04 }, { ZYD_CR23, 0x66 }, { ZYD_CR24, 0x14 }, \ - { ZYD_CR26, 0x90 }, { ZYD_CR31, 0x80 }, { ZYD_CR34, 0x06 }, \ - { ZYD_CR35, 0x3e }, { ZYD_CR38, 0x38 }, { ZYD_CR46, 0x90 }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR64, 0x64 }, { ZYD_CR79, 0xb5 }, \ - { ZYD_CR80, 0x38 }, { ZYD_CR81, 0x30 }, { ZYD_CR113, 0xc0 }, \ - { ZYD_CR127, 0x03 } \ -} - -#define ZYD_AL2210_RF \ -{ \ - 0x2396c0, 0x00fcb1, 0x358132, 0x0108b3, 0xc77804, 0x456415, \ - 0xff2226, 0x806667, 0x7860f8, 0xbb01c9, 0x00000a, 0x00000b \ -} - -#define ZYD_AL2210_CHANTABLE \ -{ \ - 0x0196c0, 0x019710, 0x019760, 0x0197b0, 0x019800, 0x019850, \ - 0x0198a0, 0x0198f0, 0x019940, 0x019990, 0x0199e0, 0x019a30, \ - 0x019a80, 0x019b40 \ -} - -#define ZYD_GCT_PHY \ -{ \ - { ZYD_CR10, 0x89 }, { ZYD_CR15, 0x20 }, { ZYD_CR17, 0x28 }, \ - { ZYD_CR23, 0x38 }, { ZYD_CR24, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR27, 0x15 }, { ZYD_CR28, 0x3e }, { ZYD_CR29, 0x00 }, \ - { ZYD_CR33, 0x28 }, { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x43 }, \ - { ZYD_CR41, 0x24 }, { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x92 }, \ - { ZYD_CR47, 0x1e }, { ZYD_CR48, 0x04 }, { ZYD_CR49, 0xfa }, \ - { ZYD_CR79, 0x58 }, { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, \ - { ZYD_CR87, 0x0a }, { ZYD_CR89, 0x04 }, { ZYD_CR91, 0x00 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR98, 0x8d }, { ZYD_CR99, 0x28 }, \ - { ZYD_CR100, 0x02 }, { ZYD_CR101, 0x09 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x1c }, { ZYD_CR107, 0x1c }, { ZYD_CR109, 0x13 }, \ - { ZYD_CR110, 0x1f }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x1f }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x23 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xfa }, { ZYD_CR118, 0xf0 }, \ - { ZYD_CR119, 0x1a }, { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x1f }, \ - { ZYD_CR122, 0xf0 }, { ZYD_CR123, 0x57 }, { ZYD_CR125, 0xad }, \ - { ZYD_CR126, 0x6c }, { ZYD_CR127, 0x03 }, { ZYD_CR128, 0x14 }, \ - { ZYD_CR129, 0x12 }, { ZYD_CR130, 0x10 }, { ZYD_CR137, 0x50 }, \ - { ZYD_CR138, 0xa8 }, { ZYD_CR144, 0xac }, { ZYD_CR146, 0x20 }, \ - { ZYD_CR252, 0xff }, { ZYD_CR253, 0xff } \ -} - -#define ZYD_GCT_RF \ -{ \ - 0x40002b, 0x519e4f, 0x6f81ad, 0x73fffe, 0x25f9c, 0x100047, \ - 0x200999, 0x307602, 0x346063, \ -} - -#define ZYD_GCT_VCO \ -{ \ - { 0x664d, 0x604d, 0x6675, 0x6475, 0x6655, 0x6455, 0x6665 }, \ - { 0x666d, 0x606d, 0x664d, 0x644d, 0x6675, 0x6475, 0x6655 }, \ - { 0x665d, 0x605d, 0x666d, 0x646d, 0x664d, 0x644d, 0x6675 }, \ - { 0x667d, 0x607d, 0x665d, 0x645d, 0x666d, 0x646d, 0x664d }, \ - { 0x6643, 0x6043, 0x667d, 0x647d, 0x665d, 0x645d, 0x666d }, \ - { 0x6663, 0x6063, 0x6643, 0x6443, 0x667d, 0x647d, 0x665d }, \ - { 0x6653, 0x6053, 0x6663, 0x6463, 0x6643, 0x6443, 0x667d }, \ - { 0x6673, 0x6073, 0x6653, 0x6453, 0x6663, 0x6463, 0x6643 }, \ - { 0x664b, 0x604b, 0x6673, 0x6473, 0x6653, 0x6453, 0x6663 }, \ - { 0x666b, 0x606b, 0x664b, 0x644b, 0x6673, 0x6473, 0x6653 }, \ - { 0x665b, 0x605b, 0x666b, 0x646b, 0x664b, 0x644b, 0x6673 } \ -} - -#define ZYD_GCT_TXGAIN \ -{ \ - 0x0e313, 0x0fb13, 0x0e093, 0x0f893, 0x0ea93, 0x1f093, 0x1f493, \ - 0x1f693, 0x1f393, 0x1f35b, 0x1e6db, 0x1ff3f, 0x1ffff, 0x361d7, \ - 0x37fbf, 0x3ff8b, 0x3ff33, 0x3fb3f, 0x3ffff \ -} - -#define ZYD_GCT_CHANNEL_ACAL \ -{ \ - 0x106847, 0x106847, 0x106867, 0x106867, 0x106867, 0x106867, \ - 0x106857, 0x106857, 0x106857, 0x106857, 0x106877, 0x106877, \ - 0x106877, 0x10684f \ -} - -#define ZYD_GCT_CHANNEL_STD \ -{ \ - 0x100047, 0x100047, 0x100067, 0x100067, 0x100067, 0x100067, \ - 0x100057, 0x100057, 0x100057, 0x100057, 0x100077, 0x100077, \ - 0x100077, 0x10004f \ -} - -#define ZYD_GCT_CHANNEL_DIV \ -{ \ - 0x200999, 0x20099b, 0x200998, 0x20099a, 0x200999, 0x20099b, \ - 0x200998, 0x20099a, 0x200999, 0x20099b, 0x200998, 0x20099a, \ - 0x200999, 0x200ccc \ -} - -#define ZYD_MAXIM2_PHY \ -{ \ - { ZYD_CR23, 0x40 }, { ZYD_CR15, 0x20 }, { ZYD_CR28, 0x3e }, \ - { ZYD_CR29, 0x00 }, { ZYD_CR26, 0x11 }, { ZYD_CR44, 0x33 }, \ - { ZYD_CR106, 0x2a }, { ZYD_CR107, 0x1a }, { ZYD_CR109, 0x2b }, \ - { ZYD_CR110, 0x2b }, { ZYD_CR111, 0x2b }, { ZYD_CR112, 0x2b }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0xfa }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x77 }, { ZYD_CR122, 0xfe }, \ - { ZYD_CR10, 0x89 }, { ZYD_CR17, 0x20 }, { ZYD_CR26, 0x93 }, \ - { ZYD_CR34, 0x30 }, { ZYD_CR35, 0x40 }, { ZYD_CR41, 0x24 }, \ - { ZYD_CR44, 0x32 }, { ZYD_CR46, 0x90 }, { ZYD_CR79, 0x58 }, \ - { ZYD_CR80, 0x30 }, { ZYD_CR81, 0x30 }, { ZYD_CR89, 0x18 }, \ - { ZYD_CR92, 0x0a }, { ZYD_CR101, 0x13 }, { ZYD_CR102, 0x27 }, \ - { ZYD_CR106, 0x20 }, { ZYD_CR107, 0x24 }, { ZYD_CR109, 0x09 }, \ - { ZYD_CR110, 0x13 }, { ZYD_CR111, 0x13 }, { ZYD_CR112, 0x13 }, \ - { ZYD_CR113, 0x27 }, { ZYD_CR114, 0x27 }, { ZYD_CR115, 0x24 }, \ - { ZYD_CR116, 0x24 }, { ZYD_CR117, 0xf4 }, { ZYD_CR118, 0x00 }, \ - { ZYD_CR120, 0x4f }, { ZYD_CR121, 0x06 }, { ZYD_CR122, 0xfe } \ -} - -#define ZYD_MAXIM2_RF \ -{ \ - 0x33334, 0x10a03, 0x00400, 0x00ca1, 0x10072, 0x18645, 0x04006, \ - 0x000a7, 0x08258, 0x03fc9, 0x0040a, 0x0000b, 0x0026c \ -} - -#define ZYD_MAXIM2_CHANTABLE_F \ -{ \ - 0x33334, 0x08884, 0x1ddd4, 0x33334, 0x08884, 0x1ddd4, 0x33334, \ - 0x08884, 0x1ddd4, 0x33334, 0x08884, 0x1ddd4, 0x33334, 0x26664 \ -} - -#define ZYD_MAXIM2_CHANTABLE \ -{ \ - { 0x33334, 0x10a03 }, \ - { 0x08884, 0x20a13 }, \ - { 0x1ddd4, 0x30a13 }, \ - { 0x33334, 0x10a13 }, \ - { 0x08884, 0x20a23 }, \ - { 0x1ddd4, 0x30a23 }, \ - { 0x33334, 0x10a23 }, \ - { 0x08884, 0x20a33 }, \ - { 0x1ddd4, 0x30a33 }, \ - { 0x33334, 0x10a33 }, \ - { 0x08884, 0x20a43 }, \ - { 0x1ddd4, 0x30a43 }, \ - { 0x33334, 0x10a43 }, \ - { 0x26664, 0x20a53 } \ -} - -#define ZYD_TX_RATEDIV \ -{ \ - 0x1, 0x2, 0xb, 0xb, 0x0, 0x0, 0x0, 0x0, 0x30, 0x18, 0xc, 0x6, \ - 0x36, 0x24, 0x12, 0x9 \ -} - -/* - * Control pipe requests. - */ -#define ZYD_DOWNLOADREQ 0x30 -#define ZYD_DOWNLOADSTS 0x31 -#define ZYD_READFWDATAREQ 0x32 - -/* possible values for register ZYD_CR_INTERRUPT */ -#define ZYD_HWINT_MASK 0x004f0000 - -/* possible values for register ZYD_MAC_MISC */ -#define ZYD_UNLOCK_PHY_REGS 0x80 - -/* possible values for register ZYD_MAC_ENCRYPTION_TYPE */ -#define ZYD_ENC_SNIFFER 8 - -/* flags for register ZYD_MAC_RXFILTER */ -#define ZYD_FILTER_ASS_REQ (1 << 0) -#define ZYD_FILTER_ASS_RSP (1 << 1) -#define ZYD_FILTER_REASS_REQ (1 << 2) -#define ZYD_FILTER_REASS_RSP (1 << 3) -#define ZYD_FILTER_PRB_REQ (1 << 4) -#define ZYD_FILTER_PRB_RSP (1 << 5) -#define ZYD_FILTER_BCN (1 << 8) -#define ZYD_FILTER_ATIM (1 << 9) -#define ZYD_FILTER_DEASS (1 << 10) -#define ZYD_FILTER_AUTH (1 << 11) -#define ZYD_FILTER_DEAUTH (1 << 12) -#define ZYD_FILTER_PS_POLL (1 << 26) -#define ZYD_FILTER_RTS (1 << 27) -#define ZYD_FILTER_CTS (1 << 28) -#define ZYD_FILTER_ACK (1 << 29) -#define ZYD_FILTER_CFE (1 << 30) -#define ZYD_FILTER_CFE_A (1 << 31) - -/* helpers for register ZYD_MAC_RXFILTER */ -#define ZYD_FILTER_MONITOR 0xffffffff -#define ZYD_FILTER_BSS \ - (ZYD_FILTER_ASS_REQ | ZYD_FILTER_ASS_RSP | \ - ZYD_FILTER_REASS_REQ | ZYD_FILTER_REASS_RSP | \ - ZYD_FILTER_PRB_REQ | ZYD_FILTER_PRB_RSP | \ - (0x3 << 6) | \ - ZYD_FILTER_BCN | ZYD_FILTER_ATIM | ZYD_FILTER_DEASS | \ - ZYD_FILTER_AUTH | ZYD_FILTER_DEAUTH | \ - (0x7 << 13) | \ - ZYD_FILTER_PS_POLL | ZYD_FILTER_ACK) -#define ZYD_FILTER_HOSTAP \ - (ZYD_FILTER_ASS_REQ | ZYD_FILTER_REASS_REQ | \ - ZYD_FILTER_PRB_REQ | ZYD_FILTER_DEASS | ZYD_FILTER_AUTH | \ - ZYD_FILTER_DEAUTH | ZYD_FILTER_PS_POLL) - -struct zyd_tx_desc { - uint8_t phy; -#define ZYD_TX_PHY_SIGNAL(x) ((x) & 0xf) -#define ZYD_TX_PHY_OFDM (1 << 4) -#define ZYD_TX_PHY_SHPREAMBLE (1 << 5) /* CCK */ -#define ZYD_TX_PHY_5GHZ (1 << 5) /* OFDM */ - uint16_t len; - uint8_t flags; -#define ZYD_TX_FLAG_BACKOFF (1 << 0) -#define ZYD_TX_FLAG_MULTICAST (1 << 1) -#define ZYD_TX_FLAG_TYPE(x) (((x) & 0x3) << 2) -#define ZYD_TX_TYPE_DATA 0 -#define ZYD_TX_TYPE_PS_POLL 1 -#define ZYD_TX_TYPE_MGMT 2 -#define ZYD_TX_TYPE_CTL 3 -#define ZYD_TX_FLAG_WAKEUP (1 << 4) -#define ZYD_TX_FLAG_RTS (1 << 5) -#define ZYD_TX_FLAG_ENCRYPT (1 << 6) -#define ZYD_TX_FLAG_CTS_TO_SELF (1 << 7) - uint16_t pktlen; - uint16_t plcp_length; - uint8_t plcp_service; -#define ZYD_PLCP_LENGEXT 0x80 - uint16_t nextlen; -} __packed; - -struct zyd_plcphdr { - uint8_t signal; - uint8_t reserved[2]; - uint16_t service; /* unaligned! */ -} __packed; - -struct zyd_rx_stat { - uint8_t signal_cck; - uint8_t rssi; - uint8_t signal_ofdm; - uint8_t cipher; -#define ZYD_RX_CIPHER_WEP64 1 -#define ZYD_RX_CIPHER_TKIP 2 -#define ZYD_RX_CIPHER_AES 4 -#define ZYD_RX_CIPHER_WEP128 5 -#define ZYD_RX_CIPHER_WEP256 6 -#define ZYD_RX_CIPHER_WEP \ - (ZYD_RX_CIPHER_WEP64 | ZYD_RX_CIPHER_WEP128 | ZYD_RX_CIPHER_WEP256) - uint8_t flags; -#define ZYD_RX_OFDM (1 << 0) -#define ZYD_RX_TIMEOUT (1 << 1) -#define ZYD_RX_OVERRUN (1 << 2) -#define ZYD_RX_DECRYPTERR (1 << 3) -#define ZYD_RX_BADCRC32 (1 << 4) -#define ZYD_RX_NOT2ME (1 << 5) -#define ZYD_RX_BADCRC16 (1 << 6) -#define ZYD_RX_ERROR (1 << 7) -} __packed; - -/* this structure may be unaligned */ -struct zyd_rx_desc { -#define ZYD_MAX_RXFRAMECNT 3 - uWord len[ZYD_MAX_RXFRAMECNT]; - uWord tag; -#define ZYD_TAG_MULTIFRAME 0x697e -} __packed; - -/* I2C bus alike */ -struct zyd_rfwrite_cmd { - uint16_t code; - uint16_t width; - uint16_t bit[32]; -#define ZYD_RF_IF_LE (1 << 1) -#define ZYD_RF_CLK (1 << 2) -#define ZYD_RF_DATA (1 << 3) -} __packed; - -struct zyd_cmd { - uint16_t code; -#define ZYD_CMD_IOWR 0x0021 /* write HMAC or PHY register */ -#define ZYD_CMD_IORD 0x0022 /* read HMAC or PHY register */ -#define ZYD_CMD_RFCFG 0x0023 /* write RF register */ -#define ZYD_NOTIF_IORD 0x9001 /* response for ZYD_CMD_IORD */ -#define ZYD_NOTIF_MACINTR 0x9001 /* interrupt notification */ -#define ZYD_NOTIF_RETRYSTATUS 0xa001 /* Tx retry notification */ - uint8_t data[64]; -} __packed; - -/* structure for command ZYD_CMD_IOWR */ -struct zyd_pair { - uint16_t reg; -/* helpers macros to read/write 32-bit registers */ -#define ZYD_REG32_LO(reg) (reg) -#define ZYD_REG32_HI(reg) \ - ((reg) + ((((reg) & 0xf000) == 0x9000) ? 2 : 1)) - uint16_t val; -} __packed; - -/* structure for notification ZYD_NOTIF_RETRYSTATUS */ -struct zyd_notif_retry { - uint16_t rate; - uint8_t macaddr[IEEE80211_ADDR_LEN]; - uint16_t count; -} __packed; - -#define ZYD_CONFIG_INDEX 0 -#define ZYD_IFACE_INDEX 0 - -#define ZYD_INTR_TIMEOUT 1000 -#define ZYD_TX_TIMEOUT 10000 - -#define ZYD_MAX_TXBUFSZ \ - (sizeof(struct zyd_tx_desc) + MCLBYTES) -#define ZYD_MIN_FRAGSZ \ - (sizeof(struct zyd_plcphdr) + IEEE80211_MIN_LEN + \ - sizeof(struct zyd_rx_stat)) -#define ZYD_MIN_RXBUFSZ ZYD_MIN_FRAGSZ -#define ZYX_MAX_RXBUFSZ \ - ((sizeof (struct zyd_plcphdr) + IEEE80211_MAX_LEN + \ - sizeof (struct zyd_rx_stat)) * ZYD_MAX_RXFRAMECNT + \ - sizeof (struct zyd_rx_desc)) -#define ZYD_TX_DESC_SIZE (sizeof (struct zyd_tx_desc)) - -#define ZYD_RX_LIST_CNT 1 -#define ZYD_TX_LIST_CNT 5 -#define ZYD_CMD_FLAG_READ (1 << 0) -#define ZYD_CMD_FLAG_SENT (1 << 1) - -/* quickly determine if a given rate is CCK or OFDM */ -#define ZYD_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) - -struct zyd_phy_pair { - uint16_t reg; - uint8_t val; -}; - -struct zyd_mac_pair { - uint16_t reg; - uint32_t val; -}; - -struct zyd_tx_data { - STAILQ_ENTRY(zyd_tx_data) next; - struct zyd_softc *sc; - struct zyd_tx_desc desc; - struct mbuf *m; - struct ieee80211_node *ni; - int rate; -}; -typedef STAILQ_HEAD(, zyd_tx_data) zyd_txdhead; - -struct zyd_rx_data { - struct mbuf *m; - int rssi; -}; - -struct zyd_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - int8_t wr_antsignal; - int8_t wr_antnoise; -} __packed; - -#define ZYD_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct zyd_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint8_t wt_rate; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define ZYD_TX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL)) - -struct zyd_softc; /* forward declaration */ - -struct zyd_rf { - /* RF methods */ - int (*init)(struct zyd_rf *); - int (*switch_radio)(struct zyd_rf *, int); - int (*set_channel)(struct zyd_rf *, uint8_t); - int (*bandedge6)(struct zyd_rf *, - struct ieee80211_channel *); - /* RF attributes */ - struct zyd_softc *rf_sc; /* back-pointer */ - int width; - int idx; /* for GIT RF */ - int update_pwr; -}; - -struct zyd_rq { - struct zyd_cmd *cmd; - const uint16_t *idata; - struct zyd_pair *odata; - int ilen; - int olen; - int flags; - STAILQ_ENTRY(zyd_rq) rq; -}; - -struct zyd_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define ZYD_VAP(vap) ((struct zyd_vap *)(vap)) - -enum { - ZYD_BULK_WR, - ZYD_BULK_RD, - ZYD_INTR_WR, - ZYD_INTR_RD, - ZYD_N_TRANSFER = 4, -}; - -struct zyd_softc { - struct ifnet *sc_ifp; - device_t sc_dev; - struct usb_device *sc_udev; - - struct usb_xfer *sc_xfer[ZYD_N_TRANSFER]; - - int sc_flags; -#define ZYD_FLAG_FWLOADED (1 << 0) -#define ZYD_FLAG_INITONCE (1 << 1) -#define ZYD_FLAG_INITDONE (1 << 2) - - struct zyd_rf sc_rf; - - STAILQ_HEAD(, zyd_rq) sc_rtx; - STAILQ_HEAD(, zyd_rq) sc_rqh; - - uint8_t sc_bssid[IEEE80211_ADDR_LEN]; - uint16_t sc_fwbase; - uint8_t sc_regdomain; - uint8_t sc_macrev; - uint16_t sc_fwrev; - uint8_t sc_rfrev; - uint8_t sc_parev; - uint8_t sc_al2230s; - uint8_t sc_bandedge6; - uint8_t sc_newphy; - uint8_t sc_cckgain; - uint8_t sc_fix_cr157; - uint8_t sc_ledtype; - uint8_t sc_txled; - - uint32_t sc_atim_wnd; - uint32_t sc_pre_tbtt; - uint32_t sc_bcn_int; - - uint8_t sc_pwrcal[14]; - uint8_t sc_pwrint[14]; - uint8_t sc_ofdm36_cal[14]; - uint8_t sc_ofdm48_cal[14]; - uint8_t sc_ofdm54_cal[14]; - - struct mtx sc_mtx; - struct zyd_tx_data tx_data[ZYD_TX_LIST_CNT]; - zyd_txdhead tx_q; - zyd_txdhead tx_free; - int tx_nfree; - struct zyd_rx_desc sc_rx_desc; - struct zyd_rx_data sc_rx_data[ZYD_MAX_RXFRAMECNT]; - int sc_rx_count; - - struct zyd_cmd sc_ibuf; - - struct zyd_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct zyd_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define ZYD_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define ZYD_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define ZYD_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) - diff --git a/sys/dev/misc/ipmi/Makefile b/sys/dev/misc/ipmi/Makefile index 3bc299dac1..7ca94d1918 100644 --- a/sys/dev/misc/ipmi/Makefile +++ b/sys/dev/misc/ipmi/Makefile @@ -1,7 +1,5 @@ # $FreeBSD: head/sys/modules/ipmi/Makefile 190445 2009-03-26 17:14:22Z ambrisko $ -#SUBDIR+= ipmi_linux - # XXX - ipmi_smbus and ipmi_ssif depend on smbus # XXX - ipmi_acpi depends on acpi KMOD= ipmi diff --git a/sys/dev/misc/ipmi/ipmi_linux.c b/sys/dev/misc/ipmi/ipmi_linux.c deleted file mode 100644 index b3ded96f0b..0000000000 --- a/sys/dev/misc/ipmi/ipmi_linux.c +++ /dev/null @@ -1,114 +0,0 @@ -/*- - * Copyright (c) 2009 IronPort Systems Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: head/sys/dev/ipmi/ipmi_linux.c 263233 2014-03-16 10:55:57Z rwatson $ - */ - -/* - * Linux ioctl handler for the ipmi device driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __amd64__ -#include -#include -#else -#include -#include -#endif -#include -#include - -/* There are multiple ioctl number ranges that need to be handled */ -#define IPMI_LINUX_IOCTL_MIN 0x690b -#define IPMI_LINUX_IOCTL_MAX 0x6915 - -/* Linux versions of ioctl's */ -#define L_IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv) -#define L_IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv) -#define L_IPMICTL_SEND_COMMAND _IOW(IPMI_IOC_MAGIC, 13, struct ipmi_req) -#define L_IPMICTL_REGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec) -#define L_IPMICTL_UNREGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec) -#define L_IPMICTL_SET_GETS_EVENTS_CMD _IOW(IPMI_IOC_MAGIC, 16, int) -#define L_IPMICTL_SET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 17, unsigned int) -#define L_IPMICTL_GET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 18, unsigned int) -#define L_IPMICTL_SET_MY_LUN_CMD _IOW(IPMI_IOC_MAGIC, 19, unsigned int) -#define L_IPMICTL_GET_MY_LUN_CMD _IOW(IPMI_IOC_MAGIC, 20, unsigned int) - -static linux_ioctl_function_t ipmi_linux_ioctl; -static struct linux_ioctl_handler ipmi_linux_handler = {ipmi_linux_ioctl, - IPMI_LINUX_IOCTL_MIN, - IPMI_LINUX_IOCTL_MAX}; - -SYSINIT (ipmi_linux_register, SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_register_handler, &ipmi_linux_handler); -SYSUNINIT(ipmi_linux_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_unregister_handler, &ipmi_linux_handler); - -static int -ipmi_linux_modevent(module_t mod, int type, void *data) -{ - /* Do we care about any specific load/unload actions? */ - return (0); -} - -DEV_MODULE(ipmi_linux, ipmi_linux_modevent, NULL); -MODULE_DEPEND(ipmi_linux, linux, 1, 1, 1); - -static int -ipmi_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) -{ - cap_rights_t rights; - struct file *fp; - u_long cmd; - int error; - - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); - if (error != 0) - return (error); - cmd = args->cmd; - - switch(cmd) { - case L_IPMICTL_GET_MY_ADDRESS_CMD: - cmd = IPMICTL_GET_MY_ADDRESS_CMD; - break; - case L_IPMICTL_GET_MY_LUN_CMD: - cmd = IPMICTL_GET_MY_LUN_CMD; - break; - } - /* - * Pass the ioctl off to our standard handler. - */ - error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td)); - fdrop(fp, td); - return (error); -} diff --git a/sys/dev/misc/ipmi/ipmi_linux/Makefile b/sys/dev/misc/ipmi/ipmi_linux/Makefile deleted file mode 100644 index c743c8bf87..0000000000 --- a/sys/dev/misc/ipmi/ipmi_linux/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD: head/sys/modules/ipmi/ipmi_linux/Makefile 190452 2009-03-26 19:15:31Z ambrisko $ - -.PATH: ${.CURDIR}/.. - -KMOD= ipmi_linux -SRCS= ipmi_linux.c - -.include diff --git a/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8 b/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8 index 6915d4a4dd..45791b3b0d 100644 --- a/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8 +++ b/usr.sbin/802_11/wpa_supplicant/wpa_supplicant.8 @@ -157,11 +157,9 @@ Wait for a control interface monitor before starting. .Xr iwi 4 , .Xr ral 4 , .Xr rum 4 , -.\".Xr ural 4 , .Xr wi 4 , .Xr wlan 4 , .Xr wpi 4 , -.\".Xr zyd 4 , .Xr wpa_supplicant.conf 5 , .Xr devd 8 , .Xr ifconfig 8 ,