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>