Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Jul 2006 12:08:46 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 102449 for review
Message-ID:  <200607261208.k6QC8kQF004512@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=102449

Change 102449 by hselasky@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@free.fr>
+ *
+ * Copyright (c) 2006
+ *	Hans Petter Selasky <hselasky@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) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607261208.k6QC8kQF004512>