PERFORCE change 102449 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Jul 26 12:08:47 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=102449
Change 102449 by hselasky at hselasky_mini_itx on 2006/07/26 12:08:39
Import rewritten "if_ural" driver. Some bugs were fixed. None of the bugs
posed a security risk to the system, rather a panic. Again there are a lot
of changes. Mostly because all of the configuration had to be moved into a
separate thread, that allows sleeping. Please test.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/if_ural.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/if_uralreg.h#3 add
.. //depot/projects/usb/src/sys/dev/usb/if_uralvar.h#3 add
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/if_ural.c#4 (text+ko) ====
@@ -1,0 +1,2991 @@
+/*-
+ * Copyright (c) 2005, 2006
+ * Damien Bergamini <damien.bergamini at free.fr>
+ *
+ * Copyright (c) 2006
+ * Hans Petter Selasky <hselasky at freebsd.org>
+ *
+ * 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.
+ *
+ *
+ * NOTE: all function names beginning like "ural_cfg_" can only
+ * be called from within the "ural_config_thread()" function!
+ */
+
+/*-
+ * Ralink Technology RT2500USB chipset driver
+ * http://www.ralinktech.com/
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/endian.h>
+#include <sys/kthread.h>
+#include <sys/unistd.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+
+#include <dev/usb/usb_port.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_subr.h>
+
+#include "usbdevs.h"
+
+#include <dev/usb/../usb/if_uralreg.h>
+#include <dev/usb/../usb/if_uralvar.h>
+
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.38 2006/05/16 14:36:32 phk Exp $");
+
+#ifdef USB_DEBUG
+#define DPRINTF(sc,n,fmt,...) \
+ do { if (ural_debug > (n)) { \
+ printf("%s:%s: " fmt, (sc)->sc_name, \
+ __FUNCTION__,## __VA_ARGS__); } } while (0)
+
+static int ural_debug = 0;
+SYSCTL_NODE(_hw_usb, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural");
+SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0,
+ "ural debug level");
+#else
+#define DPRINTF(...)
+#endif
+
+/* prototypes */
+static device_probe_t ural_probe;
+static device_attach_t ural_attach;
+static device_detach_t ural_detach;
+
+static void
+ural_cfg_do_request(struct ural_softc *sc, usb_device_request_t *req,
+ void *data);
+static void
+ural_cfg_set_testmode(struct ural_softc *sc);
+
+static void
+ural_cfg_eeprom_read(struct ural_softc *sc, u_int16_t addr,
+ void *buf, int len);
+static u_int16_t
+ural_cfg_read(struct ural_softc *sc, u_int16_t reg);
+
+static void
+ural_cfg_read_multi(struct ural_softc *sc, u_int16_t reg,
+ void *buf, int len);
+static void
+ural_cfg_write(struct ural_softc *sc, u_int16_t reg, u_int16_t val);
+
+static void
+ural_cfg_write_multi(struct ural_softc *sc, u_int16_t reg,
+ void *buf, int len);
+static void
+ural_cfg_bbp_write(struct ural_softc *sc, u_int8_t reg, u_int8_t val);
+
+static u_int8_t
+ural_cfg_bbp_read(struct ural_softc *sc, u_int8_t reg);
+
+static void
+ural_cfg_rf_write(struct ural_softc *sc, u_int8_t reg, u_int32_t val);
+
+static void
+ural_config_thread(void *arg);
+
+static void
+ural_config_copy(struct ural_softc *sc, struct ural_config_copy *cc);
+
+static void
+ural_queue_command(struct ural_softc *sc, ural_command_t *command_func);
+
+static void
+ural_check_gone(struct ural_softc *sc);
+
+static const char *
+ural_get_rf(int rev);
+
+static int
+ural_rxrate(struct ural_rx_desc *desc);
+
+static void
+ural_bulk_read_callback(struct usbd_xfer *xfer);
+
+static void
+ural_bulk_read_clear_stall_callback(struct usbd_xfer *xfer);
+
+static u_int16_t
+ural_ack_rate(struct ieee80211com *ic, u_int16_t rate);
+
+static u_int16_t
+ural_txtime(struct ural_softc *sc, u_int16_t len, u_int16_t rate, u_int32_t flags);
+
+static u_int8_t
+ural_plcp_signal(u_int16_t rate);
+
+static void
+ural_setup_tx_desc(struct ural_softc *sc, u_int32_t flags, u_int16_t len,
+ u_int16_t rate);
+static void
+ural_bulk_write_callback(struct usbd_xfer *xfer);
+
+static void
+ural_bulk_write_clear_stall_callback(struct usbd_xfer *xfer);
+
+static void
+ural_watchdog(void *arg);
+
+static void
+ural_init_cb(void *arg);
+
+static int
+ural_ioctl_cb(struct ifnet *ifp, u_long cmd, caddr_t data);
+
+static void
+ural_start_cb(struct ifnet *ifp);
+
+static int
+ural_media_change_cb(struct ifnet *ifp);
+
+static int
+ural_reset_cb(struct ifnet *ifp);
+
+static int
+ural_newstate_cb(struct ieee80211com *ic, enum ieee80211_state nstate, int arg);
+
+static void
+ural_cfg_sleep(struct ural_softc *sc, u_int32_t timeout);
+
+static void
+ural_tx_bcn_complete(struct ural_softc *sc);
+
+static void
+ural_cfg_tx_bcn(struct ural_softc *sc);
+
+static void
+ural_cfg_dummy(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_set_chan(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_set_run(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_disable_rf_tune(struct ural_softc *sc);
+
+static void
+ural_cfg_enable_tsf_sync(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_disable_tsf_sync(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_update_slot(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_set_txpreamble(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_set_basicrates(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_set_bssid(struct ural_softc *sc, const u_int8_t *bssid);
+
+static void
+ural_cfg_set_macaddr(struct ural_softc *sc, const u_int8_t *addr);
+
+static void
+ural_cfg_update_promisc(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_set_txantenna(struct ural_softc *sc, u_int8_t antenna);
+
+static void
+ural_cfg_set_rxantenna(struct ural_softc *sc, u_int8_t antenna);
+
+static void
+ural_cfg_read_eeprom(struct ural_softc *sc);
+
+static u_int8_t
+ural_cfg_bbp_init(struct ural_softc *sc);
+
+static void
+ural_cfg_init(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_stop(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_cfg_amrr_start(struct ural_softc *sc);
+
+static void
+ural_cfg_amrr_timeout(struct ural_softc *sc,
+ struct ural_config_copy *cc);
+static void
+ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni);
+
+/* various supported device vendors/products */
+static const struct usb_devno ural_devs[] = {
+ { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL167G },
+ { USB_VENDOR_ASUS, USB_PRODUCT_RALINK_RT2570 },
+ { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050 },
+ { USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_C54U },
+ { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG122 },
+ { USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWBKG },
+ { USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254 },
+ { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB54G },
+ { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB54GP },
+ { USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_HU200TS },
+ { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54 },
+ { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54AI },
+ { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54YB },
+ { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_NINWIFI },
+ { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570 },
+ { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_2 },
+ { USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_3 },
+ { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570 },
+ { USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_2 },
+ { USB_VENDOR_VTECH, USB_PRODUCT_VTECH_RT2570 },
+ { USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570 }
+};
+
+/*
+ * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
+ */
+static const struct ieee80211_rateset ural_rateset_11a =
+ { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
+
+static const struct ieee80211_rateset ural_rateset_11b =
+ { 4, { 2, 4, 11, 22 } };
+
+static const struct ieee80211_rateset ural_rateset_11g =
+ { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
+
+/*
+ * Default values for MAC registers; values taken from
+ * the reference driver:
+ */
+static const struct {
+ u_int16_t reg;
+ u_int16_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, 0x0780 },
+ { 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 {
+ u_int8_t reg;
+ u_int8_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 u_int32_t ural_rf2522_r2[] = {
+ 0x307f6, 0x307fb, 0x30800, 0x30805, 0x3080a, 0x3080f, 0x30814,
+ 0x30819, 0x3081e, 0x30823, 0x30828, 0x3082d, 0x30832, 0x3083e
+};
+
+static const u_int32_t ural_rf2523_r2[] = {
+ 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
+ 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
+};
+
+static const u_int32_t ural_rf2524_r2[] = {
+ 0x00327, 0x00328, 0x00329, 0x0032a, 0x0032b, 0x0032c, 0x0032d,
+ 0x0032e, 0x0032f, 0x00340, 0x00341, 0x00342, 0x00343, 0x00346
+};
+
+static const u_int32_t ural_rf2525_r2[] = {
+ 0x20327, 0x20328, 0x20329, 0x2032a, 0x2032b, 0x2032c, 0x2032d,
+ 0x2032e, 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20346
+};
+
+static const u_int32_t ural_rf2525_hi_r2[] = {
+ 0x2032f, 0x20340, 0x20341, 0x20342, 0x20343, 0x20344, 0x20345,
+ 0x20346, 0x20347, 0x20348, 0x20349, 0x2034a, 0x2034b, 0x2034e
+};
+
+static const u_int32_t ural_rf2525e_r2[] = {
+ 0x2044d, 0x2044e, 0x2044f, 0x20460, 0x20461, 0x20462, 0x20463,
+ 0x20464, 0x20465, 0x20466, 0x20467, 0x20468, 0x20469, 0x2046b
+};
+
+static const u_int32_t ural_rf2526_hi_r2[] = {
+ 0x0022a, 0x0022b, 0x0022b, 0x0022c, 0x0022c, 0x0022d, 0x0022d,
+ 0x0022e, 0x0022e, 0x0022f, 0x0022d, 0x00240, 0x00240, 0x00241
+};
+
+static const u_int32_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 {
+ u_int8_t chan;
+ u_int32_t r1;
+ u_int32_t r2;
+ u_int32_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 usbd_config ural_config[URAL_N_TRANSFER] = {
+ [0] = {
+ .type = UE_BULK,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_OUT,
+ .bufsize = (MCLBYTES + RAL_TX_DESC_SIZE + 4),
+ .flags = (USBD_USE_DMA|USBD_FORCE_SHORT_XFER),
+ .callback = &ural_bulk_write_callback,
+ },
+
+ [1] = {
+ .type = UE_BULK,
+ .endpoint = -1, /* any */
+ .direction = UE_DIR_IN,
+ .bufsize = (MCLBYTES + RAL_RX_DESC_SIZE),
+ .flags = (USBD_USE_DMA|USBD_SHORT_XFER_OK),
+ .callback = &ural_bulk_read_callback,
+ },
+
+ [2] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &ural_bulk_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+
+ [3] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* Control pipe */
+ .direction = -1,
+ .bufsize = sizeof(usb_device_request_t),
+ .callback = &ural_bulk_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ },
+};
+
+static devclass_t ural_devclass;
+
+static device_method_t ural_methods[] = {
+ DEVMETHOD(device_probe, ural_probe),
+ DEVMETHOD(device_attach, ural_attach),
+ DEVMETHOD(device_detach, ural_detach),
+ { 0, 0 }
+};
+
+static driver_t ural_driver = {
+ .name = "ural",
+ .methods = ural_methods,
+ .size = sizeof(struct ural_softc),
+};
+
+DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, usbd_driver_load, 0);
+MODULE_DEPEND(ural, usb, 1, 1, 1);
+MODULE_DEPEND(ural, wlan, 1, 1, 1);
+
+static int
+ural_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ if (uaa->iface != NULL) {
+ return UMATCH_NONE;
+ }
+
+ return ((usb_lookup(ural_devs, uaa->vendor, uaa->product) != NULL) ?
+ UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
+}
+
+static int
+ural_attach(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct ural_softc *sc = device_get_softc(dev);
+ int error;
+
+ if (sc == NULL) {
+ return ENOMEM;
+ }
+
+ usbd_set_desc(dev, uaa->device);
+
+ mtx_init(&sc->sc_mtx, "ural lock", MTX_NETWORK_LOCK,
+ MTX_DEF | MTX_RECURSE);
+
+ snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
+ device_get_nameunit(dev));
+
+ sc->sc_udev = uaa->device; /* XXX */
+ sc->sc_unit = device_get_unit(dev);
+
+ __callout_init_mtx(&(sc->sc_watchdog),
+ &(sc->sc_mtx), CALLOUT_RETURNUNLOCKED);
+
+ error = usbd_set_config_no(uaa->device, RAL_CONFIG_NO, 0);
+
+ if (error) {
+ device_printf(dev, "could not set configuration "
+ "number, err=%s!\n", usbd_errstr(error));
+ goto detach;
+ }
+
+ error = usbd_transfer_setup(uaa->device, RAL_IFACE_INDEX,
+ sc->sc_xfer, ural_config, URAL_N_TRANSFER,
+ sc, &(sc->sc_mtx), &(sc->sc_mem_wait));
+ if (error) {
+ device_printf(dev, "could not allocate USB transfers, "
+ "err=%s\n", usbd_errstr(error)) ;
+ goto detach;
+ }
+
+ sc->sc_cmd_queue_ptr =
+ usbd_alloc_mbufs(M_DEVBUF, &(sc->sc_cmd_free),
+ sizeof(struct ural_config_copy), 16);
+
+ if (sc->sc_cmd_queue_ptr == NULL) {
+ device_printf(dev, "could not allocate memory for "
+ "command queue!\n");
+ goto detach;
+ }
+
+ if(usb_kthread_create1(&ural_config_thread, sc,
+ &(sc->sc_config_thread), "%s", sc->sc_name))
+ {
+ sc->sc_config_thread = NULL;
+ device_printf(dev, "unable to create config thread!\n");
+ goto detach;
+ }
+
+ /* start watchdog */
+
+ mtx_lock(&(sc->sc_mtx));
+ ural_watchdog(sc);
+
+ return 0; /* success */
+
+ detach:
+ ural_detach(dev);
+ return ENXIO; /* failure */
+}
+
+static int
+ural_detach(device_t dev)
+{
+ struct ural_softc *sc = device_get_softc(dev);
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
+ register int error;
+
+ mtx_lock(&(sc->sc_mtx));
+
+ sc->sc_flags |= URAL_FLAG_DEV_GONE;
+
+ __callout_stop(&sc->sc_watchdog);
+
+ ural_queue_command(sc, &ural_cfg_dummy);
+
+ ural_cfg_stop(sc, NULL);
+
+ if (sc->sc_config_thread) {
+
+ while (!(sc->sc_flags & URAL_FLAG_TD_EXIT)) {
+
+ if (cold) {
+ panic("cannot stop config thread!\n");
+ }
+
+ error = msleep(&(sc->sc_wakeup_td_gone),
+ &(sc->sc_mtx), 0, "ural wait TD", 0);
+ }
+ }
+
+ ic = &(sc->sc_ic);
+ ifp = ic->ic_ifp;
+
+ mtx_unlock(&(sc->sc_mtx));
+
+ if (ifp) {
+ bpfdetach(ifp);
+ ieee80211_ifdetach(ic);
+ if_free(ifp);
+ }
+
+ usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
+
+ usbd_transfer_drain(&(sc->sc_mem_wait), &(sc->sc_mtx));
+
+ if (sc->sc_cmd_queue_ptr) {
+ free(sc->sc_cmd_queue_ptr, M_DEVBUF);
+ sc->sc_cmd_queue_ptr = NULL;
+ }
+
+ mtx_destroy(&sc->sc_mtx);
+
+ return 0;
+}
+
+/*========================================================================*
+ * REGISTER READ / WRITE WRAPPER ROUTINES
+ *========================================================================*/
+
+static void
+ural_cfg_do_request(struct ural_softc *sc, usb_device_request_t *req,
+ void *data)
+{
+ usbd_status err;
+
+ err = usbd_do_request_flags_mtx(sc->sc_udev, &(sc->sc_mtx), req,
+ data, 0, NULL, 1000);
+ ural_check_gone(sc);
+
+ if (err) {
+ u_int16_t length = UGETW(req->wLength);
+
+ printf("%s: device request failed, err=%s "
+ "(ignored)\n", sc->sc_name, usbd_errstr(err));
+
+ if ((req->bmRequestType & UT_READ) && length) {
+ bzero(data, length);
+ }
+ }
+ return;
+}
+
+static void
+ural_cfg_set_testmode(struct ural_softc *sc)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RAL_VENDOR_REQUEST;
+ USETW(req.wValue, 4);
+ USETW(req.wIndex, 1);
+ USETW(req.wLength, 0);
+
+ ural_cfg_do_request(sc, &req, NULL);
+ return;
+}
+
+static void
+ural_cfg_eeprom_read(struct ural_softc *sc, u_int16_t addr,
+ void *buf, int len)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = RAL_READ_EEPROM;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, addr);
+ USETW(req.wLength, len);
+
+ ural_cfg_do_request(sc, &req, buf);
+ return;
+}
+
+static u_int16_t
+ural_cfg_read(struct ural_softc *sc, u_int16_t reg)
+{
+ usb_device_request_t req;
+ u_int16_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(val));
+
+ ural_cfg_do_request(sc, &req, &val);
+
+ return le16toh(val);
+}
+
+static void
+ural_cfg_read_multi(struct ural_softc *sc, u_int16_t reg,
+ void *buf, int len)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = RAL_READ_MULTI_MAC;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, len);
+
+ ural_cfg_do_request(sc, &req, buf);
+ return;
+}
+
+static void
+ural_cfg_write(struct ural_softc *sc, u_int16_t reg, u_int16_t val)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RAL_WRITE_MAC;
+ USETW(req.wValue, val);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, 0);
+
+ ural_cfg_do_request(sc, &req, NULL);
+ return;
+}
+
+static void
+ural_cfg_write_multi(struct ural_softc *sc, u_int16_t reg,
+ void *buf, int len)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RAL_WRITE_MULTI_MAC;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, len);
+
+ ural_cfg_do_request(sc, &req, buf);
+ return;
+}
+
+static void
+ural_cfg_bbp_write(struct ural_softc *sc, u_int8_t reg, u_int8_t val)
+{
+ u_int16_t tmp;
+ u_int8_t to;
+
+ for (to = 0; ; to++) {
+ if (to < 5) {
+ tmp = ural_cfg_read(sc, RAL_PHY_CSR8);
+
+ if (!(tmp & RAL_BBP_BUSY)) {
+ break;
+ }
+ } else {
+ printf("%s: could not write to BBP\n",
+ sc->sc_name);
+ return;
+ }
+ }
+
+ tmp = (reg << 8) | val;
+ ural_cfg_write(sc, RAL_PHY_CSR7, tmp);
+ return;
+}
+
+static u_int8_t
+ural_cfg_bbp_read(struct ural_softc *sc, u_int8_t reg)
+{
+ u_int16_t val;
+ u_int8_t to;
+
+ val = RAL_BBP_WRITE | (reg << 8);
+ ural_cfg_write(sc, RAL_PHY_CSR7, val);
+
+ for (to = 0; ; to++) {
+ if (to < 5) {
+ val = ural_cfg_read(sc, RAL_PHY_CSR8);
+
+ if (!(val & RAL_BBP_BUSY)) {
+ break;
+ }
+ } else {
+ printf("%s: could not read BBP\n",
+ sc->sc_name);
+ return 0;
+ }
+ }
+ return (ural_cfg_read(sc, RAL_PHY_CSR7) & 0xff);
+}
+
+static void
+ural_cfg_rf_write(struct ural_softc *sc, u_int8_t reg, u_int32_t val)
+{
+ u_int32_t tmp;
+ u_int8_t to;
+
+ reg &= 3;
+
+ for (to = 0; ; to++) {
+ if (to < 5) {
+ tmp = ural_cfg_read(sc, RAL_PHY_CSR10);
+
+ if (!(tmp & RAL_RF_LOBUSY)) {
+ break;
+ }
+ } else {
+ printf("%s: could not write to RF\n",
+ sc->sc_name);
+ return;
+ }
+ }
+
+ tmp = RAL_RF_BUSY | RAL_RF_20BIT | ((val & 0xfffff) << 2) | reg;
+ ural_cfg_write(sc, RAL_PHY_CSR9, tmp & 0xffff);
+ ural_cfg_write(sc, RAL_PHY_CSR10, tmp >> 16);
+
+ /* remember last written value in sc */
+ sc->sc_rf_regs[reg] = val;
+
+ DPRINTF(sc, 15, "RF R[%u] <- 0x%05x\n", reg, val & 0xfffff);
+ return;
+}
+
+/*========================================================================*
+ * CONFIGURE THREAD
+ *========================================================================*/
+
+static void
+ural_config_thread(void *arg)
+{
+ struct ural_softc *sc = arg;
+ struct ieee80211com *ic = &(sc->sc_ic);
+ struct ifnet *ifp;
+ struct usbd_mbuf *m;
+ struct ural_config_copy *cc;
+ register int error;
+ register u_int16_t i;
+
+ mtx_lock(&(sc->sc_mtx));
+
+ /* retrieve RT2570 rev. no */
+ sc->sc_asic_rev = ural_cfg_read(sc, RAL_MAC_CSR0);
+
+ /* retrieve MAC address and various other things from EEPROM */
+ ural_cfg_read_eeprom(sc);
+
+ printf("%s: MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
+ sc->sc_name, sc->sc_asic_rev, ural_get_rf(sc->sc_rf_rev));
+
+ mtx_unlock(&(sc->sc_mtx));
+
+ ifp = if_alloc(IFT_ETHER);
+
+ mtx_lock(&(sc->sc_mtx));
+
+ if (ifp == NULL) {
+ printf("%s: could not if_alloc()!\n",
+ sc->sc_name);
+ goto command_loop;
+ }
+
+ sc->sc_ifp = ifp;
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "ural", sc->sc_unit);
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = &ural_init_cb;
+ ifp->if_ioctl = &ural_ioctl_cb;
+ ifp->if_start = &ural_start_cb;
+ ifp->if_watchdog = NULL;
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic->ic_ifp = ifp;
+ ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
+ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
+ ic->ic_state = IEEE80211_S_INIT;
+
+ /* set device capabilities */
+ ic->ic_caps =
+ 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_WPA; /* 802.11i */
+
+ if (sc->sc_rf_rev == RAL_RF_5222) {
+
+ /* set supported .11a rates */
+ ic->ic_sup_rates[IEEE80211_MODE_11A] = ural_rateset_11a;
+
+ /* set supported .11a channels */
+ for (i = 36; i <= 64; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ for (i = 100; i <= 140; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ for (i = 149; i <= 161; i += 4) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
+ ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
+ }
+ }
+
+ /* set supported .11b and .11g rates */
+ ic->ic_sup_rates[IEEE80211_MODE_11B] = ural_rateset_11b;
+ ic->ic_sup_rates[IEEE80211_MODE_11G] = ural_rateset_11g;
+
+ /* set supported .11b and .11g channels (1 through 14) */
+ for (i = 1; i <= 14; i++) {
+ ic->ic_channels[i].ic_freq =
+ ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
+ ic->ic_channels[i].ic_flags =
+ IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
+ }
+
+ mtx_unlock(&(sc->sc_mtx));
+
+ ieee80211_ifattach(ic);
+
+ mtx_lock(&(sc->sc_mtx));
+
+ ic->ic_reset = &ural_reset_cb;
+
+ /* enable SW bmiss handling in sta mode */
+ ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
+
+ /* override state transition machine */
+ sc->sc_newstate = ic->ic_newstate;
+ ic->ic_newstate = ural_newstate_cb;
+
+ mtx_unlock(&(sc->sc_mtx));
+
+ ieee80211_media_init(ic, ural_media_change_cb, ieee80211_media_status);
+
+ bpfattach2(ifp, DLT_IEEE802_11_RADIO,
+ sizeof(struct ieee80211_frame) + 64, &sc->sc_drvbpf);
+
+ mtx_lock(&(sc->sc_mtx));
+
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list