zd1211rw: move under zydas vendor directory
authorKalle Valo <kvalo@codeaurora.org>
Wed, 18 Nov 2015 07:27:32 +0000 (09:27 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 18 Nov 2015 12:28:30 +0000 (14:28 +0200)
Part of reorganising wireless drivers directory and Kconfig.

Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
35 files changed:
MAINTAINERS
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/zd1211rw/Kconfig [deleted file]
drivers/net/wireless/zd1211rw/Makefile [deleted file]
drivers/net/wireless/zd1211rw/zd_chip.c [deleted file]
drivers/net/wireless/zd1211rw/zd_chip.h [deleted file]
drivers/net/wireless/zd1211rw/zd_def.h [deleted file]
drivers/net/wireless/zd1211rw/zd_mac.c [deleted file]
drivers/net/wireless/zd1211rw/zd_mac.h [deleted file]
drivers/net/wireless/zd1211rw/zd_rf.c [deleted file]
drivers/net/wireless/zd1211rw/zd_rf.h [deleted file]
drivers/net/wireless/zd1211rw/zd_rf_al2230.c [deleted file]
drivers/net/wireless/zd1211rw/zd_rf_al7230b.c [deleted file]
drivers/net/wireless/zd1211rw/zd_rf_rf2959.c [deleted file]
drivers/net/wireless/zd1211rw/zd_rf_uw2453.c [deleted file]
drivers/net/wireless/zd1211rw/zd_usb.c [deleted file]
drivers/net/wireless/zd1211rw/zd_usb.h [deleted file]
drivers/net/wireless/zydas/Kconfig
drivers/net/wireless/zydas/Makefile
drivers/net/wireless/zydas/zd1211rw/Kconfig [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/Makefile [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_chip.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_chip.h [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_def.h [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_mac.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_mac.h [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_rf.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_rf.h [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_rf_al2230.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_rf_al7230b.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_rf_rf2959.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_rf_uw2453.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_usb.c [new file with mode: 0644]
drivers/net/wireless/zydas/zd1211rw/zd_usb.h [new file with mode: 0644]

index ec09837..f2e7842 100644 (file)
@@ -11883,7 +11883,7 @@ W:      http://zd1211.ath.cx/wiki/DriverRewrite
 L:     linux-wireless@vger.kernel.org
 L:     zd1211-devs@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 L:     linux-wireless@vger.kernel.org
 L:     zd1211-devs@lists.sourceforge.net (subscribers-only)
 S:     Maintained
-F:     drivers/net/wireless/zd1211rw/
+F:     drivers/net/wireless/zydas/zd1211rw/
 
 ZPOOL COMPRESSED PAGE STORAGE API
 M:     Dan Streetman <ddstreet@ieee.org>
 
 ZPOOL COMPRESSED PAGE STORAGE API
 M:     Dan Streetman <ddstreet@ieee.org>
index 35155e2..e86dcdd 100644 (file)
@@ -124,7 +124,6 @@ source "drivers/net/wireless/mediatek/Kconfig"
 source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
 source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
 source "drivers/net/wireless/ti/Kconfig"
 source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
 source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
 source "drivers/net/wireless/ti/Kconfig"
-source "drivers/net/wireless/zd1211rw/Kconfig"
 source "drivers/net/wireless/rsi/Kconfig"
 
 endif # WLAN
 source "drivers/net/wireless/rsi/Kconfig"
 
 endif # WLAN
index 4ee6d6d..8f54add 100644 (file)
@@ -16,7 +16,6 @@ obj-$(CONFIG_HERMES)          += orinoco/
 obj-$(CONFIG_PRISM54)          += prism54/
 
 obj-$(CONFIG_HOSTAP)           += hostap/
 obj-$(CONFIG_PRISM54)          += prism54/
 
 obj-$(CONFIG_HOSTAP)           += hostap/
-obj-$(CONFIG_ZD1211RW)         += zd1211rw/
 obj-$(CONFIG_WLAN)             += realtek/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_WLAN)             += realtek/
 
 # 16-bit wireless PCMCIA client drivers
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig
deleted file mode 100644 (file)
index 9592058..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-config ZD1211RW
-       tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
-       depends on USB && MAC80211
-       select FW_LOADER
-       ---help---
-         This is a driver for the ZyDAS ZD1211/ZD1211B wireless
-         chip, present in many USB-wireless adapters.
-
-         Device firmware is required alongside this driver. You can download
-         the firmware distribution from http://sf.net/projects/zd1211/files/
-
-config ZD1211RW_DEBUG
-       bool "ZyDAS ZD1211 debugging"
-       depends on ZD1211RW
-       ---help---
-         ZD1211 debugging messages. Choosing Y will result in additional debug
-         messages being saved to your kernel logs, which may help debug any
-         problems.
-
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
deleted file mode 100644 (file)
index 5728a91..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-obj-$(CONFIG_ZD1211RW) += zd1211rw.o
-
-zd1211rw-objs := zd_chip.o zd_mac.o \
-               zd_rf_al2230.o zd_rf_rf2959.o \
-               zd_rf_al7230b.o zd_rf_uw2453.o \
-               zd_rf.o zd_usb.o
-
-ccflags-$(CONFIG_ZD1211RW_DEBUG) := -DDEBUG
-
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
deleted file mode 100644 (file)
index 07b94ed..0000000
+++ /dev/null
@@ -1,1560 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-/* This file implements all the hardware specific functions for the ZD1211
- * and ZD1211B chips. Support for the ZD1211B was possible after Timothy
- * Legge sent me a ZD1211B device. Thank you Tim. -- Uli
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include "zd_def.h"
-#include "zd_chip.h"
-#include "zd_mac.h"
-#include "zd_rf.h"
-
-void zd_chip_init(struct zd_chip *chip,
-                struct ieee80211_hw *hw,
-                struct usb_interface *intf)
-{
-       memset(chip, 0, sizeof(*chip));
-       mutex_init(&chip->mutex);
-       zd_usb_init(&chip->usb, hw, intf);
-       zd_rf_init(&chip->rf);
-}
-
-void zd_chip_clear(struct zd_chip *chip)
-{
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
-       zd_usb_clear(&chip->usb);
-       zd_rf_clear(&chip->rf);
-       mutex_destroy(&chip->mutex);
-       ZD_MEMCLEAR(chip, sizeof(*chip));
-}
-
-static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
-{
-       u8 *addr = zd_mac_get_perm_addr(zd_chip_to_mac(chip));
-       return scnprintf(buffer, size, "%02x-%02x-%02x",
-                        addr[0], addr[1], addr[2]);
-}
-
-/* Prints an identifier line, which will support debugging. */
-static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
-{
-       int i = 0;
-
-       i = scnprintf(buffer, size, "zd1211%s chip ",
-                     zd_chip_is_zd1211b(chip) ? "b" : "");
-       i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
-       i += scnprintf(buffer+i, size-i, " ");
-       i += scnprint_mac_oui(chip, buffer+i, size-i);
-       i += scnprintf(buffer+i, size-i, " ");
-       i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
-       i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
-               chip->patch_cck_gain ? 'g' : '-',
-               chip->patch_cr157 ? '7' : '-',
-               chip->patch_6m_band_edge ? '6' : '-',
-               chip->new_phy_layout ? 'N' : '-',
-               chip->al2230s_bit ? 'S' : '-');
-       return i;
-}
-
-static void print_id(struct zd_chip *chip)
-{
-       char buffer[80];
-
-       scnprint_id(chip, buffer, sizeof(buffer));
-       buffer[sizeof(buffer)-1] = 0;
-       dev_info(zd_chip_dev(chip), "%s\n", buffer);
-}
-
-static zd_addr_t inc_addr(zd_addr_t addr)
-{
-       u16 a = (u16)addr;
-       /* Control registers use byte addressing, but everything else uses word
-        * addressing. */
-       if ((a & 0xf000) == CR_START)
-               a += 2;
-       else
-               a += 1;
-       return (zd_addr_t)a;
-}
-
-/* Read a variable number of 32-bit values. Parameter count is not allowed to
- * exceed USB_MAX_IOREAD32_COUNT.
- */
-int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr,
-                unsigned int count)
-{
-       int r;
-       int i;
-       zd_addr_t a16[USB_MAX_IOREAD32_COUNT * 2];
-       u16 v16[USB_MAX_IOREAD32_COUNT * 2];
-       unsigned int count16;
-
-       if (count > USB_MAX_IOREAD32_COUNT)
-               return -EINVAL;
-
-       /* Use stack for values and addresses. */
-       count16 = 2 * count;
-       BUG_ON(count16 * sizeof(zd_addr_t) > sizeof(a16));
-       BUG_ON(count16 * sizeof(u16) > sizeof(v16));
-
-       for (i = 0; i < count; i++) {
-               int j = 2*i;
-               /* We read the high word always first. */
-               a16[j] = inc_addr(addr[i]);
-               a16[j+1] = addr[i];
-       }
-
-       r = zd_ioread16v_locked(chip, v16, a16, count16);
-       if (r) {
-               dev_dbg_f(zd_chip_dev(chip),
-                         "error: %s. Error number %d\n", __func__, r);
-               return r;
-       }
-
-       for (i = 0; i < count; i++) {
-               int j = 2*i;
-               values[i] = (v16[j] << 16) | v16[j+1];
-       }
-
-       return 0;
-}
-
-static int _zd_iowrite32v_async_locked(struct zd_chip *chip,
-                                      const struct zd_ioreq32 *ioreqs,
-                                      unsigned int count)
-{
-       int i, j, r;
-       struct zd_ioreq16 ioreqs16[USB_MAX_IOWRITE32_COUNT * 2];
-       unsigned int count16;
-
-       /* Use stack for values and addresses. */
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-
-       if (count == 0)
-               return 0;
-       if (count > USB_MAX_IOWRITE32_COUNT)
-               return -EINVAL;
-
-       count16 = 2 * count;
-       BUG_ON(count16 * sizeof(struct zd_ioreq16) > sizeof(ioreqs16));
-
-       for (i = 0; i < count; i++) {
-               j = 2*i;
-               /* We write the high word always first. */
-               ioreqs16[j].value   = ioreqs[i].value >> 16;
-               ioreqs16[j].addr    = inc_addr(ioreqs[i].addr);
-               ioreqs16[j+1].value = ioreqs[i].value;
-               ioreqs16[j+1].addr  = ioreqs[i].addr;
-       }
-
-       r = zd_usb_iowrite16v_async(&chip->usb, ioreqs16, count16);
-#ifdef DEBUG
-       if (r) {
-               dev_dbg_f(zd_chip_dev(chip),
-                         "error %d in zd_usb_write16v\n", r);
-       }
-#endif /* DEBUG */
-       return r;
-}
-
-int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
-                         unsigned int count)
-{
-       int r;
-
-       zd_usb_iowrite16v_async_start(&chip->usb);
-       r = _zd_iowrite32v_async_locked(chip, ioreqs, count);
-       if (r) {
-               zd_usb_iowrite16v_async_end(&chip->usb, 0);
-               return r;
-       }
-       return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
-}
-
-int zd_iowrite16a_locked(struct zd_chip *chip,
-                  const struct zd_ioreq16 *ioreqs, unsigned int count)
-{
-       int r;
-       unsigned int i, j, t, max;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       zd_usb_iowrite16v_async_start(&chip->usb);
-
-       for (i = 0; i < count; i += j + t) {
-               t = 0;
-               max = count-i;
-               if (max > USB_MAX_IOWRITE16_COUNT)
-                       max = USB_MAX_IOWRITE16_COUNT;
-               for (j = 0; j < max; j++) {
-                       if (!ioreqs[i+j].addr) {
-                               t = 1;
-                               break;
-                       }
-               }
-
-               r = zd_usb_iowrite16v_async(&chip->usb, &ioreqs[i], j);
-               if (r) {
-                       zd_usb_iowrite16v_async_end(&chip->usb, 0);
-                       dev_dbg_f(zd_chip_dev(chip),
-                                 "error zd_usb_iowrite16v. Error number %d\n",
-                                 r);
-                       return r;
-               }
-       }
-
-       return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
-}
-
-/* Writes a variable number of 32 bit registers. The functions will split
- * that in several USB requests. A split can be forced by inserting an IO
- * request with an zero address field.
- */
-int zd_iowrite32a_locked(struct zd_chip *chip,
-                 const struct zd_ioreq32 *ioreqs, unsigned int count)
-{
-       int r;
-       unsigned int i, j, t, max;
-
-       zd_usb_iowrite16v_async_start(&chip->usb);
-
-       for (i = 0; i < count; i += j + t) {
-               t = 0;
-               max = count-i;
-               if (max > USB_MAX_IOWRITE32_COUNT)
-                       max = USB_MAX_IOWRITE32_COUNT;
-               for (j = 0; j < max; j++) {
-                       if (!ioreqs[i+j].addr) {
-                               t = 1;
-                               break;
-                       }
-               }
-
-               r = _zd_iowrite32v_async_locked(chip, &ioreqs[i], j);
-               if (r) {
-                       zd_usb_iowrite16v_async_end(&chip->usb, 0);
-                       dev_dbg_f(zd_chip_dev(chip),
-                               "error _%s. Error number %d\n", __func__,
-                               r);
-                       return r;
-               }
-       }
-
-       return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
-}
-
-int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_ioread16_locked(chip, value, addr);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_ioread32_locked(chip, value, addr);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_iowrite16_locked(chip, value, addr);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_iowrite32_locked(chip, value, addr);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
-                 u32 *values, unsigned int count)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_ioread32v_locked(chip, values, addresses, count);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
-                 unsigned int count)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_iowrite32a_locked(chip, ioreqs, count);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-static int read_pod(struct zd_chip *chip, u8 *rf_type)
-{
-       int r;
-       u32 value;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_ioread32_locked(chip, &value, E2P_POD);
-       if (r)
-               goto error;
-       dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value);
-
-       /* FIXME: AL2230 handling (Bit 7 in POD) */
-       *rf_type = value & 0x0f;
-       chip->pa_type = (value >> 16) & 0x0f;
-       chip->patch_cck_gain = (value >> 8) & 0x1;
-       chip->patch_cr157 = (value >> 13) & 0x1;
-       chip->patch_6m_band_edge = (value >> 21) & 0x1;
-       chip->new_phy_layout = (value >> 31) & 0x1;
-       chip->al2230s_bit = (value >> 7) & 0x1;
-       chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
-       chip->supports_tx_led = 1;
-       if (value & (1 << 24)) { /* LED scenario */
-               if (value & (1 << 29))
-                       chip->supports_tx_led = 0;
-       }
-
-       dev_dbg_f(zd_chip_dev(chip),
-               "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
-               "patch 6M %d new PHY %d link LED%d tx led %d\n",
-               zd_rf_name(*rf_type), *rf_type,
-               chip->pa_type, chip->patch_cck_gain,
-               chip->patch_cr157, chip->patch_6m_band_edge,
-               chip->new_phy_layout,
-               chip->link_led == LED1 ? 1 : 2,
-               chip->supports_tx_led);
-       return 0;
-error:
-       *rf_type = 0;
-       chip->pa_type = 0;
-       chip->patch_cck_gain = 0;
-       chip->patch_cr157 = 0;
-       chip->patch_6m_band_edge = 0;
-       chip->new_phy_layout = 0;
-       return r;
-}
-
-static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr,
-                                   const struct zd_ioreq32 *in_reqs,
-                                   const char *type)
-{
-       int r;
-       struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]};
-
-       if (mac_addr) {
-               reqs[0].value = (mac_addr[3] << 24)
-                             | (mac_addr[2] << 16)
-                             | (mac_addr[1] <<  8)
-                             |  mac_addr[0];
-               reqs[1].value = (mac_addr[5] <<  8)
-                             |  mac_addr[4];
-               dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr);
-       } else {
-               dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type);
-       }
-
-       mutex_lock(&chip->mutex);
-       r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
- *              CR_MAC_ADDR_P2 must be overwritten
- */
-int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
-{
-       static const struct zd_ioreq32 reqs[2] = {
-               [0] = { .addr = CR_MAC_ADDR_P1 },
-               [1] = { .addr = CR_MAC_ADDR_P2 },
-       };
-
-       return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac");
-}
-
-int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
-{
-       static const struct zd_ioreq32 reqs[2] = {
-               [0] = { .addr = CR_BSSID_P1 },
-               [1] = { .addr = CR_BSSID_P2 },
-       };
-
-       return zd_write_mac_addr_common(chip, bssid, reqs, "bssid");
-}
-
-int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
-{
-       int r;
-       u32 value;
-
-       mutex_lock(&chip->mutex);
-       r = zd_ioread32_locked(chip, &value, E2P_SUBID);
-       mutex_unlock(&chip->mutex);
-       if (r)
-               return r;
-
-       *regdomain = value >> 16;
-       dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain);
-
-       return 0;
-}
-
-static int read_values(struct zd_chip *chip, u8 *values, size_t count,
-                      zd_addr_t e2p_addr, u32 guard)
-{
-       int r;
-       int i;
-       u32 v;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       for (i = 0;;) {
-               r = zd_ioread32_locked(chip, &v,
-                                      (zd_addr_t)((u16)e2p_addr+i/2));
-               if (r)
-                       return r;
-               v -= guard;
-               if (i+4 < count) {
-                       values[i++] = v;
-                       values[i++] = v >>  8;
-                       values[i++] = v >> 16;
-                       values[i++] = v >> 24;
-                       continue;
-               }
-               for (;i < count; i++)
-                       values[i] = v >> (8*(i%3));
-               return 0;
-       }
-}
-
-static int read_pwr_cal_values(struct zd_chip *chip)
-{
-       return read_values(chip, chip->pwr_cal_values,
-                       E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1,
-                       0);
-}
-
-static int read_pwr_int_values(struct zd_chip *chip)
-{
-       return read_values(chip, chip->pwr_int_values,
-                       E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1,
-                       E2P_PWR_INT_GUARD);
-}
-
-static int read_ofdm_cal_values(struct zd_chip *chip)
-{
-       int r;
-       int i;
-       static const zd_addr_t addresses[] = {
-               E2P_36M_CAL_VALUE1,
-               E2P_48M_CAL_VALUE1,
-               E2P_54M_CAL_VALUE1,
-       };
-
-       for (i = 0; i < 3; i++) {
-               r = read_values(chip, chip->ofdm_cal_values[i],
-                               E2P_CHANNEL_COUNT, addresses[i], 0);
-               if (r)
-                       return r;
-       }
-       return 0;
-}
-
-static int read_cal_int_tables(struct zd_chip *chip)
-{
-       int r;
-
-       r = read_pwr_cal_values(chip);
-       if (r)
-               return r;
-       r = read_pwr_int_values(chip);
-       if (r)
-               return r;
-       r = read_ofdm_cal_values(chip);
-       if (r)
-               return r;
-       return 0;
-}
-
-/* phy means physical registers */
-int zd_chip_lock_phy_regs(struct zd_chip *chip)
-{
-       int r;
-       u32 tmp;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_ioread32_locked(chip, &tmp, CR_REG1);
-       if (r) {
-               dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r);
-               return r;
-       }
-
-       tmp &= ~UNLOCK_PHY_REGS;
-
-       r = zd_iowrite32_locked(chip, tmp, CR_REG1);
-       if (r)
-               dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
-       return r;
-}
-
-int zd_chip_unlock_phy_regs(struct zd_chip *chip)
-{
-       int r;
-       u32 tmp;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_ioread32_locked(chip, &tmp, CR_REG1);
-       if (r) {
-               dev_err(zd_chip_dev(chip),
-                       "error ioread32(CR_REG1): %d\n", r);
-               return r;
-       }
-
-       tmp |= UNLOCK_PHY_REGS;
-
-       r = zd_iowrite32_locked(chip, tmp, CR_REG1);
-       if (r)
-               dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
-       return r;
-}
-
-/* ZD_CR157 can be optionally patched by the EEPROM for original ZD1211 */
-static int patch_cr157(struct zd_chip *chip)
-{
-       int r;
-       u16 value;
-
-       if (!chip->patch_cr157)
-               return 0;
-
-       r = zd_ioread16_locked(chip, &value, E2P_PHY_REG);
-       if (r)
-               return r;
-
-       dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8);
-       return zd_iowrite32_locked(chip, value >> 8, ZD_CR157);
-}
-
-/*
- * 6M band edge can be optionally overwritten for certain RF's
- * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge
- * bit (for AL2230, AL2230S)
- */
-static int patch_6m_band_edge(struct zd_chip *chip, u8 channel)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       if (!chip->patch_6m_band_edge)
-               return 0;
-
-       return zd_rf_patch_6m_band_edge(&chip->rf, channel);
-}
-
-/* Generic implementation of 6M band edge patching, used by most RFs via
- * zd_rf_generic_patch_6m() */
-int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel)
-{
-       struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
-               { ZD_CR47,  0x1e },
-       };
-
-       /* FIXME: Channel 11 is not the edge for all regulatory domains. */
-       if (channel == 1 || channel == 11)
-               ioreqs[0].value = 0x12;
-
-       dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel);
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int zd1211_hw_reset_phy(struct zd_chip *chip)
-{
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR0,   0x0a }, { ZD_CR1,   0x06 }, { ZD_CR2,   0x26 },
-               { ZD_CR3,   0x38 }, { ZD_CR4,   0x80 }, { ZD_CR9,   0xa0 },
-               { ZD_CR10,  0x81 }, { ZD_CR11,  0x00 }, { ZD_CR12,  0x7f },
-               { ZD_CR13,  0x8c }, { ZD_CR14,  0x80 }, { ZD_CR15,  0x3d },
-               { ZD_CR16,  0x20 }, { ZD_CR17,  0x1e }, { ZD_CR18,  0x0a },
-               { ZD_CR19,  0x48 }, { ZD_CR20,  0x0c }, { ZD_CR21,  0x0c },
-               { ZD_CR22,  0x23 }, { ZD_CR23,  0x90 }, { ZD_CR24,  0x14 },
-               { ZD_CR25,  0x40 }, { ZD_CR26,  0x10 }, { ZD_CR27,  0x19 },
-               { ZD_CR28,  0x7f }, { ZD_CR29,  0x80 }, { ZD_CR30,  0x4b },
-               { ZD_CR31,  0x60 }, { ZD_CR32,  0x43 }, { ZD_CR33,  0x08 },
-               { ZD_CR34,  0x06 }, { ZD_CR35,  0x0a }, { ZD_CR36,  0x00 },
-               { ZD_CR37,  0x00 }, { ZD_CR38,  0x38 }, { ZD_CR39,  0x0c },
-               { ZD_CR40,  0x84 }, { ZD_CR41,  0x2a }, { ZD_CR42,  0x80 },
-               { ZD_CR43,  0x10 }, { ZD_CR44,  0x12 }, { ZD_CR46,  0xff },
-               { ZD_CR47,  0x1E }, { ZD_CR48,  0x26 }, { ZD_CR49,  0x5b },
-               { ZD_CR64,  0xd0 }, { ZD_CR65,  0x04 }, { ZD_CR66,  0x58 },
-               { ZD_CR67,  0xc9 }, { ZD_CR68,  0x88 }, { ZD_CR69,  0x41 },
-               { ZD_CR70,  0x23 }, { ZD_CR71,  0x10 }, { ZD_CR72,  0xff },
-               { ZD_CR73,  0x32 }, { ZD_CR74,  0x30 }, { ZD_CR75,  0x65 },
-               { ZD_CR76,  0x41 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x30 },
-               { ZD_CR79,  0x68 }, { ZD_CR80,  0x64 }, { ZD_CR81,  0x64 },
-               { ZD_CR82,  0x00 }, { ZD_CR83,  0x00 }, { ZD_CR84,  0x00 },
-               { ZD_CR85,  0x02 }, { ZD_CR86,  0x00 }, { ZD_CR87,  0x00 },
-               { ZD_CR88,  0xff }, { ZD_CR89,  0xfc }, { ZD_CR90,  0x00 },
-               { ZD_CR91,  0x00 }, { ZD_CR92,  0x00 }, { ZD_CR93,  0x08 },
-               { ZD_CR94,  0x00 }, { ZD_CR95,  0x00 }, { ZD_CR96,  0xff },
-               { ZD_CR97,  0xe7 }, { ZD_CR98,  0x00 }, { ZD_CR99,  0x00 },
-               { ZD_CR100, 0x00 }, { ZD_CR101, 0xae }, { ZD_CR102, 0x02 },
-               { ZD_CR103, 0x00 }, { ZD_CR104, 0x03 }, { ZD_CR105, 0x65 },
-               { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, { ZD_CR108, 0x0a },
-               { ZD_CR109, 0xaa }, { ZD_CR110, 0xaa }, { ZD_CR111, 0x25 },
-               { ZD_CR112, 0x25 }, { ZD_CR113, 0x00 }, { ZD_CR119, 0x1e },
-               { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 },
-               { },
-               { ZD_CR5,   0x00 }, { ZD_CR6,   0x00 }, { ZD_CR7,   0x00 },
-               { ZD_CR8,   0x00 }, { ZD_CR9,   0x20 }, { ZD_CR12,  0xf0 },
-               { ZD_CR20,  0x0e }, { ZD_CR21,  0x0e }, { ZD_CR27,  0x10 },
-               { ZD_CR44,  0x33 }, { ZD_CR47,  0x1E }, { ZD_CR83,  0x24 },
-               { ZD_CR84,  0x04 }, { ZD_CR85,  0x00 }, { ZD_CR86,  0x0C },
-               { ZD_CR87,  0x12 }, { ZD_CR88,  0x0C }, { ZD_CR89,  0x00 },
-               { ZD_CR90,  0x10 }, { ZD_CR91,  0x08 }, { ZD_CR93,  0x00 },
-               { ZD_CR94,  0x01 }, { ZD_CR95,  0x00 }, { ZD_CR96,  0x50 },
-               { ZD_CR97,  0x37 }, { ZD_CR98,  0x35 }, { ZD_CR101, 0x13 },
-               { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 },
-               { ZD_CR105, 0x12 }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 },
-               { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 },
-               { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 },
-               { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR120, 0x4f },
-               { ZD_CR125, 0xaa }, { ZD_CR127, 0x03 }, { ZD_CR128, 0x14 },
-               { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, { ZD_CR131, 0x0C },
-               { ZD_CR136, 0xdf }, { ZD_CR137, 0x40 }, { ZD_CR138, 0xa0 },
-               { ZD_CR139, 0xb0 }, { ZD_CR140, 0x99 }, { ZD_CR141, 0x82 },
-               { ZD_CR142, 0x54 }, { ZD_CR143, 0x1c }, { ZD_CR144, 0x6c },
-               { ZD_CR147, 0x07 }, { ZD_CR148, 0x4c }, { ZD_CR149, 0x50 },
-               { ZD_CR150, 0x0e }, { ZD_CR151, 0x18 }, { ZD_CR160, 0xfe },
-               { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa },
-               { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe },
-               { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba },
-               { ZD_CR170, 0xba }, { ZD_CR171, 0xba },
-               /* Note: ZD_CR204 must lead the ZD_CR203 */
-               { ZD_CR204, 0x7d },
-               { },
-               { ZD_CR203, 0x30 },
-       };
-
-       int r, t;
-
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-
-       r = zd_chip_lock_phy_regs(chip);
-       if (r)
-               goto out;
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               goto unlock;
-
-       r = patch_cr157(chip);
-unlock:
-       t = zd_chip_unlock_phy_regs(chip);
-       if (t && !r)
-               r = t;
-out:
-       return r;
-}
-
-static int zd1211b_hw_reset_phy(struct zd_chip *chip)
-{
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR0,   0x14 }, { ZD_CR1,   0x06 }, { ZD_CR2,   0x26 },
-               { ZD_CR3,   0x38 }, { ZD_CR4,   0x80 }, { ZD_CR9,   0xe0 },
-               { ZD_CR10,  0x81 },
-               /* power control { { ZD_CR11,  1 << 6 }, */
-               { ZD_CR11,  0x00 },
-               { ZD_CR12,  0xf0 }, { ZD_CR13,  0x8c }, { ZD_CR14,  0x80 },
-               { ZD_CR15,  0x3d }, { ZD_CR16,  0x20 }, { ZD_CR17,  0x1e },
-               { ZD_CR18,  0x0a }, { ZD_CR19,  0x48 },
-               { ZD_CR20,  0x10 }, /* Org:0x0E, ComTrend:RalLink AP */
-               { ZD_CR21,  0x0e }, { ZD_CR22,  0x23 }, { ZD_CR23,  0x90 },
-               { ZD_CR24,  0x14 }, { ZD_CR25,  0x40 }, { ZD_CR26,  0x10 },
-               { ZD_CR27,  0x10 }, { ZD_CR28,  0x7f }, { ZD_CR29,  0x80 },
-               { ZD_CR30,  0x4b }, /* ASIC/FWT, no jointly decoder */
-               { ZD_CR31,  0x60 }, { ZD_CR32,  0x43 }, { ZD_CR33,  0x08 },
-               { ZD_CR34,  0x06 }, { ZD_CR35,  0x0a }, { ZD_CR36,  0x00 },
-               { ZD_CR37,  0x00 }, { ZD_CR38,  0x38 }, { ZD_CR39,  0x0c },
-               { ZD_CR40,  0x84 }, { ZD_CR41,  0x2a }, { ZD_CR42,  0x80 },
-               { ZD_CR43,  0x10 }, { ZD_CR44,  0x33 }, { ZD_CR46,  0xff },
-               { ZD_CR47,  0x1E }, { ZD_CR48,  0x26 }, { ZD_CR49,  0x5b },
-               { ZD_CR64,  0xd0 }, { ZD_CR65,  0x04 }, { ZD_CR66,  0x58 },
-               { ZD_CR67,  0xc9 }, { ZD_CR68,  0x88 }, { ZD_CR69,  0x41 },
-               { ZD_CR70,  0x23 }, { ZD_CR71,  0x10 }, { ZD_CR72,  0xff },
-               { ZD_CR73,  0x32 }, { ZD_CR74,  0x30 }, { ZD_CR75,  0x65 },
-               { ZD_CR76,  0x41 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x30 },
-               { ZD_CR79,  0xf0 }, { ZD_CR80,  0x64 }, { ZD_CR81,  0x64 },
-               { ZD_CR82,  0x00 }, { ZD_CR83,  0x24 }, { ZD_CR84,  0x04 },
-               { ZD_CR85,  0x00 }, { ZD_CR86,  0x0c }, { ZD_CR87,  0x12 },
-               { ZD_CR88,  0x0c }, { ZD_CR89,  0x00 }, { ZD_CR90,  0x58 },
-               { ZD_CR91,  0x04 }, { ZD_CR92,  0x00 }, { ZD_CR93,  0x00 },
-               { ZD_CR94,  0x01 },
-               { ZD_CR95,  0x20 }, /* ZD1211B */
-               { ZD_CR96,  0x50 }, { ZD_CR97,  0x37 }, { ZD_CR98,  0x35 },
-               { ZD_CR99,  0x00 }, { ZD_CR100, 0x01 }, { ZD_CR101, 0x13 },
-               { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 },
-               { ZD_CR105, 0x12 }, { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 },
-               { ZD_CR108, 0x0a }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 },
-               { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 },
-               { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 },
-               { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x1e },
-               { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 },
-               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
-               { ZD_CR131, 0x0c }, { ZD_CR136, 0xdf }, { ZD_CR137, 0xa0 },
-               { ZD_CR138, 0xa8 }, { ZD_CR139, 0xb4 }, { ZD_CR140, 0x98 },
-               { ZD_CR141, 0x82 }, { ZD_CR142, 0x53 }, { ZD_CR143, 0x1c },
-               { ZD_CR144, 0x6c }, { ZD_CR147, 0x07 }, { ZD_CR148, 0x40 },
-               { ZD_CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */
-               { ZD_CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */
-               { ZD_CR151, 0x18 }, { ZD_CR159, 0x70 }, { ZD_CR160, 0xfe },
-               { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa },
-               { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe },
-               { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba },
-               { ZD_CR170, 0xba }, { ZD_CR171, 0xba },
-               /* Note: ZD_CR204 must lead the ZD_CR203 */
-               { ZD_CR204, 0x7d },
-               {},
-               { ZD_CR203, 0x30 },
-       };
-
-       int r, t;
-
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-
-       r = zd_chip_lock_phy_regs(chip);
-       if (r)
-               goto out;
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       t = zd_chip_unlock_phy_regs(chip);
-       if (t && !r)
-               r = t;
-out:
-       return r;
-}
-
-static int hw_reset_phy(struct zd_chip *chip)
-{
-       return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) :
-                                 zd1211_hw_reset_phy(chip);
-}
-
-static int zd1211_hw_init_hmac(struct zd_chip *chip)
-{
-       static const struct zd_ioreq32 ioreqs[] = {
-               { CR_ZD1211_RETRY_MAX,          ZD1211_RETRY_COUNT },
-               { CR_RX_THRESHOLD,              0x000c0640 },
-       };
-
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int zd1211b_hw_init_hmac(struct zd_chip *chip)
-{
-       static const struct zd_ioreq32 ioreqs[] = {
-               { CR_ZD1211B_RETRY_MAX,         ZD1211B_RETRY_COUNT },
-               { CR_ZD1211B_CWIN_MAX_MIN_AC0,  0x007f003f },
-               { CR_ZD1211B_CWIN_MAX_MIN_AC1,  0x007f003f },
-               { CR_ZD1211B_CWIN_MAX_MIN_AC2,  0x003f001f },
-               { CR_ZD1211B_CWIN_MAX_MIN_AC3,  0x001f000f },
-               { CR_ZD1211B_AIFS_CTL1,         0x00280028 },
-               { CR_ZD1211B_AIFS_CTL2,         0x008C003C },
-               { CR_ZD1211B_TXOP,              0x01800824 },
-               { CR_RX_THRESHOLD,              0x000c0eff, },
-       };
-
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int hw_init_hmac(struct zd_chip *chip)
-{
-       int r;
-       static const struct zd_ioreq32 ioreqs[] = {
-               { CR_ACK_TIMEOUT_EXT,           0x20 },
-               { CR_ADDA_MBIAS_WARMTIME,       0x30000808 },
-               { CR_SNIFFER_ON,                0 },
-               { CR_RX_FILTER,                 STA_RX_FILTER },
-               { CR_GROUP_HASH_P1,             0x00 },
-               { CR_GROUP_HASH_P2,             0x80000000 },
-               { CR_REG1,                      0xa4 },
-               { CR_ADDA_PWR_DWN,              0x7f },
-               { CR_BCN_PLCP_CFG,              0x00f00401 },
-               { CR_PHY_DELAY,                 0x00 },
-               { CR_ACK_TIMEOUT_EXT,           0x80 },
-               { CR_ADDA_PWR_DWN,              0x00 },
-               { CR_ACK_TIME_80211,            0x100 },
-               { CR_RX_PE_DELAY,               0x70 },
-               { CR_PS_CTRL,                   0x10000000 },
-               { CR_RTS_CTS_RATE,              0x02030203 },
-               { CR_AFTER_PNP,                 0x1 },
-               { CR_WEP_PROTECT,               0x114 },
-               { CR_IFS_VALUE,                 IFS_VALUE_DEFAULT },
-               { CR_CAM_MODE,                  MODE_AP_WDS},
-       };
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               return r;
-
-       return zd_chip_is_zd1211b(chip) ?
-               zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
-}
-
-struct aw_pt_bi {
-       u32 atim_wnd_period;
-       u32 pre_tbtt;
-       u32 beacon_interval;
-};
-
-static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
-{
-       int r;
-       static const zd_addr_t aw_pt_bi_addr[] =
-               { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL };
-       u32 values[3];
-
-       r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr,
-                        ARRAY_SIZE(aw_pt_bi_addr));
-       if (r) {
-               memset(s, 0, sizeof(*s));
-               return r;
-       }
-
-       s->atim_wnd_period = values[0];
-       s->pre_tbtt = values[1];
-       s->beacon_interval = values[2];
-       return 0;
-}
-
-static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
-{
-       struct zd_ioreq32 reqs[3];
-       u16 b_interval = s->beacon_interval & 0xffff;
-
-       if (b_interval <= 5)
-               b_interval = 5;
-       if (s->pre_tbtt < 4 || s->pre_tbtt >= b_interval)
-               s->pre_tbtt = b_interval - 1;
-       if (s->atim_wnd_period >= s->pre_tbtt)
-               s->atim_wnd_period = s->pre_tbtt - 1;
-
-       reqs[0].addr = CR_ATIM_WND_PERIOD;
-       reqs[0].value = s->atim_wnd_period;
-       reqs[1].addr = CR_PRE_TBTT;
-       reqs[1].value = s->pre_tbtt;
-       reqs[2].addr = CR_BCN_INTERVAL;
-       reqs[2].value = (s->beacon_interval & ~0xffff) | b_interval;
-
-       return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
-}
-
-
-static int set_beacon_interval(struct zd_chip *chip, u16 interval,
-                              u8 dtim_period, int type)
-{
-       int r;
-       struct aw_pt_bi s;
-       u32 b_interval, mode_flag;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-
-       if (interval > 0) {
-               switch (type) {
-               case NL80211_IFTYPE_ADHOC:
-               case NL80211_IFTYPE_MESH_POINT:
-                       mode_flag = BCN_MODE_IBSS;
-                       break;
-               case NL80211_IFTYPE_AP:
-                       mode_flag = BCN_MODE_AP;
-                       break;
-               default:
-                       mode_flag = 0;
-                       break;
-               }
-       } else {
-               dtim_period = 0;
-               mode_flag = 0;
-       }
-
-       b_interval = mode_flag | (dtim_period << 16) | interval;
-
-       r = zd_iowrite32_locked(chip, b_interval, CR_BCN_INTERVAL);
-       if (r)
-               return r;
-       r = get_aw_pt_bi(chip, &s);
-       if (r)
-               return r;
-       return set_aw_pt_bi(chip, &s);
-}
-
-int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
-                          int type)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = set_beacon_interval(chip, interval, dtim_period, type);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-static int hw_init(struct zd_chip *chip)
-{
-       int r;
-
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = hw_reset_phy(chip);
-       if (r)
-               return r;
-
-       r = hw_init_hmac(chip);
-       if (r)
-               return r;
-
-       return set_beacon_interval(chip, 100, 0, NL80211_IFTYPE_UNSPECIFIED);
-}
-
-static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
-{
-       return (zd_addr_t)((u16)chip->fw_regs_base + offset);
-}
-
-#ifdef DEBUG
-static int dump_cr(struct zd_chip *chip, const zd_addr_t addr,
-                  const char *addr_string)
-{
-       int r;
-       u32 value;
-
-       r = zd_ioread32_locked(chip, &value, addr);
-       if (r) {
-               dev_dbg_f(zd_chip_dev(chip),
-                       "error reading %s. Error number %d\n", addr_string, r);
-               return r;
-       }
-
-       dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n",
-               addr_string, (unsigned int)value);
-       return 0;
-}
-
-static int test_init(struct zd_chip *chip)
-{
-       int r;
-
-       r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP");
-       if (r)
-               return r;
-       r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN");
-       if (r)
-               return r;
-       return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT");
-}
-
-static void dump_fw_registers(struct zd_chip *chip)
-{
-       const zd_addr_t addr[4] = {
-               fw_reg_addr(chip, FW_REG_FIRMWARE_VER),
-               fw_reg_addr(chip, FW_REG_USB_SPEED),
-               fw_reg_addr(chip, FW_REG_FIX_TX_RATE),
-               fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
-       };
-
-       int r;
-       u16 values[4];
-
-       r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr,
-                        ARRAY_SIZE(addr));
-       if (r) {
-               dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n",
-                        r);
-               return;
-       }
-
-       dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]);
-       dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]);
-       dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]);
-       dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]);
-}
-#endif /* DEBUG */
-
-static int print_fw_version(struct zd_chip *chip)
-{
-       struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy;
-       int r;
-       u16 version;
-
-       r = zd_ioread16_locked(chip, &version,
-               fw_reg_addr(chip, FW_REG_FIRMWARE_VER));
-       if (r)
-               return r;
-
-       dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version);
-
-       snprintf(wiphy->fw_version, sizeof(wiphy->fw_version),
-                       "%04hx", version);
-
-       return 0;
-}
-
-static int set_mandatory_rates(struct zd_chip *chip, int gmode)
-{
-       u32 rates;
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       /* This sets the mandatory rates, which only depend from the standard
-        * that the device is supporting. Until further notice we should try
-        * to support 802.11g also for full speed USB.
-        */
-       if (!gmode)
-               rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
-       else
-               rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
-                       CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
-
-       return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
-}
-
-int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
-                                   int preamble)
-{
-       u32 value = 0;
-
-       dev_dbg_f(zd_chip_dev(chip), "preamble=%x\n", preamble);
-       value |= preamble << RTSCTS_SH_RTS_PMB_TYPE;
-       value |= preamble << RTSCTS_SH_CTS_PMB_TYPE;
-
-       /* We always send 11M RTS/self-CTS messages, like the vendor driver. */
-       value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_RTS_RATE;
-       value |= ZD_RX_CCK << RTSCTS_SH_RTS_MOD_TYPE;
-       value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_CTS_RATE;
-       value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE;
-
-       return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE);
-}
-
-int zd_chip_enable_hwint(struct zd_chip *chip)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-static int disable_hwint(struct zd_chip *chip)
-{
-       return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT);
-}
-
-int zd_chip_disable_hwint(struct zd_chip *chip)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = disable_hwint(chip);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-static int read_fw_regs_offset(struct zd_chip *chip)
-{
-       int r;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_ioread16_locked(chip, (u16*)&chip->fw_regs_base,
-                              FWRAW_REGS_ADDR);
-       if (r)
-               return r;
-       dev_dbg_f(zd_chip_dev(chip), "fw_regs_base: %#06hx\n",
-                 (u16)chip->fw_regs_base);
-
-       return 0;
-}
-
-/* Read mac address using pre-firmware interface */
-int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr)
-{
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-       return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr,
-               ETH_ALEN);
-}
-
-int zd_chip_init_hw(struct zd_chip *chip)
-{
-       int r;
-       u8 rf_type;
-
-       dev_dbg_f(zd_chip_dev(chip), "\n");
-
-       mutex_lock(&chip->mutex);
-
-#ifdef DEBUG
-       r = test_init(chip);
-       if (r)
-               goto out;
-#endif
-       r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP);
-       if (r)
-               goto out;
-
-       r = read_fw_regs_offset(chip);
-       if (r)
-               goto out;
-
-       /* GPI is always disabled, also in the other driver.
-        */
-       r = zd_iowrite32_locked(chip, 0, CR_GPI_EN);
-       if (r)
-               goto out;
-       r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX);
-       if (r)
-               goto out;
-       /* Currently we support IEEE 802.11g for full and high speed USB.
-        * It might be discussed, whether we should support pure b mode for
-        * full speed USB.
-        */
-       r = set_mandatory_rates(chip, 1);
-       if (r)
-               goto out;
-       /* Disabling interrupts is certainly a smart thing here.
-        */
-       r = disable_hwint(chip);
-       if (r)
-               goto out;
-       r = read_pod(chip, &rf_type);
-       if (r)
-               goto out;
-       r = hw_init(chip);
-       if (r)
-               goto out;
-       r = zd_rf_init_hw(&chip->rf, rf_type);
-       if (r)
-               goto out;
-
-       r = print_fw_version(chip);
-       if (r)
-               goto out;
-
-#ifdef DEBUG
-       dump_fw_registers(chip);
-       r = test_init(chip);
-       if (r)
-               goto out;
-#endif /* DEBUG */
-
-       r = read_cal_int_tables(chip);
-       if (r)
-               goto out;
-
-       print_id(chip);
-out:
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-static int update_pwr_int(struct zd_chip *chip, u8 channel)
-{
-       u8 value = chip->pwr_int_values[channel - 1];
-       return zd_iowrite16_locked(chip, value, ZD_CR31);
-}
-
-static int update_pwr_cal(struct zd_chip *chip, u8 channel)
-{
-       u8 value = chip->pwr_cal_values[channel-1];
-       return zd_iowrite16_locked(chip, value, ZD_CR68);
-}
-
-static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
-{
-       struct zd_ioreq16 ioreqs[3];
-
-       ioreqs[0].addr = ZD_CR67;
-       ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1];
-       ioreqs[1].addr = ZD_CR66;
-       ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1];
-       ioreqs[2].addr = ZD_CR65;
-       ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1];
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int update_channel_integration_and_calibration(struct zd_chip *chip,
-                                                     u8 channel)
-{
-       int r;
-
-       if (!zd_rf_should_update_pwr_int(&chip->rf))
-               return 0;
-
-       r = update_pwr_int(chip, channel);
-       if (r)
-               return r;
-       if (zd_chip_is_zd1211b(chip)) {
-               static const struct zd_ioreq16 ioreqs[] = {
-                       { ZD_CR69, 0x28 },
-                       {},
-                       { ZD_CR69, 0x2a },
-               };
-
-               r = update_ofdm_cal(chip, channel);
-               if (r)
-                       return r;
-               r = update_pwr_cal(chip, channel);
-               if (r)
-                       return r;
-               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-               if (r)
-                       return r;
-       }
-
-       return 0;
-}
-
-/* The CCK baseband gain can be optionally patched by the EEPROM */
-static int patch_cck_gain(struct zd_chip *chip)
-{
-       int r;
-       u32 value;
-
-       if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
-               return 0;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_ioread32_locked(chip, &value, E2P_PHY_REG);
-       if (r)
-               return r;
-       dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff);
-       return zd_iowrite16_locked(chip, value & 0xff, ZD_CR47);
-}
-
-int zd_chip_set_channel(struct zd_chip *chip, u8 channel)
-{
-       int r, t;
-
-       mutex_lock(&chip->mutex);
-       r = zd_chip_lock_phy_regs(chip);
-       if (r)
-               goto out;
-       r = zd_rf_set_channel(&chip->rf, channel);
-       if (r)
-               goto unlock;
-       r = update_channel_integration_and_calibration(chip, channel);
-       if (r)
-               goto unlock;
-       r = patch_cck_gain(chip);
-       if (r)
-               goto unlock;
-       r = patch_6m_band_edge(chip, channel);
-       if (r)
-               goto unlock;
-       r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS);
-unlock:
-       t = zd_chip_unlock_phy_regs(chip);
-       if (t && !r)
-               r = t;
-out:
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-u8 zd_chip_get_channel(struct zd_chip *chip)
-{
-       u8 channel;
-
-       mutex_lock(&chip->mutex);
-       channel = chip->rf.channel;
-       mutex_unlock(&chip->mutex);
-       return channel;
-}
-
-int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
-{
-       const zd_addr_t a[] = {
-               fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
-               CR_LED,
-       };
-
-       int r;
-       u16 v[ARRAY_SIZE(a)];
-       struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
-               [0] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS) },
-               [1] = { CR_LED },
-       };
-       u16 other_led;
-
-       mutex_lock(&chip->mutex);
-       r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a));
-       if (r)
-               goto out;
-
-       other_led = chip->link_led == LED1 ? LED2 : LED1;
-
-       switch (status) {
-       case ZD_LED_OFF:
-               ioreqs[0].value = FW_LINK_OFF;
-               ioreqs[1].value = v[1] & ~(LED1|LED2);
-               break;
-       case ZD_LED_SCANNING:
-               ioreqs[0].value = FW_LINK_OFF;
-               ioreqs[1].value = v[1] & ~other_led;
-               if (get_seconds() % 3 == 0) {
-                       ioreqs[1].value &= ~chip->link_led;
-               } else {
-                       ioreqs[1].value |= chip->link_led;
-               }
-               break;
-       case ZD_LED_ASSOCIATED:
-               ioreqs[0].value = FW_LINK_TX;
-               ioreqs[1].value = v[1] & ~other_led;
-               ioreqs[1].value |= chip->link_led;
-               break;
-       default:
-               r = -EINVAL;
-               goto out;
-       }
-
-       if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) {
-               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-               if (r)
-                       goto out;
-       }
-       r = 0;
-out:
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
-{
-       int r;
-
-       if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
-               return -EINVAL;
-
-       mutex_lock(&chip->mutex);
-       r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame)
-{
-       return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame);
-}
-
-/**
- * zd_rx_rate - report zd-rate
- * @rx_frame - received frame
- * @rx_status - rx_status as given by the device
- *
- * This function converts the rate as encoded in the received packet to the
- * zd-rate, we are using on other places in the driver.
- */
-u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
-{
-       u8 zd_rate;
-       if (status->frame_status & ZD_RX_OFDM) {
-               zd_rate = zd_rate_from_ofdm_plcp_header(rx_frame);
-       } else {
-               switch (zd_cck_plcp_header_signal(rx_frame)) {
-               case ZD_CCK_PLCP_SIGNAL_1M:
-                       zd_rate = ZD_CCK_RATE_1M;
-                       break;
-               case ZD_CCK_PLCP_SIGNAL_2M:
-                       zd_rate = ZD_CCK_RATE_2M;
-                       break;
-               case ZD_CCK_PLCP_SIGNAL_5M5:
-                       zd_rate = ZD_CCK_RATE_5_5M;
-                       break;
-               case ZD_CCK_PLCP_SIGNAL_11M:
-                       zd_rate = ZD_CCK_RATE_11M;
-                       break;
-               default:
-                       zd_rate = 0;
-               }
-       }
-
-       return zd_rate;
-}
-
-int zd_chip_switch_radio_on(struct zd_chip *chip)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_switch_radio_on(&chip->rf);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_chip_switch_radio_off(struct zd_chip *chip)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_switch_radio_off(&chip->rf);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_chip_enable_int(struct zd_chip *chip)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       r = zd_usb_enable_int(&chip->usb);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-void zd_chip_disable_int(struct zd_chip *chip)
-{
-       mutex_lock(&chip->mutex);
-       zd_usb_disable_int(&chip->usb);
-       mutex_unlock(&chip->mutex);
-
-       /* cancel pending interrupt work */
-       cancel_work_sync(&zd_chip_to_mac(chip)->process_intr);
-}
-
-int zd_chip_enable_rxtx(struct zd_chip *chip)
-{
-       int r;
-
-       mutex_lock(&chip->mutex);
-       zd_usb_enable_tx(&chip->usb);
-       r = zd_usb_enable_rx(&chip->usb);
-       zd_tx_watchdog_enable(&chip->usb);
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-void zd_chip_disable_rxtx(struct zd_chip *chip)
-{
-       mutex_lock(&chip->mutex);
-       zd_tx_watchdog_disable(&chip->usb);
-       zd_usb_disable_rx(&chip->usb);
-       zd_usb_disable_tx(&chip->usb);
-       mutex_unlock(&chip->mutex);
-}
-
-int zd_rfwritev_locked(struct zd_chip *chip,
-                      const u32* values, unsigned int count, u8 bits)
-{
-       int r;
-       unsigned int i;
-
-       for (i = 0; i < count; i++) {
-               r = zd_rfwrite_locked(chip, values[i], bits);
-               if (r)
-                       return r;
-       }
-
-       return 0;
-}
-
-/*
- * We can optionally program the RF directly through CR regs, if supported by
- * the hardware. This is much faster than the older method.
- */
-int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value)
-{
-       const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR244, (value >> 16) & 0xff },
-               { ZD_CR243, (value >>  8) & 0xff },
-               { ZD_CR242,  value        & 0xff },
-       };
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-int zd_rfwritev_cr_locked(struct zd_chip *chip,
-                         const u32 *values, unsigned int count)
-{
-       int r;
-       unsigned int i;
-
-       for (i = 0; i < count; i++) {
-               r = zd_rfwrite_cr_locked(chip, values[i]);
-               if (r)
-                       return r;
-       }
-
-       return 0;
-}
-
-int zd_chip_set_multicast_hash(struct zd_chip *chip,
-                              struct zd_mc_hash *hash)
-{
-       const struct zd_ioreq32 ioreqs[] = {
-               { CR_GROUP_HASH_P1, hash->low },
-               { CR_GROUP_HASH_P2, hash->high },
-       };
-
-       return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-u64 zd_chip_get_tsf(struct zd_chip *chip)
-{
-       int r;
-       static const zd_addr_t aw_pt_bi_addr[] =
-               { CR_TSF_LOW_PART, CR_TSF_HIGH_PART };
-       u32 values[2];
-       u64 tsf;
-
-       mutex_lock(&chip->mutex);
-       r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr,
-                               ARRAY_SIZE(aw_pt_bi_addr));
-       mutex_unlock(&chip->mutex);
-       if (r)
-               return 0;
-
-       tsf = values[1];
-       tsf = (tsf << 32) | values[0];
-
-       return tsf;
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
deleted file mode 100644 (file)
index b03786c..0000000
+++ /dev/null
@@ -1,983 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ZD_CHIP_H
-#define _ZD_CHIP_H
-
-#include <net/mac80211.h>
-
-#include "zd_rf.h"
-#include "zd_usb.h"
-
-/* Header for the Media Access Controller (MAC) and the Baseband Processor
- * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and
- * adds a processor for handling the USB protocol.
- */
-
-/* Address space */
-enum {
-       /* CONTROL REGISTERS */
-       CR_START                        = 0x9000,
-
-
-       /* FIRMWARE */
-       FW_START                        = 0xee00,
-
-
-       /* EEPROM */
-       E2P_START                       = 0xf800,
-       E2P_LEN                         = 0x800,
-
-       /* EEPROM layout */
-       E2P_LOAD_CODE_LEN               = 0xe,          /* base 0xf800 */
-       E2P_LOAD_VECT_LEN               = 0x9,          /* base 0xf80e */
-       /* E2P_DATA indexes into this */
-       E2P_DATA_LEN                    = 0x7e,         /* base 0xf817 */
-       E2P_BOOT_CODE_LEN               = 0x760,        /* base 0xf895 */
-       E2P_INTR_VECT_LEN               = 0xb,          /* base 0xfff5 */
-
-       /* Some precomputed offsets into the EEPROM */
-       E2P_DATA_OFFSET                 = E2P_LOAD_CODE_LEN + E2P_LOAD_VECT_LEN,
-       E2P_BOOT_CODE_OFFSET            = E2P_DATA_OFFSET + E2P_DATA_LEN,
-};
-
-#define CTL_REG(offset) ((zd_addr_t)(CR_START + (offset)))
-#define E2P_DATA(offset) ((zd_addr_t)(E2P_START + E2P_DATA_OFFSET + (offset)))
-#define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset)))
-
-/* 8-bit hardware registers */
-#define ZD_CR0   CTL_REG(0x0000)
-#define ZD_CR1   CTL_REG(0x0004)
-#define ZD_CR2   CTL_REG(0x0008)
-#define ZD_CR3   CTL_REG(0x000C)
-
-#define ZD_CR5   CTL_REG(0x0010)
-/*     bit 5: if set short preamble used
- *     bit 6: filter band - Japan channel 14 on, else off
- */
-#define ZD_CR6   CTL_REG(0x0014)
-#define ZD_CR7   CTL_REG(0x0018)
-#define ZD_CR8   CTL_REG(0x001C)
-
-#define ZD_CR4   CTL_REG(0x0020)
-
-#define ZD_CR9   CTL_REG(0x0024)
-/*     bit 2: antenna switch (together with ZD_CR10) */
-#define ZD_CR10  CTL_REG(0x0028)
-/*     bit 1: antenna switch (together with ZD_CR9)
- *     RF2959 controls with ZD_CR11 radion on and off
- */
-#define ZD_CR11  CTL_REG(0x002C)
-/*     bit 6:  TX power control for OFDM
- *     RF2959 controls with ZD_CR10 radio on and off
- */
-#define ZD_CR12  CTL_REG(0x0030)
-#define ZD_CR13  CTL_REG(0x0034)
-#define ZD_CR14  CTL_REG(0x0038)
-#define ZD_CR15  CTL_REG(0x003C)
-#define ZD_CR16  CTL_REG(0x0040)
-#define ZD_CR17  CTL_REG(0x0044)
-#define ZD_CR18  CTL_REG(0x0048)
-#define ZD_CR19  CTL_REG(0x004C)
-#define ZD_CR20  CTL_REG(0x0050)
-#define ZD_CR21  CTL_REG(0x0054)
-#define ZD_CR22  CTL_REG(0x0058)
-#define ZD_CR23  CTL_REG(0x005C)
-#define ZD_CR24  CTL_REG(0x0060)       /* CCA threshold */
-#define ZD_CR25  CTL_REG(0x0064)
-#define ZD_CR26  CTL_REG(0x0068)
-#define ZD_CR27  CTL_REG(0x006C)
-#define ZD_CR28  CTL_REG(0x0070)
-#define ZD_CR29  CTL_REG(0x0074)
-#define ZD_CR30  CTL_REG(0x0078)
-#define ZD_CR31  CTL_REG(0x007C)       /* TX power control for RF in
-                                        * CCK mode
-                                        */
-#define ZD_CR32  CTL_REG(0x0080)
-#define ZD_CR33  CTL_REG(0x0084)
-#define ZD_CR34  CTL_REG(0x0088)
-#define ZD_CR35  CTL_REG(0x008C)
-#define ZD_CR36  CTL_REG(0x0090)
-#define ZD_CR37  CTL_REG(0x0094)
-#define ZD_CR38  CTL_REG(0x0098)
-#define ZD_CR39  CTL_REG(0x009C)
-#define ZD_CR40  CTL_REG(0x00A0)
-#define ZD_CR41  CTL_REG(0x00A4)
-#define ZD_CR42  CTL_REG(0x00A8)
-#define ZD_CR43  CTL_REG(0x00AC)
-#define ZD_CR44  CTL_REG(0x00B0)
-#define ZD_CR45  CTL_REG(0x00B4)
-#define ZD_CR46  CTL_REG(0x00B8)
-#define ZD_CR47  CTL_REG(0x00BC)       /* CCK baseband gain
-                                        * (patch value might be in EEPROM)
-                                        */
-#define ZD_CR48  CTL_REG(0x00C0)
-#define ZD_CR49  CTL_REG(0x00C4)
-#define ZD_CR50  CTL_REG(0x00C8)
-#define ZD_CR51  CTL_REG(0x00CC)       /* TX power control for RF in
-                                        * 6-36M modes
-                                        */
-#define ZD_CR52  CTL_REG(0x00D0)       /* TX power control for RF in
-                                        * 48M mode
-                                        */
-#define ZD_CR53  CTL_REG(0x00D4)       /* TX power control for RF in
-                                        * 54M mode
-                                        */
-#define ZD_CR54  CTL_REG(0x00D8)
-#define ZD_CR55  CTL_REG(0x00DC)
-#define ZD_CR56  CTL_REG(0x00E0)
-#define ZD_CR57  CTL_REG(0x00E4)
-#define ZD_CR58  CTL_REG(0x00E8)
-#define ZD_CR59  CTL_REG(0x00EC)
-#define ZD_CR60  CTL_REG(0x00F0)
-#define ZD_CR61  CTL_REG(0x00F4)
-#define ZD_CR62  CTL_REG(0x00F8)
-#define ZD_CR63  CTL_REG(0x00FC)
-#define ZD_CR64  CTL_REG(0x0100)
-#define ZD_CR65  CTL_REG(0x0104) /* OFDM 54M calibration */
-#define ZD_CR66  CTL_REG(0x0108) /* OFDM 48M calibration */
-#define ZD_CR67  CTL_REG(0x010C) /* OFDM 36M calibration */
-#define ZD_CR68  CTL_REG(0x0110) /* CCK calibration */
-#define ZD_CR69  CTL_REG(0x0114)
-#define ZD_CR70  CTL_REG(0x0118)
-#define ZD_CR71  CTL_REG(0x011C)
-#define ZD_CR72  CTL_REG(0x0120)
-#define ZD_CR73  CTL_REG(0x0124)
-#define ZD_CR74  CTL_REG(0x0128)
-#define ZD_CR75  CTL_REG(0x012C)
-#define ZD_CR76  CTL_REG(0x0130)
-#define ZD_CR77  CTL_REG(0x0134)
-#define ZD_CR78  CTL_REG(0x0138)
-#define ZD_CR79  CTL_REG(0x013C)
-#define ZD_CR80  CTL_REG(0x0140)
-#define ZD_CR81  CTL_REG(0x0144)
-#define ZD_CR82  CTL_REG(0x0148)
-#define ZD_CR83  CTL_REG(0x014C)
-#define ZD_CR84  CTL_REG(0x0150)
-#define ZD_CR85  CTL_REG(0x0154)
-#define ZD_CR86  CTL_REG(0x0158)
-#define ZD_CR87  CTL_REG(0x015C)
-#define ZD_CR88  CTL_REG(0x0160)
-#define ZD_CR89  CTL_REG(0x0164)
-#define ZD_CR90  CTL_REG(0x0168)
-#define ZD_CR91  CTL_REG(0x016C)
-#define ZD_CR92  CTL_REG(0x0170)
-#define ZD_CR93  CTL_REG(0x0174)
-#define ZD_CR94  CTL_REG(0x0178)
-#define ZD_CR95  CTL_REG(0x017C)
-#define ZD_CR96  CTL_REG(0x0180)
-#define ZD_CR97  CTL_REG(0x0184)
-#define ZD_CR98  CTL_REG(0x0188)
-#define ZD_CR99  CTL_REG(0x018C)
-#define ZD_CR100 CTL_REG(0x0190)
-#define ZD_CR101 CTL_REG(0x0194)
-#define ZD_CR102 CTL_REG(0x0198)
-#define ZD_CR103 CTL_REG(0x019C)
-#define ZD_CR104 CTL_REG(0x01A0)
-#define ZD_CR105 CTL_REG(0x01A4)
-#define ZD_CR106 CTL_REG(0x01A8)
-#define ZD_CR107 CTL_REG(0x01AC)
-#define ZD_CR108 CTL_REG(0x01B0)
-#define ZD_CR109 CTL_REG(0x01B4)
-#define ZD_CR110 CTL_REG(0x01B8)
-#define ZD_CR111 CTL_REG(0x01BC)
-#define ZD_CR112 CTL_REG(0x01C0)
-#define ZD_CR113 CTL_REG(0x01C4)
-#define ZD_CR114 CTL_REG(0x01C8)
-#define ZD_CR115 CTL_REG(0x01CC)
-#define ZD_CR116 CTL_REG(0x01D0)
-#define ZD_CR117 CTL_REG(0x01D4)
-#define ZD_CR118 CTL_REG(0x01D8)
-#define ZD_CR119 CTL_REG(0x01DC)
-#define ZD_CR120 CTL_REG(0x01E0)
-#define ZD_CR121 CTL_REG(0x01E4)
-#define ZD_CR122 CTL_REG(0x01E8)
-#define ZD_CR123 CTL_REG(0x01EC)
-#define ZD_CR124 CTL_REG(0x01F0)
-#define ZD_CR125 CTL_REG(0x01F4)
-#define ZD_CR126 CTL_REG(0x01F8)
-#define ZD_CR127 CTL_REG(0x01FC)
-#define ZD_CR128 CTL_REG(0x0200)
-#define ZD_CR129 CTL_REG(0x0204)
-#define ZD_CR130 CTL_REG(0x0208)
-#define ZD_CR131 CTL_REG(0x020C)
-#define ZD_CR132 CTL_REG(0x0210)
-#define ZD_CR133 CTL_REG(0x0214)
-#define ZD_CR134 CTL_REG(0x0218)
-#define ZD_CR135 CTL_REG(0x021C)
-#define ZD_CR136 CTL_REG(0x0220)
-#define ZD_CR137 CTL_REG(0x0224)
-#define ZD_CR138 CTL_REG(0x0228)
-#define ZD_CR139 CTL_REG(0x022C)
-#define ZD_CR140 CTL_REG(0x0230)
-#define ZD_CR141 CTL_REG(0x0234)
-#define ZD_CR142 CTL_REG(0x0238)
-#define ZD_CR143 CTL_REG(0x023C)
-#define ZD_CR144 CTL_REG(0x0240)
-#define ZD_CR145 CTL_REG(0x0244)
-#define ZD_CR146 CTL_REG(0x0248)
-#define ZD_CR147 CTL_REG(0x024C)
-#define ZD_CR148 CTL_REG(0x0250)
-#define ZD_CR149 CTL_REG(0x0254)
-#define ZD_CR150 CTL_REG(0x0258)
-#define ZD_CR151 CTL_REG(0x025C)
-#define ZD_CR152 CTL_REG(0x0260)
-#define ZD_CR153 CTL_REG(0x0264)
-#define ZD_CR154 CTL_REG(0x0268)
-#define ZD_CR155 CTL_REG(0x026C)
-#define ZD_CR156 CTL_REG(0x0270)
-#define ZD_CR157 CTL_REG(0x0274)
-#define ZD_CR158 CTL_REG(0x0278)
-#define ZD_CR159 CTL_REG(0x027C)
-#define ZD_CR160 CTL_REG(0x0280)
-#define ZD_CR161 CTL_REG(0x0284)
-#define ZD_CR162 CTL_REG(0x0288)
-#define ZD_CR163 CTL_REG(0x028C)
-#define ZD_CR164 CTL_REG(0x0290)
-#define ZD_CR165 CTL_REG(0x0294)
-#define ZD_CR166 CTL_REG(0x0298)
-#define ZD_CR167 CTL_REG(0x029C)
-#define ZD_CR168 CTL_REG(0x02A0)
-#define ZD_CR169 CTL_REG(0x02A4)
-#define ZD_CR170 CTL_REG(0x02A8)
-#define ZD_CR171 CTL_REG(0x02AC)
-#define ZD_CR172 CTL_REG(0x02B0)
-#define ZD_CR173 CTL_REG(0x02B4)
-#define ZD_CR174 CTL_REG(0x02B8)
-#define ZD_CR175 CTL_REG(0x02BC)
-#define ZD_CR176 CTL_REG(0x02C0)
-#define ZD_CR177 CTL_REG(0x02C4)
-#define ZD_CR178 CTL_REG(0x02C8)
-#define ZD_CR179 CTL_REG(0x02CC)
-#define ZD_CR180 CTL_REG(0x02D0)
-#define ZD_CR181 CTL_REG(0x02D4)
-#define ZD_CR182 CTL_REG(0x02D8)
-#define ZD_CR183 CTL_REG(0x02DC)
-#define ZD_CR184 CTL_REG(0x02E0)
-#define ZD_CR185 CTL_REG(0x02E4)
-#define ZD_CR186 CTL_REG(0x02E8)
-#define ZD_CR187 CTL_REG(0x02EC)
-#define ZD_CR188 CTL_REG(0x02F0)
-#define ZD_CR189 CTL_REG(0x02F4)
-#define ZD_CR190 CTL_REG(0x02F8)
-#define ZD_CR191 CTL_REG(0x02FC)
-#define ZD_CR192 CTL_REG(0x0300)
-#define ZD_CR193 CTL_REG(0x0304)
-#define ZD_CR194 CTL_REG(0x0308)
-#define ZD_CR195 CTL_REG(0x030C)
-#define ZD_CR196 CTL_REG(0x0310)
-#define ZD_CR197 CTL_REG(0x0314)
-#define ZD_CR198 CTL_REG(0x0318)
-#define ZD_CR199 CTL_REG(0x031C)
-#define ZD_CR200 CTL_REG(0x0320)
-#define ZD_CR201 CTL_REG(0x0324)
-#define ZD_CR202 CTL_REG(0x0328)
-#define ZD_CR203 CTL_REG(0x032C)       /* I2C bus template value & flash
-                                        * control
-                                        */
-#define ZD_CR204 CTL_REG(0x0330)
-#define ZD_CR205 CTL_REG(0x0334)
-#define ZD_CR206 CTL_REG(0x0338)
-#define ZD_CR207 CTL_REG(0x033C)
-#define ZD_CR208 CTL_REG(0x0340)
-#define ZD_CR209 CTL_REG(0x0344)
-#define ZD_CR210 CTL_REG(0x0348)
-#define ZD_CR211 CTL_REG(0x034C)
-#define ZD_CR212 CTL_REG(0x0350)
-#define ZD_CR213 CTL_REG(0x0354)
-#define ZD_CR214 CTL_REG(0x0358)
-#define ZD_CR215 CTL_REG(0x035C)
-#define ZD_CR216 CTL_REG(0x0360)
-#define ZD_CR217 CTL_REG(0x0364)
-#define ZD_CR218 CTL_REG(0x0368)
-#define ZD_CR219 CTL_REG(0x036C)
-#define ZD_CR220 CTL_REG(0x0370)
-#define ZD_CR221 CTL_REG(0x0374)
-#define ZD_CR222 CTL_REG(0x0378)
-#define ZD_CR223 CTL_REG(0x037C)
-#define ZD_CR224 CTL_REG(0x0380)
-#define ZD_CR225 CTL_REG(0x0384)
-#define ZD_CR226 CTL_REG(0x0388)
-#define ZD_CR227 CTL_REG(0x038C)
-#define ZD_CR228 CTL_REG(0x0390)
-#define ZD_CR229 CTL_REG(0x0394)
-#define ZD_CR230 CTL_REG(0x0398)
-#define ZD_CR231 CTL_REG(0x039C)
-#define ZD_CR232 CTL_REG(0x03A0)
-#define ZD_CR233 CTL_REG(0x03A4)
-#define ZD_CR234 CTL_REG(0x03A8)
-#define ZD_CR235 CTL_REG(0x03AC)
-#define ZD_CR236 CTL_REG(0x03B0)
-
-#define ZD_CR240 CTL_REG(0x03C0)
-/*             bit 7: host-controlled RF register writes
- * ZD_CR241-ZD_CR245: for hardware controlled writing of RF bits, not needed for
- *                    USB
- */
-#define ZD_CR241 CTL_REG(0x03C4)
-#define ZD_CR242 CTL_REG(0x03C8)
-#define ZD_CR243 CTL_REG(0x03CC)
-#define ZD_CR244 CTL_REG(0x03D0)
-#define ZD_CR245 CTL_REG(0x03D4)
-
-#define ZD_CR251 CTL_REG(0x03EC)       /* only used for activation and
-                                        * deactivation of Airoha RFs AL2230
-                                        * and AL7230B
-                                        */
-#define ZD_CR252 CTL_REG(0x03F0)
-#define ZD_CR253 CTL_REG(0x03F4)
-#define ZD_CR254 CTL_REG(0x03F8)
-#define ZD_CR255 CTL_REG(0x03FC)
-
-#define CR_MAX_PHY_REG 255
-
-/* Taken from the ZYDAS driver, not all of them are relevant for the ZD1211
- * driver.
- */
-
-#define CR_RF_IF_CLK                   CTL_REG(0x0400)
-#define CR_RF_IF_DATA                  CTL_REG(0x0404)
-#define CR_PE1_PE2                     CTL_REG(0x0408)
-#define CR_PE2_DLY                     CTL_REG(0x040C)
-#define CR_LE1                         CTL_REG(0x0410)
-#define CR_LE2                         CTL_REG(0x0414)
-/* Seems to enable/disable GPI (General Purpose IO?) */
-#define CR_GPI_EN                      CTL_REG(0x0418)
-#define CR_RADIO_PD                    CTL_REG(0x042C)
-#define CR_RF2948_PD                   CTL_REG(0x042C)
-#define CR_ENABLE_PS_MANUAL_AGC                CTL_REG(0x043C)
-#define CR_CONFIG_PHILIPS              CTL_REG(0x0440)
-#define CR_SA2400_SER_AP               CTL_REG(0x0444)
-#define CR_I2C_WRITE                   CTL_REG(0x0444)
-#define CR_SA2400_SER_RP               CTL_REG(0x0448)
-#define CR_RADIO_PE                    CTL_REG(0x0458)
-#define CR_RST_BUS_MASTER              CTL_REG(0x045C)
-#define CR_RFCFG                       CTL_REG(0x0464)
-#define CR_HSTSCHG                     CTL_REG(0x046C)
-#define CR_PHY_ON                      CTL_REG(0x0474)
-#define CR_RX_DELAY                    CTL_REG(0x0478)
-#define CR_RX_PE_DELAY                 CTL_REG(0x047C)
-#define CR_GPIO_1                      CTL_REG(0x0490)
-#define CR_GPIO_2                      CTL_REG(0x0494)
-#define CR_EncryBufMux                 CTL_REG(0x04A8)
-#define CR_PS_CTRL                     CTL_REG(0x0500)
-#define CR_ADDA_PWR_DWN                        CTL_REG(0x0504)
-#define CR_ADDA_MBIAS_WARMTIME         CTL_REG(0x0508)
-#define CR_MAC_PS_STATE                        CTL_REG(0x050C)
-
-#define CR_INTERRUPT                   CTL_REG(0x0510)
-#define INT_TX_COMPLETE                        (1 <<  0)
-#define INT_RX_COMPLETE                        (1 <<  1)
-#define INT_RETRY_FAIL                 (1 <<  2)
-#define INT_WAKEUP                     (1 <<  3)
-#define INT_DTIM_NOTIFY                        (1 <<  5)
-#define INT_CFG_NEXT_BCN               (1 <<  6)
-#define INT_BUS_ABORT                  (1 <<  7)
-#define INT_TX_FIFO_READY              (1 <<  8)
-#define INT_UART                       (1 <<  9)
-#define INT_TX_COMPLETE_EN             (1 << 16)
-#define INT_RX_COMPLETE_EN             (1 << 17)
-#define INT_RETRY_FAIL_EN              (1 << 18)
-#define INT_WAKEUP_EN                  (1 << 19)
-#define INT_DTIM_NOTIFY_EN             (1 << 21)
-#define INT_CFG_NEXT_BCN_EN            (1 << 22)
-#define INT_BUS_ABORT_EN               (1 << 23)
-#define INT_TX_FIFO_READY_EN           (1 << 24)
-#define INT_UART_EN                    (1 << 25)
-
-#define CR_TSF_LOW_PART                        CTL_REG(0x0514)
-#define CR_TSF_HIGH_PART               CTL_REG(0x0518)
-
-/* Following three values are in time units (1024us)
- * Following condition must be met:
- * atim < tbtt < bcn
- */
-#define CR_ATIM_WND_PERIOD             CTL_REG(0x051C)
-#define CR_BCN_INTERVAL                        CTL_REG(0x0520)
-#define CR_PRE_TBTT                    CTL_REG(0x0524)
-/* in units of TU(1024us) */
-
-/* for UART support */
-#define CR_UART_RBR_THR_DLL            CTL_REG(0x0540)
-#define CR_UART_DLM_IER                        CTL_REG(0x0544)
-#define CR_UART_IIR_FCR                        CTL_REG(0x0548)
-#define CR_UART_LCR                    CTL_REG(0x054c)
-#define CR_UART_MCR                    CTL_REG(0x0550)
-#define CR_UART_LSR                    CTL_REG(0x0554)
-#define CR_UART_MSR                    CTL_REG(0x0558)
-#define CR_UART_ECR                    CTL_REG(0x055c)
-#define CR_UART_STATUS                 CTL_REG(0x0560)
-
-#define CR_PCI_TX_ADDR_P1              CTL_REG(0x0600)
-#define CR_PCI_TX_AddR_P2              CTL_REG(0x0604)
-#define CR_PCI_RX_AddR_P1              CTL_REG(0x0608)
-#define CR_PCI_RX_AddR_P2              CTL_REG(0x060C)
-
-/* must be overwritten if custom MAC address will be used */
-#define CR_MAC_ADDR_P1                 CTL_REG(0x0610)
-#define CR_MAC_ADDR_P2                 CTL_REG(0x0614)
-#define CR_BSSID_P1                    CTL_REG(0x0618)
-#define CR_BSSID_P2                    CTL_REG(0x061C)
-#define CR_BCN_PLCP_CFG                        CTL_REG(0x0620)
-
-/* Group hash table for filtering incoming packets.
- *
- * The group hash table is 64 bit large and split over two parts. The first
- * part is the lower part. The upper 6 bits of the last byte of the target
- * address are used as index. Packets are received if the hash table bit is
- * set. This is used for multicast handling, but for broadcasts (address
- * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set.
- */
-#define CR_GROUP_HASH_P1               CTL_REG(0x0624)
-#define CR_GROUP_HASH_P2               CTL_REG(0x0628)
-
-#define CR_RX_TIMEOUT                  CTL_REG(0x062C)
-
-/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
- * device will use a rate in this table that is less than or equal to the rate
- * of the incoming frame which prompted the response. */
-#define CR_BASIC_RATE_TBL              CTL_REG(0x0630)
-#define CR_RATE_1M     (1 <<  0)       /* 802.11b */
-#define CR_RATE_2M     (1 <<  1)       /* 802.11b */
-#define CR_RATE_5_5M   (1 <<  2)       /* 802.11b */
-#define CR_RATE_11M    (1 <<  3)       /* 802.11b */
-#define CR_RATE_6M      (1 <<  8)      /* 802.11g */
-#define CR_RATE_9M      (1 <<  9)      /* 802.11g */
-#define CR_RATE_12M    (1 << 10)       /* 802.11g */
-#define CR_RATE_18M    (1 << 11)       /* 802.11g */
-#define CR_RATE_24M     (1 << 12)      /* 802.11g */
-#define CR_RATE_36M     (1 << 13)      /* 802.11g */
-#define CR_RATE_48M     (1 << 14)      /* 802.11g */
-#define CR_RATE_54M     (1 << 15)      /* 802.11g */
-#define CR_RATES_80211G        0xff00
-#define CR_RATES_80211B        0x000f
-
-/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if
- * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will
- * look for a rate in this table that is less than or equal to the rate of
- * the incoming frame. */
-#define CR_MANDATORY_RATE_TBL          CTL_REG(0x0634)
-#define CR_RTS_CTS_RATE                        CTL_REG(0x0638)
-
-/* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */
-#define RTSCTS_SH_RTS_RATE             0
-#define RTSCTS_SH_EXP_CTS_RATE         4
-#define RTSCTS_SH_RTS_MOD_TYPE         8
-#define RTSCTS_SH_RTS_PMB_TYPE         9
-#define RTSCTS_SH_CTS_RATE             16
-#define RTSCTS_SH_CTS_MOD_TYPE         24
-#define RTSCTS_SH_CTS_PMB_TYPE         25
-
-#define CR_WEP_PROTECT                 CTL_REG(0x063C)
-#define CR_RX_THRESHOLD                        CTL_REG(0x0640)
-
-/* register for controlling the LEDS */
-#define CR_LED                         CTL_REG(0x0644)
-/* masks for controlling LEDs */
-#define LED1                           (1 <<  8)
-#define LED2                           (1 <<  9)
-#define LED_SW                         (1 << 10)
-
-/* Seems to indicate that the configuration is over.
- */
-#define CR_AFTER_PNP                   CTL_REG(0x0648)
-#define CR_ACK_TIME_80211              CTL_REG(0x0658)
-
-#define CR_RX_OFFSET                   CTL_REG(0x065c)
-
-#define CR_BCN_LENGTH                  CTL_REG(0x0664)
-#define CR_PHY_DELAY                   CTL_REG(0x066C)
-#define CR_BCN_FIFO                    CTL_REG(0x0670)
-#define CR_SNIFFER_ON                  CTL_REG(0x0674)
-
-#define CR_ENCRYPTION_TYPE             CTL_REG(0x0678)
-#define NO_WEP                         0
-#define WEP64                          1
-#define WEP128                         5
-#define WEP256                         6
-#define ENC_SNIFFER                    8
-
-#define CR_ZD1211_RETRY_MAX            CTL_REG(0x067C)
-
-#define CR_REG1                                CTL_REG(0x0680)
-/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical
- * registers, so one could argue it is a LOCK bit. But calling it
- * LOCK_PHY_REGS makes it confusing.
- */
-#define UNLOCK_PHY_REGS                        (1 << 7)
-
-#define CR_DEVICE_STATE                        CTL_REG(0x0684)
-#define CR_UNDERRUN_CNT                        CTL_REG(0x0688)
-
-#define CR_RX_FILTER                   CTL_REG(0x068c)
-#define RX_FILTER_ASSOC_REQUEST                (1 <<  0)
-#define RX_FILTER_ASSOC_RESPONSE       (1 <<  1)
-#define RX_FILTER_REASSOC_REQUEST      (1 <<  2)
-#define RX_FILTER_REASSOC_RESPONSE     (1 <<  3)
-#define RX_FILTER_PROBE_REQUEST                (1 <<  4)
-#define RX_FILTER_PROBE_RESPONSE       (1 <<  5)
-/* bits 6 and 7 reserved */
-#define RX_FILTER_BEACON               (1 <<  8)
-#define RX_FILTER_ATIM                 (1 <<  9)
-#define RX_FILTER_DISASSOC             (1 << 10)
-#define RX_FILTER_AUTH                 (1 << 11)
-#define RX_FILTER_DEAUTH               (1 << 12)
-#define RX_FILTER_PSPOLL               (1 << 26)
-#define RX_FILTER_RTS                  (1 << 27)
-#define RX_FILTER_CTS                  (1 << 28)
-#define RX_FILTER_ACK                  (1 << 29)
-#define RX_FILTER_CFEND                        (1 << 30)
-#define RX_FILTER_CFACK                        (1 << 31)
-
-/* Enable bits for all frames you are interested in. */
-#define STA_RX_FILTER  (RX_FILTER_ASSOC_REQUEST | RX_FILTER_ASSOC_RESPONSE | \
-       RX_FILTER_REASSOC_REQUEST | RX_FILTER_REASSOC_RESPONSE | \
-       RX_FILTER_PROBE_REQUEST | RX_FILTER_PROBE_RESPONSE | \
-       (0x3 << 6) /* vendor driver sets these reserved bits */ | \
-       RX_FILTER_BEACON | RX_FILTER_ATIM | RX_FILTER_DISASSOC | \
-       RX_FILTER_AUTH | RX_FILTER_DEAUTH | \
-       (0x7 << 13) /* vendor driver sets these reserved bits */ | \
-       RX_FILTER_PSPOLL | RX_FILTER_ACK) /* 0x2400ffff */
-
-#define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
-       RX_FILTER_CFEND | RX_FILTER_CFACK)
-
-#define BCN_MODE_AP                    0x1000000
-#define BCN_MODE_IBSS                  0x2000000
-
-/* Monitor mode sets filter to 0xfffff */
-
-#define CR_ACK_TIMEOUT_EXT             CTL_REG(0x0690)
-#define CR_BCN_FIFO_SEMAPHORE          CTL_REG(0x0694)
-
-#define CR_IFS_VALUE                   CTL_REG(0x0698)
-#define IFS_VALUE_DIFS_SH              0
-#define IFS_VALUE_EIFS_SH              12
-#define IFS_VALUE_SIFS_SH              24
-#define IFS_VALUE_DEFAULT              ((  50 << IFS_VALUE_DIFS_SH) | \
-                                        (1148 << IFS_VALUE_EIFS_SH) | \
-                                        (  10 << IFS_VALUE_SIFS_SH))
-
-#define CR_RX_TIME_OUT                 CTL_REG(0x069C)
-#define CR_TOTAL_RX_FRM                        CTL_REG(0x06A0)
-#define CR_CRC32_CNT                   CTL_REG(0x06A4)
-#define CR_CRC16_CNT                   CTL_REG(0x06A8)
-#define CR_DECRYPTION_ERR_UNI          CTL_REG(0x06AC)
-#define CR_RX_FIFO_OVERRUN             CTL_REG(0x06B0)
-
-#define CR_DECRYPTION_ERR_MUL          CTL_REG(0x06BC)
-
-#define CR_NAV_CNT                     CTL_REG(0x06C4)
-#define CR_NAV_CCA                     CTL_REG(0x06C8)
-#define CR_RETRY_CNT                   CTL_REG(0x06CC)
-
-#define CR_READ_TCB_ADDR               CTL_REG(0x06E8)
-#define CR_READ_RFD_ADDR               CTL_REG(0x06EC)
-#define CR_CWMIN_CWMAX                 CTL_REG(0x06F0)
-#define CR_TOTAL_TX_FRM                        CTL_REG(0x06F4)
-
-/* CAM: Continuous Access Mode (power management) */
-#define CR_CAM_MODE                    CTL_REG(0x0700)
-#define MODE_IBSS                      0x0
-#define MODE_AP                                0x1
-#define MODE_STA                       0x2
-#define MODE_AP_WDS                    0x3
-
-#define CR_CAM_ROLL_TB_LOW             CTL_REG(0x0704)
-#define CR_CAM_ROLL_TB_HIGH            CTL_REG(0x0708)
-#define CR_CAM_ADDRESS                 CTL_REG(0x070C)
-#define CR_CAM_DATA                    CTL_REG(0x0710)
-
-#define CR_ROMDIR                      CTL_REG(0x0714)
-
-#define CR_DECRY_ERR_FLG_LOW           CTL_REG(0x0714)
-#define CR_DECRY_ERR_FLG_HIGH          CTL_REG(0x0718)
-
-#define CR_WEPKEY0                     CTL_REG(0x0720)
-#define CR_WEPKEY1                     CTL_REG(0x0724)
-#define CR_WEPKEY2                     CTL_REG(0x0728)
-#define CR_WEPKEY3                     CTL_REG(0x072C)
-#define CR_WEPKEY4                     CTL_REG(0x0730)
-#define CR_WEPKEY5                     CTL_REG(0x0734)
-#define CR_WEPKEY6                     CTL_REG(0x0738)
-#define CR_WEPKEY7                     CTL_REG(0x073C)
-#define CR_WEPKEY8                     CTL_REG(0x0740)
-#define CR_WEPKEY9                     CTL_REG(0x0744)
-#define CR_WEPKEY10                    CTL_REG(0x0748)
-#define CR_WEPKEY11                    CTL_REG(0x074C)
-#define CR_WEPKEY12                    CTL_REG(0x0750)
-#define CR_WEPKEY13                    CTL_REG(0x0754)
-#define CR_WEPKEY14                    CTL_REG(0x0758)
-#define CR_WEPKEY15                    CTL_REG(0x075c)
-#define CR_TKIP_MODE                   CTL_REG(0x0760)
-
-#define CR_EEPROM_PROTECT0             CTL_REG(0x0758)
-#define CR_EEPROM_PROTECT1             CTL_REG(0x075C)
-
-#define CR_DBG_FIFO_RD                 CTL_REG(0x0800)
-#define CR_DBG_SELECT                  CTL_REG(0x0804)
-#define CR_FIFO_Length                 CTL_REG(0x0808)
-
-
-#define CR_RSSI_MGC                    CTL_REG(0x0810)
-
-#define CR_PON                         CTL_REG(0x0818)
-#define CR_RX_ON                       CTL_REG(0x081C)
-#define CR_TX_ON                       CTL_REG(0x0820)
-#define CR_CHIP_EN                     CTL_REG(0x0824)
-#define CR_LO_SW                       CTL_REG(0x0828)
-#define CR_TXRX_SW                     CTL_REG(0x082C)
-#define CR_S_MD                                CTL_REG(0x0830)
-
-#define CR_USB_DEBUG_PORT              CTL_REG(0x0888)
-#define CR_ZD1211B_CWIN_MAX_MIN_AC0    CTL_REG(0x0b00)
-#define CR_ZD1211B_CWIN_MAX_MIN_AC1    CTL_REG(0x0b04)
-#define CR_ZD1211B_CWIN_MAX_MIN_AC2    CTL_REG(0x0b08)
-#define CR_ZD1211B_CWIN_MAX_MIN_AC3    CTL_REG(0x0b0c)
-#define CR_ZD1211B_AIFS_CTL1           CTL_REG(0x0b10)
-#define CR_ZD1211B_AIFS_CTL2           CTL_REG(0x0b14)
-#define CR_ZD1211B_TXOP                        CTL_REG(0x0b20)
-#define CR_ZD1211B_RETRY_MAX           CTL_REG(0x0b28)
-
-/* Value for CR_ZD1211_RETRY_MAX & CR_ZD1211B_RETRY_MAX. Vendor driver uses 2,
- * we use 0. The first rate is tried (count+2), then all next rates are tried
- * twice, until 1 Mbits is tried. */
-#define        ZD1211_RETRY_COUNT              0
-#define        ZD1211B_RETRY_COUNT     \
-       (ZD1211_RETRY_COUNT <<  0)|     \
-       (ZD1211_RETRY_COUNT <<  8)|     \
-       (ZD1211_RETRY_COUNT << 16)|     \
-       (ZD1211_RETRY_COUNT << 24)
-
-/* Used to detect PLL lock */
-#define UW2453_INTR_REG                        ((zd_addr_t)0x85c1)
-
-#define CWIN_SIZE                      0x007f043f
-
-
-#define HWINT_ENABLED                  \
-       (INT_TX_COMPLETE_EN|            \
-        INT_RX_COMPLETE_EN|            \
-        INT_RETRY_FAIL_EN|             \
-        INT_WAKEUP_EN|                 \
-        INT_CFG_NEXT_BCN_EN)
-
-#define HWINT_DISABLED                 0
-
-#define E2P_PWR_INT_GUARD              8
-#define E2P_CHANNEL_COUNT              14
-
-/* If you compare this addresses with the ZYDAS orignal driver, please notify
- * that we use word mapping for the EEPROM.
- */
-
-/*
- * Upper 16 bit contains the regulatory domain.
- */
-#define E2P_SUBID              E2P_DATA(0x00)
-#define E2P_POD                        E2P_DATA(0x02)
-#define E2P_MAC_ADDR_P1                E2P_DATA(0x04)
-#define E2P_MAC_ADDR_P2                E2P_DATA(0x06)
-#define E2P_PWR_CAL_VALUE1     E2P_DATA(0x08)
-#define E2P_PWR_CAL_VALUE2     E2P_DATA(0x0a)
-#define E2P_PWR_CAL_VALUE3     E2P_DATA(0x0c)
-#define E2P_PWR_CAL_VALUE4      E2P_DATA(0x0e)
-#define E2P_PWR_INT_VALUE1     E2P_DATA(0x10)
-#define E2P_PWR_INT_VALUE2     E2P_DATA(0x12)
-#define E2P_PWR_INT_VALUE3     E2P_DATA(0x14)
-#define E2P_PWR_INT_VALUE4     E2P_DATA(0x16)
-
-/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30)
- * also only 11 channels. */
-#define E2P_ALLOWED_CHANNEL    E2P_DATA(0x18)
-
-#define E2P_DEVICE_VER         E2P_DATA(0x20)
-#define E2P_PHY_REG            E2P_DATA(0x25)
-#define E2P_36M_CAL_VALUE1     E2P_DATA(0x28)
-#define E2P_36M_CAL_VALUE2      E2P_DATA(0x2a)
-#define E2P_36M_CAL_VALUE3      E2P_DATA(0x2c)
-#define E2P_36M_CAL_VALUE4     E2P_DATA(0x2e)
-#define E2P_11A_INT_VALUE1     E2P_DATA(0x30)
-#define E2P_11A_INT_VALUE2     E2P_DATA(0x32)
-#define E2P_11A_INT_VALUE3     E2P_DATA(0x34)
-#define E2P_11A_INT_VALUE4     E2P_DATA(0x36)
-#define E2P_48M_CAL_VALUE1     E2P_DATA(0x38)
-#define E2P_48M_CAL_VALUE2     E2P_DATA(0x3a)
-#define E2P_48M_CAL_VALUE3     E2P_DATA(0x3c)
-#define E2P_48M_CAL_VALUE4     E2P_DATA(0x3e)
-#define E2P_48M_INT_VALUE1     E2P_DATA(0x40)
-#define E2P_48M_INT_VALUE2     E2P_DATA(0x42)
-#define E2P_48M_INT_VALUE3     E2P_DATA(0x44)
-#define E2P_48M_INT_VALUE4     E2P_DATA(0x46)
-#define E2P_54M_CAL_VALUE1     E2P_DATA(0x48)  /* ??? */
-#define E2P_54M_CAL_VALUE2     E2P_DATA(0x4a)
-#define E2P_54M_CAL_VALUE3     E2P_DATA(0x4c)
-#define E2P_54M_CAL_VALUE4     E2P_DATA(0x4e)
-#define E2P_54M_INT_VALUE1     E2P_DATA(0x50)
-#define E2P_54M_INT_VALUE2     E2P_DATA(0x52)
-#define E2P_54M_INT_VALUE3     E2P_DATA(0x54)
-#define E2P_54M_INT_VALUE4     E2P_DATA(0x56)
-
-/* This word contains the base address of the FW_REG_ registers below */
-#define FWRAW_REGS_ADDR                FWRAW_DATA(0x1d)
-
-/* All 16 bit values, offset from the address in FWRAW_REGS_ADDR */
-enum {
-       FW_REG_FIRMWARE_VER     = 0,
-       /* non-zero if USB high speed connection */
-       FW_REG_USB_SPEED        = 1,
-       FW_REG_FIX_TX_RATE      = 2,
-       /* Seems to be able to control LEDs over the firmware */
-       FW_REG_LED_LINK_STATUS  = 3,
-       FW_REG_SOFT_RESET       = 4,
-       FW_REG_FLASH_CHK        = 5,
-};
-
-/* Values for FW_LINK_STATUS */
-#define FW_LINK_OFF            0x0
-#define FW_LINK_TX             0x1
-/* 0x2 - link led on? */
-
-enum {
-       /* indices for ofdm_cal_values */
-       OFDM_36M_INDEX = 0,
-       OFDM_48M_INDEX = 1,
-       OFDM_54M_INDEX = 2,
-};
-
-struct zd_chip {
-       struct zd_usb usb;
-       struct zd_rf rf;
-       struct mutex mutex;
-       /* Base address of FW_REG_ registers */
-       zd_addr_t fw_regs_base;
-       /* EepSetPoint in the vendor driver */
-       u8 pwr_cal_values[E2P_CHANNEL_COUNT];
-       /* integration values in the vendor driver */
-       u8 pwr_int_values[E2P_CHANNEL_COUNT];
-       /* SetPointOFDM in the vendor driver */
-       u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
-       u16 link_led;
-       unsigned int pa_type:4,
-               patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-               new_phy_layout:1, al2230s_bit:1,
-               supports_tx_led:1;
-};
-
-static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
-{
-       return container_of(usb, struct zd_chip, usb);
-}
-
-static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
-{
-       return container_of(rf, struct zd_chip, rf);
-}
-
-#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
-
-void zd_chip_init(struct zd_chip *chip,
-                struct ieee80211_hw *hw,
-                struct usb_interface *intf);
-void zd_chip_clear(struct zd_chip *chip);
-int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
-int zd_chip_init_hw(struct zd_chip *chip);
-int zd_chip_reset(struct zd_chip *chip);
-
-static inline int zd_chip_is_zd1211b(struct zd_chip *chip)
-{
-       return chip->usb.is_zd1211b;
-}
-
-static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
-                                     const zd_addr_t *addresses,
-                                     unsigned int count)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_usb_ioread16v(&chip->usb, values, addresses, count);
-}
-
-static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value,
-                                    const zd_addr_t addr)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_usb_ioread16(&chip->usb, value, addr);
-}
-
-int zd_ioread32v_locked(struct zd_chip *chip, u32 *values,
-                       const zd_addr_t *addresses, unsigned int count);
-
-static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value,
-                                    const zd_addr_t addr)
-{
-       return zd_ioread32v_locked(chip, value, &addr, 1);
-}
-
-static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value,
-                                     zd_addr_t addr)
-{
-       struct zd_ioreq16 ioreq;
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       ioreq.addr = addr;
-       ioreq.value = value;
-
-       return zd_usb_iowrite16v(&chip->usb, &ioreq, 1);
-}
-
-int zd_iowrite16a_locked(struct zd_chip *chip,
-                         const struct zd_ioreq16 *ioreqs, unsigned int count);
-
-int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
-                         unsigned int count);
-
-static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value,
-                                     zd_addr_t addr)
-{
-       struct zd_ioreq32 ioreq;
-
-       ioreq.addr = addr;
-       ioreq.value = value;
-
-       return _zd_iowrite32v_locked(chip, &ioreq, 1);
-}
-
-int zd_iowrite32a_locked(struct zd_chip *chip,
-                        const struct zd_ioreq32 *ioreqs, unsigned int count);
-
-static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_usb_rfwrite(&chip->usb, value, bits);
-}
-
-int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value);
-
-int zd_rfwritev_locked(struct zd_chip *chip,
-                      const u32* values, unsigned int count, u8 bits);
-int zd_rfwritev_cr_locked(struct zd_chip *chip,
-                         const u32* values, unsigned int count);
-
-/* Locking functions for reading and writing registers.
- * The different parameters are intentional.
- */
-int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value);
-int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value);
-int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value);
-int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value);
-int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
-                 u32 *values, unsigned int count);
-int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
-                  unsigned int count);
-
-int zd_chip_set_channel(struct zd_chip *chip, u8 channel);
-static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
-{
-       return chip->rf.channel;
-}
-u8  zd_chip_get_channel(struct zd_chip *chip);
-int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
-int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
-int zd_write_bssid(struct zd_chip *chip, const u8 *bssid);
-int zd_chip_switch_radio_on(struct zd_chip *chip);
-int zd_chip_switch_radio_off(struct zd_chip *chip);
-int zd_chip_enable_int(struct zd_chip *chip);
-void zd_chip_disable_int(struct zd_chip *chip);
-int zd_chip_enable_rxtx(struct zd_chip *chip);
-void zd_chip_disable_rxtx(struct zd_chip *chip);
-int zd_chip_enable_hwint(struct zd_chip *chip);
-int zd_chip_disable_hwint(struct zd_chip *chip);
-int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel);
-int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, int preamble);
-
-static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
-{
-       return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type);
-}
-
-static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type)
-{
-       return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type);
-}
-
-static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
-{
-       return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
-}
-
-int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
-
-int zd_chip_lock_phy_regs(struct zd_chip *chip);
-int zd_chip_unlock_phy_regs(struct zd_chip *chip);
-
-enum led_status {
-       ZD_LED_OFF = 0,
-       ZD_LED_SCANNING = 1,
-       ZD_LED_ASSOCIATED = 2,
-};
-
-int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
-
-int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
-                          int type);
-
-static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
-{
-       return zd_ioread32(chip, CR_BCN_INTERVAL, interval);
-}
-
-struct rx_status;
-
-u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
-
-struct zd_mc_hash {
-       u32 low;
-       u32 high;
-};
-
-static inline void zd_mc_clear(struct zd_mc_hash *hash)
-{
-       hash->low = 0;
-       /* The interfaces must always received broadcasts.
-        * The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63.
-        */
-       hash->high = 0x80000000;
-}
-
-static inline void zd_mc_add_all(struct zd_mc_hash *hash)
-{
-       hash->low = hash->high = 0xffffffff;
-}
-
-static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr)
-{
-       unsigned int i = addr[5] >> 2;
-       if (i < 32) {
-               hash->low |= 1 << i;
-       } else {
-               hash->high |= 1 << (i-32);
-       }
-}
-
-int zd_chip_set_multicast_hash(struct zd_chip *chip,
-                              struct zd_mc_hash *hash);
-
-u64 zd_chip_get_tsf(struct zd_chip *chip);
-
-#endif /* _ZD_CHIP_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
deleted file mode 100644 (file)
index 41bd755..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ZD_DEF_H
-#define _ZD_DEF_H
-
-#include <linux/kernel.h>
-#include <linux/stringify.h>
-#include <linux/device.h>
-
-typedef u16 __nocast zd_addr_t;
-
-#define dev_printk_f(level, dev, fmt, args...) \
-       dev_printk(level, dev, "%s() " fmt, __func__, ##args)
-
-#ifdef DEBUG
-#  define dev_dbg_f(dev, fmt, args...) \
-         dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
-#  define dev_dbg_f_limit(dev, fmt, args...) do { \
-       if (net_ratelimit()) \
-               dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
-} while (0)
-#  define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
-       bool __cond = !!(cond); \
-       if (unlikely(__cond)) \
-               dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
-})
-#else
-#  define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
-#  define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
-#  define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
-#endif /* DEBUG */
-
-#ifdef DEBUG
-#  define ZD_ASSERT(x) \
-do { \
-       if (unlikely(!(x))) { \
-               pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
-                       __FILE__, __LINE__, __stringify(x)); \
-               dump_stack(); \
-       } \
-} while (0)
-#else
-#  define ZD_ASSERT(x) do { } while (0)
-#endif
-
-#ifdef DEBUG
-#  define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size))
-#else
-#  define ZD_MEMCLEAR(pointer, size) do { } while (0)
-#endif
-
-#endif /* _ZD_DEF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
deleted file mode 100644 (file)
index e539d9b..0000000
+++ /dev/null
@@ -1,1550 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
- * Copyright (C) 2007-2008 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/jiffies.h>
-#include <net/ieee80211_radiotap.h>
-
-#include "zd_def.h"
-#include "zd_chip.h"
-#include "zd_mac.h"
-#include "zd_rf.h"
-
-struct zd_reg_alpha2_map {
-       u32 reg;
-       char alpha2[2];
-};
-
-static struct zd_reg_alpha2_map reg_alpha2_map[] = {
-       { ZD_REGDOMAIN_FCC, "US" },
-       { ZD_REGDOMAIN_IC, "CA" },
-       { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
-       { ZD_REGDOMAIN_JAPAN, "JP" },
-       { ZD_REGDOMAIN_JAPAN_2, "JP" },
-       { ZD_REGDOMAIN_JAPAN_3, "JP" },
-       { ZD_REGDOMAIN_SPAIN, "ES" },
-       { ZD_REGDOMAIN_FRANCE, "FR" },
-};
-
-/* This table contains the hardware specific values for the modulation rates. */
-static const struct ieee80211_rate zd_rates[] = {
-       { .bitrate = 10,
-         .hw_value = ZD_CCK_RATE_1M, },
-       { .bitrate = 20,
-         .hw_value = ZD_CCK_RATE_2M,
-         .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
-         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-       { .bitrate = 55,
-         .hw_value = ZD_CCK_RATE_5_5M,
-         .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
-         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-       { .bitrate = 110,
-         .hw_value = ZD_CCK_RATE_11M,
-         .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
-         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-       { .bitrate = 60,
-         .hw_value = ZD_OFDM_RATE_6M,
-         .flags = 0 },
-       { .bitrate = 90,
-         .hw_value = ZD_OFDM_RATE_9M,
-         .flags = 0 },
-       { .bitrate = 120,
-         .hw_value = ZD_OFDM_RATE_12M,
-         .flags = 0 },
-       { .bitrate = 180,
-         .hw_value = ZD_OFDM_RATE_18M,
-         .flags = 0 },
-       { .bitrate = 240,
-         .hw_value = ZD_OFDM_RATE_24M,
-         .flags = 0 },
-       { .bitrate = 360,
-         .hw_value = ZD_OFDM_RATE_36M,
-         .flags = 0 },
-       { .bitrate = 480,
-         .hw_value = ZD_OFDM_RATE_48M,
-         .flags = 0 },
-       { .bitrate = 540,
-         .hw_value = ZD_OFDM_RATE_54M,
-         .flags = 0 },
-};
-
-/*
- * Zydas retry rates table. Each line is listed in the same order as
- * in zd_rates[] and contains all the rate used when a packet is sent
- * starting with a given rates. Let's consider an example :
- *
- * "11 Mbits : 4, 3, 2, 1, 0" means :
- * - packet is sent using 4 different rates
- * - 1st rate is index 3 (ie 11 Mbits)
- * - 2nd rate is index 2 (ie 5.5 Mbits)
- * - 3rd rate is index 1 (ie 2 Mbits)
- * - 4th rate is index 0 (ie 1 Mbits)
- */
-
-static const struct tx_retry_rate zd_retry_rates[] = {
-       { /*  1 Mbits */        1, { 0 }},
-       { /*  2 Mbits */        2, { 1,  0 }},
-       { /*  5.5 Mbits */      3, { 2,  1, 0 }},
-       { /* 11 Mbits */        4, { 3,  2, 1, 0 }},
-       { /*  6 Mbits */        5, { 4,  3, 2, 1, 0 }},
-       { /*  9 Mbits */        6, { 5,  4, 3, 2, 1, 0}},
-       { /* 12 Mbits */        5, { 6,  3, 2, 1, 0 }},
-       { /* 18 Mbits */        6, { 7,  6, 3, 2, 1, 0 }},
-       { /* 24 Mbits */        6, { 8,  6, 3, 2, 1, 0 }},
-       { /* 36 Mbits */        7, { 9,  8, 6, 3, 2, 1, 0 }},
-       { /* 48 Mbits */        8, {10,  9, 8, 6, 3, 2, 1, 0 }},
-       { /* 54 Mbits */        9, {11, 10, 9, 8, 6, 3, 2, 1, 0 }}
-};
-
-static const struct ieee80211_channel zd_channels[] = {
-       { .center_freq = 2412, .hw_value = 1 },
-       { .center_freq = 2417, .hw_value = 2 },
-       { .center_freq = 2422, .hw_value = 3 },
-       { .center_freq = 2427, .hw_value = 4 },
-       { .center_freq = 2432, .hw_value = 5 },
-       { .center_freq = 2437, .hw_value = 6 },
-       { .center_freq = 2442, .hw_value = 7 },
-       { .center_freq = 2447, .hw_value = 8 },
-       { .center_freq = 2452, .hw_value = 9 },
-       { .center_freq = 2457, .hw_value = 10 },
-       { .center_freq = 2462, .hw_value = 11 },
-       { .center_freq = 2467, .hw_value = 12 },
-       { .center_freq = 2472, .hw_value = 13 },
-       { .center_freq = 2484, .hw_value = 14 },
-};
-
-static void housekeeping_init(struct zd_mac *mac);
-static void housekeeping_enable(struct zd_mac *mac);
-static void housekeeping_disable(struct zd_mac *mac);
-static void beacon_init(struct zd_mac *mac);
-static void beacon_enable(struct zd_mac *mac);
-static void beacon_disable(struct zd_mac *mac);
-static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
-static int zd_mac_config_beacon(struct ieee80211_hw *hw,
-                               struct sk_buff *beacon, bool in_intr);
-
-static int zd_reg2alpha2(u8 regdomain, char *alpha2)
-{
-       unsigned int i;
-       struct zd_reg_alpha2_map *reg_map;
-       for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
-               reg_map = &reg_alpha2_map[i];
-               if (regdomain == reg_map->reg) {
-                       alpha2[0] = reg_map->alpha2[0];
-                       alpha2[1] = reg_map->alpha2[1];
-                       return 0;
-               }
-       }
-       return 1;
-}
-
-static int zd_check_signal(struct ieee80211_hw *hw, int signal)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-
-       dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
-                       "%s: signal value from device not in range 0..100, "
-                       "but %d.\n", __func__, signal);
-
-       if (signal < 0)
-               signal = 0;
-       else if (signal > 100)
-               signal = 100;
-
-       return signal;
-}
-
-int zd_mac_preinit_hw(struct ieee80211_hw *hw)
-{
-       int r;
-       u8 addr[ETH_ALEN];
-       struct zd_mac *mac = zd_hw_mac(hw);
-
-       r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
-       if (r)
-               return r;
-
-       SET_IEEE80211_PERM_ADDR(hw, addr);
-
-       return 0;
-}
-
-int zd_mac_init_hw(struct ieee80211_hw *hw)
-{
-       int r;
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct zd_chip *chip = &mac->chip;
-       char alpha2[2];
-       u8 default_regdomain;
-
-       r = zd_chip_enable_int(chip);
-       if (r)
-               goto out;
-       r = zd_chip_init_hw(chip);
-       if (r)
-               goto disable_int;
-
-       ZD_ASSERT(!irqs_disabled());
-
-       r = zd_read_regdomain(chip, &default_regdomain);
-       if (r)
-               goto disable_int;
-       spin_lock_irq(&mac->lock);
-       mac->regdomain = mac->default_regdomain = default_regdomain;
-       spin_unlock_irq(&mac->lock);
-
-       /* We must inform the device that we are doing encryption/decryption in
-        * software at the moment. */
-       r = zd_set_encryption_type(chip, ENC_SNIFFER);
-       if (r)
-               goto disable_int;
-
-       r = zd_reg2alpha2(mac->regdomain, alpha2);
-       if (r)
-               goto disable_int;
-
-       r = regulatory_hint(hw->wiphy, alpha2);
-disable_int:
-       zd_chip_disable_int(chip);
-out:
-       return r;
-}
-
-void zd_mac_clear(struct zd_mac *mac)
-{
-       flush_workqueue(zd_workqueue);
-       zd_chip_clear(&mac->chip);
-       ZD_ASSERT(!spin_is_locked(&mac->lock));
-       ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
-}
-
-static int set_rx_filter(struct zd_mac *mac)
-{
-       unsigned long flags;
-       u32 filter = STA_RX_FILTER;
-
-       spin_lock_irqsave(&mac->lock, flags);
-       if (mac->pass_ctrl)
-               filter |= RX_FILTER_CTRL;
-       spin_unlock_irqrestore(&mac->lock, flags);
-
-       return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
-}
-
-static int set_mac_and_bssid(struct zd_mac *mac)
-{
-       int r;
-
-       if (!mac->vif)
-               return -1;
-
-       r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
-       if (r)
-               return r;
-
-       /* Vendor driver after setting MAC either sets BSSID for AP or
-        * filter for other modes.
-        */
-       if (mac->type != NL80211_IFTYPE_AP)
-               return set_rx_filter(mac);
-       else
-               return zd_write_bssid(&mac->chip, mac->vif->addr);
-}
-
-static int set_mc_hash(struct zd_mac *mac)
-{
-       struct zd_mc_hash hash;
-       zd_mc_clear(&hash);
-       return zd_chip_set_multicast_hash(&mac->chip, &hash);
-}
-
-int zd_op_start(struct ieee80211_hw *hw)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct zd_chip *chip = &mac->chip;
-       struct zd_usb *usb = &chip->usb;
-       int r;
-
-       if (!usb->initialized) {
-               r = zd_usb_init_hw(usb);
-               if (r)
-                       goto out;
-       }
-
-       r = zd_chip_enable_int(chip);
-       if (r < 0)
-               goto out;
-
-       r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
-       if (r < 0)
-               goto disable_int;
-       r = set_rx_filter(mac);
-       if (r)
-               goto disable_int;
-       r = set_mc_hash(mac);
-       if (r)
-               goto disable_int;
-
-       /* Wait after setting the multicast hash table and powering on
-        * the radio otherwise interface bring up will fail. This matches
-        * what the vendor driver did.
-        */
-       msleep(10);
-
-       r = zd_chip_switch_radio_on(chip);
-       if (r < 0) {
-               dev_err(zd_chip_dev(chip),
-                       "%s: failed to set radio on\n", __func__);
-               goto disable_int;
-       }
-       r = zd_chip_enable_rxtx(chip);
-       if (r < 0)
-               goto disable_radio;
-       r = zd_chip_enable_hwint(chip);
-       if (r < 0)
-               goto disable_rxtx;
-
-       housekeeping_enable(mac);
-       beacon_enable(mac);
-       set_bit(ZD_DEVICE_RUNNING, &mac->flags);
-       return 0;
-disable_rxtx:
-       zd_chip_disable_rxtx(chip);
-disable_radio:
-       zd_chip_switch_radio_off(chip);
-disable_int:
-       zd_chip_disable_int(chip);
-out:
-       return r;
-}
-
-void zd_op_stop(struct ieee80211_hw *hw)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct zd_chip *chip = &mac->chip;
-       struct sk_buff *skb;
-       struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
-
-       clear_bit(ZD_DEVICE_RUNNING, &mac->flags);
-
-       /* The order here deliberately is a little different from the open()
-        * method, since we need to make sure there is no opportunity for RX
-        * frames to be processed by mac80211 after we have stopped it.
-        */
-
-       zd_chip_disable_rxtx(chip);
-       beacon_disable(mac);
-       housekeeping_disable(mac);
-       flush_workqueue(zd_workqueue);
-
-       zd_chip_disable_hwint(chip);
-       zd_chip_switch_radio_off(chip);
-       zd_chip_disable_int(chip);
-
-
-       while ((skb = skb_dequeue(ack_wait_queue)))
-               dev_kfree_skb_any(skb);
-}
-
-int zd_restore_settings(struct zd_mac *mac)
-{
-       struct sk_buff *beacon;
-       struct zd_mc_hash multicast_hash;
-       unsigned int short_preamble;
-       int r, beacon_interval, beacon_period;
-       u8 channel;
-
-       dev_dbg_f(zd_mac_dev(mac), "\n");
-
-       spin_lock_irq(&mac->lock);
-       multicast_hash = mac->multicast_hash;
-       short_preamble = mac->short_preamble;
-       beacon_interval = mac->beacon.interval;
-       beacon_period = mac->beacon.period;
-       channel = mac->channel;
-       spin_unlock_irq(&mac->lock);
-
-       r = set_mac_and_bssid(mac);
-       if (r < 0) {
-               dev_dbg_f(zd_mac_dev(mac), "set_mac_and_bssid failed, %d\n", r);
-               return r;
-       }
-
-       r = zd_chip_set_channel(&mac->chip, channel);
-       if (r < 0) {
-               dev_dbg_f(zd_mac_dev(mac), "zd_chip_set_channel failed, %d\n",
-                         r);
-               return r;
-       }
-
-       set_rts_cts(mac, short_preamble);
-
-       r = zd_chip_set_multicast_hash(&mac->chip, &multicast_hash);
-       if (r < 0) {
-               dev_dbg_f(zd_mac_dev(mac),
-                         "zd_chip_set_multicast_hash failed, %d\n", r);
-               return r;
-       }
-
-       if (mac->type == NL80211_IFTYPE_MESH_POINT ||
-           mac->type == NL80211_IFTYPE_ADHOC ||
-           mac->type == NL80211_IFTYPE_AP) {
-               if (mac->vif != NULL) {
-                       beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-                       if (beacon)
-                               zd_mac_config_beacon(mac->hw, beacon, false);
-               }
-
-               zd_set_beacon_interval(&mac->chip, beacon_interval,
-                                       beacon_period, mac->type);
-
-               spin_lock_irq(&mac->lock);
-               mac->beacon.last_update = jiffies;
-               spin_unlock_irq(&mac->lock);
-       }
-
-       return 0;
-}
-
-/**
- * zd_mac_tx_status - reports tx status of a packet if required
- * @hw - a &struct ieee80211_hw pointer
- * @skb - a sk-buffer
- * @flags: extra flags to set in the TX status info
- * @ackssi: ACK signal strength
- * @success - True for successful transmission of the frame
- *
- * This information calls ieee80211_tx_status_irqsafe() if required by the
- * control information. It copies the control information into the status
- * information.
- *
- * If no status information has been requested, the skb is freed.
- */
-static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
-                     int ackssi, struct tx_status *tx_status)
-{
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       int i;
-       int success = 1, retry = 1;
-       int first_idx;
-       const struct tx_retry_rate *retries;
-
-       ieee80211_tx_info_clear_status(info);
-
-       if (tx_status) {
-               success = !tx_status->failure;
-               retry = tx_status->retry + success;
-       }
-
-       if (success) {
-               /* success */
-               info->flags |= IEEE80211_TX_STAT_ACK;
-       } else {
-               /* failure */
-               info->flags &= ~IEEE80211_TX_STAT_ACK;
-       }
-
-       first_idx = info->status.rates[0].idx;
-       ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates));
-       retries = &zd_retry_rates[first_idx];
-       ZD_ASSERT(1 <= retry && retry <= retries->count);
-
-       info->status.rates[0].idx = retries->rate[0];
-       info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1);
-
-       for (i=1; i<IEEE80211_TX_MAX_RATES-1 && i<retry; i++) {
-               info->status.rates[i].idx = retries->rate[i];
-               info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2);
-       }
-       for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) {
-               info->status.rates[i].idx = retries->rate[retry - 1];
-               info->status.rates[i].count = 1; // (success ? 1:2);
-       }
-       if (i<IEEE80211_TX_MAX_RATES)
-               info->status.rates[i].idx = -1; /* terminate */
-
-       info->status.ack_signal = zd_check_signal(hw, ackssi);
-       ieee80211_tx_status_irqsafe(hw, skb);
-}
-
-/**
- * zd_mac_tx_failed - callback for failed frames
- * @dev: the mac80211 wireless device
- *
- * This function is called if a frame couldn't be successfully
- * transferred. The first frame from the tx queue, will be selected and
- * reported as error to the upper layers.
- */
-void zd_mac_tx_failed(struct urb *urb)
-{
-       struct ieee80211_hw * hw = zd_usb_to_hw(urb->context);
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct sk_buff_head *q = &mac->ack_wait_queue;
-       struct sk_buff *skb;
-       struct tx_status *tx_status = (struct tx_status *)urb->transfer_buffer;
-       unsigned long flags;
-       int success = !tx_status->failure;
-       int retry = tx_status->retry + success;
-       int found = 0;
-       int i, position = 0;
-
-       q = &mac->ack_wait_queue;
-       spin_lock_irqsave(&q->lock, flags);
-
-       skb_queue_walk(q, skb) {
-               struct ieee80211_hdr *tx_hdr;
-               struct ieee80211_tx_info *info;
-               int first_idx, final_idx;
-               const struct tx_retry_rate *retries;
-               u8 final_rate;
-
-               position ++;
-
-               /* if the hardware reports a failure and we had a 802.11 ACK
-                * pending, then we skip the first skb when searching for a
-                * matching frame */
-               if (tx_status->failure && mac->ack_pending &&
-                   skb_queue_is_first(q, skb)) {
-                       continue;
-               }
-
-               tx_hdr = (struct ieee80211_hdr *)skb->data;
-
-               /* we skip all frames not matching the reported destination */
-               if (unlikely(!ether_addr_equal(tx_hdr->addr1, tx_status->mac)))
-                       continue;
-
-               /* we skip all frames not matching the reported final rate */
-
-               info = IEEE80211_SKB_CB(skb);
-               first_idx = info->status.rates[0].idx;
-               ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates));
-               retries = &zd_retry_rates[first_idx];
-               if (retry <= 0 || retry > retries->count)
-                       continue;
-
-               final_idx = retries->rate[retry - 1];
-               final_rate = zd_rates[final_idx].hw_value;
-
-               if (final_rate != tx_status->rate) {
-                       continue;
-               }
-
-               found = 1;
-               break;
-       }
-
-       if (found) {
-               for (i=1; i<=position; i++) {
-                       skb = __skb_dequeue(q);
-                       zd_mac_tx_status(hw, skb,
-                                        mac->ack_pending ? mac->ack_signal : 0,
-                                        i == position ? tx_status : NULL);
-                       mac->ack_pending = 0;
-               }
-       }
-
-       spin_unlock_irqrestore(&q->lock, flags);
-}
-
-/**
- * zd_mac_tx_to_dev - callback for USB layer
- * @skb: a &sk_buff pointer
- * @error: error value, 0 if transmission successful
- *
- * Informs the MAC layer that the frame has successfully transferred to the
- * device. If an ACK is required and the transfer to the device has been
- * successful, the packets are put on the @ack_wait_queue with
- * the control set removed.
- */
-void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
-{
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_hw *hw = info->rate_driver_data[0];
-       struct zd_mac *mac = zd_hw_mac(hw);
-
-       ieee80211_tx_info_clear_status(info);
-
-       skb_pull(skb, sizeof(struct zd_ctrlset));
-       if (unlikely(error ||
-           (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
-               /*
-                * FIXME : do we need to fill in anything ?
-                */
-               ieee80211_tx_status_irqsafe(hw, skb);
-       } else {
-               struct sk_buff_head *q = &mac->ack_wait_queue;
-
-               skb_queue_tail(q, skb);
-               while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) {
-                       zd_mac_tx_status(hw, skb_dequeue(q),
-                                        mac->ack_pending ? mac->ack_signal : 0,
-                                        NULL);
-                       mac->ack_pending = 0;
-               }
-       }
-}
-
-static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
-{
-       /* ZD_PURE_RATE() must be used to remove the modulation type flag of
-        * the zd-rate values.
-        */
-       static const u8 rate_divisor[] = {
-               [ZD_PURE_RATE(ZD_CCK_RATE_1M)]   =  1,
-               [ZD_PURE_RATE(ZD_CCK_RATE_2M)]   =  2,
-               /* Bits must be doubled. */
-               [ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
-               [ZD_PURE_RATE(ZD_CCK_RATE_11M)]  = 11,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_6M)]  =  6,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_9M)]  =  9,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
-               [ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
-       };
-
-       u32 bits = (u32)tx_length * 8;
-       u32 divisor;
-
-       divisor = rate_divisor[ZD_PURE_RATE(zd_rate)];
-       if (divisor == 0)
-               return -EINVAL;
-
-       switch (zd_rate) {
-       case ZD_CCK_RATE_5_5M:
-               bits = (2*bits) + 10; /* round up to the next integer */
-               break;
-       case ZD_CCK_RATE_11M:
-               if (service) {
-                       u32 t = bits % 11;
-                       *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION;
-                       if (0 < t && t <= 3) {
-                               *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION;
-                       }
-               }
-               bits += 10; /* round up to the next integer */
-               break;
-       }
-
-       return bits/divisor;
-}
-
-static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
-                          struct ieee80211_hdr *header,
-                          struct ieee80211_tx_info *info)
-{
-       /*
-        * CONTROL TODO:
-        * - if backoff needed, enable bit 0
-        * - if burst (backoff not needed) disable bit 0
-        */
-
-       cs->control = 0;
-
-       /* First fragment */
-       if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
-               cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
-
-       /* No ACK expected (multicast, etc.) */
-       if (info->flags & IEEE80211_TX_CTL_NO_ACK)
-               cs->control |= ZD_CS_NO_ACK;
-
-       /* PS-POLL */
-       if (ieee80211_is_pspoll(header->frame_control))
-               cs->control |= ZD_CS_PS_POLL_FRAME;
-
-       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
-               cs->control |= ZD_CS_RTS;
-
-       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
-               cs->control |= ZD_CS_SELF_CTS;
-
-       /* FIXME: Management frame? */
-}
-
-static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
-{
-       if (!mac->beacon.cur_beacon)
-               return false;
-
-       if (mac->beacon.cur_beacon->len != beacon->len)
-               return false;
-
-       return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
-}
-
-static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
-{
-       ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
-
-       kfree_skb(mac->beacon.cur_beacon);
-       mac->beacon.cur_beacon = NULL;
-}
-
-static void zd_mac_free_cur_beacon(struct zd_mac *mac)
-{
-       mutex_lock(&mac->chip.mutex);
-       zd_mac_free_cur_beacon_locked(mac);
-       mutex_unlock(&mac->chip.mutex);
-}
-
-static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
-                               bool in_intr)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       int r, ret, num_cmds, req_pos = 0;
-       u32 tmp, j = 0;
-       /* 4 more bytes for tail CRC */
-       u32 full_len = beacon->len + 4;
-       unsigned long end_jiffies, message_jiffies;
-       struct zd_ioreq32 *ioreqs;
-
-       mutex_lock(&mac->chip.mutex);
-
-       /* Check if hw already has this beacon. */
-       if (zd_mac_match_cur_beacon(mac, beacon)) {
-               r = 0;
-               goto out_nofree;
-       }
-
-       /* Alloc memory for full beacon write at once. */
-       num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
-       ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
-       if (!ioreqs) {
-               r = -ENOMEM;
-               goto out_nofree;
-       }
-
-       r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
-       if (r < 0)
-               goto out;
-       r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
-       if (r < 0)
-               goto release_sema;
-       if (in_intr && tmp & 0x2) {
-               r = -EBUSY;
-               goto release_sema;
-       }
-
-       end_jiffies = jiffies + HZ / 2; /*~500ms*/
-       message_jiffies = jiffies + HZ / 10; /*~100ms*/
-       while (tmp & 0x2) {
-               r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
-               if (r < 0)
-                       goto release_sema;
-               if (time_is_before_eq_jiffies(message_jiffies)) {
-                       message_jiffies = jiffies + HZ / 10;
-                       dev_err(zd_mac_dev(mac),
-                                       "CR_BCN_FIFO_SEMAPHORE not ready\n");
-                       if (time_is_before_eq_jiffies(end_jiffies))  {
-                               dev_err(zd_mac_dev(mac),
-                                               "Giving up beacon config.\n");
-                               r = -ETIMEDOUT;
-                               goto reset_device;
-                       }
-               }
-               msleep(20);
-       }
-
-       ioreqs[req_pos].addr = CR_BCN_FIFO;
-       ioreqs[req_pos].value = full_len - 1;
-       req_pos++;
-       if (zd_chip_is_zd1211b(&mac->chip)) {
-               ioreqs[req_pos].addr = CR_BCN_LENGTH;
-               ioreqs[req_pos].value = full_len - 1;
-               req_pos++;
-       }
-
-       for (j = 0 ; j < beacon->len; j++) {
-               ioreqs[req_pos].addr = CR_BCN_FIFO;
-               ioreqs[req_pos].value = *((u8 *)(beacon->data + j));
-               req_pos++;
-       }
-
-       for (j = 0; j < 4; j++) {
-               ioreqs[req_pos].addr = CR_BCN_FIFO;
-               ioreqs[req_pos].value = 0x0;
-               req_pos++;
-       }
-
-       BUG_ON(req_pos != num_cmds);
-
-       r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);
-
-release_sema:
-       /*
-        * Try very hard to release device beacon semaphore, as otherwise
-        * device/driver can be left in unusable state.
-        */
-       end_jiffies = jiffies + HZ / 2; /*~500ms*/
-       ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
-       while (ret < 0) {
-               if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
-                       ret = -ETIMEDOUT;
-                       break;
-               }
-
-               msleep(20);
-               ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
-       }
-
-       if (ret < 0)
-               dev_err(zd_mac_dev(mac), "Could not release "
-                                        "CR_BCN_FIFO_SEMAPHORE!\n");
-       if (r < 0 || ret < 0) {
-               if (r >= 0)
-                       r = ret;
-
-               /* We don't know if beacon was written successfully or not,
-                * so clear current. */
-               zd_mac_free_cur_beacon_locked(mac);
-
-               goto out;
-       }
-
-       /* Beacon has now been written successfully, update current. */
-       zd_mac_free_cur_beacon_locked(mac);
-       mac->beacon.cur_beacon = beacon;
-       beacon = NULL;
-
-       /* 802.11b/g 2.4G CCK 1Mb
-        * 802.11a, not yet implemented, uses different values (see GPL vendor
-        * driver)
-        */
-       r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
-                               CR_BCN_PLCP_CFG);
-out:
-       kfree(ioreqs);
-out_nofree:
-       kfree_skb(beacon);
-       mutex_unlock(&mac->chip.mutex);
-
-       return r;
-
-reset_device:
-       zd_mac_free_cur_beacon_locked(mac);
-       kfree_skb(beacon);
-
-       mutex_unlock(&mac->chip.mutex);
-       kfree(ioreqs);
-
-       /* semaphore stuck, reset device to avoid fw freeze later */
-       dev_warn(zd_mac_dev(mac), "CR_BCN_FIFO_SEMAPHORE stuck, "
-                                 "resetting device...");
-       usb_queue_reset_device(mac->chip.usb.intf);
-
-       return r;
-}
-
-static int fill_ctrlset(struct zd_mac *mac,
-                       struct sk_buff *skb)
-{
-       int r;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       unsigned int frag_len = skb->len + FCS_LEN;
-       unsigned int packet_length;
-       struct ieee80211_rate *txrate;
-       struct zd_ctrlset *cs = (struct zd_ctrlset *)
-               skb_push(skb, sizeof(struct zd_ctrlset));
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-       ZD_ASSERT(frag_len <= 0xffff);
-
-       /*
-        * Firmware computes the duration itself (for all frames except PSPoll)
-        * and needs the field set to 0 at input, otherwise firmware messes up
-        * duration_id and sets bits 14 and 15 on.
-        */
-       if (!ieee80211_is_pspoll(hdr->frame_control))
-               hdr->duration_id = 0;
-
-       txrate = ieee80211_get_tx_rate(mac->hw, info);
-
-       cs->modulation = txrate->hw_value;
-       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-               cs->modulation = txrate->hw_value_short;
-
-       cs->tx_length = cpu_to_le16(frag_len);
-
-       cs_set_control(mac, cs, hdr, info);
-
-       packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
-       ZD_ASSERT(packet_length <= 0xffff);
-       /* ZD1211B: Computing the length difference this way, gives us
-        * flexibility to compute the packet length.
-        */
-       cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
-                       packet_length - frag_len : packet_length);
-
-       /*
-        * CURRENT LENGTH:
-        * - transmit frame length in microseconds
-        * - seems to be derived from frame length
-        * - see Cal_Us_Service() in zdinlinef.h
-        * - if macp->bTxBurstEnable is enabled, then multiply by 4
-        *  - bTxBurstEnable is never set in the vendor driver
-        *
-        * SERVICE:
-        * - "for PLCP configuration"
-        * - always 0 except in some situations at 802.11b 11M
-        * - see line 53 of zdinlinef.h
-        */
-       cs->service = 0;
-       r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation),
-                                le16_to_cpu(cs->tx_length));
-       if (r < 0)
-               return r;
-       cs->current_length = cpu_to_le16(r);
-       cs->next_frame_length = 0;
-
-       return 0;
-}
-
-/**
- * zd_op_tx - transmits a network frame to the device
- *
- * @dev: mac80211 hardware device
- * @skb: socket buffer
- * @control: the control structure
- *
- * This function transmit an IEEE 802.11 network frame to the device. The
- * control block of the skbuff will be initialized. If necessary the incoming
- * mac80211 queues will be stopped.
- */
-static void zd_op_tx(struct ieee80211_hw *hw,
-                    struct ieee80211_tx_control *control,
-                    struct sk_buff *skb)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       int r;
-
-       r = fill_ctrlset(mac, skb);
-       if (r)
-               goto fail;
-
-       info->rate_driver_data[0] = hw;
-
-       r = zd_usb_tx(&mac->chip.usb, skb);
-       if (r)
-               goto fail;
-       return;
-
-fail:
-       dev_kfree_skb(skb);
-}
-
-/**
- * filter_ack - filters incoming packets for acknowledgements
- * @dev: the mac80211 device
- * @rx_hdr: received header
- * @stats: the status for the received packet
- *
- * This functions looks for ACK packets and tries to match them with the
- * frames in the tx queue. If a match is found the frame will be dequeued and
- * the upper layers is informed about the successful transmission. If
- * mac80211 queues have been stopped and the number of frames still to be
- * transmitted is low the queues will be opened again.
- *
- * Returns 1 if the frame was an ACK, 0 if it was ignored.
- */
-static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
-                     struct ieee80211_rx_status *stats)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct sk_buff *skb;
-       struct sk_buff_head *q;
-       unsigned long flags;
-       int found = 0;
-       int i, position = 0;
-
-       if (!ieee80211_is_ack(rx_hdr->frame_control))
-               return 0;
-
-       q = &mac->ack_wait_queue;
-       spin_lock_irqsave(&q->lock, flags);
-       skb_queue_walk(q, skb) {
-               struct ieee80211_hdr *tx_hdr;
-
-               position ++;
-
-               if (mac->ack_pending && skb_queue_is_first(q, skb))
-                   continue;
-
-               tx_hdr = (struct ieee80211_hdr *)skb->data;
-               if (likely(ether_addr_equal(tx_hdr->addr2, rx_hdr->addr1)))
-               {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (found) {
-               for (i=1; i<position; i++) {
-                       skb = __skb_dequeue(q);
-                       zd_mac_tx_status(hw, skb,
-                                        mac->ack_pending ? mac->ack_signal : 0,
-                                        NULL);
-                       mac->ack_pending = 0;
-               }
-
-               mac->ack_pending = 1;
-               mac->ack_signal = stats->signal;
-
-               /* Prevent pending tx-packet on AP-mode */
-               if (mac->type == NL80211_IFTYPE_AP) {
-                       skb = __skb_dequeue(q);
-                       zd_mac_tx_status(hw, skb, mac->ack_signal, NULL);
-                       mac->ack_pending = 0;
-               }
-       }
-
-       spin_unlock_irqrestore(&q->lock, flags);
-       return 1;
-}
-
-int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct ieee80211_rx_status stats;
-       const struct rx_status *status;
-       struct sk_buff *skb;
-       int bad_frame = 0;
-       __le16 fc;
-       int need_padding;
-       int i;
-       u8 rate;
-
-       if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
-                    FCS_LEN + sizeof(struct rx_status))
-               return -EINVAL;
-
-       memset(&stats, 0, sizeof(stats));
-
-       /* Note about pass_failed_fcs and pass_ctrl access below:
-        * mac locking intentionally omitted here, as this is the only unlocked
-        * reader and the only writer is configure_filter. Plus, if there were
-        * any races accessing these variables, it wouldn't really matter.
-        * If mac80211 ever provides a way for us to access filter flags
-        * from outside configure_filter, we could improve on this. Also, this
-        * situation may change once we implement some kind of DMA-into-skb
-        * RX path. */
-
-       /* Caller has to ensure that length >= sizeof(struct rx_status). */
-       status = (struct rx_status *)
-               (buffer + (length - sizeof(struct rx_status)));
-       if (status->frame_status & ZD_RX_ERROR) {
-               if (mac->pass_failed_fcs &&
-                               (status->frame_status & ZD_RX_CRC32_ERROR)) {
-                       stats.flag |= RX_FLAG_FAILED_FCS_CRC;
-                       bad_frame = 1;
-               } else {
-                       return -EINVAL;
-               }
-       }
-
-       stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
-       stats.band = IEEE80211_BAND_2GHZ;
-       stats.signal = zd_check_signal(hw, status->signal_strength);
-
-       rate = zd_rx_rate(buffer, status);
-
-       /* todo: return index in the big switches in zd_rx_rate instead */
-       for (i = 0; i < mac->band.n_bitrates; i++)
-               if (rate == mac->band.bitrates[i].hw_value)
-                       stats.rate_idx = i;
-
-       length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
-       buffer += ZD_PLCP_HEADER_SIZE;
-
-       /* Except for bad frames, filter each frame to see if it is an ACK, in
-        * which case our internal TX tracking is updated. Normally we then
-        * bail here as there's no need to pass ACKs on up to the stack, but
-        * there is also the case where the stack has requested us to pass
-        * control frames on up (pass_ctrl) which we must consider. */
-       if (!bad_frame &&
-                       filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
-                       && !mac->pass_ctrl)
-               return 0;
-
-       fc = get_unaligned((__le16*)buffer);
-       need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
-
-       skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
-       if (skb == NULL)
-               return -ENOMEM;
-       if (need_padding) {
-               /* Make sure the payload data is 4 byte aligned. */
-               skb_reserve(skb, 2);
-       }
-
-       /* FIXME : could we avoid this big memcpy ? */
-       memcpy(skb_put(skb, length), buffer, length);
-
-       memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
-       ieee80211_rx_irqsafe(hw, skb);
-       return 0;
-}
-
-static int zd_op_add_interface(struct ieee80211_hw *hw,
-                               struct ieee80211_vif *vif)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-
-       /* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */
-       if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
-               return -EOPNOTSUPP;
-
-       switch (vif->type) {
-       case NL80211_IFTYPE_MONITOR:
-       case NL80211_IFTYPE_MESH_POINT:
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_ADHOC:
-       case NL80211_IFTYPE_AP:
-               mac->type = vif->type;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       mac->vif = vif;
-
-       return set_mac_and_bssid(mac);
-}
-
-static void zd_op_remove_interface(struct ieee80211_hw *hw,
-                                   struct ieee80211_vif *vif)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       mac->type = NL80211_IFTYPE_UNSPECIFIED;
-       mac->vif = NULL;
-       zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
-       zd_write_mac_addr(&mac->chip, NULL);
-
-       zd_mac_free_cur_beacon(mac);
-}
-
-static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct ieee80211_conf *conf = &hw->conf;
-
-       spin_lock_irq(&mac->lock);
-       mac->channel = conf->chandef.chan->hw_value;
-       spin_unlock_irq(&mac->lock);
-
-       return zd_chip_set_channel(&mac->chip, conf->chandef.chan->hw_value);
-}
-
-static void zd_beacon_done(struct zd_mac *mac)
-{
-       struct sk_buff *skb, *beacon;
-
-       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
-               return;
-       if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP)
-               return;
-
-       /*
-        * Send out buffered broad- and multicast frames.
-        */
-       while (!ieee80211_queue_stopped(mac->hw, 0)) {
-               skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
-               if (!skb)
-                       break;
-               zd_op_tx(mac->hw, NULL, skb);
-       }
-
-       /*
-        * Fetch next beacon so that tim_count is updated.
-        */
-       beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-       if (beacon)
-               zd_mac_config_beacon(mac->hw, beacon, true);
-
-       spin_lock_irq(&mac->lock);
-       mac->beacon.last_update = jiffies;
-       spin_unlock_irq(&mac->lock);
-}
-
-static void zd_process_intr(struct work_struct *work)
-{
-       u16 int_status;
-       unsigned long flags;
-       struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
-
-       spin_lock_irqsave(&mac->lock, flags);
-       int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4));
-       spin_unlock_irqrestore(&mac->lock, flags);
-
-       if (int_status & INT_CFG_NEXT_BCN) {
-               /*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/
-               zd_beacon_done(mac);
-       } else {
-               dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
-       }
-
-       zd_chip_enable_hwint(&mac->chip);
-}
-
-
-static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
-                                  struct netdev_hw_addr_list *mc_list)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       struct zd_mc_hash hash;
-       struct netdev_hw_addr *ha;
-
-       zd_mc_clear(&hash);
-
-       netdev_hw_addr_list_for_each(ha, mc_list) {
-               dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", ha->addr);
-               zd_mc_add_addr(&hash, ha->addr);
-       }
-
-       return hash.low | ((u64)hash.high << 32);
-}
-
-#define SUPPORTED_FIF_FLAGS \
-       (FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
-       FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
-static void zd_op_configure_filter(struct ieee80211_hw *hw,
-                       unsigned int changed_flags,
-                       unsigned int *new_flags,
-                       u64 multicast)
-{
-       struct zd_mc_hash hash = {
-               .low = multicast,
-               .high = multicast >> 32,
-       };
-       struct zd_mac *mac = zd_hw_mac(hw);
-       unsigned long flags;
-       int r;
-
-       /* Only deal with supported flags */
-       changed_flags &= SUPPORTED_FIF_FLAGS;
-       *new_flags &= SUPPORTED_FIF_FLAGS;
-
-       /*
-        * If multicast parameter (as returned by zd_op_prepare_multicast)
-        * has changed, no bit in changed_flags is set. To handle this
-        * situation, we do not return if changed_flags is 0. If we do so,
-        * we will have some issue with IPv6 which uses multicast for link
-        * layer address resolution.
-        */
-       if (*new_flags & FIF_ALLMULTI)
-               zd_mc_add_all(&hash);
-
-       spin_lock_irqsave(&mac->lock, flags);
-       mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
-       mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
-       mac->multicast_hash = hash;
-       spin_unlock_irqrestore(&mac->lock, flags);
-
-       zd_chip_set_multicast_hash(&mac->chip, &hash);
-
-       if (changed_flags & FIF_CONTROL) {
-               r = set_rx_filter(mac);
-               if (r)
-                       dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r);
-       }
-
-       /* no handling required for FIF_OTHER_BSS as we don't currently
-        * do BSSID filtering */
-       /* FIXME: in future it would be nice to enable the probe response
-        * filter (so that the driver doesn't see them) until
-        * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd
-        * have to schedule work to enable prbresp reception, which might
-        * happen too late. For now we'll just listen and forward them all the
-        * time. */
-}
-
-static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble)
-{
-       mutex_lock(&mac->chip.mutex);
-       zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
-       mutex_unlock(&mac->chip.mutex);
-}
-
-static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
-                                  struct ieee80211_vif *vif,
-                                  struct ieee80211_bss_conf *bss_conf,
-                                  u32 changes)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       int associated;
-
-       dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
-
-       if (mac->type == NL80211_IFTYPE_MESH_POINT ||
-           mac->type == NL80211_IFTYPE_ADHOC ||
-           mac->type == NL80211_IFTYPE_AP) {
-               associated = true;
-               if (changes & BSS_CHANGED_BEACON) {
-                       struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
-
-                       if (beacon) {
-                               zd_chip_disable_hwint(&mac->chip);
-                               zd_mac_config_beacon(hw, beacon, false);
-                               zd_chip_enable_hwint(&mac->chip);
-                       }
-               }
-
-               if (changes & BSS_CHANGED_BEACON_ENABLED) {
-                       u16 interval = 0;
-                       u8 period = 0;
-
-                       if (bss_conf->enable_beacon) {
-                               period = bss_conf->dtim_period;
-                               interval = bss_conf->beacon_int;
-                       }
-
-                       spin_lock_irq(&mac->lock);
-                       mac->beacon.period = period;
-                       mac->beacon.interval = interval;
-                       mac->beacon.last_update = jiffies;
-                       spin_unlock_irq(&mac->lock);
-
-                       zd_set_beacon_interval(&mac->chip, interval, period,
-                                              mac->type);
-               }
-       } else
-               associated = is_valid_ether_addr(bss_conf->bssid);
-
-       spin_lock_irq(&mac->lock);
-       mac->associated = associated;
-       spin_unlock_irq(&mac->lock);
-
-       /* TODO: do hardware bssid filtering */
-
-       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-               spin_lock_irq(&mac->lock);
-               mac->short_preamble = bss_conf->use_short_preamble;
-               spin_unlock_irq(&mac->lock);
-
-               set_rts_cts(mac, bss_conf->use_short_preamble);
-       }
-}
-
-static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       return zd_chip_get_tsf(&mac->chip);
-}
-
-static const struct ieee80211_ops zd_ops = {
-       .tx                     = zd_op_tx,
-       .start                  = zd_op_start,
-       .stop                   = zd_op_stop,
-       .add_interface          = zd_op_add_interface,
-       .remove_interface       = zd_op_remove_interface,
-       .config                 = zd_op_config,
-       .prepare_multicast      = zd_op_prepare_multicast,
-       .configure_filter       = zd_op_configure_filter,
-       .bss_info_changed       = zd_op_bss_info_changed,
-       .get_tsf                = zd_op_get_tsf,
-};
-
-struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
-{
-       struct zd_mac *mac;
-       struct ieee80211_hw *hw;
-
-       hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
-       if (!hw) {
-               dev_dbg_f(&intf->dev, "out of memory\n");
-               return NULL;
-       }
-
-       mac = zd_hw_mac(hw);
-
-       memset(mac, 0, sizeof(*mac));
-       spin_lock_init(&mac->lock);
-       mac->hw = hw;
-
-       mac->type = NL80211_IFTYPE_UNSPECIFIED;
-
-       memcpy(mac->channels, zd_channels, sizeof(zd_channels));
-       memcpy(mac->rates, zd_rates, sizeof(zd_rates));
-       mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
-       mac->band.bitrates = mac->rates;
-       mac->band.n_channels = ARRAY_SIZE(zd_channels);
-       mac->band.channels = mac->channels;
-
-       hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
-
-       ieee80211_hw_set(hw, MFP_CAPABLE);
-       ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
-       ieee80211_hw_set(hw, RX_INCLUDES_FCS);
-       ieee80211_hw_set(hw, SIGNAL_UNSPEC);
-
-       hw->wiphy->interface_modes =
-               BIT(NL80211_IFTYPE_MESH_POINT) |
-               BIT(NL80211_IFTYPE_STATION) |
-               BIT(NL80211_IFTYPE_ADHOC) |
-               BIT(NL80211_IFTYPE_AP);
-
-       hw->max_signal = 100;
-       hw->queues = 1;
-       hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
-
-       /*
-        * Tell mac80211 that we support multi rate retries
-        */
-       hw->max_rates = IEEE80211_TX_MAX_RATES;
-       hw->max_rate_tries = 18;        /* 9 rates * 2 retries/rate */
-
-       skb_queue_head_init(&mac->ack_wait_queue);
-       mac->ack_pending = 0;
-
-       zd_chip_init(&mac->chip, hw, intf);
-       housekeeping_init(mac);
-       beacon_init(mac);
-       INIT_WORK(&mac->process_intr, zd_process_intr);
-
-       SET_IEEE80211_DEV(hw, &intf->dev);
-       return hw;
-}
-
-#define BEACON_WATCHDOG_DELAY round_jiffies_relative(HZ)
-
-static void beacon_watchdog_handler(struct work_struct *work)
-{
-       struct zd_mac *mac =
-               container_of(work, struct zd_mac, beacon.watchdog_work.work);
-       struct sk_buff *beacon;
-       unsigned long timeout;
-       int interval, period;
-
-       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
-               goto rearm;
-       if (mac->type != NL80211_IFTYPE_AP || !mac->vif)
-               goto rearm;
-
-       spin_lock_irq(&mac->lock);
-       interval = mac->beacon.interval;
-       period = mac->beacon.period;
-       timeout = mac->beacon.last_update +
-                       msecs_to_jiffies(interval * 1024 / 1000) * 3;
-       spin_unlock_irq(&mac->lock);
-
-       if (interval > 0 && time_is_before_jiffies(timeout)) {
-               dev_dbg_f(zd_mac_dev(mac), "beacon interrupt stalled, "
-                                          "restarting. "
-                                          "(interval: %d, dtim: %d)\n",
-                                          interval, period);
-
-               zd_chip_disable_hwint(&mac->chip);
-
-               beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-               if (beacon) {
-                       zd_mac_free_cur_beacon(mac);
-
-                       zd_mac_config_beacon(mac->hw, beacon, false);
-               }
-
-               zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
-
-               zd_chip_enable_hwint(&mac->chip);
-
-               spin_lock_irq(&mac->lock);
-               mac->beacon.last_update = jiffies;
-               spin_unlock_irq(&mac->lock);
-       }
-
-rearm:
-       queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
-                          BEACON_WATCHDOG_DELAY);
-}
-
-static void beacon_init(struct zd_mac *mac)
-{
-       INIT_DELAYED_WORK(&mac->beacon.watchdog_work, beacon_watchdog_handler);
-}
-
-static void beacon_enable(struct zd_mac *mac)
-{
-       dev_dbg_f(zd_mac_dev(mac), "\n");
-
-       mac->beacon.last_update = jiffies;
-       queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
-                          BEACON_WATCHDOG_DELAY);
-}
-
-static void beacon_disable(struct zd_mac *mac)
-{
-       dev_dbg_f(zd_mac_dev(mac), "\n");
-       cancel_delayed_work_sync(&mac->beacon.watchdog_work);
-
-       zd_mac_free_cur_beacon(mac);
-}
-
-#define LINK_LED_WORK_DELAY HZ
-
-static void link_led_handler(struct work_struct *work)
-{
-       struct zd_mac *mac =
-               container_of(work, struct zd_mac, housekeeping.link_led_work.work);
-       struct zd_chip *chip = &mac->chip;
-       int is_associated;
-       int r;
-
-       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
-               goto requeue;
-
-       spin_lock_irq(&mac->lock);
-       is_associated = mac->associated;
-       spin_unlock_irq(&mac->lock);
-
-       r = zd_chip_control_leds(chip,
-                                is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
-       if (r)
-               dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
-
-requeue:
-       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
-                          LINK_LED_WORK_DELAY);
-}
-
-static void housekeeping_init(struct zd_mac *mac)
-{
-       INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler);
-}
-
-static void housekeeping_enable(struct zd_mac *mac)
-{
-       dev_dbg_f(zd_mac_dev(mac), "\n");
-       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
-                          0);
-}
-
-static void housekeeping_disable(struct zd_mac *mac)
-{
-       dev_dbg_f(zd_mac_dev(mac), "\n");
-       cancel_delayed_work_sync(&mac->housekeeping.link_led_work);
-       zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
deleted file mode 100644 (file)
index 5a48423..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ZD_MAC_H
-#define _ZD_MAC_H
-
-#include <linux/kernel.h>
-#include <net/mac80211.h>
-
-#include "zd_chip.h"
-
-struct zd_ctrlset {
-       u8     modulation;
-       __le16 tx_length;
-       u8     control;
-       /* stores only the difference to tx_length on ZD1211B */
-       __le16 packet_length;
-       __le16 current_length;
-       u8     service;
-       __le16  next_frame_length;
-} __packed;
-
-#define ZD_CS_RESERVED_SIZE    25
-
-/* The field modulation of struct zd_ctrlset controls the bit rate, the use
- * of short or long preambles in 802.11b (CCK mode) or the use of 802.11a or
- * 802.11g in OFDM mode.
- *
- * The term zd-rate is used for the combination of the modulation type flag
- * and the "pure" rate value.
- */
-#define ZD_PURE_RATE_MASK       0x0f
-#define ZD_MODULATION_TYPE_MASK 0x10
-#define ZD_RATE_MASK            (ZD_PURE_RATE_MASK|ZD_MODULATION_TYPE_MASK)
-#define ZD_PURE_RATE(modulation) ((modulation) & ZD_PURE_RATE_MASK)
-#define ZD_MODULATION_TYPE(modulation) ((modulation) & ZD_MODULATION_TYPE_MASK)
-#define ZD_RATE(modulation) ((modulation) & ZD_RATE_MASK)
-
-/* The two possible modulation types. Notify that 802.11b doesn't use the CCK
- * codeing for the 1 and 2 MBit/s rate. We stay with the term here to remain
- * consistent with uses the term at other places.
- */
-#define ZD_CCK                  0x00
-#define ZD_OFDM                 0x10
-
-/* The ZD1211 firmware uses proprietary encodings of the 802.11b (CCK) rates.
- * For OFDM the PLCP rate encodings are used. We combine these "pure" rates
- * with the modulation type flag and call the resulting values zd-rates.
- */
-#define ZD_CCK_RATE_1M          (ZD_CCK|0x00)
-#define ZD_CCK_RATE_2M          (ZD_CCK|0x01)
-#define ZD_CCK_RATE_5_5M        (ZD_CCK|0x02)
-#define ZD_CCK_RATE_11M         (ZD_CCK|0x03)
-#define ZD_OFDM_RATE_6M         (ZD_OFDM|ZD_OFDM_PLCP_RATE_6M)
-#define ZD_OFDM_RATE_9M         (ZD_OFDM|ZD_OFDM_PLCP_RATE_9M)
-#define ZD_OFDM_RATE_12M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_12M)
-#define ZD_OFDM_RATE_18M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_18M)
-#define ZD_OFDM_RATE_24M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_24M)
-#define ZD_OFDM_RATE_36M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_36M)
-#define ZD_OFDM_RATE_48M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_48M)
-#define ZD_OFDM_RATE_54M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_54M)
-
-/* The bit 5 of the zd_ctrlset modulation field controls the preamble in CCK
- * mode or the 802.11a/802.11g selection in OFDM mode.
- */
-#define ZD_CCK_PREA_LONG        0x00
-#define ZD_CCK_PREA_SHORT       0x20
-#define ZD_OFDM_MODE_11G        0x00
-#define ZD_OFDM_MODE_11A        0x20
-
-/* zd_ctrlset control field */
-#define ZD_CS_NEED_RANDOM_BACKOFF      0x01
-#define ZD_CS_NO_ACK                   0x02
-
-#define ZD_CS_FRAME_TYPE_MASK          0x0c
-#define ZD_CS_DATA_FRAME               0x00
-#define ZD_CS_PS_POLL_FRAME            0x04
-#define ZD_CS_MANAGEMENT_FRAME         0x08
-#define ZD_CS_NO_SEQUENCE_CTL_FRAME    0x0c
-
-#define ZD_CS_WAKE_DESTINATION         0x10
-#define ZD_CS_RTS                      0x20
-#define ZD_CS_ENCRYPT                  0x40
-#define ZD_CS_SELF_CTS                 0x80
-
-/* Incoming frames are prepended by a PLCP header */
-#define ZD_PLCP_HEADER_SIZE            5
-
-struct rx_length_info {
-       __le16 length[3];
-       __le16 tag;
-} __packed;
-
-#define RX_LENGTH_INFO_TAG             0x697e
-
-struct rx_status {
-       u8 signal_quality_cck;
-       /* rssi */
-       u8 signal_strength;
-       u8 signal_quality_ofdm;
-       u8 decryption_type;
-       u8 frame_status;
-} __packed;
-
-/* rx_status field decryption_type */
-#define ZD_RX_NO_WEP   0
-#define ZD_RX_WEP64    1
-#define ZD_RX_TKIP     2
-#define ZD_RX_AES      4
-#define ZD_RX_WEP128   5
-#define ZD_RX_WEP256   6
-
-/* rx_status field frame_status */
-#define ZD_RX_FRAME_MODULATION_MASK    0x01
-#define ZD_RX_CCK                      0x00
-#define ZD_RX_OFDM                     0x01
-
-#define ZD_RX_TIMEOUT_ERROR            0x02
-#define ZD_RX_FIFO_OVERRUN_ERROR       0x04
-#define ZD_RX_DECRYPTION_ERROR         0x08
-#define ZD_RX_CRC32_ERROR              0x10
-#define ZD_RX_NO_ADDR1_MATCH_ERROR     0x20
-#define ZD_RX_CRC16_ERROR              0x40
-#define ZD_RX_ERROR                    0x80
-
-struct tx_retry_rate {
-       int count;      /* number of valid element in rate[] array */
-       int rate[10];   /* retry rates, described by an index in zd_rates[] */
-};
-
-struct tx_status {
-       u8 type;        /* must always be 0x01 : USB_INT_TYPE */
-       u8 id;          /* must always be 0xa0 : USB_INT_ID_RETRY_FAILED */
-       u8 rate;
-       u8 pad;
-       u8 mac[ETH_ALEN];
-       u8 retry;
-       u8 failure;
-} __packed;
-
-enum mac_flags {
-       MAC_FIXED_CHANNEL = 0x01,
-};
-
-struct housekeeping {
-       struct delayed_work link_led_work;
-};
-
-struct beacon {
-       struct delayed_work watchdog_work;
-       struct sk_buff *cur_beacon;
-       unsigned long last_update;
-       u16 interval;
-       u8 period;
-};
-
-enum zd_device_flags {
-       ZD_DEVICE_RUNNING,
-};
-
-#define ZD_MAC_STATS_BUFFER_SIZE 16
-
-#define ZD_MAC_MAX_ACK_WAITERS 50
-
-struct zd_mac {
-       struct zd_chip chip;
-       spinlock_t lock;
-       spinlock_t intr_lock;
-       struct ieee80211_hw *hw;
-       struct ieee80211_vif *vif;
-       struct housekeeping housekeeping;
-       struct beacon beacon;
-       struct work_struct set_rts_cts_work;
-       struct work_struct process_intr;
-       struct zd_mc_hash multicast_hash;
-       u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
-       u8 regdomain;
-       u8 default_regdomain;
-       u8 channel;
-       int type;
-       int associated;
-       unsigned long flags;
-       struct sk_buff_head ack_wait_queue;
-       struct ieee80211_channel channels[14];
-       struct ieee80211_rate rates[12];
-       struct ieee80211_supported_band band;
-
-       /* Short preamble (used for RTS/CTS) */
-       unsigned int short_preamble:1;
-
-       /* whether to pass frames with CRC errors to stack */
-       unsigned int pass_failed_fcs:1;
-
-       /* whether to pass control frames to stack */
-       unsigned int pass_ctrl:1;
-
-       /* whether we have received a 802.11 ACK that is pending */
-       unsigned int ack_pending:1;
-
-       /* signal strength of the last 802.11 ACK received */
-       int ack_signal;
-};
-
-#define ZD_REGDOMAIN_FCC       0x10
-#define ZD_REGDOMAIN_IC                0x20
-#define ZD_REGDOMAIN_ETSI      0x30
-#define ZD_REGDOMAIN_SPAIN     0x31
-#define ZD_REGDOMAIN_FRANCE    0x32
-#define ZD_REGDOMAIN_JAPAN_2   0x40
-#define ZD_REGDOMAIN_JAPAN     0x41
-#define ZD_REGDOMAIN_JAPAN_3   0x49
-
-enum {
-       MIN_CHANNEL24 = 1,
-       MAX_CHANNEL24 = 14,
-};
-
-#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
-
-struct ofdm_plcp_header {
-       u8 prefix[3];
-       __le16 service;
-} __packed;
-
-static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
-{
-       return header->prefix[0] & 0xf;
-}
-
-/* The following defines give the encoding of the 4-bit rate field in the
- * OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to
- * define the zd-rate values for OFDM.
- *
- * See the struct zd_ctrlset definition in zd_mac.h.
- */
-#define ZD_OFDM_PLCP_RATE_6M   0xb
-#define ZD_OFDM_PLCP_RATE_9M   0xf
-#define ZD_OFDM_PLCP_RATE_12M  0xa
-#define ZD_OFDM_PLCP_RATE_18M  0xe
-#define ZD_OFDM_PLCP_RATE_24M  0x9
-#define ZD_OFDM_PLCP_RATE_36M  0xd
-#define ZD_OFDM_PLCP_RATE_48M  0x8
-#define ZD_OFDM_PLCP_RATE_54M  0xc
-
-struct cck_plcp_header {
-       u8 signal;
-       u8 service;
-       __le16 length;
-       __le16 crc16;
-} __packed;
-
-static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
-{
-       return header->signal;
-}
-
-/* These defines give the encodings of the signal field in the 802.11b PLCP
- * header. The signal field gives the bit rate of the following packet. Even
- * if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s
- * rate to stay consistent with Zydas and our use of the term.
- *
- * Notify that these values are *not* used in the zd-rates.
- */
-#define ZD_CCK_PLCP_SIGNAL_1M  0x0a
-#define ZD_CCK_PLCP_SIGNAL_2M  0x14
-#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
-#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
-
-static inline struct zd_mac *zd_hw_mac(struct ieee80211_hw *hw)
-{
-       return hw->priv;
-}
-
-static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip)
-{
-       return container_of(chip, struct zd_mac, chip);
-}
-
-static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb)
-{
-       return zd_chip_to_mac(zd_usb_to_chip(usb));
-}
-
-static inline u8 *zd_mac_get_perm_addr(struct zd_mac *mac)
-{
-       return mac->hw->wiphy->perm_addr;
-}
-
-#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip))
-
-struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf);
-void zd_mac_clear(struct zd_mac *mac);
-
-int zd_mac_preinit_hw(struct ieee80211_hw *hw);
-int zd_mac_init_hw(struct ieee80211_hw *hw);
-
-int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length);
-void zd_mac_tx_failed(struct urb *urb);
-void zd_mac_tx_to_dev(struct sk_buff *skb, int error);
-
-int zd_op_start(struct ieee80211_hw *hw);
-void zd_op_stop(struct ieee80211_hw *hw);
-int zd_restore_settings(struct zd_mac *mac);
-
-#ifdef DEBUG
-void zd_dump_rx_status(const struct rx_status *status);
-#else
-#define zd_dump_rx_status(status)
-#endif /* DEBUG */
-
-#endif /* _ZD_MAC_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
deleted file mode 100644 (file)
index dc179c4..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include "zd_def.h"
-#include "zd_rf.h"
-#include "zd_mac.h"
-#include "zd_chip.h"
-
-static const char * const rfs[] = {
-       [0]             = "unknown RF0",
-       [1]             = "unknown RF1",
-       [UW2451_RF]     = "UW2451_RF",
-       [UCHIP_RF]      = "UCHIP_RF",
-       [AL2230_RF]     = "AL2230_RF",
-       [AL7230B_RF]    = "AL7230B_RF",
-       [THETA_RF]      = "THETA_RF",
-       [AL2210_RF]     = "AL2210_RF",
-       [MAXIM_NEW_RF]  = "MAXIM_NEW_RF",
-       [UW2453_RF]     = "UW2453_RF",
-       [AL2230S_RF]    = "AL2230S_RF",
-       [RALINK_RF]     = "RALINK_RF",
-       [INTERSIL_RF]   = "INTERSIL_RF",
-       [RF2959_RF]     = "RF2959_RF",
-       [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF",
-       [PHILIPS_RF]    = "PHILIPS_RF",
-};
-
-const char *zd_rf_name(u8 type)
-{
-       if (type & 0xf0)
-               type = 0;
-       return rfs[type];
-}
-
-void zd_rf_init(struct zd_rf *rf)
-{
-       memset(rf, 0, sizeof(*rf));
-
-       /* default to update channel integration, as almost all RF's do want
-        * this */
-       rf->update_channel_int = 1;
-}
-
-void zd_rf_clear(struct zd_rf *rf)
-{
-       if (rf->clear)
-               rf->clear(rf);
-       ZD_MEMCLEAR(rf, sizeof(*rf));
-}
-
-int zd_rf_init_hw(struct zd_rf *rf, u8 type)
-{
-       int r = 0;
-       int t;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       switch (type) {
-       case RF2959_RF:
-               r = zd_rf_init_rf2959(rf);
-               break;
-       case AL2230_RF:
-       case AL2230S_RF:
-               r = zd_rf_init_al2230(rf);
-               break;
-       case AL7230B_RF:
-               r = zd_rf_init_al7230b(rf);
-               break;
-       case MAXIM_NEW_RF:
-       case UW2453_RF:
-               r = zd_rf_init_uw2453(rf);
-               break;
-       default:
-               dev_err(zd_chip_dev(chip),
-                       "RF %s %#x is not supported\n", zd_rf_name(type), type);
-               rf->type = 0;
-               return -ENODEV;
-       }
-
-       if (r)
-               return r;
-
-       rf->type = type;
-
-       r = zd_chip_lock_phy_regs(chip);
-       if (r)
-               return r;
-       t = rf->init_hw(rf);
-       r = zd_chip_unlock_phy_regs(chip);
-       if (t)
-               r = t;
-       return r;
-}
-
-int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size)
-{
-       return scnprintf(buffer, size, "%s", zd_rf_name(rf->type));
-}
-
-int zd_rf_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int r;
-
-       ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex));
-       if (channel < MIN_CHANNEL24)
-               return -EINVAL;
-       if (channel > MAX_CHANNEL24)
-               return -EINVAL;
-       dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel);
-
-       r = rf->set_channel(rf, channel);
-       if (r >= 0)
-               rf->channel = channel;
-       return r;
-}
-
-int zd_switch_radio_on(struct zd_rf *rf)
-{
-       int r, t;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_chip_lock_phy_regs(chip);
-       if (r)
-               return r;
-       t = rf->switch_radio_on(rf);
-       r = zd_chip_unlock_phy_regs(chip);
-       if (t)
-               r = t;
-       return r;
-}
-
-int zd_switch_radio_off(struct zd_rf *rf)
-{
-       int r, t;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       /* TODO: move phy regs handling to zd_chip */
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       r = zd_chip_lock_phy_regs(chip);
-       if (r)
-               return r;
-       t = rf->switch_radio_off(rf);
-       r = zd_chip_unlock_phy_regs(chip);
-       if (t)
-               r = t;
-       return r;
-}
-
-int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel)
-{
-       if (!rf->patch_6m_band_edge)
-               return 0;
-
-       return rf->patch_6m_band_edge(rf, channel);
-}
-
-int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel)
-{
-       return zd_chip_generic_patch_6m_band(zd_rf_to_chip(rf), channel);
-}
-
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
deleted file mode 100644 (file)
index 8f14e25..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ZD_RF_H
-#define _ZD_RF_H
-
-#define UW2451_RF                      0x2
-#define UCHIP_RF                       0x3
-#define AL2230_RF                      0x4
-#define AL7230B_RF                     0x5     /* a,b,g */
-#define THETA_RF                       0x6
-#define AL2210_RF                      0x7
-#define MAXIM_NEW_RF                   0x8
-#define UW2453_RF                      0x9
-#define AL2230S_RF                     0xa
-#define RALINK_RF                      0xb
-#define INTERSIL_RF                    0xc
-#define RF2959_RF                      0xd
-#define MAXIM_NEW2_RF                  0xe
-#define PHILIPS_RF                     0xf
-
-#define RF_CHANNEL(ch) [(ch)-1]
-
-/* Provides functions of the RF transceiver. */
-
-enum {
-       RF_REG_BITS = 6,
-       RF_VALUE_BITS = 18,
-       RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS,
-};
-
-struct zd_rf {
-       u8 type;
-
-       u8 channel;
-
-       /* whether channel integration and calibration should be updated
-        * defaults to 1 (yes) */
-       u8 update_channel_int:1;
-
-       /* whether ZD_CR47 should be patched from the EEPROM, if the appropriate
-        * flag is set in the POD. The vendor driver suggests that this should
-        * be done for all RF's, but a bug in their code prevents but their
-        * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
-       u8 patch_cck_gain:1;
-
-       /* private RF driver data */
-       void *priv;
-
-       /* RF-specific functions */
-       int (*init_hw)(struct zd_rf *rf);
-       int (*set_channel)(struct zd_rf *rf, u8 channel);
-       int (*switch_radio_on)(struct zd_rf *rf);
-       int (*switch_radio_off)(struct zd_rf *rf);
-       int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
-       void (*clear)(struct zd_rf *rf);
-};
-
-const char *zd_rf_name(u8 type);
-void zd_rf_init(struct zd_rf *rf);
-void zd_rf_clear(struct zd_rf *rf);
-int zd_rf_init_hw(struct zd_rf *rf, u8 type);
-
-int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size);
-
-int zd_rf_set_channel(struct zd_rf *rf, u8 channel);
-
-int zd_switch_radio_on(struct zd_rf *rf);
-int zd_switch_radio_off(struct zd_rf *rf);
-
-int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
-int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
-
-static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
-{
-       return rf->update_channel_int;
-}
-
-static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
-{
-       return rf->patch_cck_gain;
-}
-
-int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
-int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
-
-/* Functions for individual RF chips */
-
-int zd_rf_init_rf2959(struct zd_rf *rf);
-int zd_rf_init_al2230(struct zd_rf *rf);
-int zd_rf_init_al7230b(struct zd_rf *rf);
-int zd_rf_init_uw2453(struct zd_rf *rf);
-
-#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
deleted file mode 100644 (file)
index 99aed7d..0000000
+++ /dev/null
@@ -1,443 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-
-#include "zd_rf.h"
-#include "zd_usb.h"
-#include "zd_chip.h"
-
-#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
-
-static const u32 zd1211_al2230_table[][3] = {
-       RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
-       RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
-       RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
-       RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, },
-       RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, },
-       RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, },
-       RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, },
-       RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, },
-       RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, },
-       RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, },
-       RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, },
-       RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, },
-       RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, },
-       RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
-};
-
-static const u32 zd1211b_al2230_table[][3] = {
-       RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, },
-       RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, },
-       RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, },
-       RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, },
-       RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, },
-       RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, },
-       RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, },
-       RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, },
-};
-
-static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
-       { ZD_CR240, 0x57 }, { ZD_CR9,   0xe0 },
-};
-
-static const struct zd_ioreq16 ioreqs_init_al2230s[] = {
-       { ZD_CR47,   0x1e }, /* MARK_002 */
-       { ZD_CR106,  0x22 },
-       { ZD_CR107,  0x2a }, /* MARK_002 */
-       { ZD_CR109,  0x13 }, /* MARK_002 */
-       { ZD_CR118,  0xf8 }, /* MARK_002 */
-       { ZD_CR119,  0x12 }, { ZD_CR122,  0xe0 },
-       { ZD_CR128,  0x10 }, /* MARK_001 from 0xe->0x10 */
-       { ZD_CR129,  0x0e }, /* MARK_001 from 0xd->0x0e */
-       { ZD_CR130,  0x10 }, /* MARK_001 from 0xb->0x0d */
-};
-
-static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
-{
-       int r;
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 }, { ZD_CR79,  0x58 },
-               { ZD_CR12,  0xf0 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x58 },
-               { ZD_CR203, 0x06 },
-               { },
-
-               { ZD_CR240, 0x80 },
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               return r;
-
-       /* related to antenna selection? */
-       if (chip->new_phy_layout) {
-               r = zd_iowrite16_locked(chip, 0xe1, ZD_CR9);
-               if (r)
-                       return r;
-       }
-
-       return zd_iowrite16_locked(chip, 0x06, ZD_CR203);
-}
-
-static int zd1211_al2230_init_hw(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs_init[] = {
-               { ZD_CR15,   0x20 }, { ZD_CR23,   0x40 }, { ZD_CR24,  0x20 },
-               { ZD_CR26,   0x11 }, { ZD_CR28,   0x3e }, { ZD_CR29,  0x00 },
-               { ZD_CR44,   0x33 }, { ZD_CR106,  0x2a }, { ZD_CR107, 0x1a },
-               { ZD_CR109,  0x09 }, { ZD_CR110,  0x27 }, { ZD_CR111, 0x2b },
-               { ZD_CR112,  0x2b }, { ZD_CR119,  0x0a }, { ZD_CR10,  0x89 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR17,   0x28 },
-               { ZD_CR26,   0x93 }, { ZD_CR34,   0x30 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR35,   0x3e },
-               { ZD_CR41,   0x24 }, { ZD_CR44,   0x32 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR46,   0x96 },
-               { ZD_CR47,   0x1e }, { ZD_CR79,   0x58 }, { ZD_CR80,  0x30 },
-               { ZD_CR81,   0x30 }, { ZD_CR87,   0x0a }, { ZD_CR89,  0x04 },
-               { ZD_CR92,   0x0a }, { ZD_CR99,   0x28 }, { ZD_CR100, 0x00 },
-               { ZD_CR101,  0x13 }, { ZD_CR102,  0x27 }, { ZD_CR106, 0x24 },
-               { ZD_CR107,  0x2a }, { ZD_CR109,  0x09 }, { ZD_CR110, 0x13 },
-               { ZD_CR111,  0x1f }, { ZD_CR112,  0x1f }, { ZD_CR113, 0x27 },
-               { ZD_CR114,  0x27 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR115,  0x24 },
-               { ZD_CR116,  0x24 }, { ZD_CR117,  0xf4 }, { ZD_CR118, 0xfc },
-               { ZD_CR119,  0x10 }, { ZD_CR120,  0x4f }, { ZD_CR121, 0x77 },
-               { ZD_CR122,  0xe0 }, { ZD_CR137,  0x88 }, { ZD_CR252, 0xff },
-               { ZD_CR253,  0xff },
-       };
-
-       static const struct zd_ioreq16 ioreqs_pll[] = {
-               /* shdnb(PLL_ON)=0 */
-               { ZD_CR251,  0x2f },
-               /* shdnb(PLL_ON)=1 */
-               { ZD_CR251,  0x3f },
-               { ZD_CR138,  0x28 }, { ZD_CR203,  0x06 },
-       };
-
-       static const u32 rv1[] = {
-               /* Channel 1 */
-               0x03f790,
-               0x033331,
-               0x00000d,
-
-               0x0b3331,
-               0x03b812,
-               0x00fff3,
-       };
-
-       static const u32 rv2[] = {
-               0x000da4,
-               0x0f4dc5, /* fix freq shift, 0x04edc5 */
-               0x0805b6,
-               0x011687,
-               0x000688,
-               0x0403b9, /* external control TX power (ZD_CR31) */
-               0x00dbba,
-               0x00099b,
-               0x0bdffc,
-               0x00000d,
-               0x00500f,
-       };
-
-       static const u32 rv3[] = {
-               0x00d00f,
-               0x004c0f,
-               0x00540f,
-               0x00700f,
-               0x00500f,
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs_init, ARRAY_SIZE(ioreqs_init));
-       if (r)
-               return r;
-
-       if (IS_AL2230S(chip)) {
-               r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
-                       ARRAY_SIZE(ioreqs_init_al2230s));
-               if (r)
-                       return r;
-       }
-
-       r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
-       if (r)
-               return r;
-
-       /* improve band edge for AL2230S */
-       if (IS_AL2230S(chip))
-               r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
-       else
-               r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
-       if (r)
-               return r;
-
-       r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs_pll, ARRAY_SIZE(ioreqs_pll));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
-       if (r)
-               return r;
-
-       return 0;
-}
-
-static int zd1211b_al2230_init_hw(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs1[] = {
-               { ZD_CR10,  0x89 }, { ZD_CR15,  0x20 },
-               { ZD_CR17,  0x2B }, /* for newest(3rd cut) AL2230 */
-               { ZD_CR23,  0x40 }, { ZD_CR24,  0x20 }, { ZD_CR26,  0x93 },
-               { ZD_CR28,  0x3e }, { ZD_CR29,  0x00 },
-               { ZD_CR33,  0x28 }, /* 5621 */
-               { ZD_CR34,  0x30 },
-               { ZD_CR35,  0x3e }, /* for newest(3rd cut) AL2230 */
-               { ZD_CR41,  0x24 }, { ZD_CR44,  0x32 },
-               { ZD_CR46,  0x99 }, /* for newest(3rd cut) AL2230 */
-               { ZD_CR47,  0x1e },
-
-               /* ZD1211B 05.06.10 */
-               { ZD_CR48,  0x06 }, { ZD_CR49,  0xf9 }, { ZD_CR51,  0x01 },
-               { ZD_CR52,  0x80 }, { ZD_CR53,  0x7e }, { ZD_CR65,  0x00 },
-               { ZD_CR66,  0x00 }, { ZD_CR67,  0x00 }, { ZD_CR68,  0x00 },
-               { ZD_CR69,  0x28 },
-
-               { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 },
-               { ZD_CR87,  0x0a }, { ZD_CR89,  0x04 },
-               { ZD_CR91,  0x00 }, /* 5621 */
-               { ZD_CR92,  0x0a },
-               { ZD_CR98,  0x8d }, /* 4804,  for 1212 new algorithm */
-               { ZD_CR99,  0x00 }, /* 5621 */
-               { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 },
-               { ZD_CR106, 0x24 }, /* for newest(3rd cut) AL2230 */
-               { ZD_CR107, 0x2a },
-               { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */
-               { ZD_CR110, 0x1f }, /* 4804, for 1212 new algorithm */
-               { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 },
-               { ZD_CR114, 0x27 },
-               { ZD_CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut)
-                                    * AL2230
-                                    */
-               { ZD_CR116, 0x24 },
-               { ZD_CR117, 0xfa }, /* for 1211b */
-               { ZD_CR118, 0xfa }, /* for 1211b */
-               { ZD_CR119, 0x10 },
-               { ZD_CR120, 0x4f },
-               { ZD_CR121, 0x6c }, /* for 1211b */
-               { ZD_CR122, 0xfc }, /* E0->FC at 4902 */
-               { ZD_CR123, 0x57 }, /* 5623 */
-               { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */
-               { ZD_CR126, 0x6c }, /* 5614 */
-               { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */
-               { ZD_CR137, 0x50 }, /* 5614 */
-               { ZD_CR138, 0xa8 },
-               { ZD_CR144, 0xac }, /* 5621 */
-               { ZD_CR150, 0x0d }, { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 },
-       };
-
-       static const u32 rv1[] = {
-               0x8cccd0,
-               0x481dc0,
-               0xcfff00,
-               0x25a000,
-       };
-
-       static const u32 rv2[] = {
-               /* To improve AL2230 yield, improve phase noise, 4713 */
-               0x25a000,
-               0xa3b2f0,
-
-               0x6da010, /* Reg6 update for MP versio */
-               0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */
-               0x116000,
-               0x9dc020, /* External control TX power (ZD_CR31) */
-               0x5ddb00, /* RegA update for MP version */
-               0xd99000, /* RegB update for MP version */
-               0x3ffbd0, /* RegC update for MP version */
-               0xb00000, /* RegD update for MP version */
-
-               /* improve phase noise and remove phase calibration,4713 */
-               0xf01a00,
-       };
-
-       static const struct zd_ioreq16 ioreqs2[] = {
-               { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=0 */
-               { ZD_CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
-       };
-
-       static const u32 rv3[] = {
-               /* To improve AL2230 yield, 4713 */
-               0xf01b00,
-               0xf01e00,
-               0xf01a00,
-       };
-
-       static const struct zd_ioreq16 ioreqs3[] = {
-               /* related to 6M band edge patching, happens unconditionally */
-               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
-       };
-
-       r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
-               ARRAY_SIZE(zd1211b_ioreqs_shared_1));
-       if (r)
-               return r;
-       r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
-       if (r)
-               return r;
-
-       if (IS_AL2230S(chip)) {
-               r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
-                       ARRAY_SIZE(ioreqs_init_al2230s));
-               if (r)
-                       return r;
-       }
-
-       r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3);
-       if (r)
-               return r;
-       r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1));
-       if (r)
-               return r;
-
-       if (IS_AL2230S(chip))
-               r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
-       else
-               r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2));
-       if (r)
-               return r;
-       r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
-       if (r)
-               return r;
-       r = zd_rfwritev_cr_locked(chip, rv3, ARRAY_SIZE(rv3));
-       if (r)
-               return r;
-       r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
-       if (r)
-               return r;
-       return zd1211b_al2230_finalize_rf(chip);
-}
-
-static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int r;
-       const u32 *rv = zd1211_al2230_table[channel-1];
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR138, 0x28 },
-               { ZD_CR203, 0x06 },
-       };
-
-       r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS);
-       if (r)
-               return r;
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int r;
-       const u32 *rv = zd1211b_al2230_table[channel-1];
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
-               ARRAY_SIZE(zd1211b_ioreqs_shared_1));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv, 3);
-       if (r)
-               return r;
-
-       return zd1211b_al2230_finalize_rf(chip);
-}
-
-static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x00 },
-               { ZD_CR251, 0x3f },
-       };
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x00 },
-               { ZD_CR251, 0x7f },
-       };
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int al2230_switch_radio_off(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x04 },
-               { ZD_CR251, 0x2f },
-       };
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-int zd_rf_init_al2230(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       rf->switch_radio_off = al2230_switch_radio_off;
-       if (zd_chip_is_zd1211b(chip)) {
-               rf->init_hw = zd1211b_al2230_init_hw;
-               rf->set_channel = zd1211b_al2230_set_channel;
-               rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
-       } else {
-               rf->init_hw = zd1211_al2230_init_hw;
-               rf->set_channel = zd1211_al2230_set_channel;
-               rf->switch_radio_on = zd1211_al2230_switch_radio_on;
-       }
-       rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
-       rf->patch_cck_gain = 1;
-       return 0;
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
deleted file mode 100644 (file)
index 5fea485..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-
-#include "zd_rf.h"
-#include "zd_usb.h"
-#include "zd_chip.h"
-
-static const u32 chan_rv[][2] = {
-       RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 },
-       RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 },
-       RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 },
-       RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 },
-       RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 },
-       RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 },
-       RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 },
-       RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 },
-       RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 },
-       RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 },
-       RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 },
-       RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 },
-       RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 },
-       RF_CHANNEL(14) = { 0x03ec00, 0x866660 },
-};
-
-static const u32 std_rv[] = {
-       0x4ff821,
-       0xc5fbfc,
-       0x21ebfe,
-       0xafd401, /* freq shift 0xaad401 */
-       0x6cf56a,
-       0xe04073,
-       0x193d76,
-       0x9dd844,
-       0x500007,
-       0xd8c010,
-};
-
-static const u32 rv_init1[] = {
-       0x3c9000,
-       0xbfffff,
-       0x700000,
-       0xf15d58,
-};
-
-static const u32 rv_init2[] = {
-       0xf15d59,
-       0xf15d5c,
-       0xf15d58,
-};
-
-static const struct zd_ioreq16 ioreqs_sw[] = {
-       { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
-       { ZD_CR38,  0x38 }, { ZD_CR136, 0xdf },
-};
-
-static int zd1211b_al7230b_finalize(struct zd_chip *chip)
-{
-       int r;
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 }, { ZD_CR79,  0x58 },
-               { ZD_CR12,  0xf0 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x58 },
-               { ZD_CR203, 0x04 },
-               { },
-               { ZD_CR240, 0x80 },
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               return r;
-
-       if (chip->new_phy_layout) {
-               /* antenna selection? */
-               r = zd_iowrite16_locked(chip, 0xe5, ZD_CR9);
-               if (r)
-                       return r;
-       }
-
-       return zd_iowrite16_locked(chip, 0x04, ZD_CR203);
-}
-
-static int zd1211_al7230b_init_hw(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       /* All of these writes are identical to AL2230 unless otherwise
-        * specified */
-       static const struct zd_ioreq16 ioreqs_1[] = {
-               /* This one is 7230-specific, and happens before the rest */
-               { ZD_CR240,  0x57 },
-               { },
-
-               { ZD_CR15,   0x20 }, { ZD_CR23,   0x40 }, { ZD_CR24,  0x20 },
-               { ZD_CR26,   0x11 }, { ZD_CR28,   0x3e }, { ZD_CR29,  0x00 },
-               { ZD_CR44,   0x33 },
-               /* This value is different for 7230 (was: 0x2a) */
-               { ZD_CR106,  0x22 },
-               { ZD_CR107,  0x1a }, { ZD_CR109,  0x09 }, { ZD_CR110,  0x27 },
-               { ZD_CR111,  0x2b }, { ZD_CR112,  0x2b }, { ZD_CR119,  0x0a },
-               /* This happened further down in AL2230,
-                * and the value changed (was: 0xe0) */
-               { ZD_CR122,  0xfc },
-               { ZD_CR10,   0x89 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR17,   0x28 },
-               { ZD_CR26,   0x93 }, { ZD_CR34,   0x30 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR35,   0x3e },
-               { ZD_CR41,   0x24 }, { ZD_CR44,   0x32 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR46,   0x96 },
-               { ZD_CR47,   0x1e }, { ZD_CR79,   0x58 }, { ZD_CR80,  0x30 },
-               { ZD_CR81,   0x30 }, { ZD_CR87,   0x0a }, { ZD_CR89,  0x04 },
-               { ZD_CR92,   0x0a }, { ZD_CR99,   0x28 },
-               /* This value is different for 7230 (was: 0x00) */
-               { ZD_CR100,  0x02 },
-               { ZD_CR101,  0x13 }, { ZD_CR102,  0x27 },
-               /* This value is different for 7230 (was: 0x24) */
-               { ZD_CR106,  0x22 },
-               /* This value is different for 7230 (was: 0x2a) */
-               { ZD_CR107,  0x3f },
-               { ZD_CR109,  0x09 },
-               /* This value is different for 7230 (was: 0x13) */
-               { ZD_CR110,  0x1f },
-               { ZD_CR111,  0x1f }, { ZD_CR112,  0x1f }, { ZD_CR113, 0x27 },
-               { ZD_CR114,  0x27 },
-               /* for newest (3rd cut) AL2300 */
-               { ZD_CR115,  0x24 },
-               /* This value is different for 7230 (was: 0x24) */
-               { ZD_CR116,  0x3f },
-               /* This value is different for 7230 (was: 0xf4) */
-               { ZD_CR117,  0xfa },
-               { ZD_CR118,  0xfc }, { ZD_CR119,  0x10 }, { ZD_CR120, 0x4f },
-               { ZD_CR121,  0x77 }, { ZD_CR137,  0x88 },
-               /* This one is 7230-specific */
-               { ZD_CR138,  0xa8 },
-               /* This value is different for 7230 (was: 0xff) */
-               { ZD_CR252,  0x34 },
-               /* This value is different for 7230 (was: 0xff) */
-               { ZD_CR253,  0x34 },
-
-               /* PLL_OFF */
-               { ZD_CR251, 0x2f },
-       };
-
-       static const struct zd_ioreq16 ioreqs_2[] = {
-               { ZD_CR251, 0x3f }, /* PLL_ON */
-               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
-               { ZD_CR38,  0x38 }, { ZD_CR136, 0xdf },
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, chan_rv[0], ARRAY_SIZE(chan_rv[0]));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv_init1, ARRAY_SIZE(rv_init1));
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv_init2, ARRAY_SIZE(rv_init2));
-       if (r)
-               return r;
-
-       r = zd_iowrite16_locked(chip, 0x06, ZD_CR203);
-       if (r)
-               return r;
-       r = zd_iowrite16_locked(chip, 0x80, ZD_CR240);
-       if (r)
-               return r;
-
-       return 0;
-}
-
-static int zd1211b_al7230b_init_hw(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs_1[] = {
-               { ZD_CR240, 0x57 }, { ZD_CR9,   0x9 },
-               { },
-               { ZD_CR10,  0x8b }, { ZD_CR15,  0x20 },
-               { ZD_CR17,  0x2B }, /* for newest (3rd cut) AL2230 */
-               { ZD_CR20,  0x10 }, /* 4N25->Stone Request */
-               { ZD_CR23,  0x40 }, { ZD_CR24,  0x20 }, { ZD_CR26,  0x93 },
-               { ZD_CR28,  0x3e }, { ZD_CR29,  0x00 },
-               { ZD_CR33,  0x28 }, /* 5613 */
-               { ZD_CR34,  0x30 },
-               { ZD_CR35,  0x3e }, /* for newest (3rd cut) AL2230 */
-               { ZD_CR41,  0x24 }, { ZD_CR44,  0x32 },
-               { ZD_CR46,  0x99 }, /* for newest (3rd cut) AL2230 */
-               { ZD_CR47,  0x1e },
-
-               /* ZD1215 5610 */
-               { ZD_CR48,  0x00 }, { ZD_CR49,  0x00 }, { ZD_CR51,  0x01 },
-               { ZD_CR52,  0x80 }, { ZD_CR53,  0x7e }, { ZD_CR65,  0x00 },
-               { ZD_CR66,  0x00 }, { ZD_CR67,  0x00 }, { ZD_CR68,  0x00 },
-               { ZD_CR69,  0x28 },
-
-               { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 },
-               { ZD_CR87,  0x0A }, { ZD_CR89,  0x04 },
-               { ZD_CR90,  0x58 }, /* 5112 */
-               { ZD_CR91,  0x00 }, /* 5613 */
-               { ZD_CR92,  0x0a },
-               { ZD_CR98,  0x8d }, /* 4804, for 1212 new algorithm */
-               { ZD_CR99,  0x00 }, { ZD_CR100, 0x02 }, { ZD_CR101, 0x13 },
-               { ZD_CR102, 0x27 },
-               { ZD_CR106, 0x20 }, /* change to 0x24 for AL7230B */
-               { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */
-               { ZD_CR112, 0x1f },
-       };
-
-       static const struct zd_ioreq16 ioreqs_new_phy[] = {
-               { ZD_CR107, 0x28 },
-               { ZD_CR110, 0x1f }, /* 5127, 0x13->0x1f */
-               { ZD_CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */
-               { ZD_CR116, 0x2a }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x12 },
-               { ZD_CR121, 0x6c }, /* 5613 */
-       };
-
-       static const struct zd_ioreq16 ioreqs_old_phy[] = {
-               { ZD_CR107, 0x24 },
-               { ZD_CR110, 0x13 }, /* 5127, 0x13->0x1f */
-               { ZD_CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */
-               { ZD_CR116, 0x24 }, { ZD_CR118, 0xfc }, { ZD_CR119, 0x11 },
-               { ZD_CR121, 0x6a }, /* 5613 */
-       };
-
-       static const struct zd_ioreq16 ioreqs_2[] = {
-               { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x24 },
-               { ZD_CR117, 0xfa }, { ZD_CR120, 0x4f },
-               { ZD_CR122, 0xfc }, /* E0->FCh at 4901 */
-               { ZD_CR123, 0x57 }, /* 5613 */
-               { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */
-               { ZD_CR126, 0x6c }, /* 5613 */
-               { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */
-               { ZD_CR130, 0x10 },
-               { ZD_CR131, 0x00 }, /* 5112 */
-               { ZD_CR137, 0x50 }, /* 5613 */
-               { ZD_CR138, 0xa8 }, /* 5112 */
-               { ZD_CR144, 0xac }, /* 5613 */
-               { ZD_CR148, 0x40 }, /* 5112 */
-               { ZD_CR149, 0x40 }, /* 4O07, 50->40 */
-               { ZD_CR150, 0x1a }, /* 5112, 0C->1A */
-               { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 },
-               { ZD_CR251, 0x2f }, /* PLL_OFF */
-       };
-
-       static const struct zd_ioreq16 ioreqs_3[] = {
-               { ZD_CR251, 0x7f }, /* PLL_ON */
-               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
-               { ZD_CR38,  0x38 }, { ZD_CR136, 0xdf },
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
-       if (r)
-               return r;
-
-       if (chip->new_phy_layout)
-               r = zd_iowrite16a_locked(chip, ioreqs_new_phy,
-                       ARRAY_SIZE(ioreqs_new_phy));
-       else
-               r = zd_iowrite16a_locked(chip, ioreqs_old_phy,
-                       ARRAY_SIZE(ioreqs_old_phy));
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, chan_rv[0], ARRAY_SIZE(chan_rv[0]));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv_init1, ARRAY_SIZE(rv_init1));
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs_3, ARRAY_SIZE(ioreqs_3));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv_init2, ARRAY_SIZE(rv_init2));
-       if (r)
-               return r;
-
-       return zd1211b_al7230b_finalize(chip);
-}
-
-static int zd1211_al7230b_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int r;
-       const u32 *rv = chan_rv[channel-1];
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs[] = {
-               /* PLL_ON */
-               { ZD_CR251, 0x3f },
-               { ZD_CR203, 0x06 }, { ZD_CR240, 0x08 },
-       };
-
-       r = zd_iowrite16_locked(chip, 0x57, ZD_CR240);
-       if (r)
-               return r;
-
-       /* PLL_OFF */
-       r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251);
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
-       if (r)
-               return r;
-
-       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
-       if (r)
-               return r;
-       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs_sw, ARRAY_SIZE(ioreqs_sw));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv, 2);
-       if (r)
-               return r;
-
-       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
-       if (r)
-               return r;
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int r;
-       const u32 *rv = chan_rv[channel-1];
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       r = zd_iowrite16_locked(chip, 0x57, ZD_CR240);
-       if (r)
-               return r;
-       r = zd_iowrite16_locked(chip, 0xe4, ZD_CR9);
-       if (r)
-               return r;
-
-       /* PLL_OFF */
-       r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251);
-       if (r)
-               return r;
-       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
-       if (r)
-               return r;
-
-       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
-       if (r)
-               return r;
-       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs_sw, ARRAY_SIZE(ioreqs_sw));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_cr_locked(chip, rv, 2);
-       if (r)
-               return r;
-
-       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
-       if (r)
-               return r;
-
-       r = zd_iowrite16_locked(chip, 0x7f, ZD_CR251);
-       if (r)
-               return r;
-
-       return zd1211b_al7230b_finalize(chip);
-}
-
-static int zd1211_al7230b_switch_radio_on(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x00 },
-               { ZD_CR251, 0x3f },
-       };
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int zd1211b_al7230b_switch_radio_on(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x00 },
-               { ZD_CR251, 0x7f },
-       };
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int al7230b_switch_radio_off(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x04 },
-               { ZD_CR251, 0x2f },
-       };
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-/* ZD1211B+AL7230B 6m band edge patching differs slightly from other
- * configurations */
-static int zd1211b_al7230b_patch_6m(struct zd_rf *rf, u8 channel)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 },
-       };
-
-       /* FIXME: Channel 11 is not the edge for all regulatory domains. */
-       if (channel == 1) {
-               ioreqs[0].value = 0x0e;
-               ioreqs[1].value = 0x10;
-       } else if (channel == 11) {
-               ioreqs[0].value = 0x10;
-               ioreqs[1].value = 0x10;
-       }
-
-       dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel);
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-int zd_rf_init_al7230b(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       if (zd_chip_is_zd1211b(chip)) {
-               rf->init_hw = zd1211b_al7230b_init_hw;
-               rf->switch_radio_on = zd1211b_al7230b_switch_radio_on;
-               rf->set_channel = zd1211b_al7230b_set_channel;
-               rf->patch_6m_band_edge = zd1211b_al7230b_patch_6m;
-       } else {
-               rf->init_hw = zd1211_al7230b_init_hw;
-               rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
-               rf->set_channel = zd1211_al7230b_set_channel;
-               rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
-               rf->patch_cck_gain = 1;
-       }
-
-       rf->switch_radio_off = al7230b_switch_radio_off;
-
-       return 0;
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
deleted file mode 100644 (file)
index a93f657..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-
-#include "zd_rf.h"
-#include "zd_usb.h"
-#include "zd_chip.h"
-
-static const u32 rf2959_table[][2] = {
-       RF_CHANNEL( 1) = { 0x181979, 0x1e6666 },
-       RF_CHANNEL( 2) = { 0x181989, 0x1e6666 },
-       RF_CHANNEL( 3) = { 0x181999, 0x1e6666 },
-       RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 },
-       RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 },
-       RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 },
-       RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 },
-       RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 },
-       RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 },
-       RF_CHANNEL(10) = { 0x181a09, 0x1e6666 },
-       RF_CHANNEL(11) = { 0x181a19, 0x1e6666 },
-       RF_CHANNEL(12) = { 0x181a29, 0x1e6666 },
-       RF_CHANNEL(13) = { 0x181a39, 0x1e6666 },
-       RF_CHANNEL(14) = { 0x181a60, 0x1c0000 },
-};
-
-#if 0
-static int bits(u32 rw, int from, int to)
-{
-       rw &= ~(0xffffffffU << (to+1));
-       rw >>= from;
-       return rw;
-}
-
-static int bit(u32 rw, int bit)
-{
-       return bits(rw, bit, bit);
-}
-
-static void dump_regwrite(u32 rw)
-{
-       int reg = bits(rw, 18, 22);
-       int rw_flag = bits(rw, 23, 23);
-       PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag);
-
-       switch (reg) {
-       case 0:
-               PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d"
-                      " if_vco_reg_en %d if_vga_en %d",
-                      bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1),
-                      bit(rw, 0));
-               break;
-       case 1:
-               PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d"
-                      " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d"
-                      " ifloopc %d dac1 %d",
-                      bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
-                      bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
-                      bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3));
-               break;
-       case 2:
-               PDEBUG("reg2 IFPLL2 n1 %d num1 %d",
-                      bits(rw, 6, 17), bits(rw, 0, 5));
-               break;
-       case 3:
-               PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17));
-               break;
-       case 4:
-               PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d",
-                      bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
-               break;
-       case 5:
-               PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d"
-                      " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d"
-                      " dac %d",
-                      bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
-                      bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
-                      bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3));
-               break;
-       case 6:
-               PDEBUG("reg6 RFPLL2 n %d num %d",
-                      bits(rw, 6, 17), bits(rw, 0, 5));
-               break;
-       case 7:
-               PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17));
-               break;
-       case 8:
-               PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d",
-                      bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
-               break;
-       case 9:
-               PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d",
-                      bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7),
-                      bits(rw, 0, 2));
-               break;
-       case 10:
-               PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d"
-                      " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d"
-                      " intbiasen %d tybypass %d",
-                      bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14),
-                      bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2),
-                      bit(rw, 1), bit(rw, 0));
-               break;
-       case 11:
-               PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d"
-                       " tx_delay %d",
-                       bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8),
-                       bits(rw, 0, 2));
-               break;
-       case 12:
-               PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d",
-                      bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5));
-               break;
-       case 13:
-               PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d"
-                      " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d"
-                      " rf_biasvco %d",
-                      bit(rw, 17), bit(rw, 16), bit(rw, 15),
-                      bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4),
-                      bits(rw, 0, 2));
-               break;
-       case 14:
-               PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d"
-                      " tx_acal %d tx_pcal %d",
-                      bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8),
-                      bits(rw, 0, 3));
-               break;
-       }
-}
-#endif /* 0 */
-
-static int rf2959_init_hw(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR2,   0x1E }, { ZD_CR9,   0x20 }, { ZD_CR10,  0x89 },
-               { ZD_CR11,  0x00 }, { ZD_CR15,  0xD0 }, { ZD_CR17,  0x68 },
-               { ZD_CR19,  0x4a }, { ZD_CR20,  0x0c }, { ZD_CR21,  0x0E },
-               { ZD_CR23,  0x48 },
-               /* normal size for cca threshold */
-               { ZD_CR24,  0x14 },
-               /* { ZD_CR24,  0x20 }, */
-               { ZD_CR26,  0x90 }, { ZD_CR27,  0x30 }, { ZD_CR29,  0x20 },
-               { ZD_CR31,  0xb2 }, { ZD_CR32,  0x43 }, { ZD_CR33,  0x28 },
-               { ZD_CR38,  0x30 }, { ZD_CR34,  0x0f }, { ZD_CR35,  0xF0 },
-               { ZD_CR41,  0x2a }, { ZD_CR46,  0x7F }, { ZD_CR47,  0x1E },
-               { ZD_CR51,  0xc5 }, { ZD_CR52,  0xc5 }, { ZD_CR53,  0xc5 },
-               { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 },
-               { ZD_CR82,  0x00 }, { ZD_CR83,  0x24 }, { ZD_CR84,  0x04 },
-               { ZD_CR85,  0x00 }, { ZD_CR86,  0x10 }, { ZD_CR87,  0x2A },
-               { ZD_CR88,  0x10 }, { ZD_CR89,  0x24 }, { ZD_CR90,  0x18 },
-               /* { ZD_CR91,  0x18 }, */
-               /* should solve continuous CTS frame problems */
-               { ZD_CR91,  0x00 },
-               { ZD_CR92,  0x0a }, { ZD_CR93,  0x00 }, { ZD_CR94,  0x01 },
-               { ZD_CR95,  0x00 }, { ZD_CR96,  0x40 }, { ZD_CR97,  0x37 },
-               { ZD_CR98,  0x05 }, { ZD_CR99,  0x28 }, { ZD_CR100, 0x00 },
-               { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 },
-               { ZD_CR104, 0x18 }, { ZD_CR105, 0x12 },
-               /* normal size */
-               { ZD_CR106, 0x1a },
-               /* { ZD_CR106, 0x22 }, */
-               { ZD_CR107, 0x24 }, { ZD_CR108, 0x0a }, { ZD_CR109, 0x13 },
-               { ZD_CR110, 0x2F }, { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 },
-               { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x40 },
-               { ZD_CR116, 0x40 }, { ZD_CR117, 0xF0 }, { ZD_CR118, 0xF0 },
-               { ZD_CR119, 0x16 },
-               /* no TX continuation */
-               { ZD_CR122, 0x00 },
-               /* { ZD_CR122, 0xff }, */
-               { ZD_CR127, 0x03 }, { ZD_CR131, 0x08 }, { ZD_CR138, 0x28 },
-               { ZD_CR148, 0x44 }, { ZD_CR150, 0x10 }, { ZD_CR169, 0xBB },
-               { ZD_CR170, 0xBB },
-       };
-
-       static const u32 rv[] = {
-               0x000007,  /* REG0(CFG1) */
-               0x07dd43,  /* REG1(IFPLL1) */
-               0x080959,  /* REG2(IFPLL2) */
-               0x0e6666,
-               0x116a57,  /* REG4 */
-               0x17dd43,  /* REG5 */
-               0x1819f9,  /* REG6 */
-               0x1e6666,
-               0x214554,
-               0x25e7fa,
-               0x27fffa,
-               /* The Zydas driver somehow forgets to set this value. It's
-                * only set for Japan. We are using internal power control
-                * for now.
-                */
-               0x294128, /* internal power */
-               /* 0x28252c, */ /* External control TX power */
-               /* ZD_CR31_CCK, ZD_CR51_6-36M, ZD_CR52_48M, ZD_CR53_54M */
-               0x2c0000,
-               0x300000,
-               0x340000,  /* REG13(0xD) */
-               0x381e0f,  /* REG14(0xE) */
-               /* Bogus, RF2959's data sheet doesn't know register 27, which is
-                * actually referenced here. The commented 0x11 is 17.
-                */
-               0x6c180f,  /* REG27(0x11) */
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               return r;
-
-       return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
-}
-
-static int rf2959_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int i, r;
-       const u32 *rv = rf2959_table[channel-1];
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       for (i = 0; i < 2; i++) {
-               r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS);
-               if (r)
-                       return r;
-       }
-       return 0;
-}
-
-static int rf2959_switch_radio_on(struct zd_rf *rf)
-{
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR10, 0x89 },
-               { ZD_CR11, 0x00 },
-       };
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int rf2959_switch_radio_off(struct zd_rf *rf)
-{
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR10, 0x15 },
-               { ZD_CR11, 0x81 },
-       };
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-int zd_rf_init_rf2959(struct zd_rf *rf)
-{
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       if (zd_chip_is_zd1211b(chip)) {
-               dev_err(zd_chip_dev(chip),
-                      "RF2959 is currently not supported for ZD1211B"
-                      " devices\n");
-               return -ENODEV;
-       }
-       rf->init_hw = rf2959_init_hw;
-       rf->set_channel = rf2959_set_channel;
-       rf->switch_radio_on = rf2959_switch_radio_on;
-       rf->switch_radio_off = rf2959_switch_radio_off;
-       return 0;
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
deleted file mode 100644 (file)
index 61b9240..0000000
+++ /dev/null
@@ -1,539 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include "zd_rf.h"
-#include "zd_usb.h"
-#include "zd_chip.h"
-
-/* This RF programming code is based upon the code found in v2.16.0.0 of the
- * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
- * for this RF on their website, so we're able to understand more than
- * usual as to what is going on. Thumbs up for Ubec for doing that. */
-
-/* The 3-wire serial interface provides access to 8 write-only registers.
- * The data format is a 4 bit register address followed by a 20 bit value. */
-#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
-
-/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
- * fractional divide ratio) and 3 (VCO config).
- *
- * We configure the RF to produce an interrupt when the PLL is locked onto
- * the configured frequency. During initialization, we run through a variety
- * of different VCO configurations on channel 1 until we detect a PLL lock.
- * When this happens, we remember which VCO configuration produced the lock
- * and use it later. Actually, we use the configuration *after* the one that
- * produced the lock, which seems odd, but it works.
- *
- * If we do not see a PLL lock on any standard VCO config, we fall back on an
- * autocal configuration, which has a fixed (as opposed to per-channel) VCO
- * config and different synth values from the standard set (divide ratio
- * is still shared with the standard set). */
-
-/* The per-channel synth values for all standard VCO configurations. These get
- * written to register 1. */
-static const u8 uw2453_std_synth[] = {
-       RF_CHANNEL( 1) = 0x47,
-       RF_CHANNEL( 2) = 0x47,
-       RF_CHANNEL( 3) = 0x67,
-       RF_CHANNEL( 4) = 0x67,
-       RF_CHANNEL( 5) = 0x67,
-       RF_CHANNEL( 6) = 0x67,
-       RF_CHANNEL( 7) = 0x57,
-       RF_CHANNEL( 8) = 0x57,
-       RF_CHANNEL( 9) = 0x57,
-       RF_CHANNEL(10) = 0x57,
-       RF_CHANNEL(11) = 0x77,
-       RF_CHANNEL(12) = 0x77,
-       RF_CHANNEL(13) = 0x77,
-       RF_CHANNEL(14) = 0x4f,
-};
-
-/* This table stores the synthesizer fractional divide ratio for *all* VCO
- * configurations (both standard and autocal). These get written to register 2.
- */
-static const u16 uw2453_synth_divide[] = {
-       RF_CHANNEL( 1) = 0x999,
-       RF_CHANNEL( 2) = 0x99b,
-       RF_CHANNEL( 3) = 0x998,
-       RF_CHANNEL( 4) = 0x99a,
-       RF_CHANNEL( 5) = 0x999,
-       RF_CHANNEL( 6) = 0x99b,
-       RF_CHANNEL( 7) = 0x998,
-       RF_CHANNEL( 8) = 0x99a,
-       RF_CHANNEL( 9) = 0x999,
-       RF_CHANNEL(10) = 0x99b,
-       RF_CHANNEL(11) = 0x998,
-       RF_CHANNEL(12) = 0x99a,
-       RF_CHANNEL(13) = 0x999,
-       RF_CHANNEL(14) = 0xccc,
-};
-
-/* Here is the data for all the standard VCO configurations. We shrink our
- * table a little by observing that both channels in a consecutive pair share
- * the same value. We also observe that the high 4 bits ([0:3] in the specs)
- * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
- * below. */
-#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
-#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
-static const u16 uw2453_std_vco_cfg[][7] = {
-       { /* table 1 */
-               RF_CHANPAIR( 1,  2) = 0x664d,
-               RF_CHANPAIR( 3,  4) = 0x604d,
-               RF_CHANPAIR( 5,  6) = 0x6675,
-               RF_CHANPAIR( 7,  8) = 0x6475,
-               RF_CHANPAIR( 9, 10) = 0x6655,
-               RF_CHANPAIR(11, 12) = 0x6455,
-               RF_CHANPAIR(13, 14) = 0x6665,
-       },
-       { /* table 2 */
-               RF_CHANPAIR( 1,  2) = 0x666d,
-               RF_CHANPAIR( 3,  4) = 0x606d,
-               RF_CHANPAIR( 5,  6) = 0x664d,
-               RF_CHANPAIR( 7,  8) = 0x644d,
-               RF_CHANPAIR( 9, 10) = 0x6675,
-               RF_CHANPAIR(11, 12) = 0x6475,
-               RF_CHANPAIR(13, 14) = 0x6655,
-       },
-       { /* table 3 */
-               RF_CHANPAIR( 1,  2) = 0x665d,
-               RF_CHANPAIR( 3,  4) = 0x605d,
-               RF_CHANPAIR( 5,  6) = 0x666d,
-               RF_CHANPAIR( 7,  8) = 0x646d,
-               RF_CHANPAIR( 9, 10) = 0x664d,
-               RF_CHANPAIR(11, 12) = 0x644d,
-               RF_CHANPAIR(13, 14) = 0x6675,
-       },
-       { /* table 4 */
-               RF_CHANPAIR( 1,  2) = 0x667d,
-               RF_CHANPAIR( 3,  4) = 0x607d,
-               RF_CHANPAIR( 5,  6) = 0x665d,
-               RF_CHANPAIR( 7,  8) = 0x645d,
-               RF_CHANPAIR( 9, 10) = 0x666d,
-               RF_CHANPAIR(11, 12) = 0x646d,
-               RF_CHANPAIR(13, 14) = 0x664d,
-       },
-       { /* table 5 */
-               RF_CHANPAIR( 1,  2) = 0x6643,
-               RF_CHANPAIR( 3,  4) = 0x6043,
-               RF_CHANPAIR( 5,  6) = 0x667d,
-               RF_CHANPAIR( 7,  8) = 0x647d,
-               RF_CHANPAIR( 9, 10) = 0x665d,
-               RF_CHANPAIR(11, 12) = 0x645d,
-               RF_CHANPAIR(13, 14) = 0x666d,
-       },
-       { /* table 6 */
-               RF_CHANPAIR( 1,  2) = 0x6663,
-               RF_CHANPAIR( 3,  4) = 0x6063,
-               RF_CHANPAIR( 5,  6) = 0x6643,
-               RF_CHANPAIR( 7,  8) = 0x6443,
-               RF_CHANPAIR( 9, 10) = 0x667d,
-               RF_CHANPAIR(11, 12) = 0x647d,
-               RF_CHANPAIR(13, 14) = 0x665d,
-       },
-       { /* table 7 */
-               RF_CHANPAIR( 1,  2) = 0x6653,
-               RF_CHANPAIR( 3,  4) = 0x6053,
-               RF_CHANPAIR( 5,  6) = 0x6663,
-               RF_CHANPAIR( 7,  8) = 0x6463,
-               RF_CHANPAIR( 9, 10) = 0x6643,
-               RF_CHANPAIR(11, 12) = 0x6443,
-               RF_CHANPAIR(13, 14) = 0x667d,
-       },
-       { /* table 8 */
-               RF_CHANPAIR( 1,  2) = 0x6673,
-               RF_CHANPAIR( 3,  4) = 0x6073,
-               RF_CHANPAIR( 5,  6) = 0x6653,
-               RF_CHANPAIR( 7,  8) = 0x6453,
-               RF_CHANPAIR( 9, 10) = 0x6663,
-               RF_CHANPAIR(11, 12) = 0x6463,
-               RF_CHANPAIR(13, 14) = 0x6643,
-       },
-       { /* table 9 */
-               RF_CHANPAIR( 1,  2) = 0x664b,
-               RF_CHANPAIR( 3,  4) = 0x604b,
-               RF_CHANPAIR( 5,  6) = 0x6673,
-               RF_CHANPAIR( 7,  8) = 0x6473,
-               RF_CHANPAIR( 9, 10) = 0x6653,
-               RF_CHANPAIR(11, 12) = 0x6453,
-               RF_CHANPAIR(13, 14) = 0x6663,
-       },
-       { /* table 10 */
-               RF_CHANPAIR( 1,  2) = 0x666b,
-               RF_CHANPAIR( 3,  4) = 0x606b,
-               RF_CHANPAIR( 5,  6) = 0x664b,
-               RF_CHANPAIR( 7,  8) = 0x644b,
-               RF_CHANPAIR( 9, 10) = 0x6673,
-               RF_CHANPAIR(11, 12) = 0x6473,
-               RF_CHANPAIR(13, 14) = 0x6653,
-       },
-       { /* table 11 */
-               RF_CHANPAIR( 1,  2) = 0x665b,
-               RF_CHANPAIR( 3,  4) = 0x605b,
-               RF_CHANPAIR( 5,  6) = 0x666b,
-               RF_CHANPAIR( 7,  8) = 0x646b,
-               RF_CHANPAIR( 9, 10) = 0x664b,
-               RF_CHANPAIR(11, 12) = 0x644b,
-               RF_CHANPAIR(13, 14) = 0x6673,
-       },
-
-};
-
-/* The per-channel synth values for autocal. These get written to register 1. */
-static const u16 uw2453_autocal_synth[] = {
-       RF_CHANNEL( 1) = 0x6847,
-       RF_CHANNEL( 2) = 0x6847,
-       RF_CHANNEL( 3) = 0x6867,
-       RF_CHANNEL( 4) = 0x6867,
-       RF_CHANNEL( 5) = 0x6867,
-       RF_CHANNEL( 6) = 0x6867,
-       RF_CHANNEL( 7) = 0x6857,
-       RF_CHANNEL( 8) = 0x6857,
-       RF_CHANNEL( 9) = 0x6857,
-       RF_CHANNEL(10) = 0x6857,
-       RF_CHANNEL(11) = 0x6877,
-       RF_CHANNEL(12) = 0x6877,
-       RF_CHANNEL(13) = 0x6877,
-       RF_CHANNEL(14) = 0x684f,
-};
-
-/* The VCO configuration for autocal (all channels) */
-static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
-
-/* TX gain settings. The array index corresponds to the TX power integration
- * values found in the EEPROM. The values get written to register 7. */
-static u32 uw2453_txgain[] = {
-       [0x00] = 0x0e313,
-       [0x01] = 0x0fb13,
-       [0x02] = 0x0e093,
-       [0x03] = 0x0f893,
-       [0x04] = 0x0ea93,
-       [0x05] = 0x1f093,
-       [0x06] = 0x1f493,
-       [0x07] = 0x1f693,
-       [0x08] = 0x1f393,
-       [0x09] = 0x1f35b,
-       [0x0a] = 0x1e6db,
-       [0x0b] = 0x1ff3f,
-       [0x0c] = 0x1ffff,
-       [0x0d] = 0x361d7,
-       [0x0e] = 0x37fbf,
-       [0x0f] = 0x3ff8b,
-       [0x10] = 0x3ff33,
-       [0x11] = 0x3fb3f,
-       [0x12] = 0x3ffff,
-};
-
-/* RF-specific structure */
-struct uw2453_priv {
-       /* index into synth/VCO config tables where PLL lock was found
-        * -1 means autocal */
-       int config;
-};
-
-#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
-
-static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
-       bool autocal)
-{
-       int r;
-       int idx = channel - 1;
-       u32 val;
-
-       if (autocal)
-               val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
-       else
-               val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
-
-       r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
-       if (r)
-               return r;
-
-       return zd_rfwrite_locked(chip,
-               UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
-}
-
-static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
-{
-       /* vendor driver always sets these upper bits even though the specs say
-        * they are reserved */
-       u32 val = 0x40000 | value;
-       return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
-}
-
-static int uw2453_init_mode(struct zd_chip *chip)
-{
-       static const u32 rv[] = {
-               UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
-               UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
-               UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
-               UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
-       };
-
-       return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
-}
-
-static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
-{
-       u8 int_value = chip->pwr_int_values[channel - 1];
-
-       if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
-               dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
-                         "int value %x on channel %d\n", int_value, channel);
-               return 0;
-       }
-
-       return zd_rfwrite_locked(chip,
-               UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
-}
-
-static int uw2453_init_hw(struct zd_rf *rf)
-{
-       int i, r;
-       int found_config = -1;
-       u16 intr_status;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR10,  0x89 }, { ZD_CR15,  0x20 },
-               { ZD_CR17,  0x28 }, /* 6112 no change */
-               { ZD_CR23,  0x38 }, { ZD_CR24,  0x20 }, { ZD_CR26,  0x93 },
-               { ZD_CR27,  0x15 }, { ZD_CR28,  0x3e }, { ZD_CR29,  0x00 },
-               { ZD_CR33,  0x28 }, { ZD_CR34,  0x30 },
-               { ZD_CR35,  0x43 }, /* 6112 3e->43 */
-               { ZD_CR41,  0x24 }, { ZD_CR44,  0x32 },
-               { ZD_CR46,  0x92 }, /* 6112 96->92 */
-               { ZD_CR47,  0x1e },
-               { ZD_CR48,  0x04 }, /* 5602 Roger */
-               { ZD_CR49,  0xfa }, { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 },
-               { ZD_CR81,  0x30 }, { ZD_CR87,  0x0a }, { ZD_CR89,  0x04 },
-               { ZD_CR91,  0x00 }, { ZD_CR92,  0x0a }, { ZD_CR98,  0x8d },
-               { ZD_CR99,  0x28 }, { ZD_CR100, 0x02 },
-               { ZD_CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
-               { ZD_CR102, 0x27 },
-               { ZD_CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f
-                                    * 6221 1f->1c
-                                    */
-               { ZD_CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
-               { ZD_CR109, 0x13 },
-               { ZD_CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
-               { ZD_CR111, 0x13 }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 },
-               { ZD_CR114, 0x23 }, /* 6221 27->23 */
-               { ZD_CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
-               { ZD_CR116, 0x24 }, /* 6220 1c->24 */
-               { ZD_CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
-               { ZD_CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
-               { ZD_CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
-               { ZD_CR120, 0x4f },
-               { ZD_CR121, 0x1f }, /* 6220 4f->1f */
-               { ZD_CR122, 0xf0 }, { ZD_CR123, 0x57 }, { ZD_CR125, 0xad },
-               { ZD_CR126, 0x6c }, { ZD_CR127, 0x03 },
-               { ZD_CR128, 0x14 }, /* 6302 12->11 */
-               { ZD_CR129, 0x12 }, /* 6301 10->0f */
-               { ZD_CR130, 0x10 }, { ZD_CR137, 0x50 }, { ZD_CR138, 0xa8 },
-               { ZD_CR144, 0xac }, { ZD_CR146, 0x20 }, { ZD_CR252, 0xff },
-               { ZD_CR253, 0xff },
-       };
-
-       static const u32 rv[] = {
-               UW2453_REGWRITE(4, 0x2b),    /* configure receiver gain */
-               UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
-               UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
-               UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
-
-               /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
-                * RSSI circuit powered down, reduced RSSI range */
-               UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
-
-               /* synthesizer configuration for channel 1 */
-               UW2453_REGWRITE(1, 0x47),
-               UW2453_REGWRITE(2, 0x999),
-
-               /* disable manual VCO band selection */
-               UW2453_REGWRITE(3, 0x7602),
-
-               /* enable manual VCO band selection, configure current level */
-               UW2453_REGWRITE(3, 0x46063),
-       };
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               return r;
-
-       r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
-       if (r)
-               return r;
-
-       r = uw2453_init_mode(chip);
-       if (r)
-               return r;
-
-       /* Try all standard VCO configuration settings on channel 1 */
-       for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
-               /* Configure synthesizer for channel 1 */
-               r = uw2453_synth_set_channel(chip, 1, false);
-               if (r)
-                       return r;
-
-               /* Write VCO config */
-               r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
-               if (r)
-                       return r;
-
-               /* ack interrupt event */
-               r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
-               if (r)
-                       return r;
-
-               /* check interrupt status */
-               r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
-               if (r)
-                       return r;
-
-               if (!(intr_status & 0xf)) {
-                       dev_dbg_f(zd_chip_dev(chip),
-                               "PLL locked on configuration %d\n", i);
-                       found_config = i;
-                       break;
-               }
-       }
-
-       if (found_config == -1) {
-               /* autocal */
-               dev_dbg_f(zd_chip_dev(chip),
-                       "PLL did not lock, using autocal\n");
-
-               r = uw2453_synth_set_channel(chip, 1, true);
-               if (r)
-                       return r;
-
-               r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
-               if (r)
-                       return r;
-       }
-
-       /* To match the vendor driver behaviour, we use the configuration after
-        * the one that produced a lock. */
-       UW2453_PRIV(rf)->config = found_config + 1;
-
-       return zd_iowrite16_locked(chip, 0x06, ZD_CR203);
-}
-
-static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
-{
-       int r;
-       u16 vco_cfg;
-       int config = UW2453_PRIV(rf)->config;
-       bool autocal = (config == -1);
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 }, { ZD_CR79,  0x58 },
-               { ZD_CR12,  0xf0 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x58 },
-       };
-
-       r = uw2453_synth_set_channel(chip, channel, autocal);
-       if (r)
-               return r;
-
-       if (autocal)
-               vco_cfg = UW2453_AUTOCAL_VCO_CFG;
-       else
-               vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
-
-       r = uw2453_write_vco_cfg(chip, vco_cfg);
-       if (r)
-               return r;
-
-       r = uw2453_init_mode(chip);
-       if (r)
-               return r;
-
-       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-       if (r)
-               return r;
-
-       r = uw2453_set_tx_gain_level(chip, channel);
-       if (r)
-               return r;
-
-       return zd_iowrite16_locked(chip, 0x06, ZD_CR203);
-}
-
-static int uw2453_switch_radio_on(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x00 }, { ZD_CR251, 0x3f },
-       };
-
-       /* enter RXTX mode */
-       r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
-       if (r)
-               return r;
-
-       if (zd_chip_is_zd1211b(chip))
-               ioreqs[1].value = 0x7f;
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static int uw2453_switch_radio_off(struct zd_rf *rf)
-{
-       int r;
-       struct zd_chip *chip = zd_rf_to_chip(rf);
-       static const struct zd_ioreq16 ioreqs[] = {
-               { ZD_CR11,  0x04 }, { ZD_CR251, 0x2f },
-       };
-
-       /* enter IDLE mode */
-       /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
-       r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
-       if (r)
-               return r;
-
-       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
-}
-
-static void uw2453_clear(struct zd_rf *rf)
-{
-       kfree(rf->priv);
-}
-
-int zd_rf_init_uw2453(struct zd_rf *rf)
-{
-       rf->init_hw = uw2453_init_hw;
-       rf->set_channel = uw2453_set_channel;
-       rf->switch_radio_on = uw2453_switch_radio_on;
-       rf->switch_radio_off = uw2453_switch_radio_off;
-       rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
-       rf->clear = uw2453_clear;
-       /* we have our own TX integration code */
-       rf->update_channel_int = 0;
-
-       rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
-       if (rf->priv == NULL)
-               return -ENOMEM;
-
-       return 0;
-}
-
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
deleted file mode 100644 (file)
index a912dc0..0000000
+++ /dev/null
@@ -1,2060 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/firmware.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-#include <linux/workqueue.h>
-#include <linux/module.h>
-#include <net/mac80211.h>
-#include <asm/unaligned.h>
-
-#include "zd_def.h"
-#include "zd_mac.h"
-#include "zd_usb.h"
-
-static struct usb_device_id usb_ids[] = {
-       /* ZD1211 */
-       { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x14ea, 0xab10), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x157e, 0x3207), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
-       /* ZD1211B */
-       { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B },
-       { USB_DEVICE(0x2019, 0xed01), .driver_info = DEVICE_ZD1211B },
-       /* "Driverless" devices that need ejecting */
-       { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
-       { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
-       {}
-};
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip.");
-MODULE_AUTHOR("Ulrich Kunitz");
-MODULE_AUTHOR("Daniel Drake");
-MODULE_VERSION("1.0");
-MODULE_DEVICE_TABLE(usb, usb_ids);
-
-#define FW_ZD1211_PREFIX       "zd1211/zd1211_"
-#define FW_ZD1211B_PREFIX      "zd1211/zd1211b_"
-
-static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
-                           unsigned int count);
-
-/* USB device initialization */
-static void int_urb_complete(struct urb *urb);
-
-static int request_fw_file(
-       const struct firmware **fw, const char *name, struct device *device)
-{
-       int r;
-
-       dev_dbg_f(device, "fw name %s\n", name);
-
-       r = request_firmware(fw, name, device);
-       if (r)
-               dev_err(device,
-                      "Could not load firmware file %s. Error number %d\n",
-                      name, r);
-       return r;
-}
-
-static inline u16 get_bcdDevice(const struct usb_device *udev)
-{
-       return le16_to_cpu(udev->descriptor.bcdDevice);
-}
-
-enum upload_code_flags {
-       REBOOT = 1,
-};
-
-/* Ensures that MAX_TRANSFER_SIZE is even. */
-#define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1)
-
-static int upload_code(struct usb_device *udev,
-       const u8 *data, size_t size, u16 code_offset, int flags)
-{
-       u8 *p;
-       int r;
-
-       /* USB request blocks need "kmalloced" buffers.
-        */
-       p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL);
-       if (!p) {
-               r = -ENOMEM;
-               goto error;
-       }
-
-       size &= ~1;
-       while (size > 0) {
-               size_t transfer_size = size <= MAX_TRANSFER_SIZE ?
-                       size : MAX_TRANSFER_SIZE;
-
-               dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size);
-
-               memcpy(p, data, transfer_size);
-               r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                       USB_REQ_FIRMWARE_DOWNLOAD,
-                       USB_DIR_OUT | USB_TYPE_VENDOR,
-                       code_offset, 0, p, transfer_size, 1000 /* ms */);
-               if (r < 0) {
-                       dev_err(&udev->dev,
-                              "USB control request for firmware upload"
-                              " failed. Error number %d\n", r);
-                       goto error;
-               }
-               transfer_size = r & ~1;
-
-               size -= transfer_size;
-               data += transfer_size;
-               code_offset += transfer_size/sizeof(u16);
-       }
-
-       if (flags & REBOOT) {
-               u8 ret;
-
-               /* Use "DMA-aware" buffer. */
-               r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                       USB_REQ_FIRMWARE_CONFIRM,
-                       USB_DIR_IN | USB_TYPE_VENDOR,
-                       0, 0, p, sizeof(ret), 5000 /* ms */);
-               if (r != sizeof(ret)) {
-                       dev_err(&udev->dev,
-                               "control request firmeware confirmation failed."
-                               " Return value %d\n", r);
-                       if (r >= 0)
-                               r = -ENODEV;
-                       goto error;
-               }
-               ret = p[0];
-               if (ret & 0x80) {
-                       dev_err(&udev->dev,
-                               "Internal error while downloading."
-                               " Firmware confirm return value %#04x\n",
-                               (unsigned int)ret);
-                       r = -ENODEV;
-                       goto error;
-               }
-               dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n",
-                       (unsigned int)ret);
-       }
-
-       r = 0;
-error:
-       kfree(p);
-       return r;
-}
-
-static u16 get_word(const void *data, u16 offset)
-{
-       const __le16 *p = data;
-       return le16_to_cpu(p[offset]);
-}
-
-static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
-                      const char* postfix)
-{
-       scnprintf(buffer, size, "%s%s",
-               usb->is_zd1211b ?
-                       FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
-               postfix);
-       return buffer;
-}
-
-static int handle_version_mismatch(struct zd_usb *usb,
-       const struct firmware *ub_fw)
-{
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       const struct firmware *ur_fw = NULL;
-       int offset;
-       int r = 0;
-       char fw_name[128];
-
-       r = request_fw_file(&ur_fw,
-               get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
-               &udev->dev);
-       if (r)
-               goto error;
-
-       r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START, REBOOT);
-       if (r)
-               goto error;
-
-       offset = (E2P_BOOT_CODE_OFFSET * sizeof(u16));
-       r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset,
-               E2P_START + E2P_BOOT_CODE_OFFSET, REBOOT);
-
-       /* At this point, the vendor driver downloads the whole firmware
-        * image, hacks around with version IDs, and uploads it again,
-        * completely overwriting the boot code. We do not do this here as
-        * it is not required on any tested devices, and it is suspected to
-        * cause problems. */
-error:
-       release_firmware(ur_fw);
-       return r;
-}
-
-static int upload_firmware(struct zd_usb *usb)
-{
-       int r;
-       u16 fw_bcdDevice;
-       u16 bcdDevice;
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       const struct firmware *ub_fw = NULL;
-       const struct firmware *uph_fw = NULL;
-       char fw_name[128];
-
-       bcdDevice = get_bcdDevice(udev);
-
-       r = request_fw_file(&ub_fw,
-               get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
-               &udev->dev);
-       if (r)
-               goto error;
-
-       fw_bcdDevice = get_word(ub_fw->data, E2P_DATA_OFFSET);
-
-       if (fw_bcdDevice != bcdDevice) {
-               dev_info(&udev->dev,
-                       "firmware version %#06x and device bootcode version "
-                       "%#06x differ\n", fw_bcdDevice, bcdDevice);
-               if (bcdDevice <= 0x4313)
-                       dev_warn(&udev->dev, "device has old bootcode, please "
-                               "report success or failure\n");
-
-               r = handle_version_mismatch(usb, ub_fw);
-               if (r)
-                       goto error;
-       } else {
-               dev_dbg_f(&udev->dev,
-                       "firmware device id %#06x is equal to the "
-                       "actual device id\n", fw_bcdDevice);
-       }
-
-
-       r = request_fw_file(&uph_fw,
-               get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
-               &udev->dev);
-       if (r)
-               goto error;
-
-       r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START, REBOOT);
-       if (r) {
-               dev_err(&udev->dev,
-                       "Could not upload firmware code uph. Error number %d\n",
-                       r);
-       }
-
-       /* FALL-THROUGH */
-error:
-       release_firmware(ub_fw);
-       release_firmware(uph_fw);
-       return r;
-}
-
-MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ur");
-MODULE_FIRMWARE(FW_ZD1211_PREFIX "ur");
-MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ub");
-MODULE_FIRMWARE(FW_ZD1211_PREFIX "ub");
-MODULE_FIRMWARE(FW_ZD1211B_PREFIX "uphr");
-MODULE_FIRMWARE(FW_ZD1211_PREFIX "uphr");
-
-/* Read data from device address space using "firmware interface" which does
- * not require firmware to be loaded. */
-int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
-{
-       int r;
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       u8 *buf;
-
-       /* Use "DMA-aware" buffer. */
-       buf = kmalloc(len, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-               USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
-               buf, len, 5000);
-       if (r < 0) {
-               dev_err(&udev->dev,
-                       "read over firmware interface failed: %d\n", r);
-               goto exit;
-       } else if (r != len) {
-               dev_err(&udev->dev,
-                       "incomplete read over firmware interface: %d/%d\n",
-                       r, len);
-               r = -EIO;
-               goto exit;
-       }
-       r = 0;
-       memcpy(data, buf, len);
-exit:
-       kfree(buf);
-       return r;
-}
-
-#define urb_dev(urb) (&(urb)->dev->dev)
-
-static inline void handle_regs_int_override(struct urb *urb)
-{
-       struct zd_usb *usb = urb->context;
-       struct zd_usb_interrupt *intr = &usb->intr;
-
-       spin_lock(&intr->lock);
-       if (atomic_read(&intr->read_regs_enabled)) {
-               atomic_set(&intr->read_regs_enabled, 0);
-               intr->read_regs_int_overridden = 1;
-               complete(&intr->read_regs.completion);
-       }
-       spin_unlock(&intr->lock);
-}
-
-static inline void handle_regs_int(struct urb *urb)
-{
-       struct zd_usb *usb = urb->context;
-       struct zd_usb_interrupt *intr = &usb->intr;
-       int len;
-       u16 int_num;
-
-       ZD_ASSERT(in_interrupt());
-       spin_lock(&intr->lock);
-
-       int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
-       if (int_num == CR_INTERRUPT) {
-               struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
-               spin_lock(&mac->lock);
-               memcpy(&mac->intr_buffer, urb->transfer_buffer,
-                               USB_MAX_EP_INT_BUFFER);
-               spin_unlock(&mac->lock);
-               schedule_work(&mac->process_intr);
-       } else if (atomic_read(&intr->read_regs_enabled)) {
-               len = urb->actual_length;
-               intr->read_regs.length = urb->actual_length;
-               if (len > sizeof(intr->read_regs.buffer))
-                       len = sizeof(intr->read_regs.buffer);
-
-               memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
-
-               /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
-                * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
-                * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
-                * retry unhandled. Next read-reg command then might catch
-                * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
-                */
-               if (!check_read_regs(usb, intr->read_regs.req,
-                                               intr->read_regs.req_count))
-                       goto out;
-
-               atomic_set(&intr->read_regs_enabled, 0);
-               intr->read_regs_int_overridden = 0;
-               complete(&intr->read_regs.completion);
-
-               goto out;
-       }
-
-out:
-       spin_unlock(&intr->lock);
-
-       /* CR_INTERRUPT might override read_reg too. */
-       if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
-               handle_regs_int_override(urb);
-}
-
-static void int_urb_complete(struct urb *urb)
-{
-       int r;
-       struct usb_int_header *hdr;
-       struct zd_usb *usb;
-       struct zd_usb_interrupt *intr;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ESHUTDOWN:
-       case -EINVAL:
-       case -ENODEV:
-       case -ENOENT:
-       case -ECONNRESET:
-       case -EPIPE:
-               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
-               return;
-       default:
-               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
-               goto resubmit;
-       }
-
-       if (urb->actual_length < sizeof(hdr)) {
-               dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb);
-               goto resubmit;
-       }
-
-       hdr = urb->transfer_buffer;
-       if (hdr->type != USB_INT_TYPE) {
-               dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb);
-               goto resubmit;
-       }
-
-       /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
-        * pending USB_INT_ID_REGS causing read command timeout.
-        */
-       usb = urb->context;
-       intr = &usb->intr;
-       if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
-               handle_regs_int_override(urb);
-
-       switch (hdr->id) {
-       case USB_INT_ID_REGS:
-               handle_regs_int(urb);
-               break;
-       case USB_INT_ID_RETRY_FAILED:
-               zd_mac_tx_failed(urb);
-               break;
-       default:
-               dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb,
-                       (unsigned int)hdr->id);
-               goto resubmit;
-       }
-
-resubmit:
-       r = usb_submit_urb(urb, GFP_ATOMIC);
-       if (r) {
-               dev_dbg_f(urb_dev(urb), "error: resubmit urb %p err code %d\n",
-                         urb, r);
-               /* TODO: add worker to reset intr->urb */
-       }
-       return;
-}
-
-static inline int int_urb_interval(struct usb_device *udev)
-{
-       switch (udev->speed) {
-       case USB_SPEED_HIGH:
-               return 4;
-       case USB_SPEED_LOW:
-               return 10;
-       case USB_SPEED_FULL:
-       default:
-               return 1;
-       }
-}
-
-static inline int usb_int_enabled(struct zd_usb *usb)
-{
-       unsigned long flags;
-       struct zd_usb_interrupt *intr = &usb->intr;
-       struct urb *urb;
-
-       spin_lock_irqsave(&intr->lock, flags);
-       urb = intr->urb;
-       spin_unlock_irqrestore(&intr->lock, flags);
-       return urb != NULL;
-}
-
-int zd_usb_enable_int(struct zd_usb *usb)
-{
-       int r;
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       struct zd_usb_interrupt *intr = &usb->intr;
-       struct urb *urb;
-
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!urb) {
-               r = -ENOMEM;
-               goto out;
-       }
-
-       ZD_ASSERT(!irqs_disabled());
-       spin_lock_irq(&intr->lock);
-       if (intr->urb) {
-               spin_unlock_irq(&intr->lock);
-               r = 0;
-               goto error_free_urb;
-       }
-       intr->urb = urb;
-       spin_unlock_irq(&intr->lock);
-
-       r = -ENOMEM;
-       intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER,
-                                         GFP_KERNEL, &intr->buffer_dma);
-       if (!intr->buffer) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "couldn't allocate transfer_buffer\n");
-               goto error_set_urb_null;
-       }
-
-       usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN),
-                        intr->buffer, USB_MAX_EP_INT_BUFFER,
-                        int_urb_complete, usb,
-                        intr->interval);
-       urb->transfer_dma = intr->buffer_dma;
-       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
-       r = usb_submit_urb(urb, GFP_KERNEL);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                        "Couldn't submit urb. Error number %d\n", r);
-               goto error;
-       }
-
-       return 0;
-error:
-       usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
-                         intr->buffer, intr->buffer_dma);
-error_set_urb_null:
-       spin_lock_irq(&intr->lock);
-       intr->urb = NULL;
-       spin_unlock_irq(&intr->lock);
-error_free_urb:
-       usb_free_urb(urb);
-out:
-       return r;
-}
-
-void zd_usb_disable_int(struct zd_usb *usb)
-{
-       unsigned long flags;
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       struct zd_usb_interrupt *intr = &usb->intr;
-       struct urb *urb;
-       void *buffer;
-       dma_addr_t buffer_dma;
-
-       spin_lock_irqsave(&intr->lock, flags);
-       urb = intr->urb;
-       if (!urb) {
-               spin_unlock_irqrestore(&intr->lock, flags);
-               return;
-       }
-       intr->urb = NULL;
-       buffer = intr->buffer;
-       buffer_dma = intr->buffer_dma;
-       intr->buffer = NULL;
-       spin_unlock_irqrestore(&intr->lock, flags);
-
-       usb_kill_urb(urb);
-       dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb);
-       usb_free_urb(urb);
-
-       if (buffer)
-               usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
-                                 buffer, buffer_dma);
-}
-
-static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
-                            unsigned int length)
-{
-       int i;
-       const struct rx_length_info *length_info;
-
-       if (length < sizeof(struct rx_length_info)) {
-               /* It's not a complete packet anyhow. */
-               dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
-                                          length);
-               return;
-       }
-       length_info = (struct rx_length_info *)
-               (buffer + length - sizeof(struct rx_length_info));
-
-       /* It might be that three frames are merged into a single URB
-        * transaction. We have to check for the length info tag.
-        *
-        * While testing we discovered that length_info might be unaligned,
-        * because if USB transactions are merged, the last packet will not
-        * be padded. Unaligned access might also happen if the length_info
-        * structure is not present.
-        */
-       if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG)
-       {
-               unsigned int l, k, n;
-               for (i = 0, l = 0;; i++) {
-                       k = get_unaligned_le16(&length_info->length[i]);
-                       if (k == 0)
-                               return;
-                       n = l+k;
-                       if (n > length)
-                               return;
-                       zd_mac_rx(zd_usb_to_hw(usb), buffer+l, k);
-                       if (i >= 2)
-                               return;
-                       l = (n+3) & ~3;
-               }
-       } else {
-               zd_mac_rx(zd_usb_to_hw(usb), buffer, length);
-       }
-}
-
-static void rx_urb_complete(struct urb *urb)
-{
-       int r;
-       struct zd_usb *usb;
-       struct zd_usb_rx *rx;
-       const u8 *buffer;
-       unsigned int length;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ESHUTDOWN:
-       case -EINVAL:
-       case -ENODEV:
-       case -ENOENT:
-       case -ECONNRESET:
-       case -EPIPE:
-               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
-               return;
-       default:
-               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
-               goto resubmit;
-       }
-
-       buffer = urb->transfer_buffer;
-       length = urb->actual_length;
-       usb = urb->context;
-       rx = &usb->rx;
-
-       tasklet_schedule(&rx->reset_timer_tasklet);
-
-       if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
-               /* If there is an old first fragment, we don't care. */
-               dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
-               ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment));
-               spin_lock(&rx->lock);
-               memcpy(rx->fragment, buffer, length);
-               rx->fragment_length = length;
-               spin_unlock(&rx->lock);
-               goto resubmit;
-       }
-
-       spin_lock(&rx->lock);
-       if (rx->fragment_length > 0) {
-               /* We are on a second fragment, we believe */
-               ZD_ASSERT(length + rx->fragment_length <=
-                         ARRAY_SIZE(rx->fragment));
-               dev_dbg_f(urb_dev(urb), "*** second fragment ***\n");
-               memcpy(rx->fragment+rx->fragment_length, buffer, length);
-               handle_rx_packet(usb, rx->fragment,
-                                rx->fragment_length + length);
-               rx->fragment_length = 0;
-               spin_unlock(&rx->lock);
-       } else {
-               spin_unlock(&rx->lock);
-               handle_rx_packet(usb, buffer, length);
-       }
-
-resubmit:
-       r = usb_submit_urb(urb, GFP_ATOMIC);
-       if (r)
-               dev_dbg_f(urb_dev(urb), "urb %p resubmit error %d\n", urb, r);
-}
-
-static struct urb *alloc_rx_urb(struct zd_usb *usb)
-{
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       struct urb *urb;
-       void *buffer;
-
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!urb)
-               return NULL;
-       buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
-                                   &urb->transfer_dma);
-       if (!buffer) {
-               usb_free_urb(urb);
-               return NULL;
-       }
-
-       usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
-                         buffer, USB_MAX_RX_SIZE,
-                         rx_urb_complete, usb);
-       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       return urb;
-}
-
-static void free_rx_urb(struct urb *urb)
-{
-       if (!urb)
-               return;
-       usb_free_coherent(urb->dev, urb->transfer_buffer_length,
-                         urb->transfer_buffer, urb->transfer_dma);
-       usb_free_urb(urb);
-}
-
-static int __zd_usb_enable_rx(struct zd_usb *usb)
-{
-       int i, r;
-       struct zd_usb_rx *rx = &usb->rx;
-       struct urb **urbs;
-
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       r = -ENOMEM;
-       urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
-       if (!urbs)
-               goto error;
-       for (i = 0; i < RX_URBS_COUNT; i++) {
-               urbs[i] = alloc_rx_urb(usb);
-               if (!urbs[i])
-                       goto error;
-       }
-
-       ZD_ASSERT(!irqs_disabled());
-       spin_lock_irq(&rx->lock);
-       if (rx->urbs) {
-               spin_unlock_irq(&rx->lock);
-               r = 0;
-               goto error;
-       }
-       rx->urbs = urbs;
-       rx->urbs_count = RX_URBS_COUNT;
-       spin_unlock_irq(&rx->lock);
-
-       for (i = 0; i < RX_URBS_COUNT; i++) {
-               r = usb_submit_urb(urbs[i], GFP_KERNEL);
-               if (r)
-                       goto error_submit;
-       }
-
-       return 0;
-error_submit:
-       for (i = 0; i < RX_URBS_COUNT; i++) {
-               usb_kill_urb(urbs[i]);
-       }
-       spin_lock_irq(&rx->lock);
-       rx->urbs = NULL;
-       rx->urbs_count = 0;
-       spin_unlock_irq(&rx->lock);
-error:
-       if (urbs) {
-               for (i = 0; i < RX_URBS_COUNT; i++)
-                       free_rx_urb(urbs[i]);
-       }
-       return r;
-}
-
-int zd_usb_enable_rx(struct zd_usb *usb)
-{
-       int r;
-       struct zd_usb_rx *rx = &usb->rx;
-
-       mutex_lock(&rx->setup_mutex);
-       r = __zd_usb_enable_rx(usb);
-       mutex_unlock(&rx->setup_mutex);
-
-       zd_usb_reset_rx_idle_timer(usb);
-
-       return r;
-}
-
-static void __zd_usb_disable_rx(struct zd_usb *usb)
-{
-       int i;
-       unsigned long flags;
-       struct urb **urbs;
-       unsigned int count;
-       struct zd_usb_rx *rx = &usb->rx;
-
-       spin_lock_irqsave(&rx->lock, flags);
-       urbs = rx->urbs;
-       count = rx->urbs_count;
-       spin_unlock_irqrestore(&rx->lock, flags);
-       if (!urbs)
-               return;
-
-       for (i = 0; i < count; i++) {
-               usb_kill_urb(urbs[i]);
-               free_rx_urb(urbs[i]);
-       }
-       kfree(urbs);
-
-       spin_lock_irqsave(&rx->lock, flags);
-       rx->urbs = NULL;
-       rx->urbs_count = 0;
-       spin_unlock_irqrestore(&rx->lock, flags);
-}
-
-void zd_usb_disable_rx(struct zd_usb *usb)
-{
-       struct zd_usb_rx *rx = &usb->rx;
-
-       mutex_lock(&rx->setup_mutex);
-       __zd_usb_disable_rx(usb);
-       mutex_unlock(&rx->setup_mutex);
-
-       tasklet_kill(&rx->reset_timer_tasklet);
-       cancel_delayed_work_sync(&rx->idle_work);
-}
-
-static void zd_usb_reset_rx(struct zd_usb *usb)
-{
-       bool do_reset;
-       struct zd_usb_rx *rx = &usb->rx;
-       unsigned long flags;
-
-       mutex_lock(&rx->setup_mutex);
-
-       spin_lock_irqsave(&rx->lock, flags);
-       do_reset = rx->urbs != NULL;
-       spin_unlock_irqrestore(&rx->lock, flags);
-
-       if (do_reset) {
-               __zd_usb_disable_rx(usb);
-               __zd_usb_enable_rx(usb);
-       }
-
-       mutex_unlock(&rx->setup_mutex);
-
-       if (do_reset)
-               zd_usb_reset_rx_idle_timer(usb);
-}
-
-/**
- * zd_usb_disable_tx - disable transmission
- * @usb: the zd1211rw-private USB structure
- *
- * Frees all URBs in the free list and marks the transmission as disabled.
- */
-void zd_usb_disable_tx(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-       unsigned long flags;
-
-       atomic_set(&tx->enabled, 0);
-
-       /* kill all submitted tx-urbs */
-       usb_kill_anchored_urbs(&tx->submitted);
-
-       spin_lock_irqsave(&tx->lock, flags);
-       WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
-       WARN_ON(tx->submitted_urbs != 0);
-       tx->submitted_urbs = 0;
-       spin_unlock_irqrestore(&tx->lock, flags);
-
-       /* The stopped state is ignored, relying on ieee80211_wake_queues()
-        * in a potentionally following zd_usb_enable_tx().
-        */
-}
-
-/**
- * zd_usb_enable_tx - enables transmission
- * @usb: a &struct zd_usb pointer
- *
- * This function enables transmission and prepares the &zd_usb_tx data
- * structure.
- */
-void zd_usb_enable_tx(struct zd_usb *usb)
-{
-       unsigned long flags;
-       struct zd_usb_tx *tx = &usb->tx;
-
-       spin_lock_irqsave(&tx->lock, flags);
-       atomic_set(&tx->enabled, 1);
-       tx->submitted_urbs = 0;
-       ieee80211_wake_queues(zd_usb_to_hw(usb));
-       tx->stopped = 0;
-       spin_unlock_irqrestore(&tx->lock, flags);
-}
-
-static void tx_dec_submitted_urbs(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tx->lock, flags);
-       --tx->submitted_urbs;
-       if (tx->stopped && tx->submitted_urbs <= ZD_USB_TX_LOW) {
-               ieee80211_wake_queues(zd_usb_to_hw(usb));
-               tx->stopped = 0;
-       }
-       spin_unlock_irqrestore(&tx->lock, flags);
-}
-
-static void tx_inc_submitted_urbs(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-       unsigned long flags;
-
-       spin_lock_irqsave(&tx->lock, flags);
-       ++tx->submitted_urbs;
-       if (!tx->stopped && tx->submitted_urbs > ZD_USB_TX_HIGH) {
-               ieee80211_stop_queues(zd_usb_to_hw(usb));
-               tx->stopped = 1;
-       }
-       spin_unlock_irqrestore(&tx->lock, flags);
-}
-
-/**
- * tx_urb_complete - completes the execution of an URB
- * @urb: a URB
- *
- * This function is called if the URB has been transferred to a device or an
- * error has happened.
- */
-static void tx_urb_complete(struct urb *urb)
-{
-       int r;
-       struct sk_buff *skb;
-       struct ieee80211_tx_info *info;
-       struct zd_usb *usb;
-       struct zd_usb_tx *tx;
-
-       skb = (struct sk_buff *)urb->context;
-       info = IEEE80211_SKB_CB(skb);
-       /*
-        * grab 'usb' pointer before handing off the skb (since
-        * it might be freed by zd_mac_tx_to_dev or mac80211)
-        */
-       usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
-       tx = &usb->tx;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ESHUTDOWN:
-       case -EINVAL:
-       case -ENODEV:
-       case -ENOENT:
-       case -ECONNRESET:
-       case -EPIPE:
-               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
-               break;
-       default:
-               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
-               goto resubmit;
-       }
-free_urb:
-       skb_unlink(skb, &usb->tx.submitted_skbs);
-       zd_mac_tx_to_dev(skb, urb->status);
-       usb_free_urb(urb);
-       tx_dec_submitted_urbs(usb);
-       return;
-resubmit:
-       usb_anchor_urb(urb, &tx->submitted);
-       r = usb_submit_urb(urb, GFP_ATOMIC);
-       if (r) {
-               usb_unanchor_urb(urb);
-               dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
-               goto free_urb;
-       }
-}
-
-/**
- * zd_usb_tx: initiates transfer of a frame of the device
- *
- * @usb: the zd1211rw-private USB structure
- * @skb: a &struct sk_buff pointer
- *
- * This function tranmits a frame to the device. It doesn't wait for
- * completion. The frame must contain the control set and have all the
- * control set information available.
- *
- * The function returns 0 if the transfer has been successfully initiated.
- */
-int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
-{
-       int r;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct usb_device *udev = zd_usb_to_usbdev(usb);
-       struct urb *urb;
-       struct zd_usb_tx *tx = &usb->tx;
-
-       if (!atomic_read(&tx->enabled)) {
-               r = -ENOENT;
-               goto out;
-       }
-
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               r = -ENOMEM;
-               goto out;
-       }
-
-       usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
-                         skb->data, skb->len, tx_urb_complete, skb);
-
-       info->rate_driver_data[1] = (void *)jiffies;
-       skb_queue_tail(&tx->submitted_skbs, skb);
-       usb_anchor_urb(urb, &tx->submitted);
-
-       r = usb_submit_urb(urb, GFP_ATOMIC);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r);
-               usb_unanchor_urb(urb);
-               skb_unlink(skb, &tx->submitted_skbs);
-               goto error;
-       }
-       tx_inc_submitted_urbs(usb);
-       return 0;
-error:
-       usb_free_urb(urb);
-out:
-       return r;
-}
-
-static bool zd_tx_timeout(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-       struct sk_buff_head *q = &tx->submitted_skbs;
-       struct sk_buff *skb, *skbnext;
-       struct ieee80211_tx_info *info;
-       unsigned long flags, trans_start;
-       bool have_timedout = false;
-
-       spin_lock_irqsave(&q->lock, flags);
-       skb_queue_walk_safe(q, skb, skbnext) {
-               info = IEEE80211_SKB_CB(skb);
-               trans_start = (unsigned long)info->rate_driver_data[1];
-
-               if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) {
-                       have_timedout = true;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&q->lock, flags);
-
-       return have_timedout;
-}
-
-static void zd_tx_watchdog_handler(struct work_struct *work)
-{
-       struct zd_usb *usb =
-               container_of(work, struct zd_usb, tx.watchdog_work.work);
-       struct zd_usb_tx *tx = &usb->tx;
-
-       if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled)
-               goto out;
-       if (!zd_tx_timeout(usb))
-               goto out;
-
-       /* TX halted, try reset */
-       dev_warn(zd_usb_dev(usb), "TX-stall detected, resetting device...");
-
-       usb_queue_reset_device(usb->intf);
-
-       /* reset will stop this worker, don't rearm */
-       return;
-out:
-       queue_delayed_work(zd_workqueue, &tx->watchdog_work,
-                          ZD_TX_WATCHDOG_INTERVAL);
-}
-
-void zd_tx_watchdog_enable(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-
-       if (!tx->watchdog_enabled) {
-               dev_dbg_f(zd_usb_dev(usb), "\n");
-               queue_delayed_work(zd_workqueue, &tx->watchdog_work,
-                                  ZD_TX_WATCHDOG_INTERVAL);
-               tx->watchdog_enabled = 1;
-       }
-}
-
-void zd_tx_watchdog_disable(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-
-       if (tx->watchdog_enabled) {
-               dev_dbg_f(zd_usb_dev(usb), "\n");
-               tx->watchdog_enabled = 0;
-               cancel_delayed_work_sync(&tx->watchdog_work);
-       }
-}
-
-static void zd_rx_idle_timer_handler(struct work_struct *work)
-{
-       struct zd_usb *usb =
-               container_of(work, struct zd_usb, rx.idle_work.work);
-       struct zd_mac *mac = zd_usb_to_mac(usb);
-
-       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
-               return;
-
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       /* 30 seconds since last rx, reset rx */
-       zd_usb_reset_rx(usb);
-}
-
-static void zd_usb_reset_rx_idle_timer_tasklet(unsigned long param)
-{
-       struct zd_usb *usb = (struct zd_usb *)param;
-
-       zd_usb_reset_rx_idle_timer(usb);
-}
-
-void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
-{
-       struct zd_usb_rx *rx = &usb->rx;
-
-       mod_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
-}
-
-static inline void init_usb_interrupt(struct zd_usb *usb)
-{
-       struct zd_usb_interrupt *intr = &usb->intr;
-
-       spin_lock_init(&intr->lock);
-       intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
-       init_completion(&intr->read_regs.completion);
-       atomic_set(&intr->read_regs_enabled, 0);
-       intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
-}
-
-static inline void init_usb_rx(struct zd_usb *usb)
-{
-       struct zd_usb_rx *rx = &usb->rx;
-
-       spin_lock_init(&rx->lock);
-       mutex_init(&rx->setup_mutex);
-       if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
-               rx->usb_packet_size = 512;
-       } else {
-               rx->usb_packet_size = 64;
-       }
-       ZD_ASSERT(rx->fragment_length == 0);
-       INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
-       rx->reset_timer_tasklet.func = zd_usb_reset_rx_idle_timer_tasklet;
-       rx->reset_timer_tasklet.data = (unsigned long)usb;
-}
-
-static inline void init_usb_tx(struct zd_usb *usb)
-{
-       struct zd_usb_tx *tx = &usb->tx;
-
-       spin_lock_init(&tx->lock);
-       atomic_set(&tx->enabled, 0);
-       tx->stopped = 0;
-       skb_queue_head_init(&tx->submitted_skbs);
-       init_usb_anchor(&tx->submitted);
-       tx->submitted_urbs = 0;
-       tx->watchdog_enabled = 0;
-       INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler);
-}
-
-void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
-                struct usb_interface *intf)
-{
-       memset(usb, 0, sizeof(*usb));
-       usb->intf = usb_get_intf(intf);
-       usb_set_intfdata(usb->intf, hw);
-       init_usb_anchor(&usb->submitted_cmds);
-       init_usb_interrupt(usb);
-       init_usb_tx(usb);
-       init_usb_rx(usb);
-}
-
-void zd_usb_clear(struct zd_usb *usb)
-{
-       usb_set_intfdata(usb->intf, NULL);
-       usb_put_intf(usb->intf);
-       ZD_MEMCLEAR(usb, sizeof(*usb));
-       /* FIXME: usb_interrupt, usb_tx, usb_rx? */
-}
-
-static const char *speed(enum usb_device_speed speed)
-{
-       switch (speed) {
-       case USB_SPEED_LOW:
-               return "low";
-       case USB_SPEED_FULL:
-               return "full";
-       case USB_SPEED_HIGH:
-               return "high";
-       default:
-               return "unknown speed";
-       }
-}
-
-static int scnprint_id(struct usb_device *udev, char *buffer, size_t size)
-{
-       return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s",
-               le16_to_cpu(udev->descriptor.idVendor),
-               le16_to_cpu(udev->descriptor.idProduct),
-               get_bcdDevice(udev),
-               speed(udev->speed));
-}
-
-int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size)
-{
-       struct usb_device *udev = interface_to_usbdev(usb->intf);
-       return scnprint_id(udev, buffer, size);
-}
-
-#ifdef DEBUG
-static void print_id(struct usb_device *udev)
-{
-       char buffer[40];
-
-       scnprint_id(udev, buffer, sizeof(buffer));
-       buffer[sizeof(buffer)-1] = 0;
-       dev_dbg_f(&udev->dev, "%s\n", buffer);
-}
-#else
-#define print_id(udev) do { } while (0)
-#endif
-
-static int eject_installer(struct usb_interface *intf)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct usb_host_interface *iface_desc = &intf->altsetting[0];
-       struct usb_endpoint_descriptor *endpoint;
-       unsigned char *cmd;
-       u8 bulk_out_ep;
-       int r;
-
-       /* Find bulk out endpoint */
-       for (r = 1; r >= 0; r--) {
-               endpoint = &iface_desc->endpoint[r].desc;
-               if (usb_endpoint_dir_out(endpoint) &&
-                   usb_endpoint_xfer_bulk(endpoint)) {
-                       bulk_out_ep = endpoint->bEndpointAddress;
-                       break;
-               }
-       }
-       if (r == -1) {
-               dev_err(&udev->dev,
-                       "zd1211rw: Could not find bulk out endpoint\n");
-               return -ENODEV;
-       }
-
-       cmd = kzalloc(31, GFP_KERNEL);
-       if (cmd == NULL)
-               return -ENODEV;
-
-       /* USB bulk command block */
-       cmd[0] = 0x55;  /* bulk command signature */
-       cmd[1] = 0x53;  /* bulk command signature */
-       cmd[2] = 0x42;  /* bulk command signature */
-       cmd[3] = 0x43;  /* bulk command signature */
-       cmd[14] = 6;    /* command length */
-
-       cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
-       cmd[19] = 0x2;  /* eject disc */
-
-       dev_info(&udev->dev, "Ejecting virtual installer media...\n");
-       r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
-               cmd, 31, NULL, 2000);
-       kfree(cmd);
-       if (r)
-               return r;
-
-       /* At this point, the device disconnects and reconnects with the real
-        * ID numbers. */
-
-       usb_set_intfdata(intf, NULL);
-       return 0;
-}
-
-int zd_usb_init_hw(struct zd_usb *usb)
-{
-       int r;
-       struct zd_mac *mac = zd_usb_to_mac(usb);
-
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       r = upload_firmware(usb);
-       if (r) {
-               dev_err(zd_usb_dev(usb),
-                      "couldn't load firmware. Error number %d\n", r);
-               return r;
-       }
-
-       r = usb_reset_configuration(zd_usb_to_usbdev(usb));
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "couldn't reset configuration. Error number %d\n", r);
-               return r;
-       }
-
-       r = zd_mac_init_hw(mac->hw);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                        "couldn't initialize mac. Error number %d\n", r);
-               return r;
-       }
-
-       usb->initialized = 1;
-       return 0;
-}
-
-static int probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       int r;
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct zd_usb *usb;
-       struct ieee80211_hw *hw = NULL;
-
-       print_id(udev);
-
-       if (id->driver_info & DEVICE_INSTALLER)
-               return eject_installer(intf);
-
-       switch (udev->speed) {
-       case USB_SPEED_LOW:
-       case USB_SPEED_FULL:
-       case USB_SPEED_HIGH:
-               break;
-       default:
-               dev_dbg_f(&intf->dev, "Unknown USB speed\n");
-               r = -ENODEV;
-               goto error;
-       }
-
-       r = usb_reset_device(udev);
-       if (r) {
-               dev_err(&intf->dev,
-                       "couldn't reset usb device. Error number %d\n", r);
-               goto error;
-       }
-
-       hw = zd_mac_alloc_hw(intf);
-       if (hw == NULL) {
-               r = -ENOMEM;
-               goto error;
-       }
-
-       usb = &zd_hw_mac(hw)->chip.usb;
-       usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
-
-       r = zd_mac_preinit_hw(hw);
-       if (r) {
-               dev_dbg_f(&intf->dev,
-                        "couldn't initialize mac. Error number %d\n", r);
-               goto error;
-       }
-
-       r = ieee80211_register_hw(hw);
-       if (r) {
-               dev_dbg_f(&intf->dev,
-                        "couldn't register device. Error number %d\n", r);
-               goto error;
-       }
-
-       dev_dbg_f(&intf->dev, "successful\n");
-       dev_info(&intf->dev, "%s\n", wiphy_name(hw->wiphy));
-       return 0;
-error:
-       usb_reset_device(interface_to_usbdev(intf));
-       if (hw) {
-               zd_mac_clear(zd_hw_mac(hw));
-               ieee80211_free_hw(hw);
-       }
-       return r;
-}
-
-static void disconnect(struct usb_interface *intf)
-{
-       struct ieee80211_hw *hw = zd_intf_to_hw(intf);
-       struct zd_mac *mac;
-       struct zd_usb *usb;
-
-       /* Either something really bad happened, or we're just dealing with
-        * a DEVICE_INSTALLER. */
-       if (hw == NULL)
-               return;
-
-       mac = zd_hw_mac(hw);
-       usb = &mac->chip.usb;
-
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       ieee80211_unregister_hw(hw);
-
-       /* Just in case something has gone wrong! */
-       zd_usb_disable_tx(usb);
-       zd_usb_disable_rx(usb);
-       zd_usb_disable_int(usb);
-
-       /* If the disconnect has been caused by a removal of the
-        * driver module, the reset allows reloading of the driver. If the
-        * reset will not be executed here, the upload of the firmware in the
-        * probe function caused by the reloading of the driver will fail.
-        */
-       usb_reset_device(interface_to_usbdev(intf));
-
-       zd_mac_clear(mac);
-       ieee80211_free_hw(hw);
-       dev_dbg(&intf->dev, "disconnected\n");
-}
-
-static void zd_usb_resume(struct zd_usb *usb)
-{
-       struct zd_mac *mac = zd_usb_to_mac(usb);
-       int r;
-
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       r = zd_op_start(zd_usb_to_hw(usb));
-       if (r < 0) {
-               dev_warn(zd_usb_dev(usb), "Device resume failed "
-                        "with error code %d. Retrying...\n", r);
-               if (usb->was_running)
-                       set_bit(ZD_DEVICE_RUNNING, &mac->flags);
-               usb_queue_reset_device(usb->intf);
-               return;
-       }
-
-       if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
-               r = zd_restore_settings(mac);
-               if (r < 0) {
-                       dev_dbg(zd_usb_dev(usb),
-                               "failed to restore settings, %d\n", r);
-                       return;
-               }
-       }
-}
-
-static void zd_usb_stop(struct zd_usb *usb)
-{
-       dev_dbg_f(zd_usb_dev(usb), "\n");
-
-       zd_op_stop(zd_usb_to_hw(usb));
-
-       zd_usb_disable_tx(usb);
-       zd_usb_disable_rx(usb);
-       zd_usb_disable_int(usb);
-
-       usb->initialized = 0;
-}
-
-static int pre_reset(struct usb_interface *intf)
-{
-       struct ieee80211_hw *hw = usb_get_intfdata(intf);
-       struct zd_mac *mac;
-       struct zd_usb *usb;
-
-       if (!hw || intf->condition != USB_INTERFACE_BOUND)
-               return 0;
-
-       mac = zd_hw_mac(hw);
-       usb = &mac->chip.usb;
-
-       usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags);
-
-       zd_usb_stop(usb);
-
-       mutex_lock(&mac->chip.mutex);
-       return 0;
-}
-
-static int post_reset(struct usb_interface *intf)
-{
-       struct ieee80211_hw *hw = usb_get_intfdata(intf);
-       struct zd_mac *mac;
-       struct zd_usb *usb;
-
-       if (!hw || intf->condition != USB_INTERFACE_BOUND)
-               return 0;
-
-       mac = zd_hw_mac(hw);
-       usb = &mac->chip.usb;
-
-       mutex_unlock(&mac->chip.mutex);
-
-       if (usb->was_running)
-               zd_usb_resume(usb);
-       return 0;
-}
-
-static struct usb_driver driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = usb_ids,
-       .probe          = probe,
-       .disconnect     = disconnect,
-       .pre_reset      = pre_reset,
-       .post_reset     = post_reset,
-       .disable_hub_initiated_lpm = 1,
-};
-
-struct workqueue_struct *zd_workqueue;
-
-static int __init usb_init(void)
-{
-       int r;
-
-       pr_debug("%s usb_init()\n", driver.name);
-
-       zd_workqueue = create_singlethread_workqueue(driver.name);
-       if (zd_workqueue == NULL) {
-               printk(KERN_ERR "%s couldn't create workqueue\n", driver.name);
-               return -ENOMEM;
-       }
-
-       r = usb_register(&driver);
-       if (r) {
-               destroy_workqueue(zd_workqueue);
-               printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
-                      driver.name, r);
-               return r;
-       }
-
-       pr_debug("%s initialized\n", driver.name);
-       return 0;
-}
-
-static void __exit usb_exit(void)
-{
-       pr_debug("%s usb_exit()\n", driver.name);
-       usb_deregister(&driver);
-       destroy_workqueue(zd_workqueue);
-}
-
-module_init(usb_init);
-module_exit(usb_exit);
-
-static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len,
-                             int *actual_length, int timeout)
-{
-       /* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in
-        * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint
-        * descriptor.
-        */
-       struct usb_host_endpoint *ep;
-       unsigned int pipe;
-
-       pipe = usb_sndintpipe(udev, EP_REGS_OUT);
-       ep = usb_pipe_endpoint(udev, pipe);
-       if (!ep)
-               return -EINVAL;
-
-       if (usb_endpoint_xfer_int(&ep->desc)) {
-               return usb_interrupt_msg(udev, pipe, data, len,
-                                        actual_length, timeout);
-       } else {
-               pipe = usb_sndbulkpipe(udev, EP_REGS_OUT);
-               return usb_bulk_msg(udev, pipe, data, len, actual_length,
-                                   timeout);
-       }
-}
-
-static int usb_int_regs_length(unsigned int count)
-{
-       return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
-}
-
-static void prepare_read_regs_int(struct zd_usb *usb,
-                                 struct usb_req_read_regs *req,
-                                 unsigned int count)
-{
-       struct zd_usb_interrupt *intr = &usb->intr;
-
-       spin_lock_irq(&intr->lock);
-       atomic_set(&intr->read_regs_enabled, 1);
-       intr->read_regs.req = req;
-       intr->read_regs.req_count = count;
-       reinit_completion(&intr->read_regs.completion);
-       spin_unlock_irq(&intr->lock);
-}
-
-static void disable_read_regs_int(struct zd_usb *usb)
-{
-       struct zd_usb_interrupt *intr = &usb->intr;
-
-       spin_lock_irq(&intr->lock);
-       atomic_set(&intr->read_regs_enabled, 0);
-       spin_unlock_irq(&intr->lock);
-}
-
-static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
-                           unsigned int count)
-{
-       int i;
-       struct zd_usb_interrupt *intr = &usb->intr;
-       struct read_regs_int *rr = &intr->read_regs;
-       struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
-
-       /* The created block size seems to be larger than expected.
-        * However results appear to be correct.
-        */
-       if (rr->length < usb_int_regs_length(count)) {
-               dev_dbg_f(zd_usb_dev(usb),
-                        "error: actual length %d less than expected %d\n",
-                        rr->length, usb_int_regs_length(count));
-               return false;
-       }
-
-       if (rr->length > sizeof(rr->buffer)) {
-               dev_dbg_f(zd_usb_dev(usb),
-                        "error: actual length %d exceeds buffer size %zu\n",
-                        rr->length, sizeof(rr->buffer));
-               return false;
-       }
-
-       for (i = 0; i < count; i++) {
-               struct reg_data *rd = &regs->regs[i];
-               if (rd->addr != req->addr[i]) {
-                       dev_dbg_f(zd_usb_dev(usb),
-                                "rd[%d] addr %#06hx expected %#06hx\n", i,
-                                le16_to_cpu(rd->addr),
-                                le16_to_cpu(req->addr[i]));
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-static int get_results(struct zd_usb *usb, u16 *values,
-                      struct usb_req_read_regs *req, unsigned int count,
-                      bool *retry)
-{
-       int r;
-       int i;
-       struct zd_usb_interrupt *intr = &usb->intr;
-       struct read_regs_int *rr = &intr->read_regs;
-       struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
-
-       spin_lock_irq(&intr->lock);
-
-       r = -EIO;
-
-       /* Read failed because firmware bug? */
-       *retry = !!intr->read_regs_int_overridden;
-       if (*retry)
-               goto error_unlock;
-
-       if (!check_read_regs(usb, req, count)) {
-               dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
-               goto error_unlock;
-       }
-
-       for (i = 0; i < count; i++) {
-               struct reg_data *rd = &regs->regs[i];
-               values[i] = le16_to_cpu(rd->value);
-       }
-
-       r = 0;
-error_unlock:
-       spin_unlock_irq(&intr->lock);
-       return r;
-}
-
-int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
-                    const zd_addr_t *addresses, unsigned int count)
-{
-       int r, i, req_len, actual_req_len, try_count = 0;
-       struct usb_device *udev;
-       struct usb_req_read_regs *req = NULL;
-       unsigned long timeout;
-       bool retry = false;
-
-       if (count < 1) {
-               dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
-               return -EINVAL;
-       }
-       if (count > USB_MAX_IOREAD16_COUNT) {
-               dev_dbg_f(zd_usb_dev(usb),
-                        "error: count %u exceeds possible max %u\n",
-                        count, USB_MAX_IOREAD16_COUNT);
-               return -EINVAL;
-       }
-       if (in_atomic()) {
-               dev_dbg_f(zd_usb_dev(usb),
-                        "error: io in atomic context not supported\n");
-               return -EWOULDBLOCK;
-       }
-       if (!usb_int_enabled(usb)) {
-               dev_dbg_f(zd_usb_dev(usb),
-                         "error: usb interrupt not enabled\n");
-               return -EWOULDBLOCK;
-       }
-
-       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
-       BUILD_BUG_ON(sizeof(struct usb_req_read_regs) + USB_MAX_IOREAD16_COUNT *
-                    sizeof(__le16) > sizeof(usb->req_buf));
-       BUG_ON(sizeof(struct usb_req_read_regs) + count * sizeof(__le16) >
-              sizeof(usb->req_buf));
-
-       req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
-       req = (void *)usb->req_buf;
-
-       req->id = cpu_to_le16(USB_REQ_READ_REGS);
-       for (i = 0; i < count; i++)
-               req->addr[i] = cpu_to_le16((u16)addresses[i]);
-
-retry_read:
-       try_count++;
-       udev = zd_usb_to_usbdev(usb);
-       prepare_read_regs_int(usb, req, count);
-       r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error in zd_ep_regs_out_msg(). Error number %d\n", r);
-               goto error;
-       }
-       if (req_len != actual_req_len) {
-               dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n"
-                       " req_len %d != actual_req_len %d\n",
-                       req_len, actual_req_len);
-               r = -EIO;
-               goto error;
-       }
-
-       timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion,
-                                             msecs_to_jiffies(50));
-       if (!timeout) {
-               disable_read_regs_int(usb);
-               dev_dbg_f(zd_usb_dev(usb), "read timed out\n");
-               r = -ETIMEDOUT;
-               goto error;
-       }
-
-       r = get_results(usb, values, req, count, &retry);
-       if (retry && try_count < 20) {
-               dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
-                               try_count);
-               goto retry_read;
-       }
-error:
-       return r;
-}
-
-static void iowrite16v_urb_complete(struct urb *urb)
-{
-       struct zd_usb *usb = urb->context;
-
-       if (urb->status && !usb->cmd_error)
-               usb->cmd_error = urb->status;
-
-       if (!usb->cmd_error &&
-                       urb->actual_length != urb->transfer_buffer_length)
-               usb->cmd_error = -EIO;
-}
-
-static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
-{
-       int r = 0;
-       struct urb *urb = usb->urb_async_waiting;
-
-       if (!urb)
-               return 0;
-
-       usb->urb_async_waiting = NULL;
-
-       if (!last)
-               urb->transfer_flags |= URB_NO_INTERRUPT;
-
-       usb_anchor_urb(urb, &usb->submitted_cmds);
-       r = usb_submit_urb(urb, GFP_KERNEL);
-       if (r) {
-               usb_unanchor_urb(urb);
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error in usb_submit_urb(). Error number %d\n", r);
-               goto error;
-       }
-
-       /* fall-through with r == 0 */
-error:
-       usb_free_urb(urb);
-       return r;
-}
-
-void zd_usb_iowrite16v_async_start(struct zd_usb *usb)
-{
-       ZD_ASSERT(usb_anchor_empty(&usb->submitted_cmds));
-       ZD_ASSERT(usb->urb_async_waiting == NULL);
-       ZD_ASSERT(!usb->in_async);
-
-       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
-
-       usb->in_async = 1;
-       usb->cmd_error = 0;
-       usb->urb_async_waiting = NULL;
-}
-
-int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout)
-{
-       int r;
-
-       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
-       ZD_ASSERT(usb->in_async);
-
-       /* Submit last iowrite16v URB */
-       r = zd_submit_waiting_urb(usb, true);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error in zd_submit_waiting_usb(). "
-                       "Error number %d\n", r);
-
-               usb_kill_anchored_urbs(&usb->submitted_cmds);
-               goto error;
-       }
-
-       if (timeout)
-               timeout = usb_wait_anchor_empty_timeout(&usb->submitted_cmds,
-                                                       timeout);
-       if (!timeout) {
-               usb_kill_anchored_urbs(&usb->submitted_cmds);
-               if (usb->cmd_error == -ENOENT) {
-                       dev_dbg_f(zd_usb_dev(usb), "timed out");
-                       r = -ETIMEDOUT;
-                       goto error;
-               }
-       }
-
-       r = usb->cmd_error;
-error:
-       usb->in_async = 0;
-       return r;
-}
-
-int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
-                           unsigned int count)
-{
-       int r;
-       struct usb_device *udev;
-       struct usb_req_write_regs *req = NULL;
-       int i, req_len;
-       struct urb *urb;
-       struct usb_host_endpoint *ep;
-
-       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
-       ZD_ASSERT(usb->in_async);
-
-       if (count == 0)
-               return 0;
-       if (count > USB_MAX_IOWRITE16_COUNT) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error: count %u exceeds possible max %u\n",
-                       count, USB_MAX_IOWRITE16_COUNT);
-               return -EINVAL;
-       }
-       if (in_atomic()) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error: io in atomic context not supported\n");
-               return -EWOULDBLOCK;
-       }
-
-       udev = zd_usb_to_usbdev(usb);
-
-       ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT));
-       if (!ep)
-               return -ENOENT;
-
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!urb)
-               return -ENOMEM;
-
-       req_len = sizeof(struct usb_req_write_regs) +
-                 count * sizeof(struct reg_data);
-       req = kmalloc(req_len, GFP_KERNEL);
-       if (!req) {
-               r = -ENOMEM;
-               goto error;
-       }
-
-       req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
-       for (i = 0; i < count; i++) {
-               struct reg_data *rw  = &req->reg_writes[i];
-               rw->addr = cpu_to_le16((u16)ioreqs[i].addr);
-               rw->value = cpu_to_le16(ioreqs[i].value);
-       }
-
-       /* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode
-        * endpoint is bulk. Select correct type URB by endpoint descriptor.
-        */
-       if (usb_endpoint_xfer_int(&ep->desc))
-               usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
-                                req, req_len, iowrite16v_urb_complete, usb,
-                                ep->desc.bInterval);
-       else
-               usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-                                 req, req_len, iowrite16v_urb_complete, usb);
-
-       urb->transfer_flags |= URB_FREE_BUFFER;
-
-       /* Submit previous URB */
-       r = zd_submit_waiting_urb(usb, false);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error in zd_submit_waiting_usb(). "
-                       "Error number %d\n", r);
-               goto error;
-       }
-
-       /* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs
-        * of currect batch except for very last.
-        */
-       usb->urb_async_waiting = urb;
-       return 0;
-error:
-       usb_free_urb(urb);
-       return r;
-}
-
-int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
-                       unsigned int count)
-{
-       int r;
-
-       zd_usb_iowrite16v_async_start(usb);
-       r = zd_usb_iowrite16v_async(usb, ioreqs, count);
-       if (r) {
-               zd_usb_iowrite16v_async_end(usb, 0);
-               return r;
-       }
-       return zd_usb_iowrite16v_async_end(usb, 50 /* ms */);
-}
-
-int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
-{
-       int r;
-       struct usb_device *udev;
-       struct usb_req_rfwrite *req = NULL;
-       int i, req_len, actual_req_len;
-       u16 bit_value_template;
-
-       if (in_atomic()) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error: io in atomic context not supported\n");
-               return -EWOULDBLOCK;
-       }
-       if (bits < USB_MIN_RFWRITE_BIT_COUNT) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error: bits %d are smaller than"
-                       " USB_MIN_RFWRITE_BIT_COUNT %d\n",
-                       bits, USB_MIN_RFWRITE_BIT_COUNT);
-               return -EINVAL;
-       }
-       if (bits > USB_MAX_RFWRITE_BIT_COUNT) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n",
-                       bits, USB_MAX_RFWRITE_BIT_COUNT);
-               return -EINVAL;
-       }
-#ifdef DEBUG
-       if (value & (~0UL << bits)) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error: value %#09x has bits >= %d set\n",
-                       value, bits);
-               return -EINVAL;
-       }
-#endif /* DEBUG */
-
-       dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits);
-
-       r = zd_usb_ioread16(usb, &bit_value_template, ZD_CR203);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error %d: Couldn't read ZD_CR203\n", r);
-               return r;
-       }
-       bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
-
-       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
-       BUILD_BUG_ON(sizeof(struct usb_req_rfwrite) +
-                    USB_MAX_RFWRITE_BIT_COUNT * sizeof(__le16) >
-                    sizeof(usb->req_buf));
-       BUG_ON(sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16) >
-              sizeof(usb->req_buf));
-
-       req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
-       req = (void *)usb->req_buf;
-
-       req->id = cpu_to_le16(USB_REQ_WRITE_RF);
-       /* 1: 3683a, but not used in ZYDAS driver */
-       req->value = cpu_to_le16(2);
-       req->bits = cpu_to_le16(bits);
-
-       for (i = 0; i < bits; i++) {
-               u16 bv = bit_value_template;
-               if (value & (1 << (bits-1-i)))
-                       bv |= RF_DATA;
-               req->bit_values[i] = cpu_to_le16(bv);
-       }
-
-       udev = zd_usb_to_usbdev(usb);
-       r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
-       if (r) {
-               dev_dbg_f(zd_usb_dev(usb),
-                       "error in zd_ep_regs_out_msg(). Error number %d\n", r);
-               goto out;
-       }
-       if (req_len != actual_req_len) {
-               dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()"
-                       " req_len %d != actual_req_len %d\n",
-                       req_len, actual_req_len);
-               r = -EIO;
-               goto out;
-       }
-
-       /* FALL-THROUGH with r == 0 */
-out:
-       return r;
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
deleted file mode 100644 (file)
index a9075f2..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/* ZD1211 USB-WLAN driver for Linux
- *
- * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
- * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _ZD_USB_H
-#define _ZD_USB_H
-
-#include <linux/completion.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-
-#include "zd_def.h"
-
-#define ZD_USB_TX_HIGH  5
-#define ZD_USB_TX_LOW   2
-
-#define ZD_TX_TIMEOUT          (HZ * 5)
-#define ZD_TX_WATCHDOG_INTERVAL        round_jiffies_relative(HZ)
-#define ZD_RX_IDLE_INTERVAL    round_jiffies_relative(30 * HZ)
-
-enum devicetype {
-       DEVICE_ZD1211  = 0,
-       DEVICE_ZD1211B = 1,
-       DEVICE_INSTALLER = 2,
-};
-
-enum endpoints {
-       EP_CTRL     = 0,
-       EP_DATA_OUT = 1,
-       EP_DATA_IN  = 2,
-       EP_INT_IN   = 3,
-       EP_REGS_OUT = 4,
-};
-
-enum {
-       USB_MAX_TRANSFER_SIZE           = 4096, /* bytes */
-       /* FIXME: The original driver uses this value. We have to check,
-        * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be
-        * used if one combined frame is split over two USB transactions.
-        */
-       USB_MAX_RX_SIZE                 = 4800, /* bytes */
-       USB_MAX_IOWRITE16_COUNT         = 15,
-       USB_MAX_IOWRITE32_COUNT         = USB_MAX_IOWRITE16_COUNT/2,
-       USB_MAX_IOREAD16_COUNT          = 15,
-       USB_MAX_IOREAD32_COUNT          = USB_MAX_IOREAD16_COUNT/2,
-       USB_MIN_RFWRITE_BIT_COUNT       = 16,
-       USB_MAX_RFWRITE_BIT_COUNT       = 28,
-       USB_MAX_EP_INT_BUFFER           = 64,
-       USB_ZD1211B_BCD_DEVICE          = 0x4810,
-};
-
-enum control_requests {
-       USB_REQ_WRITE_REGS              = 0x21,
-       USB_REQ_READ_REGS               = 0x22,
-       USB_REQ_WRITE_RF                = 0x23,
-       USB_REQ_PROG_FLASH              = 0x24,
-       USB_REQ_EEPROM_START            = 0x0128, /* ? request is a byte */
-       USB_REQ_EEPROM_MID              = 0x28,
-       USB_REQ_EEPROM_END              = 0x0228, /* ? request is a byte */
-       USB_REQ_FIRMWARE_DOWNLOAD       = 0x30,
-       USB_REQ_FIRMWARE_CONFIRM        = 0x31,
-       USB_REQ_FIRMWARE_READ_DATA      = 0x32,
-};
-
-struct usb_req_read_regs {
-       __le16 id;
-       __le16 addr[0];
-} __packed;
-
-struct reg_data {
-       __le16 addr;
-       __le16 value;
-} __packed;
-
-struct usb_req_write_regs {
-       __le16 id;
-       struct reg_data reg_writes[0];
-} __packed;
-
-enum {
-       RF_IF_LE = 0x02,
-       RF_CLK   = 0x04,
-       RF_DATA  = 0x08,
-};
-
-struct usb_req_rfwrite {
-       __le16 id;
-       __le16 value;
-       /* 1: 3683a */
-       /* 2: other (default) */
-       __le16 bits;
-       /* RF2595: 24 */
-       __le16 bit_values[0];
-       /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
-} __packed;
-
-/* USB interrupt */
-
-enum usb_int_id {
-       USB_INT_TYPE                    = 0x01,
-       USB_INT_ID_REGS                 = 0x90,
-       USB_INT_ID_RETRY_FAILED         = 0xa0,
-};
-
-enum usb_int_flags {
-       USB_INT_READ_REGS_EN            = 0x01,
-};
-
-struct usb_int_header {
-       u8 type;        /* must always be 1 */
-       u8 id;
-} __packed;
-
-struct usb_int_regs {
-       struct usb_int_header hdr;
-       struct reg_data regs[0];
-} __packed;
-
-struct usb_int_retry_fail {
-       struct usb_int_header hdr;
-       u8 new_rate;
-       u8 _dummy;
-       u8 addr[ETH_ALEN];
-       u8 ibss_wakeup_dest;
-} __packed;
-
-struct read_regs_int {
-       struct completion completion;
-       struct usb_req_read_regs *req;
-       unsigned int req_count;
-       /* Stores the USB int structure and contains the USB address of the
-        * first requested register before request.
-        */
-       u8 buffer[USB_MAX_EP_INT_BUFFER];
-       int length;
-       __le16 cr_int_addr;
-};
-
-struct zd_ioreq16 {
-       zd_addr_t addr;
-       u16 value;
-};
-
-struct zd_ioreq32 {
-       zd_addr_t addr;
-       u32 value;
-};
-
-struct zd_usb_interrupt {
-       struct read_regs_int read_regs;
-       spinlock_t lock;
-       struct urb *urb;
-       void *buffer;
-       dma_addr_t buffer_dma;
-       int interval;
-       atomic_t read_regs_enabled;
-       u8 read_regs_int_overridden:1;
-};
-
-static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
-{
-       return (struct usb_int_regs *)intr->read_regs.buffer;
-}
-
-#define RX_URBS_COUNT 5
-
-struct zd_usb_rx {
-       spinlock_t lock;
-       struct mutex setup_mutex;
-       struct delayed_work idle_work;
-       struct tasklet_struct reset_timer_tasklet;
-       u8 fragment[2 * USB_MAX_RX_SIZE];
-       unsigned int fragment_length;
-       unsigned int usb_packet_size;
-       struct urb **urbs;
-       int urbs_count;
-};
-
-/**
- * struct zd_usb_tx - structure used for transmitting frames
- * @enabled: atomic enabled flag, indicates whether tx is enabled
- * @lock: lock for transmission
- * @submitted: anchor for URBs sent to device
- * @submitted_urbs: atomic integer that counts the URBs having sent to the
- *     device, which haven't been completed
- * @stopped: indicates whether higher level tx queues are stopped
- */
-struct zd_usb_tx {
-       atomic_t enabled;
-       spinlock_t lock;
-       struct delayed_work watchdog_work;
-       struct sk_buff_head submitted_skbs;
-       struct usb_anchor submitted;
-       int submitted_urbs;
-       u8 stopped:1, watchdog_enabled:1;
-};
-
-/* Contains the usb parts. The structure doesn't require a lock because intf
- * will not be changed after initialization.
- */
-struct zd_usb {
-       struct zd_usb_interrupt intr;
-       struct zd_usb_rx rx;
-       struct zd_usb_tx tx;
-       struct usb_interface *intf;
-       struct usb_anchor submitted_cmds;
-       struct urb *urb_async_waiting;
-       int cmd_error;
-       u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */
-       u8 is_zd1211b:1, initialized:1, was_running:1, in_async:1;
-};
-
-#define zd_usb_dev(usb) (&usb->intf->dev)
-
-static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb)
-{
-       return interface_to_usbdev(usb->intf);
-}
-
-static inline struct ieee80211_hw *zd_intf_to_hw(struct usb_interface *intf)
-{
-       return usb_get_intfdata(intf);
-}
-
-static inline struct ieee80211_hw *zd_usb_to_hw(struct zd_usb *usb)
-{
-       return zd_intf_to_hw(usb->intf);
-}
-
-void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
-                struct usb_interface *intf);
-int zd_usb_init_hw(struct zd_usb *usb);
-void zd_usb_clear(struct zd_usb *usb);
-
-int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
-
-void zd_tx_watchdog_enable(struct zd_usb *usb);
-void zd_tx_watchdog_disable(struct zd_usb *usb);
-
-int zd_usb_enable_int(struct zd_usb *usb);
-void zd_usb_disable_int(struct zd_usb *usb);
-
-int zd_usb_enable_rx(struct zd_usb *usb);
-void zd_usb_disable_rx(struct zd_usb *usb);
-
-void zd_usb_reset_rx_idle_timer(struct zd_usb *usb);
-
-void zd_usb_enable_tx(struct zd_usb *usb);
-void zd_usb_disable_tx(struct zd_usb *usb);
-
-int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb);
-
-int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
-                const zd_addr_t *addresses, unsigned int count);
-
-static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value,
-                             const zd_addr_t addr)
-{
-       return zd_usb_ioread16v(usb, value, &addr, 1);
-}
-
-void zd_usb_iowrite16v_async_start(struct zd_usb *usb);
-int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout);
-int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
-                           unsigned int count);
-int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
-                     unsigned int count);
-
-int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
-
-int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len);
-
-extern struct workqueue_struct *zd_workqueue;
-
-#endif /* _ZD_USB_H */
index 6140dfa..a58c0f6 100644 (file)
@@ -30,4 +30,6 @@ config USB_ZD1201
          To compile this driver as a module, choose M here: the
          module will be called zd1201.
 
          To compile this driver as a module, choose M here: the
          module will be called zd1201.
 
+source "drivers/net/wireless/zydas/zd1211rw/Kconfig"
+
 endif # WLAN_VENDOR_ZYDAS
 endif # WLAN_VENDOR_ZYDAS
index 37179ef..679fbbf 100644 (file)
@@ -1 +1,3 @@
+obj-$(CONFIG_ZD1211RW)         += zd1211rw/
+
 obj-$(CONFIG_USB_ZD1201)       += zd1201.o
 obj-$(CONFIG_USB_ZD1201)       += zd1201.o
diff --git a/drivers/net/wireless/zydas/zd1211rw/Kconfig b/drivers/net/wireless/zydas/zd1211rw/Kconfig
new file mode 100644 (file)
index 0000000..9592058
--- /dev/null
@@ -0,0 +1,19 @@
+config ZD1211RW
+       tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
+       depends on USB && MAC80211
+       select FW_LOADER
+       ---help---
+         This is a driver for the ZyDAS ZD1211/ZD1211B wireless
+         chip, present in many USB-wireless adapters.
+
+         Device firmware is required alongside this driver. You can download
+         the firmware distribution from http://sf.net/projects/zd1211/files/
+
+config ZD1211RW_DEBUG
+       bool "ZyDAS ZD1211 debugging"
+       depends on ZD1211RW
+       ---help---
+         ZD1211 debugging messages. Choosing Y will result in additional debug
+         messages being saved to your kernel logs, which may help debug any
+         problems.
+
diff --git a/drivers/net/wireless/zydas/zd1211rw/Makefile b/drivers/net/wireless/zydas/zd1211rw/Makefile
new file mode 100644 (file)
index 0000000..5728a91
--- /dev/null
@@ -0,0 +1,9 @@
+obj-$(CONFIG_ZD1211RW) += zd1211rw.o
+
+zd1211rw-objs := zd_chip.o zd_mac.o \
+               zd_rf_al2230.o zd_rf_rf2959.o \
+               zd_rf_al7230b.o zd_rf_uw2453.o \
+               zd_rf.o zd_usb.o
+
+ccflags-$(CONFIG_ZD1211RW_DEBUG) := -DDEBUG
+
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_chip.c b/drivers/net/wireless/zydas/zd1211rw/zd_chip.c
new file mode 100644 (file)
index 0000000..07b94ed
--- /dev/null
@@ -0,0 +1,1560 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This file implements all the hardware specific functions for the ZD1211
+ * and ZD1211B chips. Support for the ZD1211B was possible after Timothy
+ * Legge sent me a ZD1211B device. Thank you Tim. -- Uli
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include "zd_def.h"
+#include "zd_chip.h"
+#include "zd_mac.h"
+#include "zd_rf.h"
+
+void zd_chip_init(struct zd_chip *chip,
+                struct ieee80211_hw *hw,
+                struct usb_interface *intf)
+{
+       memset(chip, 0, sizeof(*chip));
+       mutex_init(&chip->mutex);
+       zd_usb_init(&chip->usb, hw, intf);
+       zd_rf_init(&chip->rf);
+}
+
+void zd_chip_clear(struct zd_chip *chip)
+{
+       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
+       zd_usb_clear(&chip->usb);
+       zd_rf_clear(&chip->rf);
+       mutex_destroy(&chip->mutex);
+       ZD_MEMCLEAR(chip, sizeof(*chip));
+}
+
+static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
+{
+       u8 *addr = zd_mac_get_perm_addr(zd_chip_to_mac(chip));
+       return scnprintf(buffer, size, "%02x-%02x-%02x",
+                        addr[0], addr[1], addr[2]);
+}
+
+/* Prints an identifier line, which will support debugging. */
+static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size)
+{
+       int i = 0;
+
+       i = scnprintf(buffer, size, "zd1211%s chip ",
+                     zd_chip_is_zd1211b(chip) ? "b" : "");
+       i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i);
+       i += scnprintf(buffer+i, size-i, " ");
+       i += scnprint_mac_oui(chip, buffer+i, size-i);
+       i += scnprintf(buffer+i, size-i, " ");
+       i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
+       i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type,
+               chip->patch_cck_gain ? 'g' : '-',
+               chip->patch_cr157 ? '7' : '-',
+               chip->patch_6m_band_edge ? '6' : '-',
+               chip->new_phy_layout ? 'N' : '-',
+               chip->al2230s_bit ? 'S' : '-');
+       return i;
+}
+
+static void print_id(struct zd_chip *chip)
+{
+       char buffer[80];
+
+       scnprint_id(chip, buffer, sizeof(buffer));
+       buffer[sizeof(buffer)-1] = 0;
+       dev_info(zd_chip_dev(chip), "%s\n", buffer);
+}
+
+static zd_addr_t inc_addr(zd_addr_t addr)
+{
+       u16 a = (u16)addr;
+       /* Control registers use byte addressing, but everything else uses word
+        * addressing. */
+       if ((a & 0xf000) == CR_START)
+               a += 2;
+       else
+               a += 1;
+       return (zd_addr_t)a;
+}
+
+/* Read a variable number of 32-bit values. Parameter count is not allowed to
+ * exceed USB_MAX_IOREAD32_COUNT.
+ */
+int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr,
+                unsigned int count)
+{
+       int r;
+       int i;
+       zd_addr_t a16[USB_MAX_IOREAD32_COUNT * 2];
+       u16 v16[USB_MAX_IOREAD32_COUNT * 2];
+       unsigned int count16;
+
+       if (count > USB_MAX_IOREAD32_COUNT)
+               return -EINVAL;
+
+       /* Use stack for values and addresses. */
+       count16 = 2 * count;
+       BUG_ON(count16 * sizeof(zd_addr_t) > sizeof(a16));
+       BUG_ON(count16 * sizeof(u16) > sizeof(v16));
+
+       for (i = 0; i < count; i++) {
+               int j = 2*i;
+               /* We read the high word always first. */
+               a16[j] = inc_addr(addr[i]);
+               a16[j+1] = addr[i];
+       }
+
+       r = zd_ioread16v_locked(chip, v16, a16, count16);
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                         "error: %s. Error number %d\n", __func__, r);
+               return r;
+       }
+
+       for (i = 0; i < count; i++) {
+               int j = 2*i;
+               values[i] = (v16[j] << 16) | v16[j+1];
+       }
+
+       return 0;
+}
+
+static int _zd_iowrite32v_async_locked(struct zd_chip *chip,
+                                      const struct zd_ioreq32 *ioreqs,
+                                      unsigned int count)
+{
+       int i, j, r;
+       struct zd_ioreq16 ioreqs16[USB_MAX_IOWRITE32_COUNT * 2];
+       unsigned int count16;
+
+       /* Use stack for values and addresses. */
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+
+       if (count == 0)
+               return 0;
+       if (count > USB_MAX_IOWRITE32_COUNT)
+               return -EINVAL;
+
+       count16 = 2 * count;
+       BUG_ON(count16 * sizeof(struct zd_ioreq16) > sizeof(ioreqs16));
+
+       for (i = 0; i < count; i++) {
+               j = 2*i;
+               /* We write the high word always first. */
+               ioreqs16[j].value   = ioreqs[i].value >> 16;
+               ioreqs16[j].addr    = inc_addr(ioreqs[i].addr);
+               ioreqs16[j+1].value = ioreqs[i].value;
+               ioreqs16[j+1].addr  = ioreqs[i].addr;
+       }
+
+       r = zd_usb_iowrite16v_async(&chip->usb, ioreqs16, count16);
+#ifdef DEBUG
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                         "error %d in zd_usb_write16v\n", r);
+       }
+#endif /* DEBUG */
+       return r;
+}
+
+int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                         unsigned int count)
+{
+       int r;
+
+       zd_usb_iowrite16v_async_start(&chip->usb);
+       r = _zd_iowrite32v_async_locked(chip, ioreqs, count);
+       if (r) {
+               zd_usb_iowrite16v_async_end(&chip->usb, 0);
+               return r;
+       }
+       return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
+}
+
+int zd_iowrite16a_locked(struct zd_chip *chip,
+                  const struct zd_ioreq16 *ioreqs, unsigned int count)
+{
+       int r;
+       unsigned int i, j, t, max;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       zd_usb_iowrite16v_async_start(&chip->usb);
+
+       for (i = 0; i < count; i += j + t) {
+               t = 0;
+               max = count-i;
+               if (max > USB_MAX_IOWRITE16_COUNT)
+                       max = USB_MAX_IOWRITE16_COUNT;
+               for (j = 0; j < max; j++) {
+                       if (!ioreqs[i+j].addr) {
+                               t = 1;
+                               break;
+                       }
+               }
+
+               r = zd_usb_iowrite16v_async(&chip->usb, &ioreqs[i], j);
+               if (r) {
+                       zd_usb_iowrite16v_async_end(&chip->usb, 0);
+                       dev_dbg_f(zd_chip_dev(chip),
+                                 "error zd_usb_iowrite16v. Error number %d\n",
+                                 r);
+                       return r;
+               }
+       }
+
+       return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
+}
+
+/* Writes a variable number of 32 bit registers. The functions will split
+ * that in several USB requests. A split can be forced by inserting an IO
+ * request with an zero address field.
+ */
+int zd_iowrite32a_locked(struct zd_chip *chip,
+                 const struct zd_ioreq32 *ioreqs, unsigned int count)
+{
+       int r;
+       unsigned int i, j, t, max;
+
+       zd_usb_iowrite16v_async_start(&chip->usb);
+
+       for (i = 0; i < count; i += j + t) {
+               t = 0;
+               max = count-i;
+               if (max > USB_MAX_IOWRITE32_COUNT)
+                       max = USB_MAX_IOWRITE32_COUNT;
+               for (j = 0; j < max; j++) {
+                       if (!ioreqs[i+j].addr) {
+                               t = 1;
+                               break;
+                       }
+               }
+
+               r = _zd_iowrite32v_async_locked(chip, &ioreqs[i], j);
+               if (r) {
+                       zd_usb_iowrite16v_async_end(&chip->usb, 0);
+                       dev_dbg_f(zd_chip_dev(chip),
+                               "error _%s. Error number %d\n", __func__,
+                               r);
+                       return r;
+               }
+       }
+
+       return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
+}
+
+int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread16_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite16_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32_locked(chip, value, addr);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
+                 u32 *values, unsigned int count)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32v_locked(chip, values, addresses, count);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                 unsigned int count)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32a_locked(chip, ioreqs, count);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int read_pod(struct zd_chip *chip, u8 *rf_type)
+{
+       int r;
+       u32 value;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &value, E2P_POD);
+       if (r)
+               goto error;
+       dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value);
+
+       /* FIXME: AL2230 handling (Bit 7 in POD) */
+       *rf_type = value & 0x0f;
+       chip->pa_type = (value >> 16) & 0x0f;
+       chip->patch_cck_gain = (value >> 8) & 0x1;
+       chip->patch_cr157 = (value >> 13) & 0x1;
+       chip->patch_6m_band_edge = (value >> 21) & 0x1;
+       chip->new_phy_layout = (value >> 31) & 0x1;
+       chip->al2230s_bit = (value >> 7) & 0x1;
+       chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
+       chip->supports_tx_led = 1;
+       if (value & (1 << 24)) { /* LED scenario */
+               if (value & (1 << 29))
+                       chip->supports_tx_led = 0;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip),
+               "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
+               "patch 6M %d new PHY %d link LED%d tx led %d\n",
+               zd_rf_name(*rf_type), *rf_type,
+               chip->pa_type, chip->patch_cck_gain,
+               chip->patch_cr157, chip->patch_6m_band_edge,
+               chip->new_phy_layout,
+               chip->link_led == LED1 ? 1 : 2,
+               chip->supports_tx_led);
+       return 0;
+error:
+       *rf_type = 0;
+       chip->pa_type = 0;
+       chip->patch_cck_gain = 0;
+       chip->patch_cr157 = 0;
+       chip->patch_6m_band_edge = 0;
+       chip->new_phy_layout = 0;
+       return r;
+}
+
+static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr,
+                                   const struct zd_ioreq32 *in_reqs,
+                                   const char *type)
+{
+       int r;
+       struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]};
+
+       if (mac_addr) {
+               reqs[0].value = (mac_addr[3] << 24)
+                             | (mac_addr[2] << 16)
+                             | (mac_addr[1] <<  8)
+                             |  mac_addr[0];
+               reqs[1].value = (mac_addr[5] <<  8)
+                             |  mac_addr[4];
+               dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr);
+       } else {
+               dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type);
+       }
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
+ *              CR_MAC_ADDR_P2 must be overwritten
+ */
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+{
+       static const struct zd_ioreq32 reqs[2] = {
+               [0] = { .addr = CR_MAC_ADDR_P1 },
+               [1] = { .addr = CR_MAC_ADDR_P2 },
+       };
+
+       return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac");
+}
+
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+       static const struct zd_ioreq32 reqs[2] = {
+               [0] = { .addr = CR_BSSID_P1 },
+               [1] = { .addr = CR_BSSID_P2 },
+       };
+
+       return zd_write_mac_addr_common(chip, bssid, reqs, "bssid");
+}
+
+int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
+{
+       int r;
+       u32 value;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32_locked(chip, &value, E2P_SUBID);
+       mutex_unlock(&chip->mutex);
+       if (r)
+               return r;
+
+       *regdomain = value >> 16;
+       dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain);
+
+       return 0;
+}
+
+static int read_values(struct zd_chip *chip, u8 *values, size_t count,
+                      zd_addr_t e2p_addr, u32 guard)
+{
+       int r;
+       int i;
+       u32 v;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       for (i = 0;;) {
+               r = zd_ioread32_locked(chip, &v,
+                                      (zd_addr_t)((u16)e2p_addr+i/2));
+               if (r)
+                       return r;
+               v -= guard;
+               if (i+4 < count) {
+                       values[i++] = v;
+                       values[i++] = v >>  8;
+                       values[i++] = v >> 16;
+                       values[i++] = v >> 24;
+                       continue;
+               }
+               for (;i < count; i++)
+                       values[i] = v >> (8*(i%3));
+               return 0;
+       }
+}
+
+static int read_pwr_cal_values(struct zd_chip *chip)
+{
+       return read_values(chip, chip->pwr_cal_values,
+                       E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1,
+                       0);
+}
+
+static int read_pwr_int_values(struct zd_chip *chip)
+{
+       return read_values(chip, chip->pwr_int_values,
+                       E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1,
+                       E2P_PWR_INT_GUARD);
+}
+
+static int read_ofdm_cal_values(struct zd_chip *chip)
+{
+       int r;
+       int i;
+       static const zd_addr_t addresses[] = {
+               E2P_36M_CAL_VALUE1,
+               E2P_48M_CAL_VALUE1,
+               E2P_54M_CAL_VALUE1,
+       };
+
+       for (i = 0; i < 3; i++) {
+               r = read_values(chip, chip->ofdm_cal_values[i],
+                               E2P_CHANNEL_COUNT, addresses[i], 0);
+               if (r)
+                       return r;
+       }
+       return 0;
+}
+
+static int read_cal_int_tables(struct zd_chip *chip)
+{
+       int r;
+
+       r = read_pwr_cal_values(chip);
+       if (r)
+               return r;
+       r = read_pwr_int_values(chip);
+       if (r)
+               return r;
+       r = read_ofdm_cal_values(chip);
+       if (r)
+               return r;
+       return 0;
+}
+
+/* phy means physical registers */
+int zd_chip_lock_phy_regs(struct zd_chip *chip)
+{
+       int r;
+       u32 tmp;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &tmp, CR_REG1);
+       if (r) {
+               dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r);
+               return r;
+       }
+
+       tmp &= ~UNLOCK_PHY_REGS;
+
+       r = zd_iowrite32_locked(chip, tmp, CR_REG1);
+       if (r)
+               dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
+       return r;
+}
+
+int zd_chip_unlock_phy_regs(struct zd_chip *chip)
+{
+       int r;
+       u32 tmp;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &tmp, CR_REG1);
+       if (r) {
+               dev_err(zd_chip_dev(chip),
+                       "error ioread32(CR_REG1): %d\n", r);
+               return r;
+       }
+
+       tmp |= UNLOCK_PHY_REGS;
+
+       r = zd_iowrite32_locked(chip, tmp, CR_REG1);
+       if (r)
+               dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r);
+       return r;
+}
+
+/* ZD_CR157 can be optionally patched by the EEPROM for original ZD1211 */
+static int patch_cr157(struct zd_chip *chip)
+{
+       int r;
+       u16 value;
+
+       if (!chip->patch_cr157)
+               return 0;
+
+       r = zd_ioread16_locked(chip, &value, E2P_PHY_REG);
+       if (r)
+               return r;
+
+       dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8);
+       return zd_iowrite32_locked(chip, value >> 8, ZD_CR157);
+}
+
+/*
+ * 6M band edge can be optionally overwritten for certain RF's
+ * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge
+ * bit (for AL2230, AL2230S)
+ */
+static int patch_6m_band_edge(struct zd_chip *chip, u8 channel)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       if (!chip->patch_6m_band_edge)
+               return 0;
+
+       return zd_rf_patch_6m_band_edge(&chip->rf, channel);
+}
+
+/* Generic implementation of 6M band edge patching, used by most RFs via
+ * zd_rf_generic_patch_6m() */
+int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel)
+{
+       struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
+               { ZD_CR47,  0x1e },
+       };
+
+       /* FIXME: Channel 11 is not the edge for all regulatory domains. */
+       if (channel == 1 || channel == 11)
+               ioreqs[0].value = 0x12;
+
+       dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel);
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211_hw_reset_phy(struct zd_chip *chip)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR0,   0x0a }, { ZD_CR1,   0x06 }, { ZD_CR2,   0x26 },
+               { ZD_CR3,   0x38 }, { ZD_CR4,   0x80 }, { ZD_CR9,   0xa0 },
+               { ZD_CR10,  0x81 }, { ZD_CR11,  0x00 }, { ZD_CR12,  0x7f },
+               { ZD_CR13,  0x8c }, { ZD_CR14,  0x80 }, { ZD_CR15,  0x3d },
+               { ZD_CR16,  0x20 }, { ZD_CR17,  0x1e }, { ZD_CR18,  0x0a },
+               { ZD_CR19,  0x48 }, { ZD_CR20,  0x0c }, { ZD_CR21,  0x0c },
+               { ZD_CR22,  0x23 }, { ZD_CR23,  0x90 }, { ZD_CR24,  0x14 },
+               { ZD_CR25,  0x40 }, { ZD_CR26,  0x10 }, { ZD_CR27,  0x19 },
+               { ZD_CR28,  0x7f }, { ZD_CR29,  0x80 }, { ZD_CR30,  0x4b },
+               { ZD_CR31,  0x60 }, { ZD_CR32,  0x43 }, { ZD_CR33,  0x08 },
+               { ZD_CR34,  0x06 }, { ZD_CR35,  0x0a }, { ZD_CR36,  0x00 },
+               { ZD_CR37,  0x00 }, { ZD_CR38,  0x38 }, { ZD_CR39,  0x0c },
+               { ZD_CR40,  0x84 }, { ZD_CR41,  0x2a }, { ZD_CR42,  0x80 },
+               { ZD_CR43,  0x10 }, { ZD_CR44,  0x12 }, { ZD_CR46,  0xff },
+               { ZD_CR47,  0x1E }, { ZD_CR48,  0x26 }, { ZD_CR49,  0x5b },
+               { ZD_CR64,  0xd0 }, { ZD_CR65,  0x04 }, { ZD_CR66,  0x58 },
+               { ZD_CR67,  0xc9 }, { ZD_CR68,  0x88 }, { ZD_CR69,  0x41 },
+               { ZD_CR70,  0x23 }, { ZD_CR71,  0x10 }, { ZD_CR72,  0xff },
+               { ZD_CR73,  0x32 }, { ZD_CR74,  0x30 }, { ZD_CR75,  0x65 },
+               { ZD_CR76,  0x41 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x30 },
+               { ZD_CR79,  0x68 }, { ZD_CR80,  0x64 }, { ZD_CR81,  0x64 },
+               { ZD_CR82,  0x00 }, { ZD_CR83,  0x00 }, { ZD_CR84,  0x00 },
+               { ZD_CR85,  0x02 }, { ZD_CR86,  0x00 }, { ZD_CR87,  0x00 },
+               { ZD_CR88,  0xff }, { ZD_CR89,  0xfc }, { ZD_CR90,  0x00 },
+               { ZD_CR91,  0x00 }, { ZD_CR92,  0x00 }, { ZD_CR93,  0x08 },
+               { ZD_CR94,  0x00 }, { ZD_CR95,  0x00 }, { ZD_CR96,  0xff },
+               { ZD_CR97,  0xe7 }, { ZD_CR98,  0x00 }, { ZD_CR99,  0x00 },
+               { ZD_CR100, 0x00 }, { ZD_CR101, 0xae }, { ZD_CR102, 0x02 },
+               { ZD_CR103, 0x00 }, { ZD_CR104, 0x03 }, { ZD_CR105, 0x65 },
+               { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 }, { ZD_CR108, 0x0a },
+               { ZD_CR109, 0xaa }, { ZD_CR110, 0xaa }, { ZD_CR111, 0x25 },
+               { ZD_CR112, 0x25 }, { ZD_CR113, 0x00 }, { ZD_CR119, 0x1e },
+               { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 },
+               { },
+               { ZD_CR5,   0x00 }, { ZD_CR6,   0x00 }, { ZD_CR7,   0x00 },
+               { ZD_CR8,   0x00 }, { ZD_CR9,   0x20 }, { ZD_CR12,  0xf0 },
+               { ZD_CR20,  0x0e }, { ZD_CR21,  0x0e }, { ZD_CR27,  0x10 },
+               { ZD_CR44,  0x33 }, { ZD_CR47,  0x1E }, { ZD_CR83,  0x24 },
+               { ZD_CR84,  0x04 }, { ZD_CR85,  0x00 }, { ZD_CR86,  0x0C },
+               { ZD_CR87,  0x12 }, { ZD_CR88,  0x0C }, { ZD_CR89,  0x00 },
+               { ZD_CR90,  0x10 }, { ZD_CR91,  0x08 }, { ZD_CR93,  0x00 },
+               { ZD_CR94,  0x01 }, { ZD_CR95,  0x00 }, { ZD_CR96,  0x50 },
+               { ZD_CR97,  0x37 }, { ZD_CR98,  0x35 }, { ZD_CR101, 0x13 },
+               { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 },
+               { ZD_CR105, 0x12 }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 },
+               { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 },
+               { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 },
+               { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR120, 0x4f },
+               { ZD_CR125, 0xaa }, { ZD_CR127, 0x03 }, { ZD_CR128, 0x14 },
+               { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 }, { ZD_CR131, 0x0C },
+               { ZD_CR136, 0xdf }, { ZD_CR137, 0x40 }, { ZD_CR138, 0xa0 },
+               { ZD_CR139, 0xb0 }, { ZD_CR140, 0x99 }, { ZD_CR141, 0x82 },
+               { ZD_CR142, 0x54 }, { ZD_CR143, 0x1c }, { ZD_CR144, 0x6c },
+               { ZD_CR147, 0x07 }, { ZD_CR148, 0x4c }, { ZD_CR149, 0x50 },
+               { ZD_CR150, 0x0e }, { ZD_CR151, 0x18 }, { ZD_CR160, 0xfe },
+               { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa },
+               { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe },
+               { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba },
+               { ZD_CR170, 0xba }, { ZD_CR171, 0xba },
+               /* Note: ZD_CR204 must lead the ZD_CR203 */
+               { ZD_CR204, 0x7d },
+               { },
+               { ZD_CR203, 0x30 },
+       };
+
+       int r, t;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               goto out;
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               goto unlock;
+
+       r = patch_cr157(chip);
+unlock:
+       t = zd_chip_unlock_phy_regs(chip);
+       if (t && !r)
+               r = t;
+out:
+       return r;
+}
+
+static int zd1211b_hw_reset_phy(struct zd_chip *chip)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR0,   0x14 }, { ZD_CR1,   0x06 }, { ZD_CR2,   0x26 },
+               { ZD_CR3,   0x38 }, { ZD_CR4,   0x80 }, { ZD_CR9,   0xe0 },
+               { ZD_CR10,  0x81 },
+               /* power control { { ZD_CR11,  1 << 6 }, */
+               { ZD_CR11,  0x00 },
+               { ZD_CR12,  0xf0 }, { ZD_CR13,  0x8c }, { ZD_CR14,  0x80 },
+               { ZD_CR15,  0x3d }, { ZD_CR16,  0x20 }, { ZD_CR17,  0x1e },
+               { ZD_CR18,  0x0a }, { ZD_CR19,  0x48 },
+               { ZD_CR20,  0x10 }, /* Org:0x0E, ComTrend:RalLink AP */
+               { ZD_CR21,  0x0e }, { ZD_CR22,  0x23 }, { ZD_CR23,  0x90 },
+               { ZD_CR24,  0x14 }, { ZD_CR25,  0x40 }, { ZD_CR26,  0x10 },
+               { ZD_CR27,  0x10 }, { ZD_CR28,  0x7f }, { ZD_CR29,  0x80 },
+               { ZD_CR30,  0x4b }, /* ASIC/FWT, no jointly decoder */
+               { ZD_CR31,  0x60 }, { ZD_CR32,  0x43 }, { ZD_CR33,  0x08 },
+               { ZD_CR34,  0x06 }, { ZD_CR35,  0x0a }, { ZD_CR36,  0x00 },
+               { ZD_CR37,  0x00 }, { ZD_CR38,  0x38 }, { ZD_CR39,  0x0c },
+               { ZD_CR40,  0x84 }, { ZD_CR41,  0x2a }, { ZD_CR42,  0x80 },
+               { ZD_CR43,  0x10 }, { ZD_CR44,  0x33 }, { ZD_CR46,  0xff },
+               { ZD_CR47,  0x1E }, { ZD_CR48,  0x26 }, { ZD_CR49,  0x5b },
+               { ZD_CR64,  0xd0 }, { ZD_CR65,  0x04 }, { ZD_CR66,  0x58 },
+               { ZD_CR67,  0xc9 }, { ZD_CR68,  0x88 }, { ZD_CR69,  0x41 },
+               { ZD_CR70,  0x23 }, { ZD_CR71,  0x10 }, { ZD_CR72,  0xff },
+               { ZD_CR73,  0x32 }, { ZD_CR74,  0x30 }, { ZD_CR75,  0x65 },
+               { ZD_CR76,  0x41 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x30 },
+               { ZD_CR79,  0xf0 }, { ZD_CR80,  0x64 }, { ZD_CR81,  0x64 },
+               { ZD_CR82,  0x00 }, { ZD_CR83,  0x24 }, { ZD_CR84,  0x04 },
+               { ZD_CR85,  0x00 }, { ZD_CR86,  0x0c }, { ZD_CR87,  0x12 },
+               { ZD_CR88,  0x0c }, { ZD_CR89,  0x00 }, { ZD_CR90,  0x58 },
+               { ZD_CR91,  0x04 }, { ZD_CR92,  0x00 }, { ZD_CR93,  0x00 },
+               { ZD_CR94,  0x01 },
+               { ZD_CR95,  0x20 }, /* ZD1211B */
+               { ZD_CR96,  0x50 }, { ZD_CR97,  0x37 }, { ZD_CR98,  0x35 },
+               { ZD_CR99,  0x00 }, { ZD_CR100, 0x01 }, { ZD_CR101, 0x13 },
+               { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 }, { ZD_CR104, 0x18 },
+               { ZD_CR105, 0x12 }, { ZD_CR106, 0x04 }, { ZD_CR107, 0x00 },
+               { ZD_CR108, 0x0a }, { ZD_CR109, 0x27 }, { ZD_CR110, 0x27 },
+               { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 }, { ZD_CR113, 0x27 },
+               { ZD_CR114, 0x27 }, { ZD_CR115, 0x26 }, { ZD_CR116, 0x24 },
+               { ZD_CR117, 0xfc }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x1e },
+               { ZD_CR125, 0x90 }, { ZD_CR126, 0x00 }, { ZD_CR127, 0x00 },
+               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
+               { ZD_CR131, 0x0c }, { ZD_CR136, 0xdf }, { ZD_CR137, 0xa0 },
+               { ZD_CR138, 0xa8 }, { ZD_CR139, 0xb4 }, { ZD_CR140, 0x98 },
+               { ZD_CR141, 0x82 }, { ZD_CR142, 0x53 }, { ZD_CR143, 0x1c },
+               { ZD_CR144, 0x6c }, { ZD_CR147, 0x07 }, { ZD_CR148, 0x40 },
+               { ZD_CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */
+               { ZD_CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */
+               { ZD_CR151, 0x18 }, { ZD_CR159, 0x70 }, { ZD_CR160, 0xfe },
+               { ZD_CR161, 0xee }, { ZD_CR162, 0xaa }, { ZD_CR163, 0xfa },
+               { ZD_CR164, 0xfa }, { ZD_CR165, 0xea }, { ZD_CR166, 0xbe },
+               { ZD_CR167, 0xbe }, { ZD_CR168, 0x6a }, { ZD_CR169, 0xba },
+               { ZD_CR170, 0xba }, { ZD_CR171, 0xba },
+               /* Note: ZD_CR204 must lead the ZD_CR203 */
+               { ZD_CR204, 0x7d },
+               {},
+               { ZD_CR203, 0x30 },
+       };
+
+       int r, t;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               goto out;
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       t = zd_chip_unlock_phy_regs(chip);
+       if (t && !r)
+               r = t;
+out:
+       return r;
+}
+
+static int hw_reset_phy(struct zd_chip *chip)
+{
+       return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) :
+                                 zd1211_hw_reset_phy(chip);
+}
+
+static int zd1211_hw_init_hmac(struct zd_chip *chip)
+{
+       static const struct zd_ioreq32 ioreqs[] = {
+               { CR_ZD1211_RETRY_MAX,          ZD1211_RETRY_COUNT },
+               { CR_RX_THRESHOLD,              0x000c0640 },
+       };
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211b_hw_init_hmac(struct zd_chip *chip)
+{
+       static const struct zd_ioreq32 ioreqs[] = {
+               { CR_ZD1211B_RETRY_MAX,         ZD1211B_RETRY_COUNT },
+               { CR_ZD1211B_CWIN_MAX_MIN_AC0,  0x007f003f },
+               { CR_ZD1211B_CWIN_MAX_MIN_AC1,  0x007f003f },
+               { CR_ZD1211B_CWIN_MAX_MIN_AC2,  0x003f001f },
+               { CR_ZD1211B_CWIN_MAX_MIN_AC3,  0x001f000f },
+               { CR_ZD1211B_AIFS_CTL1,         0x00280028 },
+               { CR_ZD1211B_AIFS_CTL2,         0x008C003C },
+               { CR_ZD1211B_TXOP,              0x01800824 },
+               { CR_RX_THRESHOLD,              0x000c0eff, },
+       };
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int hw_init_hmac(struct zd_chip *chip)
+{
+       int r;
+       static const struct zd_ioreq32 ioreqs[] = {
+               { CR_ACK_TIMEOUT_EXT,           0x20 },
+               { CR_ADDA_MBIAS_WARMTIME,       0x30000808 },
+               { CR_SNIFFER_ON,                0 },
+               { CR_RX_FILTER,                 STA_RX_FILTER },
+               { CR_GROUP_HASH_P1,             0x00 },
+               { CR_GROUP_HASH_P2,             0x80000000 },
+               { CR_REG1,                      0xa4 },
+               { CR_ADDA_PWR_DWN,              0x7f },
+               { CR_BCN_PLCP_CFG,              0x00f00401 },
+               { CR_PHY_DELAY,                 0x00 },
+               { CR_ACK_TIMEOUT_EXT,           0x80 },
+               { CR_ADDA_PWR_DWN,              0x00 },
+               { CR_ACK_TIME_80211,            0x100 },
+               { CR_RX_PE_DELAY,               0x70 },
+               { CR_PS_CTRL,                   0x10000000 },
+               { CR_RTS_CTS_RATE,              0x02030203 },
+               { CR_AFTER_PNP,                 0x1 },
+               { CR_WEP_PROTECT,               0x114 },
+               { CR_IFS_VALUE,                 IFS_VALUE_DEFAULT },
+               { CR_CAM_MODE,                  MODE_AP_WDS},
+       };
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       return zd_chip_is_zd1211b(chip) ?
+               zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip);
+}
+
+struct aw_pt_bi {
+       u32 atim_wnd_period;
+       u32 pre_tbtt;
+       u32 beacon_interval;
+};
+
+static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
+{
+       int r;
+       static const zd_addr_t aw_pt_bi_addr[] =
+               { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL };
+       u32 values[3];
+
+       r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr,
+                        ARRAY_SIZE(aw_pt_bi_addr));
+       if (r) {
+               memset(s, 0, sizeof(*s));
+               return r;
+       }
+
+       s->atim_wnd_period = values[0];
+       s->pre_tbtt = values[1];
+       s->beacon_interval = values[2];
+       return 0;
+}
+
+static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
+{
+       struct zd_ioreq32 reqs[3];
+       u16 b_interval = s->beacon_interval & 0xffff;
+
+       if (b_interval <= 5)
+               b_interval = 5;
+       if (s->pre_tbtt < 4 || s->pre_tbtt >= b_interval)
+               s->pre_tbtt = b_interval - 1;
+       if (s->atim_wnd_period >= s->pre_tbtt)
+               s->atim_wnd_period = s->pre_tbtt - 1;
+
+       reqs[0].addr = CR_ATIM_WND_PERIOD;
+       reqs[0].value = s->atim_wnd_period;
+       reqs[1].addr = CR_PRE_TBTT;
+       reqs[1].value = s->pre_tbtt;
+       reqs[2].addr = CR_BCN_INTERVAL;
+       reqs[2].value = (s->beacon_interval & ~0xffff) | b_interval;
+
+       return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
+}
+
+
+static int set_beacon_interval(struct zd_chip *chip, u16 interval,
+                              u8 dtim_period, int type)
+{
+       int r;
+       struct aw_pt_bi s;
+       u32 b_interval, mode_flag;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+
+       if (interval > 0) {
+               switch (type) {
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_MESH_POINT:
+                       mode_flag = BCN_MODE_IBSS;
+                       break;
+               case NL80211_IFTYPE_AP:
+                       mode_flag = BCN_MODE_AP;
+                       break;
+               default:
+                       mode_flag = 0;
+                       break;
+               }
+       } else {
+               dtim_period = 0;
+               mode_flag = 0;
+       }
+
+       b_interval = mode_flag | (dtim_period << 16) | interval;
+
+       r = zd_iowrite32_locked(chip, b_interval, CR_BCN_INTERVAL);
+       if (r)
+               return r;
+       r = get_aw_pt_bi(chip, &s);
+       if (r)
+               return r;
+       return set_aw_pt_bi(chip, &s);
+}
+
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+                          int type)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = set_beacon_interval(chip, interval, dtim_period, type);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int hw_init(struct zd_chip *chip)
+{
+       int r;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = hw_reset_phy(chip);
+       if (r)
+               return r;
+
+       r = hw_init_hmac(chip);
+       if (r)
+               return r;
+
+       return set_beacon_interval(chip, 100, 0, NL80211_IFTYPE_UNSPECIFIED);
+}
+
+static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
+{
+       return (zd_addr_t)((u16)chip->fw_regs_base + offset);
+}
+
+#ifdef DEBUG
+static int dump_cr(struct zd_chip *chip, const zd_addr_t addr,
+                  const char *addr_string)
+{
+       int r;
+       u32 value;
+
+       r = zd_ioread32_locked(chip, &value, addr);
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip),
+                       "error reading %s. Error number %d\n", addr_string, r);
+               return r;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n",
+               addr_string, (unsigned int)value);
+       return 0;
+}
+
+static int test_init(struct zd_chip *chip)
+{
+       int r;
+
+       r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP");
+       if (r)
+               return r;
+       r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN");
+       if (r)
+               return r;
+       return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT");
+}
+
+static void dump_fw_registers(struct zd_chip *chip)
+{
+       const zd_addr_t addr[4] = {
+               fw_reg_addr(chip, FW_REG_FIRMWARE_VER),
+               fw_reg_addr(chip, FW_REG_USB_SPEED),
+               fw_reg_addr(chip, FW_REG_FIX_TX_RATE),
+               fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
+       };
+
+       int r;
+       u16 values[4];
+
+       r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr,
+                        ARRAY_SIZE(addr));
+       if (r) {
+               dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n",
+                        r);
+               return;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]);
+       dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]);
+       dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]);
+       dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]);
+}
+#endif /* DEBUG */
+
+static int print_fw_version(struct zd_chip *chip)
+{
+       struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy;
+       int r;
+       u16 version;
+
+       r = zd_ioread16_locked(chip, &version,
+               fw_reg_addr(chip, FW_REG_FIRMWARE_VER));
+       if (r)
+               return r;
+
+       dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version);
+
+       snprintf(wiphy->fw_version, sizeof(wiphy->fw_version),
+                       "%04hx", version);
+
+       return 0;
+}
+
+static int set_mandatory_rates(struct zd_chip *chip, int gmode)
+{
+       u32 rates;
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       /* This sets the mandatory rates, which only depend from the standard
+        * that the device is supporting. Until further notice we should try
+        * to support 802.11g also for full speed USB.
+        */
+       if (!gmode)
+               rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
+       else
+               rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
+                       CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
+
+       return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
+}
+
+int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
+                                   int preamble)
+{
+       u32 value = 0;
+
+       dev_dbg_f(zd_chip_dev(chip), "preamble=%x\n", preamble);
+       value |= preamble << RTSCTS_SH_RTS_PMB_TYPE;
+       value |= preamble << RTSCTS_SH_CTS_PMB_TYPE;
+
+       /* We always send 11M RTS/self-CTS messages, like the vendor driver. */
+       value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_RTS_RATE;
+       value |= ZD_RX_CCK << RTSCTS_SH_RTS_MOD_TYPE;
+       value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_CTS_RATE;
+       value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE;
+
+       return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE);
+}
+
+int zd_chip_enable_hwint(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int disable_hwint(struct zd_chip *chip)
+{
+       return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT);
+}
+
+int zd_chip_disable_hwint(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = disable_hwint(chip);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int read_fw_regs_offset(struct zd_chip *chip)
+{
+       int r;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread16_locked(chip, (u16*)&chip->fw_regs_base,
+                              FWRAW_REGS_ADDR);
+       if (r)
+               return r;
+       dev_dbg_f(zd_chip_dev(chip), "fw_regs_base: %#06hx\n",
+                 (u16)chip->fw_regs_base);
+
+       return 0;
+}
+
+/* Read mac address using pre-firmware interface */
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr)
+{
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+       return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr,
+               ETH_ALEN);
+}
+
+int zd_chip_init_hw(struct zd_chip *chip)
+{
+       int r;
+       u8 rf_type;
+
+       dev_dbg_f(zd_chip_dev(chip), "\n");
+
+       mutex_lock(&chip->mutex);
+
+#ifdef DEBUG
+       r = test_init(chip);
+       if (r)
+               goto out;
+#endif
+       r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP);
+       if (r)
+               goto out;
+
+       r = read_fw_regs_offset(chip);
+       if (r)
+               goto out;
+
+       /* GPI is always disabled, also in the other driver.
+        */
+       r = zd_iowrite32_locked(chip, 0, CR_GPI_EN);
+       if (r)
+               goto out;
+       r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX);
+       if (r)
+               goto out;
+       /* Currently we support IEEE 802.11g for full and high speed USB.
+        * It might be discussed, whether we should support pure b mode for
+        * full speed USB.
+        */
+       r = set_mandatory_rates(chip, 1);
+       if (r)
+               goto out;
+       /* Disabling interrupts is certainly a smart thing here.
+        */
+       r = disable_hwint(chip);
+       if (r)
+               goto out;
+       r = read_pod(chip, &rf_type);
+       if (r)
+               goto out;
+       r = hw_init(chip);
+       if (r)
+               goto out;
+       r = zd_rf_init_hw(&chip->rf, rf_type);
+       if (r)
+               goto out;
+
+       r = print_fw_version(chip);
+       if (r)
+               goto out;
+
+#ifdef DEBUG
+       dump_fw_registers(chip);
+       r = test_init(chip);
+       if (r)
+               goto out;
+#endif /* DEBUG */
+
+       r = read_cal_int_tables(chip);
+       if (r)
+               goto out;
+
+       print_id(chip);
+out:
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static int update_pwr_int(struct zd_chip *chip, u8 channel)
+{
+       u8 value = chip->pwr_int_values[channel - 1];
+       return zd_iowrite16_locked(chip, value, ZD_CR31);
+}
+
+static int update_pwr_cal(struct zd_chip *chip, u8 channel)
+{
+       u8 value = chip->pwr_cal_values[channel-1];
+       return zd_iowrite16_locked(chip, value, ZD_CR68);
+}
+
+static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
+{
+       struct zd_ioreq16 ioreqs[3];
+
+       ioreqs[0].addr = ZD_CR67;
+       ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1];
+       ioreqs[1].addr = ZD_CR66;
+       ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1];
+       ioreqs[2].addr = ZD_CR65;
+       ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1];
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int update_channel_integration_and_calibration(struct zd_chip *chip,
+                                                     u8 channel)
+{
+       int r;
+
+       if (!zd_rf_should_update_pwr_int(&chip->rf))
+               return 0;
+
+       r = update_pwr_int(chip, channel);
+       if (r)
+               return r;
+       if (zd_chip_is_zd1211b(chip)) {
+               static const struct zd_ioreq16 ioreqs[] = {
+                       { ZD_CR69, 0x28 },
+                       {},
+                       { ZD_CR69, 0x2a },
+               };
+
+               r = update_ofdm_cal(chip, channel);
+               if (r)
+                       return r;
+               r = update_pwr_cal(chip, channel);
+               if (r)
+                       return r;
+               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+/* The CCK baseband gain can be optionally patched by the EEPROM */
+static int patch_cck_gain(struct zd_chip *chip)
+{
+       int r;
+       u32 value;
+
+       if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
+               return 0;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_ioread32_locked(chip, &value, E2P_PHY_REG);
+       if (r)
+               return r;
+       dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff);
+       return zd_iowrite16_locked(chip, value & 0xff, ZD_CR47);
+}
+
+int zd_chip_set_channel(struct zd_chip *chip, u8 channel)
+{
+       int r, t;
+
+       mutex_lock(&chip->mutex);
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               goto out;
+       r = zd_rf_set_channel(&chip->rf, channel);
+       if (r)
+               goto unlock;
+       r = update_channel_integration_and_calibration(chip, channel);
+       if (r)
+               goto unlock;
+       r = patch_cck_gain(chip);
+       if (r)
+               goto unlock;
+       r = patch_6m_band_edge(chip, channel);
+       if (r)
+               goto unlock;
+       r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS);
+unlock:
+       t = zd_chip_unlock_phy_regs(chip);
+       if (t && !r)
+               r = t;
+out:
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+u8 zd_chip_get_channel(struct zd_chip *chip)
+{
+       u8 channel;
+
+       mutex_lock(&chip->mutex);
+       channel = chip->rf.channel;
+       mutex_unlock(&chip->mutex);
+       return channel;
+}
+
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
+{
+       const zd_addr_t a[] = {
+               fw_reg_addr(chip, FW_REG_LED_LINK_STATUS),
+               CR_LED,
+       };
+
+       int r;
+       u16 v[ARRAY_SIZE(a)];
+       struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
+               [0] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS) },
+               [1] = { CR_LED },
+       };
+       u16 other_led;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a));
+       if (r)
+               goto out;
+
+       other_led = chip->link_led == LED1 ? LED2 : LED1;
+
+       switch (status) {
+       case ZD_LED_OFF:
+               ioreqs[0].value = FW_LINK_OFF;
+               ioreqs[1].value = v[1] & ~(LED1|LED2);
+               break;
+       case ZD_LED_SCANNING:
+               ioreqs[0].value = FW_LINK_OFF;
+               ioreqs[1].value = v[1] & ~other_led;
+               if (get_seconds() % 3 == 0) {
+                       ioreqs[1].value &= ~chip->link_led;
+               } else {
+                       ioreqs[1].value |= chip->link_led;
+               }
+               break;
+       case ZD_LED_ASSOCIATED:
+               ioreqs[0].value = FW_LINK_TX;
+               ioreqs[1].value = v[1] & ~other_led;
+               ioreqs[1].value |= chip->link_led;
+               break;
+       default:
+               r = -EINVAL;
+               goto out;
+       }
+
+       if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) {
+               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               if (r)
+                       goto out;
+       }
+       r = 0;
+out:
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
+{
+       int r;
+
+       if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame)
+{
+       return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame);
+}
+
+/**
+ * zd_rx_rate - report zd-rate
+ * @rx_frame - received frame
+ * @rx_status - rx_status as given by the device
+ *
+ * This function converts the rate as encoded in the received packet to the
+ * zd-rate, we are using on other places in the driver.
+ */
+u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
+{
+       u8 zd_rate;
+       if (status->frame_status & ZD_RX_OFDM) {
+               zd_rate = zd_rate_from_ofdm_plcp_header(rx_frame);
+       } else {
+               switch (zd_cck_plcp_header_signal(rx_frame)) {
+               case ZD_CCK_PLCP_SIGNAL_1M:
+                       zd_rate = ZD_CCK_RATE_1M;
+                       break;
+               case ZD_CCK_PLCP_SIGNAL_2M:
+                       zd_rate = ZD_CCK_RATE_2M;
+                       break;
+               case ZD_CCK_PLCP_SIGNAL_5M5:
+                       zd_rate = ZD_CCK_RATE_5_5M;
+                       break;
+               case ZD_CCK_PLCP_SIGNAL_11M:
+                       zd_rate = ZD_CCK_RATE_11M;
+                       break;
+               default:
+                       zd_rate = 0;
+               }
+       }
+
+       return zd_rate;
+}
+
+int zd_chip_switch_radio_on(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_switch_radio_on(&chip->rf);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_switch_radio_off(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_switch_radio_off(&chip->rf);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+int zd_chip_enable_int(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       r = zd_usb_enable_int(&chip->usb);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+void zd_chip_disable_int(struct zd_chip *chip)
+{
+       mutex_lock(&chip->mutex);
+       zd_usb_disable_int(&chip->usb);
+       mutex_unlock(&chip->mutex);
+
+       /* cancel pending interrupt work */
+       cancel_work_sync(&zd_chip_to_mac(chip)->process_intr);
+}
+
+int zd_chip_enable_rxtx(struct zd_chip *chip)
+{
+       int r;
+
+       mutex_lock(&chip->mutex);
+       zd_usb_enable_tx(&chip->usb);
+       r = zd_usb_enable_rx(&chip->usb);
+       zd_tx_watchdog_enable(&chip->usb);
+       mutex_unlock(&chip->mutex);
+       return r;
+}
+
+void zd_chip_disable_rxtx(struct zd_chip *chip)
+{
+       mutex_lock(&chip->mutex);
+       zd_tx_watchdog_disable(&chip->usb);
+       zd_usb_disable_rx(&chip->usb);
+       zd_usb_disable_tx(&chip->usb);
+       mutex_unlock(&chip->mutex);
+}
+
+int zd_rfwritev_locked(struct zd_chip *chip,
+                      const u32* values, unsigned int count, u8 bits)
+{
+       int r;
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               r = zd_rfwrite_locked(chip, values[i], bits);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+/*
+ * We can optionally program the RF directly through CR regs, if supported by
+ * the hardware. This is much faster than the older method.
+ */
+int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value)
+{
+       const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR244, (value >> 16) & 0xff },
+               { ZD_CR243, (value >>  8) & 0xff },
+               { ZD_CR242,  value        & 0xff },
+       };
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rfwritev_cr_locked(struct zd_chip *chip,
+                         const u32 *values, unsigned int count)
+{
+       int r;
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               r = zd_rfwrite_cr_locked(chip, values[i]);
+               if (r)
+                       return r;
+       }
+
+       return 0;
+}
+
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+                              struct zd_mc_hash *hash)
+{
+       const struct zd_ioreq32 ioreqs[] = {
+               { CR_GROUP_HASH_P1, hash->low },
+               { CR_GROUP_HASH_P2, hash->high },
+       };
+
+       return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+u64 zd_chip_get_tsf(struct zd_chip *chip)
+{
+       int r;
+       static const zd_addr_t aw_pt_bi_addr[] =
+               { CR_TSF_LOW_PART, CR_TSF_HIGH_PART };
+       u32 values[2];
+       u64 tsf;
+
+       mutex_lock(&chip->mutex);
+       r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr,
+                               ARRAY_SIZE(aw_pt_bi_addr));
+       mutex_unlock(&chip->mutex);
+       if (r)
+               return 0;
+
+       tsf = values[1];
+       tsf = (tsf << 32) | values[0];
+
+       return tsf;
+}
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_chip.h b/drivers/net/wireless/zydas/zd1211rw/zd_chip.h
new file mode 100644 (file)
index 0000000..b03786c
--- /dev/null
@@ -0,0 +1,983 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ZD_CHIP_H
+#define _ZD_CHIP_H
+
+#include <net/mac80211.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+
+/* Header for the Media Access Controller (MAC) and the Baseband Processor
+ * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and
+ * adds a processor for handling the USB protocol.
+ */
+
+/* Address space */
+enum {
+       /* CONTROL REGISTERS */
+       CR_START                        = 0x9000,
+
+
+       /* FIRMWARE */
+       FW_START                        = 0xee00,
+
+
+       /* EEPROM */
+       E2P_START                       = 0xf800,
+       E2P_LEN                         = 0x800,
+
+       /* EEPROM layout */
+       E2P_LOAD_CODE_LEN               = 0xe,          /* base 0xf800 */
+       E2P_LOAD_VECT_LEN               = 0x9,          /* base 0xf80e */
+       /* E2P_DATA indexes into this */
+       E2P_DATA_LEN                    = 0x7e,         /* base 0xf817 */
+       E2P_BOOT_CODE_LEN               = 0x760,        /* base 0xf895 */
+       E2P_INTR_VECT_LEN               = 0xb,          /* base 0xfff5 */
+
+       /* Some precomputed offsets into the EEPROM */
+       E2P_DATA_OFFSET                 = E2P_LOAD_CODE_LEN + E2P_LOAD_VECT_LEN,
+       E2P_BOOT_CODE_OFFSET            = E2P_DATA_OFFSET + E2P_DATA_LEN,
+};
+
+#define CTL_REG(offset) ((zd_addr_t)(CR_START + (offset)))
+#define E2P_DATA(offset) ((zd_addr_t)(E2P_START + E2P_DATA_OFFSET + (offset)))
+#define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset)))
+
+/* 8-bit hardware registers */
+#define ZD_CR0   CTL_REG(0x0000)
+#define ZD_CR1   CTL_REG(0x0004)
+#define ZD_CR2   CTL_REG(0x0008)
+#define ZD_CR3   CTL_REG(0x000C)
+
+#define ZD_CR5   CTL_REG(0x0010)
+/*     bit 5: if set short preamble used
+ *     bit 6: filter band - Japan channel 14 on, else off
+ */
+#define ZD_CR6   CTL_REG(0x0014)
+#define ZD_CR7   CTL_REG(0x0018)
+#define ZD_CR8   CTL_REG(0x001C)
+
+#define ZD_CR4   CTL_REG(0x0020)
+
+#define ZD_CR9   CTL_REG(0x0024)
+/*     bit 2: antenna switch (together with ZD_CR10) */
+#define ZD_CR10  CTL_REG(0x0028)
+/*     bit 1: antenna switch (together with ZD_CR9)
+ *     RF2959 controls with ZD_CR11 radion on and off
+ */
+#define ZD_CR11  CTL_REG(0x002C)
+/*     bit 6:  TX power control for OFDM
+ *     RF2959 controls with ZD_CR10 radio on and off
+ */
+#define ZD_CR12  CTL_REG(0x0030)
+#define ZD_CR13  CTL_REG(0x0034)
+#define ZD_CR14  CTL_REG(0x0038)
+#define ZD_CR15  CTL_REG(0x003C)
+#define ZD_CR16  CTL_REG(0x0040)
+#define ZD_CR17  CTL_REG(0x0044)
+#define ZD_CR18  CTL_REG(0x0048)
+#define ZD_CR19  CTL_REG(0x004C)
+#define ZD_CR20  CTL_REG(0x0050)
+#define ZD_CR21  CTL_REG(0x0054)
+#define ZD_CR22  CTL_REG(0x0058)
+#define ZD_CR23  CTL_REG(0x005C)
+#define ZD_CR24  CTL_REG(0x0060)       /* CCA threshold */
+#define ZD_CR25  CTL_REG(0x0064)
+#define ZD_CR26  CTL_REG(0x0068)
+#define ZD_CR27  CTL_REG(0x006C)
+#define ZD_CR28  CTL_REG(0x0070)
+#define ZD_CR29  CTL_REG(0x0074)
+#define ZD_CR30  CTL_REG(0x0078)
+#define ZD_CR31  CTL_REG(0x007C)       /* TX power control for RF in
+                                        * CCK mode
+                                        */
+#define ZD_CR32  CTL_REG(0x0080)
+#define ZD_CR33  CTL_REG(0x0084)
+#define ZD_CR34  CTL_REG(0x0088)
+#define ZD_CR35  CTL_REG(0x008C)
+#define ZD_CR36  CTL_REG(0x0090)
+#define ZD_CR37  CTL_REG(0x0094)
+#define ZD_CR38  CTL_REG(0x0098)
+#define ZD_CR39  CTL_REG(0x009C)
+#define ZD_CR40  CTL_REG(0x00A0)
+#define ZD_CR41  CTL_REG(0x00A4)
+#define ZD_CR42  CTL_REG(0x00A8)
+#define ZD_CR43  CTL_REG(0x00AC)
+#define ZD_CR44  CTL_REG(0x00B0)
+#define ZD_CR45  CTL_REG(0x00B4)
+#define ZD_CR46  CTL_REG(0x00B8)
+#define ZD_CR47  CTL_REG(0x00BC)       /* CCK baseband gain
+                                        * (patch value might be in EEPROM)
+                                        */
+#define ZD_CR48  CTL_REG(0x00C0)
+#define ZD_CR49  CTL_REG(0x00C4)
+#define ZD_CR50  CTL_REG(0x00C8)
+#define ZD_CR51  CTL_REG(0x00CC)       /* TX power control for RF in
+                                        * 6-36M modes
+                                        */
+#define ZD_CR52  CTL_REG(0x00D0)       /* TX power control for RF in
+                                        * 48M mode
+                                        */
+#define ZD_CR53  CTL_REG(0x00D4)       /* TX power control for RF in
+                                        * 54M mode
+                                        */
+#define ZD_CR54  CTL_REG(0x00D8)
+#define ZD_CR55  CTL_REG(0x00DC)
+#define ZD_CR56  CTL_REG(0x00E0)
+#define ZD_CR57  CTL_REG(0x00E4)
+#define ZD_CR58  CTL_REG(0x00E8)
+#define ZD_CR59  CTL_REG(0x00EC)
+#define ZD_CR60  CTL_REG(0x00F0)
+#define ZD_CR61  CTL_REG(0x00F4)
+#define ZD_CR62  CTL_REG(0x00F8)
+#define ZD_CR63  CTL_REG(0x00FC)
+#define ZD_CR64  CTL_REG(0x0100)
+#define ZD_CR65  CTL_REG(0x0104) /* OFDM 54M calibration */
+#define ZD_CR66  CTL_REG(0x0108) /* OFDM 48M calibration */
+#define ZD_CR67  CTL_REG(0x010C) /* OFDM 36M calibration */
+#define ZD_CR68  CTL_REG(0x0110) /* CCK calibration */
+#define ZD_CR69  CTL_REG(0x0114)
+#define ZD_CR70  CTL_REG(0x0118)
+#define ZD_CR71  CTL_REG(0x011C)
+#define ZD_CR72  CTL_REG(0x0120)
+#define ZD_CR73  CTL_REG(0x0124)
+#define ZD_CR74  CTL_REG(0x0128)
+#define ZD_CR75  CTL_REG(0x012C)
+#define ZD_CR76  CTL_REG(0x0130)
+#define ZD_CR77  CTL_REG(0x0134)
+#define ZD_CR78  CTL_REG(0x0138)
+#define ZD_CR79  CTL_REG(0x013C)
+#define ZD_CR80  CTL_REG(0x0140)
+#define ZD_CR81  CTL_REG(0x0144)
+#define ZD_CR82  CTL_REG(0x0148)
+#define ZD_CR83  CTL_REG(0x014C)
+#define ZD_CR84  CTL_REG(0x0150)
+#define ZD_CR85  CTL_REG(0x0154)
+#define ZD_CR86  CTL_REG(0x0158)
+#define ZD_CR87  CTL_REG(0x015C)
+#define ZD_CR88  CTL_REG(0x0160)
+#define ZD_CR89  CTL_REG(0x0164)
+#define ZD_CR90  CTL_REG(0x0168)
+#define ZD_CR91  CTL_REG(0x016C)
+#define ZD_CR92  CTL_REG(0x0170)
+#define ZD_CR93  CTL_REG(0x0174)
+#define ZD_CR94  CTL_REG(0x0178)
+#define ZD_CR95  CTL_REG(0x017C)
+#define ZD_CR96  CTL_REG(0x0180)
+#define ZD_CR97  CTL_REG(0x0184)
+#define ZD_CR98  CTL_REG(0x0188)
+#define ZD_CR99  CTL_REG(0x018C)
+#define ZD_CR100 CTL_REG(0x0190)
+#define ZD_CR101 CTL_REG(0x0194)
+#define ZD_CR102 CTL_REG(0x0198)
+#define ZD_CR103 CTL_REG(0x019C)
+#define ZD_CR104 CTL_REG(0x01A0)
+#define ZD_CR105 CTL_REG(0x01A4)
+#define ZD_CR106 CTL_REG(0x01A8)
+#define ZD_CR107 CTL_REG(0x01AC)
+#define ZD_CR108 CTL_REG(0x01B0)
+#define ZD_CR109 CTL_REG(0x01B4)
+#define ZD_CR110 CTL_REG(0x01B8)
+#define ZD_CR111 CTL_REG(0x01BC)
+#define ZD_CR112 CTL_REG(0x01C0)
+#define ZD_CR113 CTL_REG(0x01C4)
+#define ZD_CR114 CTL_REG(0x01C8)
+#define ZD_CR115 CTL_REG(0x01CC)
+#define ZD_CR116 CTL_REG(0x01D0)
+#define ZD_CR117 CTL_REG(0x01D4)
+#define ZD_CR118 CTL_REG(0x01D8)
+#define ZD_CR119 CTL_REG(0x01DC)
+#define ZD_CR120 CTL_REG(0x01E0)
+#define ZD_CR121 CTL_REG(0x01E4)
+#define ZD_CR122 CTL_REG(0x01E8)
+#define ZD_CR123 CTL_REG(0x01EC)
+#define ZD_CR124 CTL_REG(0x01F0)
+#define ZD_CR125 CTL_REG(0x01F4)
+#define ZD_CR126 CTL_REG(0x01F8)
+#define ZD_CR127 CTL_REG(0x01FC)
+#define ZD_CR128 CTL_REG(0x0200)
+#define ZD_CR129 CTL_REG(0x0204)
+#define ZD_CR130 CTL_REG(0x0208)
+#define ZD_CR131 CTL_REG(0x020C)
+#define ZD_CR132 CTL_REG(0x0210)
+#define ZD_CR133 CTL_REG(0x0214)
+#define ZD_CR134 CTL_REG(0x0218)
+#define ZD_CR135 CTL_REG(0x021C)
+#define ZD_CR136 CTL_REG(0x0220)
+#define ZD_CR137 CTL_REG(0x0224)
+#define ZD_CR138 CTL_REG(0x0228)
+#define ZD_CR139 CTL_REG(0x022C)
+#define ZD_CR140 CTL_REG(0x0230)
+#define ZD_CR141 CTL_REG(0x0234)
+#define ZD_CR142 CTL_REG(0x0238)
+#define ZD_CR143 CTL_REG(0x023C)
+#define ZD_CR144 CTL_REG(0x0240)
+#define ZD_CR145 CTL_REG(0x0244)
+#define ZD_CR146 CTL_REG(0x0248)
+#define ZD_CR147 CTL_REG(0x024C)
+#define ZD_CR148 CTL_REG(0x0250)
+#define ZD_CR149 CTL_REG(0x0254)
+#define ZD_CR150 CTL_REG(0x0258)
+#define ZD_CR151 CTL_REG(0x025C)
+#define ZD_CR152 CTL_REG(0x0260)
+#define ZD_CR153 CTL_REG(0x0264)
+#define ZD_CR154 CTL_REG(0x0268)
+#define ZD_CR155 CTL_REG(0x026C)
+#define ZD_CR156 CTL_REG(0x0270)
+#define ZD_CR157 CTL_REG(0x0274)
+#define ZD_CR158 CTL_REG(0x0278)
+#define ZD_CR159 CTL_REG(0x027C)
+#define ZD_CR160 CTL_REG(0x0280)
+#define ZD_CR161 CTL_REG(0x0284)
+#define ZD_CR162 CTL_REG(0x0288)
+#define ZD_CR163 CTL_REG(0x028C)
+#define ZD_CR164 CTL_REG(0x0290)
+#define ZD_CR165 CTL_REG(0x0294)
+#define ZD_CR166 CTL_REG(0x0298)
+#define ZD_CR167 CTL_REG(0x029C)
+#define ZD_CR168 CTL_REG(0x02A0)
+#define ZD_CR169 CTL_REG(0x02A4)
+#define ZD_CR170 CTL_REG(0x02A8)
+#define ZD_CR171 CTL_REG(0x02AC)
+#define ZD_CR172 CTL_REG(0x02B0)
+#define ZD_CR173 CTL_REG(0x02B4)
+#define ZD_CR174 CTL_REG(0x02B8)
+#define ZD_CR175 CTL_REG(0x02BC)
+#define ZD_CR176 CTL_REG(0x02C0)
+#define ZD_CR177 CTL_REG(0x02C4)
+#define ZD_CR178 CTL_REG(0x02C8)
+#define ZD_CR179 CTL_REG(0x02CC)
+#define ZD_CR180 CTL_REG(0x02D0)
+#define ZD_CR181 CTL_REG(0x02D4)
+#define ZD_CR182 CTL_REG(0x02D8)
+#define ZD_CR183 CTL_REG(0x02DC)
+#define ZD_CR184 CTL_REG(0x02E0)
+#define ZD_CR185 CTL_REG(0x02E4)
+#define ZD_CR186 CTL_REG(0x02E8)
+#define ZD_CR187 CTL_REG(0x02EC)
+#define ZD_CR188 CTL_REG(0x02F0)
+#define ZD_CR189 CTL_REG(0x02F4)
+#define ZD_CR190 CTL_REG(0x02F8)
+#define ZD_CR191 CTL_REG(0x02FC)
+#define ZD_CR192 CTL_REG(0x0300)
+#define ZD_CR193 CTL_REG(0x0304)
+#define ZD_CR194 CTL_REG(0x0308)
+#define ZD_CR195 CTL_REG(0x030C)
+#define ZD_CR196 CTL_REG(0x0310)
+#define ZD_CR197 CTL_REG(0x0314)
+#define ZD_CR198 CTL_REG(0x0318)
+#define ZD_CR199 CTL_REG(0x031C)
+#define ZD_CR200 CTL_REG(0x0320)
+#define ZD_CR201 CTL_REG(0x0324)
+#define ZD_CR202 CTL_REG(0x0328)
+#define ZD_CR203 CTL_REG(0x032C)       /* I2C bus template value & flash
+                                        * control
+                                        */
+#define ZD_CR204 CTL_REG(0x0330)
+#define ZD_CR205 CTL_REG(0x0334)
+#define ZD_CR206 CTL_REG(0x0338)
+#define ZD_CR207 CTL_REG(0x033C)
+#define ZD_CR208 CTL_REG(0x0340)
+#define ZD_CR209 CTL_REG(0x0344)
+#define ZD_CR210 CTL_REG(0x0348)
+#define ZD_CR211 CTL_REG(0x034C)
+#define ZD_CR212 CTL_REG(0x0350)
+#define ZD_CR213 CTL_REG(0x0354)
+#define ZD_CR214 CTL_REG(0x0358)
+#define ZD_CR215 CTL_REG(0x035C)
+#define ZD_CR216 CTL_REG(0x0360)
+#define ZD_CR217 CTL_REG(0x0364)
+#define ZD_CR218 CTL_REG(0x0368)
+#define ZD_CR219 CTL_REG(0x036C)
+#define ZD_CR220 CTL_REG(0x0370)
+#define ZD_CR221 CTL_REG(0x0374)
+#define ZD_CR222 CTL_REG(0x0378)
+#define ZD_CR223 CTL_REG(0x037C)
+#define ZD_CR224 CTL_REG(0x0380)
+#define ZD_CR225 CTL_REG(0x0384)
+#define ZD_CR226 CTL_REG(0x0388)
+#define ZD_CR227 CTL_REG(0x038C)
+#define ZD_CR228 CTL_REG(0x0390)
+#define ZD_CR229 CTL_REG(0x0394)
+#define ZD_CR230 CTL_REG(0x0398)
+#define ZD_CR231 CTL_REG(0x039C)
+#define ZD_CR232 CTL_REG(0x03A0)
+#define ZD_CR233 CTL_REG(0x03A4)
+#define ZD_CR234 CTL_REG(0x03A8)
+#define ZD_CR235 CTL_REG(0x03AC)
+#define ZD_CR236 CTL_REG(0x03B0)
+
+#define ZD_CR240 CTL_REG(0x03C0)
+/*             bit 7: host-controlled RF register writes
+ * ZD_CR241-ZD_CR245: for hardware controlled writing of RF bits, not needed for
+ *                    USB
+ */
+#define ZD_CR241 CTL_REG(0x03C4)
+#define ZD_CR242 CTL_REG(0x03C8)
+#define ZD_CR243 CTL_REG(0x03CC)
+#define ZD_CR244 CTL_REG(0x03D0)
+#define ZD_CR245 CTL_REG(0x03D4)
+
+#define ZD_CR251 CTL_REG(0x03EC)       /* only used for activation and
+                                        * deactivation of Airoha RFs AL2230
+                                        * and AL7230B
+                                        */
+#define ZD_CR252 CTL_REG(0x03F0)
+#define ZD_CR253 CTL_REG(0x03F4)
+#define ZD_CR254 CTL_REG(0x03F8)
+#define ZD_CR255 CTL_REG(0x03FC)
+
+#define CR_MAX_PHY_REG 255
+
+/* Taken from the ZYDAS driver, not all of them are relevant for the ZD1211
+ * driver.
+ */
+
+#define CR_RF_IF_CLK                   CTL_REG(0x0400)
+#define CR_RF_IF_DATA                  CTL_REG(0x0404)
+#define CR_PE1_PE2                     CTL_REG(0x0408)
+#define CR_PE2_DLY                     CTL_REG(0x040C)
+#define CR_LE1                         CTL_REG(0x0410)
+#define CR_LE2                         CTL_REG(0x0414)
+/* Seems to enable/disable GPI (General Purpose IO?) */
+#define CR_GPI_EN                      CTL_REG(0x0418)
+#define CR_RADIO_PD                    CTL_REG(0x042C)
+#define CR_RF2948_PD                   CTL_REG(0x042C)
+#define CR_ENABLE_PS_MANUAL_AGC                CTL_REG(0x043C)
+#define CR_CONFIG_PHILIPS              CTL_REG(0x0440)
+#define CR_SA2400_SER_AP               CTL_REG(0x0444)
+#define CR_I2C_WRITE                   CTL_REG(0x0444)
+#define CR_SA2400_SER_RP               CTL_REG(0x0448)
+#define CR_RADIO_PE                    CTL_REG(0x0458)
+#define CR_RST_BUS_MASTER              CTL_REG(0x045C)
+#define CR_RFCFG                       CTL_REG(0x0464)
+#define CR_HSTSCHG                     CTL_REG(0x046C)
+#define CR_PHY_ON                      CTL_REG(0x0474)
+#define CR_RX_DELAY                    CTL_REG(0x0478)
+#define CR_RX_PE_DELAY                 CTL_REG(0x047C)
+#define CR_GPIO_1                      CTL_REG(0x0490)
+#define CR_GPIO_2                      CTL_REG(0x0494)
+#define CR_EncryBufMux                 CTL_REG(0x04A8)
+#define CR_PS_CTRL                     CTL_REG(0x0500)
+#define CR_ADDA_PWR_DWN                        CTL_REG(0x0504)
+#define CR_ADDA_MBIAS_WARMTIME         CTL_REG(0x0508)
+#define CR_MAC_PS_STATE                        CTL_REG(0x050C)
+
+#define CR_INTERRUPT                   CTL_REG(0x0510)
+#define INT_TX_COMPLETE                        (1 <<  0)
+#define INT_RX_COMPLETE                        (1 <<  1)
+#define INT_RETRY_FAIL                 (1 <<  2)
+#define INT_WAKEUP                     (1 <<  3)
+#define INT_DTIM_NOTIFY                        (1 <<  5)
+#define INT_CFG_NEXT_BCN               (1 <<  6)
+#define INT_BUS_ABORT                  (1 <<  7)
+#define INT_TX_FIFO_READY              (1 <<  8)
+#define INT_UART                       (1 <<  9)
+#define INT_TX_COMPLETE_EN             (1 << 16)
+#define INT_RX_COMPLETE_EN             (1 << 17)
+#define INT_RETRY_FAIL_EN              (1 << 18)
+#define INT_WAKEUP_EN                  (1 << 19)
+#define INT_DTIM_NOTIFY_EN             (1 << 21)
+#define INT_CFG_NEXT_BCN_EN            (1 << 22)
+#define INT_BUS_ABORT_EN               (1 << 23)
+#define INT_TX_FIFO_READY_EN           (1 << 24)
+#define INT_UART_EN                    (1 << 25)
+
+#define CR_TSF_LOW_PART                        CTL_REG(0x0514)
+#define CR_TSF_HIGH_PART               CTL_REG(0x0518)
+
+/* Following three values are in time units (1024us)
+ * Following condition must be met:
+ * atim < tbtt < bcn
+ */
+#define CR_ATIM_WND_PERIOD             CTL_REG(0x051C)
+#define CR_BCN_INTERVAL                        CTL_REG(0x0520)
+#define CR_PRE_TBTT                    CTL_REG(0x0524)
+/* in units of TU(1024us) */
+
+/* for UART support */
+#define CR_UART_RBR_THR_DLL            CTL_REG(0x0540)
+#define CR_UART_DLM_IER                        CTL_REG(0x0544)
+#define CR_UART_IIR_FCR                        CTL_REG(0x0548)
+#define CR_UART_LCR                    CTL_REG(0x054c)
+#define CR_UART_MCR                    CTL_REG(0x0550)
+#define CR_UART_LSR                    CTL_REG(0x0554)
+#define CR_UART_MSR                    CTL_REG(0x0558)
+#define CR_UART_ECR                    CTL_REG(0x055c)
+#define CR_UART_STATUS                 CTL_REG(0x0560)
+
+#define CR_PCI_TX_ADDR_P1              CTL_REG(0x0600)
+#define CR_PCI_TX_AddR_P2              CTL_REG(0x0604)
+#define CR_PCI_RX_AddR_P1              CTL_REG(0x0608)
+#define CR_PCI_RX_AddR_P2              CTL_REG(0x060C)
+
+/* must be overwritten if custom MAC address will be used */
+#define CR_MAC_ADDR_P1                 CTL_REG(0x0610)
+#define CR_MAC_ADDR_P2                 CTL_REG(0x0614)
+#define CR_BSSID_P1                    CTL_REG(0x0618)
+#define CR_BSSID_P2                    CTL_REG(0x061C)
+#define CR_BCN_PLCP_CFG                        CTL_REG(0x0620)
+
+/* Group hash table for filtering incoming packets.
+ *
+ * The group hash table is 64 bit large and split over two parts. The first
+ * part is the lower part. The upper 6 bits of the last byte of the target
+ * address are used as index. Packets are received if the hash table bit is
+ * set. This is used for multicast handling, but for broadcasts (address
+ * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set.
+ */
+#define CR_GROUP_HASH_P1               CTL_REG(0x0624)
+#define CR_GROUP_HASH_P2               CTL_REG(0x0628)
+
+#define CR_RX_TIMEOUT                  CTL_REG(0x062C)
+
+/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
+ * device will use a rate in this table that is less than or equal to the rate
+ * of the incoming frame which prompted the response. */
+#define CR_BASIC_RATE_TBL              CTL_REG(0x0630)
+#define CR_RATE_1M     (1 <<  0)       /* 802.11b */
+#define CR_RATE_2M     (1 <<  1)       /* 802.11b */
+#define CR_RATE_5_5M   (1 <<  2)       /* 802.11b */
+#define CR_RATE_11M    (1 <<  3)       /* 802.11b */
+#define CR_RATE_6M      (1 <<  8)      /* 802.11g */
+#define CR_RATE_9M      (1 <<  9)      /* 802.11g */
+#define CR_RATE_12M    (1 << 10)       /* 802.11g */
+#define CR_RATE_18M    (1 << 11)       /* 802.11g */
+#define CR_RATE_24M     (1 << 12)      /* 802.11g */
+#define CR_RATE_36M     (1 << 13)      /* 802.11g */
+#define CR_RATE_48M     (1 << 14)      /* 802.11g */
+#define CR_RATE_54M     (1 << 15)      /* 802.11g */
+#define CR_RATES_80211G        0xff00
+#define CR_RATES_80211B        0x000f
+
+/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if
+ * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will
+ * look for a rate in this table that is less than or equal to the rate of
+ * the incoming frame. */
+#define CR_MANDATORY_RATE_TBL          CTL_REG(0x0634)
+#define CR_RTS_CTS_RATE                        CTL_REG(0x0638)
+
+/* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */
+#define RTSCTS_SH_RTS_RATE             0
+#define RTSCTS_SH_EXP_CTS_RATE         4
+#define RTSCTS_SH_RTS_MOD_TYPE         8
+#define RTSCTS_SH_RTS_PMB_TYPE         9
+#define RTSCTS_SH_CTS_RATE             16
+#define RTSCTS_SH_CTS_MOD_TYPE         24
+#define RTSCTS_SH_CTS_PMB_TYPE         25
+
+#define CR_WEP_PROTECT                 CTL_REG(0x063C)
+#define CR_RX_THRESHOLD                        CTL_REG(0x0640)
+
+/* register for controlling the LEDS */
+#define CR_LED                         CTL_REG(0x0644)
+/* masks for controlling LEDs */
+#define LED1                           (1 <<  8)
+#define LED2                           (1 <<  9)
+#define LED_SW                         (1 << 10)
+
+/* Seems to indicate that the configuration is over.
+ */
+#define CR_AFTER_PNP                   CTL_REG(0x0648)
+#define CR_ACK_TIME_80211              CTL_REG(0x0658)
+
+#define CR_RX_OFFSET                   CTL_REG(0x065c)
+
+#define CR_BCN_LENGTH                  CTL_REG(0x0664)
+#define CR_PHY_DELAY                   CTL_REG(0x066C)
+#define CR_BCN_FIFO                    CTL_REG(0x0670)
+#define CR_SNIFFER_ON                  CTL_REG(0x0674)
+
+#define CR_ENCRYPTION_TYPE             CTL_REG(0x0678)
+#define NO_WEP                         0
+#define WEP64                          1
+#define WEP128                         5
+#define WEP256                         6
+#define ENC_SNIFFER                    8
+
+#define CR_ZD1211_RETRY_MAX            CTL_REG(0x067C)
+
+#define CR_REG1                                CTL_REG(0x0680)
+/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical
+ * registers, so one could argue it is a LOCK bit. But calling it
+ * LOCK_PHY_REGS makes it confusing.
+ */
+#define UNLOCK_PHY_REGS                        (1 << 7)
+
+#define CR_DEVICE_STATE                        CTL_REG(0x0684)
+#define CR_UNDERRUN_CNT                        CTL_REG(0x0688)
+
+#define CR_RX_FILTER                   CTL_REG(0x068c)
+#define RX_FILTER_ASSOC_REQUEST                (1 <<  0)
+#define RX_FILTER_ASSOC_RESPONSE       (1 <<  1)
+#define RX_FILTER_REASSOC_REQUEST      (1 <<  2)
+#define RX_FILTER_REASSOC_RESPONSE     (1 <<  3)
+#define RX_FILTER_PROBE_REQUEST                (1 <<  4)
+#define RX_FILTER_PROBE_RESPONSE       (1 <<  5)
+/* bits 6 and 7 reserved */
+#define RX_FILTER_BEACON               (1 <<  8)
+#define RX_FILTER_ATIM                 (1 <<  9)
+#define RX_FILTER_DISASSOC             (1 << 10)
+#define RX_FILTER_AUTH                 (1 << 11)
+#define RX_FILTER_DEAUTH               (1 << 12)
+#define RX_FILTER_PSPOLL               (1 << 26)
+#define RX_FILTER_RTS                  (1 << 27)
+#define RX_FILTER_CTS                  (1 << 28)
+#define RX_FILTER_ACK                  (1 << 29)
+#define RX_FILTER_CFEND                        (1 << 30)
+#define RX_FILTER_CFACK                        (1 << 31)
+
+/* Enable bits for all frames you are interested in. */
+#define STA_RX_FILTER  (RX_FILTER_ASSOC_REQUEST | RX_FILTER_ASSOC_RESPONSE | \
+       RX_FILTER_REASSOC_REQUEST | RX_FILTER_REASSOC_RESPONSE | \
+       RX_FILTER_PROBE_REQUEST | RX_FILTER_PROBE_RESPONSE | \
+       (0x3 << 6) /* vendor driver sets these reserved bits */ | \
+       RX_FILTER_BEACON | RX_FILTER_ATIM | RX_FILTER_DISASSOC | \
+       RX_FILTER_AUTH | RX_FILTER_DEAUTH | \
+       (0x7 << 13) /* vendor driver sets these reserved bits */ | \
+       RX_FILTER_PSPOLL | RX_FILTER_ACK) /* 0x2400ffff */
+
+#define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
+       RX_FILTER_CFEND | RX_FILTER_CFACK)
+
+#define BCN_MODE_AP                    0x1000000
+#define BCN_MODE_IBSS                  0x2000000
+
+/* Monitor mode sets filter to 0xfffff */
+
+#define CR_ACK_TIMEOUT_EXT             CTL_REG(0x0690)
+#define CR_BCN_FIFO_SEMAPHORE          CTL_REG(0x0694)
+
+#define CR_IFS_VALUE                   CTL_REG(0x0698)
+#define IFS_VALUE_DIFS_SH              0
+#define IFS_VALUE_EIFS_SH              12
+#define IFS_VALUE_SIFS_SH              24
+#define IFS_VALUE_DEFAULT              ((  50 << IFS_VALUE_DIFS_SH) | \
+                                        (1148 << IFS_VALUE_EIFS_SH) | \
+                                        (  10 << IFS_VALUE_SIFS_SH))
+
+#define CR_RX_TIME_OUT                 CTL_REG(0x069C)
+#define CR_TOTAL_RX_FRM                        CTL_REG(0x06A0)
+#define CR_CRC32_CNT                   CTL_REG(0x06A4)
+#define CR_CRC16_CNT                   CTL_REG(0x06A8)
+#define CR_DECRYPTION_ERR_UNI          CTL_REG(0x06AC)
+#define CR_RX_FIFO_OVERRUN             CTL_REG(0x06B0)
+
+#define CR_DECRYPTION_ERR_MUL          CTL_REG(0x06BC)
+
+#define CR_NAV_CNT                     CTL_REG(0x06C4)
+#define CR_NAV_CCA                     CTL_REG(0x06C8)
+#define CR_RETRY_CNT                   CTL_REG(0x06CC)
+
+#define CR_READ_TCB_ADDR               CTL_REG(0x06E8)
+#define CR_READ_RFD_ADDR               CTL_REG(0x06EC)
+#define CR_CWMIN_CWMAX                 CTL_REG(0x06F0)
+#define CR_TOTAL_TX_FRM                        CTL_REG(0x06F4)
+
+/* CAM: Continuous Access Mode (power management) */
+#define CR_CAM_MODE                    CTL_REG(0x0700)
+#define MODE_IBSS                      0x0
+#define MODE_AP                                0x1
+#define MODE_STA                       0x2
+#define MODE_AP_WDS                    0x3
+
+#define CR_CAM_ROLL_TB_LOW             CTL_REG(0x0704)
+#define CR_CAM_ROLL_TB_HIGH            CTL_REG(0x0708)
+#define CR_CAM_ADDRESS                 CTL_REG(0x070C)
+#define CR_CAM_DATA                    CTL_REG(0x0710)
+
+#define CR_ROMDIR                      CTL_REG(0x0714)
+
+#define CR_DECRY_ERR_FLG_LOW           CTL_REG(0x0714)
+#define CR_DECRY_ERR_FLG_HIGH          CTL_REG(0x0718)
+
+#define CR_WEPKEY0                     CTL_REG(0x0720)
+#define CR_WEPKEY1                     CTL_REG(0x0724)
+#define CR_WEPKEY2                     CTL_REG(0x0728)
+#define CR_WEPKEY3                     CTL_REG(0x072C)
+#define CR_WEPKEY4                     CTL_REG(0x0730)
+#define CR_WEPKEY5                     CTL_REG(0x0734)
+#define CR_WEPKEY6                     CTL_REG(0x0738)
+#define CR_WEPKEY7                     CTL_REG(0x073C)
+#define CR_WEPKEY8                     CTL_REG(0x0740)
+#define CR_WEPKEY9                     CTL_REG(0x0744)
+#define CR_WEPKEY10                    CTL_REG(0x0748)
+#define CR_WEPKEY11                    CTL_REG(0x074C)
+#define CR_WEPKEY12                    CTL_REG(0x0750)
+#define CR_WEPKEY13                    CTL_REG(0x0754)
+#define CR_WEPKEY14                    CTL_REG(0x0758)
+#define CR_WEPKEY15                    CTL_REG(0x075c)
+#define CR_TKIP_MODE                   CTL_REG(0x0760)
+
+#define CR_EEPROM_PROTECT0             CTL_REG(0x0758)
+#define CR_EEPROM_PROTECT1             CTL_REG(0x075C)
+
+#define CR_DBG_FIFO_RD                 CTL_REG(0x0800)
+#define CR_DBG_SELECT                  CTL_REG(0x0804)
+#define CR_FIFO_Length                 CTL_REG(0x0808)
+
+
+#define CR_RSSI_MGC                    CTL_REG(0x0810)
+
+#define CR_PON                         CTL_REG(0x0818)
+#define CR_RX_ON                       CTL_REG(0x081C)
+#define CR_TX_ON                       CTL_REG(0x0820)
+#define CR_CHIP_EN                     CTL_REG(0x0824)
+#define CR_LO_SW                       CTL_REG(0x0828)
+#define CR_TXRX_SW                     CTL_REG(0x082C)
+#define CR_S_MD                                CTL_REG(0x0830)
+
+#define CR_USB_DEBUG_PORT              CTL_REG(0x0888)
+#define CR_ZD1211B_CWIN_MAX_MIN_AC0    CTL_REG(0x0b00)
+#define CR_ZD1211B_CWIN_MAX_MIN_AC1    CTL_REG(0x0b04)
+#define CR_ZD1211B_CWIN_MAX_MIN_AC2    CTL_REG(0x0b08)
+#define CR_ZD1211B_CWIN_MAX_MIN_AC3    CTL_REG(0x0b0c)
+#define CR_ZD1211B_AIFS_CTL1           CTL_REG(0x0b10)
+#define CR_ZD1211B_AIFS_CTL2           CTL_REG(0x0b14)
+#define CR_ZD1211B_TXOP                        CTL_REG(0x0b20)
+#define CR_ZD1211B_RETRY_MAX           CTL_REG(0x0b28)
+
+/* Value for CR_ZD1211_RETRY_MAX & CR_ZD1211B_RETRY_MAX. Vendor driver uses 2,
+ * we use 0. The first rate is tried (count+2), then all next rates are tried
+ * twice, until 1 Mbits is tried. */
+#define        ZD1211_RETRY_COUNT              0
+#define        ZD1211B_RETRY_COUNT     \
+       (ZD1211_RETRY_COUNT <<  0)|     \
+       (ZD1211_RETRY_COUNT <<  8)|     \
+       (ZD1211_RETRY_COUNT << 16)|     \
+       (ZD1211_RETRY_COUNT << 24)
+
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG                        ((zd_addr_t)0x85c1)
+
+#define CWIN_SIZE                      0x007f043f
+
+
+#define HWINT_ENABLED                  \
+       (INT_TX_COMPLETE_EN|            \
+        INT_RX_COMPLETE_EN|            \
+        INT_RETRY_FAIL_EN|             \
+        INT_WAKEUP_EN|                 \
+        INT_CFG_NEXT_BCN_EN)
+
+#define HWINT_DISABLED                 0
+
+#define E2P_PWR_INT_GUARD              8
+#define E2P_CHANNEL_COUNT              14
+
+/* If you compare this addresses with the ZYDAS orignal driver, please notify
+ * that we use word mapping for the EEPROM.
+ */
+
+/*
+ * Upper 16 bit contains the regulatory domain.
+ */
+#define E2P_SUBID              E2P_DATA(0x00)
+#define E2P_POD                        E2P_DATA(0x02)
+#define E2P_MAC_ADDR_P1                E2P_DATA(0x04)
+#define E2P_MAC_ADDR_P2                E2P_DATA(0x06)
+#define E2P_PWR_CAL_VALUE1     E2P_DATA(0x08)
+#define E2P_PWR_CAL_VALUE2     E2P_DATA(0x0a)
+#define E2P_PWR_CAL_VALUE3     E2P_DATA(0x0c)
+#define E2P_PWR_CAL_VALUE4      E2P_DATA(0x0e)
+#define E2P_PWR_INT_VALUE1     E2P_DATA(0x10)
+#define E2P_PWR_INT_VALUE2     E2P_DATA(0x12)
+#define E2P_PWR_INT_VALUE3     E2P_DATA(0x14)
+#define E2P_PWR_INT_VALUE4     E2P_DATA(0x16)
+
+/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30)
+ * also only 11 channels. */
+#define E2P_ALLOWED_CHANNEL    E2P_DATA(0x18)
+
+#define E2P_DEVICE_VER         E2P_DATA(0x20)
+#define E2P_PHY_REG            E2P_DATA(0x25)
+#define E2P_36M_CAL_VALUE1     E2P_DATA(0x28)
+#define E2P_36M_CAL_VALUE2      E2P_DATA(0x2a)
+#define E2P_36M_CAL_VALUE3      E2P_DATA(0x2c)
+#define E2P_36M_CAL_VALUE4     E2P_DATA(0x2e)
+#define E2P_11A_INT_VALUE1     E2P_DATA(0x30)
+#define E2P_11A_INT_VALUE2     E2P_DATA(0x32)
+#define E2P_11A_INT_VALUE3     E2P_DATA(0x34)
+#define E2P_11A_INT_VALUE4     E2P_DATA(0x36)
+#define E2P_48M_CAL_VALUE1     E2P_DATA(0x38)
+#define E2P_48M_CAL_VALUE2     E2P_DATA(0x3a)
+#define E2P_48M_CAL_VALUE3     E2P_DATA(0x3c)
+#define E2P_48M_CAL_VALUE4     E2P_DATA(0x3e)
+#define E2P_48M_INT_VALUE1     E2P_DATA(0x40)
+#define E2P_48M_INT_VALUE2     E2P_DATA(0x42)
+#define E2P_48M_INT_VALUE3     E2P_DATA(0x44)
+#define E2P_48M_INT_VALUE4     E2P_DATA(0x46)
+#define E2P_54M_CAL_VALUE1     E2P_DATA(0x48)  /* ??? */
+#define E2P_54M_CAL_VALUE2     E2P_DATA(0x4a)
+#define E2P_54M_CAL_VALUE3     E2P_DATA(0x4c)
+#define E2P_54M_CAL_VALUE4     E2P_DATA(0x4e)
+#define E2P_54M_INT_VALUE1     E2P_DATA(0x50)
+#define E2P_54M_INT_VALUE2     E2P_DATA(0x52)
+#define E2P_54M_INT_VALUE3     E2P_DATA(0x54)
+#define E2P_54M_INT_VALUE4     E2P_DATA(0x56)
+
+/* This word contains the base address of the FW_REG_ registers below */
+#define FWRAW_REGS_ADDR                FWRAW_DATA(0x1d)
+
+/* All 16 bit values, offset from the address in FWRAW_REGS_ADDR */
+enum {
+       FW_REG_FIRMWARE_VER     = 0,
+       /* non-zero if USB high speed connection */
+       FW_REG_USB_SPEED        = 1,
+       FW_REG_FIX_TX_RATE      = 2,
+       /* Seems to be able to control LEDs over the firmware */
+       FW_REG_LED_LINK_STATUS  = 3,
+       FW_REG_SOFT_RESET       = 4,
+       FW_REG_FLASH_CHK        = 5,
+};
+
+/* Values for FW_LINK_STATUS */
+#define FW_LINK_OFF            0x0
+#define FW_LINK_TX             0x1
+/* 0x2 - link led on? */
+
+enum {
+       /* indices for ofdm_cal_values */
+       OFDM_36M_INDEX = 0,
+       OFDM_48M_INDEX = 1,
+       OFDM_54M_INDEX = 2,
+};
+
+struct zd_chip {
+       struct zd_usb usb;
+       struct zd_rf rf;
+       struct mutex mutex;
+       /* Base address of FW_REG_ registers */
+       zd_addr_t fw_regs_base;
+       /* EepSetPoint in the vendor driver */
+       u8 pwr_cal_values[E2P_CHANNEL_COUNT];
+       /* integration values in the vendor driver */
+       u8 pwr_int_values[E2P_CHANNEL_COUNT];
+       /* SetPointOFDM in the vendor driver */
+       u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
+       u16 link_led;
+       unsigned int pa_type:4,
+               patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
+               new_phy_layout:1, al2230s_bit:1,
+               supports_tx_led:1;
+};
+
+static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
+{
+       return container_of(usb, struct zd_chip, usb);
+}
+
+static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
+{
+       return container_of(rf, struct zd_chip, rf);
+}
+
+#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
+
+void zd_chip_init(struct zd_chip *chip,
+                struct ieee80211_hw *hw,
+                struct usb_interface *intf);
+void zd_chip_clear(struct zd_chip *chip);
+int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
+int zd_chip_init_hw(struct zd_chip *chip);
+int zd_chip_reset(struct zd_chip *chip);
+
+static inline int zd_chip_is_zd1211b(struct zd_chip *chip)
+{
+       return chip->usb.is_zd1211b;
+}
+
+static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values,
+                                     const zd_addr_t *addresses,
+                                     unsigned int count)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_usb_ioread16v(&chip->usb, values, addresses, count);
+}
+
+static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value,
+                                    const zd_addr_t addr)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_usb_ioread16(&chip->usb, value, addr);
+}
+
+int zd_ioread32v_locked(struct zd_chip *chip, u32 *values,
+                       const zd_addr_t *addresses, unsigned int count);
+
+static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value,
+                                    const zd_addr_t addr)
+{
+       return zd_ioread32v_locked(chip, value, &addr, 1);
+}
+
+static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value,
+                                     zd_addr_t addr)
+{
+       struct zd_ioreq16 ioreq;
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       ioreq.addr = addr;
+       ioreq.value = value;
+
+       return zd_usb_iowrite16v(&chip->usb, &ioreq, 1);
+}
+
+int zd_iowrite16a_locked(struct zd_chip *chip,
+                         const struct zd_ioreq16 *ioreqs, unsigned int count);
+
+int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                         unsigned int count);
+
+static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value,
+                                     zd_addr_t addr)
+{
+       struct zd_ioreq32 ioreq;
+
+       ioreq.addr = addr;
+       ioreq.value = value;
+
+       return _zd_iowrite32v_locked(chip, &ioreq, 1);
+}
+
+int zd_iowrite32a_locked(struct zd_chip *chip,
+                        const struct zd_ioreq32 *ioreqs, unsigned int count);
+
+static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits)
+{
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       return zd_usb_rfwrite(&chip->usb, value, bits);
+}
+
+int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value);
+
+int zd_rfwritev_locked(struct zd_chip *chip,
+                      const u32* values, unsigned int count, u8 bits);
+int zd_rfwritev_cr_locked(struct zd_chip *chip,
+                         const u32* values, unsigned int count);
+
+/* Locking functions for reading and writing registers.
+ * The different parameters are intentional.
+ */
+int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value);
+int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value);
+int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value);
+int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value);
+int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
+                 u32 *values, unsigned int count);
+int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+                  unsigned int count);
+
+int zd_chip_set_channel(struct zd_chip *chip, u8 channel);
+static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
+{
+       return chip->rf.channel;
+}
+u8  zd_chip_get_channel(struct zd_chip *chip);
+int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid);
+int zd_chip_switch_radio_on(struct zd_chip *chip);
+int zd_chip_switch_radio_off(struct zd_chip *chip);
+int zd_chip_enable_int(struct zd_chip *chip);
+void zd_chip_disable_int(struct zd_chip *chip);
+int zd_chip_enable_rxtx(struct zd_chip *chip);
+void zd_chip_disable_rxtx(struct zd_chip *chip);
+int zd_chip_enable_hwint(struct zd_chip *chip);
+int zd_chip_disable_hwint(struct zd_chip *chip);
+int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel);
+int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, int preamble);
+
+static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
+{
+       return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type);
+}
+
+static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type)
+{
+       return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type);
+}
+
+static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
+{
+       return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
+}
+
+int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
+
+int zd_chip_lock_phy_regs(struct zd_chip *chip);
+int zd_chip_unlock_phy_regs(struct zd_chip *chip);
+
+enum led_status {
+       ZD_LED_OFF = 0,
+       ZD_LED_SCANNING = 1,
+       ZD_LED_ASSOCIATED = 2,
+};
+
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
+
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+                          int type);
+
+static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
+{
+       return zd_ioread32(chip, CR_BCN_INTERVAL, interval);
+}
+
+struct rx_status;
+
+u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
+
+struct zd_mc_hash {
+       u32 low;
+       u32 high;
+};
+
+static inline void zd_mc_clear(struct zd_mc_hash *hash)
+{
+       hash->low = 0;
+       /* The interfaces must always received broadcasts.
+        * The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63.
+        */
+       hash->high = 0x80000000;
+}
+
+static inline void zd_mc_add_all(struct zd_mc_hash *hash)
+{
+       hash->low = hash->high = 0xffffffff;
+}
+
+static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr)
+{
+       unsigned int i = addr[5] >> 2;
+       if (i < 32) {
+               hash->low |= 1 << i;
+       } else {
+               hash->high |= 1 << (i-32);
+       }
+}
+
+int zd_chip_set_multicast_hash(struct zd_chip *chip,
+                              struct zd_mc_hash *hash);
+
+u64 zd_chip_get_tsf(struct zd_chip *chip);
+
+#endif /* _ZD_CHIP_H */
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_def.h b/drivers/net/wireless/zydas/zd1211rw/zd_def.h
new file mode 100644 (file)
index 0000000..41bd755
--- /dev/null
@@ -0,0 +1,69 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ZD_DEF_H
+#define _ZD_DEF_H
+
+#include <linux/kernel.h>
+#include <linux/stringify.h>
+#include <linux/device.h>
+
+typedef u16 __nocast zd_addr_t;
+
+#define dev_printk_f(level, dev, fmt, args...) \
+       dev_printk(level, dev, "%s() " fmt, __func__, ##args)
+
+#ifdef DEBUG
+#  define dev_dbg_f(dev, fmt, args...) \
+         dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
+#  define dev_dbg_f_limit(dev, fmt, args...) do { \
+       if (net_ratelimit()) \
+               dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+} while (0)
+#  define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
+       bool __cond = !!(cond); \
+       if (unlikely(__cond)) \
+               dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+})
+#else
+#  define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
+#  define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
+#  define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
+#endif /* DEBUG */
+
+#ifdef DEBUG
+#  define ZD_ASSERT(x) \
+do { \
+       if (unlikely(!(x))) { \
+               pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
+                       __FILE__, __LINE__, __stringify(x)); \
+               dump_stack(); \
+       } \
+} while (0)
+#else
+#  define ZD_ASSERT(x) do { } while (0)
+#endif
+
+#ifdef DEBUG
+#  define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size))
+#else
+#  define ZD_MEMCLEAR(pointer, size) do { } while (0)
+#endif
+
+#endif /* _ZD_DEF_H */
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
new file mode 100644 (file)
index 0000000..e539d9b
--- /dev/null
@@ -0,0 +1,1550 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright (C) 2007-2008 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/jiffies.h>
+#include <net/ieee80211_radiotap.h>
+
+#include "zd_def.h"
+#include "zd_chip.h"
+#include "zd_mac.h"
+#include "zd_rf.h"
+
+struct zd_reg_alpha2_map {
+       u32 reg;
+       char alpha2[2];
+};
+
+static struct zd_reg_alpha2_map reg_alpha2_map[] = {
+       { ZD_REGDOMAIN_FCC, "US" },
+       { ZD_REGDOMAIN_IC, "CA" },
+       { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
+       { ZD_REGDOMAIN_JAPAN, "JP" },
+       { ZD_REGDOMAIN_JAPAN_2, "JP" },
+       { ZD_REGDOMAIN_JAPAN_3, "JP" },
+       { ZD_REGDOMAIN_SPAIN, "ES" },
+       { ZD_REGDOMAIN_FRANCE, "FR" },
+};
+
+/* This table contains the hardware specific values for the modulation rates. */
+static const struct ieee80211_rate zd_rates[] = {
+       { .bitrate = 10,
+         .hw_value = ZD_CCK_RATE_1M, },
+       { .bitrate = 20,
+         .hw_value = ZD_CCK_RATE_2M,
+         .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 55,
+         .hw_value = ZD_CCK_RATE_5_5M,
+         .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 110,
+         .hw_value = ZD_CCK_RATE_11M,
+         .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 60,
+         .hw_value = ZD_OFDM_RATE_6M,
+         .flags = 0 },
+       { .bitrate = 90,
+         .hw_value = ZD_OFDM_RATE_9M,
+         .flags = 0 },
+       { .bitrate = 120,
+         .hw_value = ZD_OFDM_RATE_12M,
+         .flags = 0 },
+       { .bitrate = 180,
+         .hw_value = ZD_OFDM_RATE_18M,
+         .flags = 0 },
+       { .bitrate = 240,
+         .hw_value = ZD_OFDM_RATE_24M,
+         .flags = 0 },
+       { .bitrate = 360,
+         .hw_value = ZD_OFDM_RATE_36M,
+         .flags = 0 },
+       { .bitrate = 480,
+         .hw_value = ZD_OFDM_RATE_48M,
+         .flags = 0 },
+       { .bitrate = 540,
+         .hw_value = ZD_OFDM_RATE_54M,
+         .flags = 0 },
+};
+
+/*
+ * Zydas retry rates table. Each line is listed in the same order as
+ * in zd_rates[] and contains all the rate used when a packet is sent
+ * starting with a given rates. Let's consider an example :
+ *
+ * "11 Mbits : 4, 3, 2, 1, 0" means :
+ * - packet is sent using 4 different rates
+ * - 1st rate is index 3 (ie 11 Mbits)
+ * - 2nd rate is index 2 (ie 5.5 Mbits)
+ * - 3rd rate is index 1 (ie 2 Mbits)
+ * - 4th rate is index 0 (ie 1 Mbits)
+ */
+
+static const struct tx_retry_rate zd_retry_rates[] = {
+       { /*  1 Mbits */        1, { 0 }},
+       { /*  2 Mbits */        2, { 1,  0 }},
+       { /*  5.5 Mbits */      3, { 2,  1, 0 }},
+       { /* 11 Mbits */        4, { 3,  2, 1, 0 }},
+       { /*  6 Mbits */        5, { 4,  3, 2, 1, 0 }},
+       { /*  9 Mbits */        6, { 5,  4, 3, 2, 1, 0}},
+       { /* 12 Mbits */        5, { 6,  3, 2, 1, 0 }},
+       { /* 18 Mbits */        6, { 7,  6, 3, 2, 1, 0 }},
+       { /* 24 Mbits */        6, { 8,  6, 3, 2, 1, 0 }},
+       { /* 36 Mbits */        7, { 9,  8, 6, 3, 2, 1, 0 }},
+       { /* 48 Mbits */        8, {10,  9, 8, 6, 3, 2, 1, 0 }},
+       { /* 54 Mbits */        9, {11, 10, 9, 8, 6, 3, 2, 1, 0 }}
+};
+
+static const struct ieee80211_channel zd_channels[] = {
+       { .center_freq = 2412, .hw_value = 1 },
+       { .center_freq = 2417, .hw_value = 2 },
+       { .center_freq = 2422, .hw_value = 3 },
+       { .center_freq = 2427, .hw_value = 4 },
+       { .center_freq = 2432, .hw_value = 5 },
+       { .center_freq = 2437, .hw_value = 6 },
+       { .center_freq = 2442, .hw_value = 7 },
+       { .center_freq = 2447, .hw_value = 8 },
+       { .center_freq = 2452, .hw_value = 9 },
+       { .center_freq = 2457, .hw_value = 10 },
+       { .center_freq = 2462, .hw_value = 11 },
+       { .center_freq = 2467, .hw_value = 12 },
+       { .center_freq = 2472, .hw_value = 13 },
+       { .center_freq = 2484, .hw_value = 14 },
+};
+
+static void housekeeping_init(struct zd_mac *mac);
+static void housekeeping_enable(struct zd_mac *mac);
+static void housekeeping_disable(struct zd_mac *mac);
+static void beacon_init(struct zd_mac *mac);
+static void beacon_enable(struct zd_mac *mac);
+static void beacon_disable(struct zd_mac *mac);
+static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
+static int zd_mac_config_beacon(struct ieee80211_hw *hw,
+                               struct sk_buff *beacon, bool in_intr);
+
+static int zd_reg2alpha2(u8 regdomain, char *alpha2)
+{
+       unsigned int i;
+       struct zd_reg_alpha2_map *reg_map;
+       for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
+               reg_map = &reg_alpha2_map[i];
+               if (regdomain == reg_map->reg) {
+                       alpha2[0] = reg_map->alpha2[0];
+                       alpha2[1] = reg_map->alpha2[1];
+                       return 0;
+               }
+       }
+       return 1;
+}
+
+static int zd_check_signal(struct ieee80211_hw *hw, int signal)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+
+       dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
+                       "%s: signal value from device not in range 0..100, "
+                       "but %d.\n", __func__, signal);
+
+       if (signal < 0)
+               signal = 0;
+       else if (signal > 100)
+               signal = 100;
+
+       return signal;
+}
+
+int zd_mac_preinit_hw(struct ieee80211_hw *hw)
+{
+       int r;
+       u8 addr[ETH_ALEN];
+       struct zd_mac *mac = zd_hw_mac(hw);
+
+       r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
+       if (r)
+               return r;
+
+       SET_IEEE80211_PERM_ADDR(hw, addr);
+
+       return 0;
+}
+
+int zd_mac_init_hw(struct ieee80211_hw *hw)
+{
+       int r;
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct zd_chip *chip = &mac->chip;
+       char alpha2[2];
+       u8 default_regdomain;
+
+       r = zd_chip_enable_int(chip);
+       if (r)
+               goto out;
+       r = zd_chip_init_hw(chip);
+       if (r)
+               goto disable_int;
+
+       ZD_ASSERT(!irqs_disabled());
+
+       r = zd_read_regdomain(chip, &default_regdomain);
+       if (r)
+               goto disable_int;
+       spin_lock_irq(&mac->lock);
+       mac->regdomain = mac->default_regdomain = default_regdomain;
+       spin_unlock_irq(&mac->lock);
+
+       /* We must inform the device that we are doing encryption/decryption in
+        * software at the moment. */
+       r = zd_set_encryption_type(chip, ENC_SNIFFER);
+       if (r)
+               goto disable_int;
+
+       r = zd_reg2alpha2(mac->regdomain, alpha2);
+       if (r)
+               goto disable_int;
+
+       r = regulatory_hint(hw->wiphy, alpha2);
+disable_int:
+       zd_chip_disable_int(chip);
+out:
+       return r;
+}
+
+void zd_mac_clear(struct zd_mac *mac)
+{
+       flush_workqueue(zd_workqueue);
+       zd_chip_clear(&mac->chip);
+       ZD_ASSERT(!spin_is_locked(&mac->lock));
+       ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
+}
+
+static int set_rx_filter(struct zd_mac *mac)
+{
+       unsigned long flags;
+       u32 filter = STA_RX_FILTER;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       if (mac->pass_ctrl)
+               filter |= RX_FILTER_CTRL;
+       spin_unlock_irqrestore(&mac->lock, flags);
+
+       return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
+}
+
+static int set_mac_and_bssid(struct zd_mac *mac)
+{
+       int r;
+
+       if (!mac->vif)
+               return -1;
+
+       r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
+       if (r)
+               return r;
+
+       /* Vendor driver after setting MAC either sets BSSID for AP or
+        * filter for other modes.
+        */
+       if (mac->type != NL80211_IFTYPE_AP)
+               return set_rx_filter(mac);
+       else
+               return zd_write_bssid(&mac->chip, mac->vif->addr);
+}
+
+static int set_mc_hash(struct zd_mac *mac)
+{
+       struct zd_mc_hash hash;
+       zd_mc_clear(&hash);
+       return zd_chip_set_multicast_hash(&mac->chip, &hash);
+}
+
+int zd_op_start(struct ieee80211_hw *hw)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct zd_chip *chip = &mac->chip;
+       struct zd_usb *usb = &chip->usb;
+       int r;
+
+       if (!usb->initialized) {
+               r = zd_usb_init_hw(usb);
+               if (r)
+                       goto out;
+       }
+
+       r = zd_chip_enable_int(chip);
+       if (r < 0)
+               goto out;
+
+       r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
+       if (r < 0)
+               goto disable_int;
+       r = set_rx_filter(mac);
+       if (r)
+               goto disable_int;
+       r = set_mc_hash(mac);
+       if (r)
+               goto disable_int;
+
+       /* Wait after setting the multicast hash table and powering on
+        * the radio otherwise interface bring up will fail. This matches
+        * what the vendor driver did.
+        */
+       msleep(10);
+
+       r = zd_chip_switch_radio_on(chip);
+       if (r < 0) {
+               dev_err(zd_chip_dev(chip),
+                       "%s: failed to set radio on\n", __func__);
+               goto disable_int;
+       }
+       r = zd_chip_enable_rxtx(chip);
+       if (r < 0)
+               goto disable_radio;
+       r = zd_chip_enable_hwint(chip);
+       if (r < 0)
+               goto disable_rxtx;
+
+       housekeeping_enable(mac);
+       beacon_enable(mac);
+       set_bit(ZD_DEVICE_RUNNING, &mac->flags);
+       return 0;
+disable_rxtx:
+       zd_chip_disable_rxtx(chip);
+disable_radio:
+       zd_chip_switch_radio_off(chip);
+disable_int:
+       zd_chip_disable_int(chip);
+out:
+       return r;
+}
+
+void zd_op_stop(struct ieee80211_hw *hw)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct zd_chip *chip = &mac->chip;
+       struct sk_buff *skb;
+       struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
+
+       clear_bit(ZD_DEVICE_RUNNING, &mac->flags);
+
+       /* The order here deliberately is a little different from the open()
+        * method, since we need to make sure there is no opportunity for RX
+        * frames to be processed by mac80211 after we have stopped it.
+        */
+
+       zd_chip_disable_rxtx(chip);
+       beacon_disable(mac);
+       housekeeping_disable(mac);
+       flush_workqueue(zd_workqueue);
+
+       zd_chip_disable_hwint(chip);
+       zd_chip_switch_radio_off(chip);
+       zd_chip_disable_int(chip);
+
+
+       while ((skb = skb_dequeue(ack_wait_queue)))
+               dev_kfree_skb_any(skb);
+}
+
+int zd_restore_settings(struct zd_mac *mac)
+{
+       struct sk_buff *beacon;
+       struct zd_mc_hash multicast_hash;
+       unsigned int short_preamble;
+       int r, beacon_interval, beacon_period;
+       u8 channel;
+
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+
+       spin_lock_irq(&mac->lock);
+       multicast_hash = mac->multicast_hash;
+       short_preamble = mac->short_preamble;
+       beacon_interval = mac->beacon.interval;
+       beacon_period = mac->beacon.period;
+       channel = mac->channel;
+       spin_unlock_irq(&mac->lock);
+
+       r = set_mac_and_bssid(mac);
+       if (r < 0) {
+               dev_dbg_f(zd_mac_dev(mac), "set_mac_and_bssid failed, %d\n", r);
+               return r;
+       }
+
+       r = zd_chip_set_channel(&mac->chip, channel);
+       if (r < 0) {
+               dev_dbg_f(zd_mac_dev(mac), "zd_chip_set_channel failed, %d\n",
+                         r);
+               return r;
+       }
+
+       set_rts_cts(mac, short_preamble);
+
+       r = zd_chip_set_multicast_hash(&mac->chip, &multicast_hash);
+       if (r < 0) {
+               dev_dbg_f(zd_mac_dev(mac),
+                         "zd_chip_set_multicast_hash failed, %d\n", r);
+               return r;
+       }
+
+       if (mac->type == NL80211_IFTYPE_MESH_POINT ||
+           mac->type == NL80211_IFTYPE_ADHOC ||
+           mac->type == NL80211_IFTYPE_AP) {
+               if (mac->vif != NULL) {
+                       beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+                       if (beacon)
+                               zd_mac_config_beacon(mac->hw, beacon, false);
+               }
+
+               zd_set_beacon_interval(&mac->chip, beacon_interval,
+                                       beacon_period, mac->type);
+
+               spin_lock_irq(&mac->lock);
+               mac->beacon.last_update = jiffies;
+               spin_unlock_irq(&mac->lock);
+       }
+
+       return 0;
+}
+
+/**
+ * zd_mac_tx_status - reports tx status of a packet if required
+ * @hw - a &struct ieee80211_hw pointer
+ * @skb - a sk-buffer
+ * @flags: extra flags to set in the TX status info
+ * @ackssi: ACK signal strength
+ * @success - True for successful transmission of the frame
+ *
+ * This information calls ieee80211_tx_status_irqsafe() if required by the
+ * control information. It copies the control information into the status
+ * information.
+ *
+ * If no status information has been requested, the skb is freed.
+ */
+static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+                     int ackssi, struct tx_status *tx_status)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       int i;
+       int success = 1, retry = 1;
+       int first_idx;
+       const struct tx_retry_rate *retries;
+
+       ieee80211_tx_info_clear_status(info);
+
+       if (tx_status) {
+               success = !tx_status->failure;
+               retry = tx_status->retry + success;
+       }
+
+       if (success) {
+               /* success */
+               info->flags |= IEEE80211_TX_STAT_ACK;
+       } else {
+               /* failure */
+               info->flags &= ~IEEE80211_TX_STAT_ACK;
+       }
+
+       first_idx = info->status.rates[0].idx;
+       ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates));
+       retries = &zd_retry_rates[first_idx];
+       ZD_ASSERT(1 <= retry && retry <= retries->count);
+
+       info->status.rates[0].idx = retries->rate[0];
+       info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1);
+
+       for (i=1; i<IEEE80211_TX_MAX_RATES-1 && i<retry; i++) {
+               info->status.rates[i].idx = retries->rate[i];
+               info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2);
+       }
+       for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) {
+               info->status.rates[i].idx = retries->rate[retry - 1];
+               info->status.rates[i].count = 1; // (success ? 1:2);
+       }
+       if (i<IEEE80211_TX_MAX_RATES)
+               info->status.rates[i].idx = -1; /* terminate */
+
+       info->status.ack_signal = zd_check_signal(hw, ackssi);
+       ieee80211_tx_status_irqsafe(hw, skb);
+}
+
+/**
+ * zd_mac_tx_failed - callback for failed frames
+ * @dev: the mac80211 wireless device
+ *
+ * This function is called if a frame couldn't be successfully
+ * transferred. The first frame from the tx queue, will be selected and
+ * reported as error to the upper layers.
+ */
+void zd_mac_tx_failed(struct urb *urb)
+{
+       struct ieee80211_hw * hw = zd_usb_to_hw(urb->context);
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct sk_buff_head *q = &mac->ack_wait_queue;
+       struct sk_buff *skb;
+       struct tx_status *tx_status = (struct tx_status *)urb->transfer_buffer;
+       unsigned long flags;
+       int success = !tx_status->failure;
+       int retry = tx_status->retry + success;
+       int found = 0;
+       int i, position = 0;
+
+       q = &mac->ack_wait_queue;
+       spin_lock_irqsave(&q->lock, flags);
+
+       skb_queue_walk(q, skb) {
+               struct ieee80211_hdr *tx_hdr;
+               struct ieee80211_tx_info *info;
+               int first_idx, final_idx;
+               const struct tx_retry_rate *retries;
+               u8 final_rate;
+
+               position ++;
+
+               /* if the hardware reports a failure and we had a 802.11 ACK
+                * pending, then we skip the first skb when searching for a
+                * matching frame */
+               if (tx_status->failure && mac->ack_pending &&
+                   skb_queue_is_first(q, skb)) {
+                       continue;
+               }
+
+               tx_hdr = (struct ieee80211_hdr *)skb->data;
+
+               /* we skip all frames not matching the reported destination */
+               if (unlikely(!ether_addr_equal(tx_hdr->addr1, tx_status->mac)))
+                       continue;
+
+               /* we skip all frames not matching the reported final rate */
+
+               info = IEEE80211_SKB_CB(skb);
+               first_idx = info->status.rates[0].idx;
+               ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates));
+               retries = &zd_retry_rates[first_idx];
+               if (retry <= 0 || retry > retries->count)
+                       continue;
+
+               final_idx = retries->rate[retry - 1];
+               final_rate = zd_rates[final_idx].hw_value;
+
+               if (final_rate != tx_status->rate) {
+                       continue;
+               }
+
+               found = 1;
+               break;
+       }
+
+       if (found) {
+               for (i=1; i<=position; i++) {
+                       skb = __skb_dequeue(q);
+                       zd_mac_tx_status(hw, skb,
+                                        mac->ack_pending ? mac->ack_signal : 0,
+                                        i == position ? tx_status : NULL);
+                       mac->ack_pending = 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&q->lock, flags);
+}
+
+/**
+ * zd_mac_tx_to_dev - callback for USB layer
+ * @skb: a &sk_buff pointer
+ * @error: error value, 0 if transmission successful
+ *
+ * Informs the MAC layer that the frame has successfully transferred to the
+ * device. If an ACK is required and the transfer to the device has been
+ * successful, the packets are put on the @ack_wait_queue with
+ * the control set removed.
+ */
+void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hw *hw = info->rate_driver_data[0];
+       struct zd_mac *mac = zd_hw_mac(hw);
+
+       ieee80211_tx_info_clear_status(info);
+
+       skb_pull(skb, sizeof(struct zd_ctrlset));
+       if (unlikely(error ||
+           (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
+               /*
+                * FIXME : do we need to fill in anything ?
+                */
+               ieee80211_tx_status_irqsafe(hw, skb);
+       } else {
+               struct sk_buff_head *q = &mac->ack_wait_queue;
+
+               skb_queue_tail(q, skb);
+               while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) {
+                       zd_mac_tx_status(hw, skb_dequeue(q),
+                                        mac->ack_pending ? mac->ack_signal : 0,
+                                        NULL);
+                       mac->ack_pending = 0;
+               }
+       }
+}
+
+static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
+{
+       /* ZD_PURE_RATE() must be used to remove the modulation type flag of
+        * the zd-rate values.
+        */
+       static const u8 rate_divisor[] = {
+               [ZD_PURE_RATE(ZD_CCK_RATE_1M)]   =  1,
+               [ZD_PURE_RATE(ZD_CCK_RATE_2M)]   =  2,
+               /* Bits must be doubled. */
+               [ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
+               [ZD_PURE_RATE(ZD_CCK_RATE_11M)]  = 11,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_6M)]  =  6,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_9M)]  =  9,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
+               [ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
+       };
+
+       u32 bits = (u32)tx_length * 8;
+       u32 divisor;
+
+       divisor = rate_divisor[ZD_PURE_RATE(zd_rate)];
+       if (divisor == 0)
+               return -EINVAL;
+
+       switch (zd_rate) {
+       case ZD_CCK_RATE_5_5M:
+               bits = (2*bits) + 10; /* round up to the next integer */
+               break;
+       case ZD_CCK_RATE_11M:
+               if (service) {
+                       u32 t = bits % 11;
+                       *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION;
+                       if (0 < t && t <= 3) {
+                               *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION;
+                       }
+               }
+               bits += 10; /* round up to the next integer */
+               break;
+       }
+
+       return bits/divisor;
+}
+
+static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
+                          struct ieee80211_hdr *header,
+                          struct ieee80211_tx_info *info)
+{
+       /*
+        * CONTROL TODO:
+        * - if backoff needed, enable bit 0
+        * - if burst (backoff not needed) disable bit 0
+        */
+
+       cs->control = 0;
+
+       /* First fragment */
+       if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+               cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
+
+       /* No ACK expected (multicast, etc.) */
+       if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+               cs->control |= ZD_CS_NO_ACK;
+
+       /* PS-POLL */
+       if (ieee80211_is_pspoll(header->frame_control))
+               cs->control |= ZD_CS_PS_POLL_FRAME;
+
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+               cs->control |= ZD_CS_RTS;
+
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+               cs->control |= ZD_CS_SELF_CTS;
+
+       /* FIXME: Management frame? */
+}
+
+static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
+{
+       if (!mac->beacon.cur_beacon)
+               return false;
+
+       if (mac->beacon.cur_beacon->len != beacon->len)
+               return false;
+
+       return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
+}
+
+static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
+{
+       ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
+
+       kfree_skb(mac->beacon.cur_beacon);
+       mac->beacon.cur_beacon = NULL;
+}
+
+static void zd_mac_free_cur_beacon(struct zd_mac *mac)
+{
+       mutex_lock(&mac->chip.mutex);
+       zd_mac_free_cur_beacon_locked(mac);
+       mutex_unlock(&mac->chip.mutex);
+}
+
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
+                               bool in_intr)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       int r, ret, num_cmds, req_pos = 0;
+       u32 tmp, j = 0;
+       /* 4 more bytes for tail CRC */
+       u32 full_len = beacon->len + 4;
+       unsigned long end_jiffies, message_jiffies;
+       struct zd_ioreq32 *ioreqs;
+
+       mutex_lock(&mac->chip.mutex);
+
+       /* Check if hw already has this beacon. */
+       if (zd_mac_match_cur_beacon(mac, beacon)) {
+               r = 0;
+               goto out_nofree;
+       }
+
+       /* Alloc memory for full beacon write at once. */
+       num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
+       ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
+       if (!ioreqs) {
+               r = -ENOMEM;
+               goto out_nofree;
+       }
+
+       r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
+       if (r < 0)
+               goto out;
+       r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
+       if (r < 0)
+               goto release_sema;
+       if (in_intr && tmp & 0x2) {
+               r = -EBUSY;
+               goto release_sema;
+       }
+
+       end_jiffies = jiffies + HZ / 2; /*~500ms*/
+       message_jiffies = jiffies + HZ / 10; /*~100ms*/
+       while (tmp & 0x2) {
+               r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
+               if (r < 0)
+                       goto release_sema;
+               if (time_is_before_eq_jiffies(message_jiffies)) {
+                       message_jiffies = jiffies + HZ / 10;
+                       dev_err(zd_mac_dev(mac),
+                                       "CR_BCN_FIFO_SEMAPHORE not ready\n");
+                       if (time_is_before_eq_jiffies(end_jiffies))  {
+                               dev_err(zd_mac_dev(mac),
+                                               "Giving up beacon config.\n");
+                               r = -ETIMEDOUT;
+                               goto reset_device;
+                       }
+               }
+               msleep(20);
+       }
+
+       ioreqs[req_pos].addr = CR_BCN_FIFO;
+       ioreqs[req_pos].value = full_len - 1;
+       req_pos++;
+       if (zd_chip_is_zd1211b(&mac->chip)) {
+               ioreqs[req_pos].addr = CR_BCN_LENGTH;
+               ioreqs[req_pos].value = full_len - 1;
+               req_pos++;
+       }
+
+       for (j = 0 ; j < beacon->len; j++) {
+               ioreqs[req_pos].addr = CR_BCN_FIFO;
+               ioreqs[req_pos].value = *((u8 *)(beacon->data + j));
+               req_pos++;
+       }
+
+       for (j = 0; j < 4; j++) {
+               ioreqs[req_pos].addr = CR_BCN_FIFO;
+               ioreqs[req_pos].value = 0x0;
+               req_pos++;
+       }
+
+       BUG_ON(req_pos != num_cmds);
+
+       r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);
+
+release_sema:
+       /*
+        * Try very hard to release device beacon semaphore, as otherwise
+        * device/driver can be left in unusable state.
+        */
+       end_jiffies = jiffies + HZ / 2; /*~500ms*/
+       ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
+       while (ret < 0) {
+               if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
+                       ret = -ETIMEDOUT;
+                       break;
+               }
+
+               msleep(20);
+               ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
+       }
+
+       if (ret < 0)
+               dev_err(zd_mac_dev(mac), "Could not release "
+                                        "CR_BCN_FIFO_SEMAPHORE!\n");
+       if (r < 0 || ret < 0) {
+               if (r >= 0)
+                       r = ret;
+
+               /* We don't know if beacon was written successfully or not,
+                * so clear current. */
+               zd_mac_free_cur_beacon_locked(mac);
+
+               goto out;
+       }
+
+       /* Beacon has now been written successfully, update current. */
+       zd_mac_free_cur_beacon_locked(mac);
+       mac->beacon.cur_beacon = beacon;
+       beacon = NULL;
+
+       /* 802.11b/g 2.4G CCK 1Mb
+        * 802.11a, not yet implemented, uses different values (see GPL vendor
+        * driver)
+        */
+       r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
+                               CR_BCN_PLCP_CFG);
+out:
+       kfree(ioreqs);
+out_nofree:
+       kfree_skb(beacon);
+       mutex_unlock(&mac->chip.mutex);
+
+       return r;
+
+reset_device:
+       zd_mac_free_cur_beacon_locked(mac);
+       kfree_skb(beacon);
+
+       mutex_unlock(&mac->chip.mutex);
+       kfree(ioreqs);
+
+       /* semaphore stuck, reset device to avoid fw freeze later */
+       dev_warn(zd_mac_dev(mac), "CR_BCN_FIFO_SEMAPHORE stuck, "
+                                 "resetting device...");
+       usb_queue_reset_device(mac->chip.usb.intf);
+
+       return r;
+}
+
+static int fill_ctrlset(struct zd_mac *mac,
+                       struct sk_buff *skb)
+{
+       int r;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       unsigned int frag_len = skb->len + FCS_LEN;
+       unsigned int packet_length;
+       struct ieee80211_rate *txrate;
+       struct zd_ctrlset *cs = (struct zd_ctrlset *)
+               skb_push(skb, sizeof(struct zd_ctrlset));
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       ZD_ASSERT(frag_len <= 0xffff);
+
+       /*
+        * Firmware computes the duration itself (for all frames except PSPoll)
+        * and needs the field set to 0 at input, otherwise firmware messes up
+        * duration_id and sets bits 14 and 15 on.
+        */
+       if (!ieee80211_is_pspoll(hdr->frame_control))
+               hdr->duration_id = 0;
+
+       txrate = ieee80211_get_tx_rate(mac->hw, info);
+
+       cs->modulation = txrate->hw_value;
+       if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+               cs->modulation = txrate->hw_value_short;
+
+       cs->tx_length = cpu_to_le16(frag_len);
+
+       cs_set_control(mac, cs, hdr, info);
+
+       packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
+       ZD_ASSERT(packet_length <= 0xffff);
+       /* ZD1211B: Computing the length difference this way, gives us
+        * flexibility to compute the packet length.
+        */
+       cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
+                       packet_length - frag_len : packet_length);
+
+       /*
+        * CURRENT LENGTH:
+        * - transmit frame length in microseconds
+        * - seems to be derived from frame length
+        * - see Cal_Us_Service() in zdinlinef.h
+        * - if macp->bTxBurstEnable is enabled, then multiply by 4
+        *  - bTxBurstEnable is never set in the vendor driver
+        *
+        * SERVICE:
+        * - "for PLCP configuration"
+        * - always 0 except in some situations at 802.11b 11M
+        * - see line 53 of zdinlinef.h
+        */
+       cs->service = 0;
+       r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation),
+                                le16_to_cpu(cs->tx_length));
+       if (r < 0)
+               return r;
+       cs->current_length = cpu_to_le16(r);
+       cs->next_frame_length = 0;
+
+       return 0;
+}
+
+/**
+ * zd_op_tx - transmits a network frame to the device
+ *
+ * @dev: mac80211 hardware device
+ * @skb: socket buffer
+ * @control: the control structure
+ *
+ * This function transmit an IEEE 802.11 network frame to the device. The
+ * control block of the skbuff will be initialized. If necessary the incoming
+ * mac80211 queues will be stopped.
+ */
+static void zd_op_tx(struct ieee80211_hw *hw,
+                    struct ieee80211_tx_control *control,
+                    struct sk_buff *skb)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       int r;
+
+       r = fill_ctrlset(mac, skb);
+       if (r)
+               goto fail;
+
+       info->rate_driver_data[0] = hw;
+
+       r = zd_usb_tx(&mac->chip.usb, skb);
+       if (r)
+               goto fail;
+       return;
+
+fail:
+       dev_kfree_skb(skb);
+}
+
+/**
+ * filter_ack - filters incoming packets for acknowledgements
+ * @dev: the mac80211 device
+ * @rx_hdr: received header
+ * @stats: the status for the received packet
+ *
+ * This functions looks for ACK packets and tries to match them with the
+ * frames in the tx queue. If a match is found the frame will be dequeued and
+ * the upper layers is informed about the successful transmission. If
+ * mac80211 queues have been stopped and the number of frames still to be
+ * transmitted is low the queues will be opened again.
+ *
+ * Returns 1 if the frame was an ACK, 0 if it was ignored.
+ */
+static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
+                     struct ieee80211_rx_status *stats)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct sk_buff *skb;
+       struct sk_buff_head *q;
+       unsigned long flags;
+       int found = 0;
+       int i, position = 0;
+
+       if (!ieee80211_is_ack(rx_hdr->frame_control))
+               return 0;
+
+       q = &mac->ack_wait_queue;
+       spin_lock_irqsave(&q->lock, flags);
+       skb_queue_walk(q, skb) {
+               struct ieee80211_hdr *tx_hdr;
+
+               position ++;
+
+               if (mac->ack_pending && skb_queue_is_first(q, skb))
+                   continue;
+
+               tx_hdr = (struct ieee80211_hdr *)skb->data;
+               if (likely(ether_addr_equal(tx_hdr->addr2, rx_hdr->addr1)))
+               {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found) {
+               for (i=1; i<position; i++) {
+                       skb = __skb_dequeue(q);
+                       zd_mac_tx_status(hw, skb,
+                                        mac->ack_pending ? mac->ack_signal : 0,
+                                        NULL);
+                       mac->ack_pending = 0;
+               }
+
+               mac->ack_pending = 1;
+               mac->ack_signal = stats->signal;
+
+               /* Prevent pending tx-packet on AP-mode */
+               if (mac->type == NL80211_IFTYPE_AP) {
+                       skb = __skb_dequeue(q);
+                       zd_mac_tx_status(hw, skb, mac->ack_signal, NULL);
+                       mac->ack_pending = 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&q->lock, flags);
+       return 1;
+}
+
+int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct ieee80211_rx_status stats;
+       const struct rx_status *status;
+       struct sk_buff *skb;
+       int bad_frame = 0;
+       __le16 fc;
+       int need_padding;
+       int i;
+       u8 rate;
+
+       if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
+                    FCS_LEN + sizeof(struct rx_status))
+               return -EINVAL;
+
+       memset(&stats, 0, sizeof(stats));
+
+       /* Note about pass_failed_fcs and pass_ctrl access below:
+        * mac locking intentionally omitted here, as this is the only unlocked
+        * reader and the only writer is configure_filter. Plus, if there were
+        * any races accessing these variables, it wouldn't really matter.
+        * If mac80211 ever provides a way for us to access filter flags
+        * from outside configure_filter, we could improve on this. Also, this
+        * situation may change once we implement some kind of DMA-into-skb
+        * RX path. */
+
+       /* Caller has to ensure that length >= sizeof(struct rx_status). */
+       status = (struct rx_status *)
+               (buffer + (length - sizeof(struct rx_status)));
+       if (status->frame_status & ZD_RX_ERROR) {
+               if (mac->pass_failed_fcs &&
+                               (status->frame_status & ZD_RX_CRC32_ERROR)) {
+                       stats.flag |= RX_FLAG_FAILED_FCS_CRC;
+                       bad_frame = 1;
+               } else {
+                       return -EINVAL;
+               }
+       }
+
+       stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
+       stats.band = IEEE80211_BAND_2GHZ;
+       stats.signal = zd_check_signal(hw, status->signal_strength);
+
+       rate = zd_rx_rate(buffer, status);
+
+       /* todo: return index in the big switches in zd_rx_rate instead */
+       for (i = 0; i < mac->band.n_bitrates; i++)
+               if (rate == mac->band.bitrates[i].hw_value)
+                       stats.rate_idx = i;
+
+       length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
+       buffer += ZD_PLCP_HEADER_SIZE;
+
+       /* Except for bad frames, filter each frame to see if it is an ACK, in
+        * which case our internal TX tracking is updated. Normally we then
+        * bail here as there's no need to pass ACKs on up to the stack, but
+        * there is also the case where the stack has requested us to pass
+        * control frames on up (pass_ctrl) which we must consider. */
+       if (!bad_frame &&
+                       filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
+                       && !mac->pass_ctrl)
+               return 0;
+
+       fc = get_unaligned((__le16*)buffer);
+       need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
+
+       skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
+       if (skb == NULL)
+               return -ENOMEM;
+       if (need_padding) {
+               /* Make sure the payload data is 4 byte aligned. */
+               skb_reserve(skb, 2);
+       }
+
+       /* FIXME : could we avoid this big memcpy ? */
+       memcpy(skb_put(skb, length), buffer, length);
+
+       memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+       ieee80211_rx_irqsafe(hw, skb);
+       return 0;
+}
+
+static int zd_op_add_interface(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+
+       /* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */
+       if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
+               return -EOPNOTSUPP;
+
+       switch (vif->type) {
+       case NL80211_IFTYPE_MONITOR:
+       case NL80211_IFTYPE_MESH_POINT:
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_ADHOC:
+       case NL80211_IFTYPE_AP:
+               mac->type = vif->type;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       mac->vif = vif;
+
+       return set_mac_and_bssid(mac);
+}
+
+static void zd_op_remove_interface(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       mac->type = NL80211_IFTYPE_UNSPECIFIED;
+       mac->vif = NULL;
+       zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
+       zd_write_mac_addr(&mac->chip, NULL);
+
+       zd_mac_free_cur_beacon(mac);
+}
+
+static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct ieee80211_conf *conf = &hw->conf;
+
+       spin_lock_irq(&mac->lock);
+       mac->channel = conf->chandef.chan->hw_value;
+       spin_unlock_irq(&mac->lock);
+
+       return zd_chip_set_channel(&mac->chip, conf->chandef.chan->hw_value);
+}
+
+static void zd_beacon_done(struct zd_mac *mac)
+{
+       struct sk_buff *skb, *beacon;
+
+       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+               return;
+       if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP)
+               return;
+
+       /*
+        * Send out buffered broad- and multicast frames.
+        */
+       while (!ieee80211_queue_stopped(mac->hw, 0)) {
+               skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+               if (!skb)
+                       break;
+               zd_op_tx(mac->hw, NULL, skb);
+       }
+
+       /*
+        * Fetch next beacon so that tim_count is updated.
+        */
+       beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+       if (beacon)
+               zd_mac_config_beacon(mac->hw, beacon, true);
+
+       spin_lock_irq(&mac->lock);
+       mac->beacon.last_update = jiffies;
+       spin_unlock_irq(&mac->lock);
+}
+
+static void zd_process_intr(struct work_struct *work)
+{
+       u16 int_status;
+       unsigned long flags;
+       struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
+
+       spin_lock_irqsave(&mac->lock, flags);
+       int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4));
+       spin_unlock_irqrestore(&mac->lock, flags);
+
+       if (int_status & INT_CFG_NEXT_BCN) {
+               /*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/
+               zd_beacon_done(mac);
+       } else {
+               dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
+       }
+
+       zd_chip_enable_hwint(&mac->chip);
+}
+
+
+static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
+                                  struct netdev_hw_addr_list *mc_list)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       struct zd_mc_hash hash;
+       struct netdev_hw_addr *ha;
+
+       zd_mc_clear(&hash);
+
+       netdev_hw_addr_list_for_each(ha, mc_list) {
+               dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", ha->addr);
+               zd_mc_add_addr(&hash, ha->addr);
+       }
+
+       return hash.low | ((u64)hash.high << 32);
+}
+
+#define SUPPORTED_FIF_FLAGS \
+       (FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
+       FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
+static void zd_op_configure_filter(struct ieee80211_hw *hw,
+                       unsigned int changed_flags,
+                       unsigned int *new_flags,
+                       u64 multicast)
+{
+       struct zd_mc_hash hash = {
+               .low = multicast,
+               .high = multicast >> 32,
+       };
+       struct zd_mac *mac = zd_hw_mac(hw);
+       unsigned long flags;
+       int r;
+
+       /* Only deal with supported flags */
+       changed_flags &= SUPPORTED_FIF_FLAGS;
+       *new_flags &= SUPPORTED_FIF_FLAGS;
+
+       /*
+        * If multicast parameter (as returned by zd_op_prepare_multicast)
+        * has changed, no bit in changed_flags is set. To handle this
+        * situation, we do not return if changed_flags is 0. If we do so,
+        * we will have some issue with IPv6 which uses multicast for link
+        * layer address resolution.
+        */
+       if (*new_flags & FIF_ALLMULTI)
+               zd_mc_add_all(&hash);
+
+       spin_lock_irqsave(&mac->lock, flags);
+       mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
+       mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
+       mac->multicast_hash = hash;
+       spin_unlock_irqrestore(&mac->lock, flags);
+
+       zd_chip_set_multicast_hash(&mac->chip, &hash);
+
+       if (changed_flags & FIF_CONTROL) {
+               r = set_rx_filter(mac);
+               if (r)
+                       dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r);
+       }
+
+       /* no handling required for FIF_OTHER_BSS as we don't currently
+        * do BSSID filtering */
+       /* FIXME: in future it would be nice to enable the probe response
+        * filter (so that the driver doesn't see them) until
+        * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd
+        * have to schedule work to enable prbresp reception, which might
+        * happen too late. For now we'll just listen and forward them all the
+        * time. */
+}
+
+static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble)
+{
+       mutex_lock(&mac->chip.mutex);
+       zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
+       mutex_unlock(&mac->chip.mutex);
+}
+
+static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_bss_conf *bss_conf,
+                                  u32 changes)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       int associated;
+
+       dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
+
+       if (mac->type == NL80211_IFTYPE_MESH_POINT ||
+           mac->type == NL80211_IFTYPE_ADHOC ||
+           mac->type == NL80211_IFTYPE_AP) {
+               associated = true;
+               if (changes & BSS_CHANGED_BEACON) {
+                       struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+
+                       if (beacon) {
+                               zd_chip_disable_hwint(&mac->chip);
+                               zd_mac_config_beacon(hw, beacon, false);
+                               zd_chip_enable_hwint(&mac->chip);
+                       }
+               }
+
+               if (changes & BSS_CHANGED_BEACON_ENABLED) {
+                       u16 interval = 0;
+                       u8 period = 0;
+
+                       if (bss_conf->enable_beacon) {
+                               period = bss_conf->dtim_period;
+                               interval = bss_conf->beacon_int;
+                       }
+
+                       spin_lock_irq(&mac->lock);
+                       mac->beacon.period = period;
+                       mac->beacon.interval = interval;
+                       mac->beacon.last_update = jiffies;
+                       spin_unlock_irq(&mac->lock);
+
+                       zd_set_beacon_interval(&mac->chip, interval, period,
+                                              mac->type);
+               }
+       } else
+               associated = is_valid_ether_addr(bss_conf->bssid);
+
+       spin_lock_irq(&mac->lock);
+       mac->associated = associated;
+       spin_unlock_irq(&mac->lock);
+
+       /* TODO: do hardware bssid filtering */
+
+       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+               spin_lock_irq(&mac->lock);
+               mac->short_preamble = bss_conf->use_short_preamble;
+               spin_unlock_irq(&mac->lock);
+
+               set_rts_cts(mac, bss_conf->use_short_preamble);
+       }
+}
+
+static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+       return zd_chip_get_tsf(&mac->chip);
+}
+
+static const struct ieee80211_ops zd_ops = {
+       .tx                     = zd_op_tx,
+       .start                  = zd_op_start,
+       .stop                   = zd_op_stop,
+       .add_interface          = zd_op_add_interface,
+       .remove_interface       = zd_op_remove_interface,
+       .config                 = zd_op_config,
+       .prepare_multicast      = zd_op_prepare_multicast,
+       .configure_filter       = zd_op_configure_filter,
+       .bss_info_changed       = zd_op_bss_info_changed,
+       .get_tsf                = zd_op_get_tsf,
+};
+
+struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
+{
+       struct zd_mac *mac;
+       struct ieee80211_hw *hw;
+
+       hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
+       if (!hw) {
+               dev_dbg_f(&intf->dev, "out of memory\n");
+               return NULL;
+       }
+
+       mac = zd_hw_mac(hw);
+
+       memset(mac, 0, sizeof(*mac));
+       spin_lock_init(&mac->lock);
+       mac->hw = hw;
+
+       mac->type = NL80211_IFTYPE_UNSPECIFIED;
+
+       memcpy(mac->channels, zd_channels, sizeof(zd_channels));
+       memcpy(mac->rates, zd_rates, sizeof(zd_rates));
+       mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
+       mac->band.bitrates = mac->rates;
+       mac->band.n_channels = ARRAY_SIZE(zd_channels);
+       mac->band.channels = mac->channels;
+
+       hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
+
+       ieee80211_hw_set(hw, MFP_CAPABLE);
+       ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
+       ieee80211_hw_set(hw, RX_INCLUDES_FCS);
+       ieee80211_hw_set(hw, SIGNAL_UNSPEC);
+
+       hw->wiphy->interface_modes =
+               BIT(NL80211_IFTYPE_MESH_POINT) |
+               BIT(NL80211_IFTYPE_STATION) |
+               BIT(NL80211_IFTYPE_ADHOC) |
+               BIT(NL80211_IFTYPE_AP);
+
+       hw->max_signal = 100;
+       hw->queues = 1;
+       hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
+
+       /*
+        * Tell mac80211 that we support multi rate retries
+        */
+       hw->max_rates = IEEE80211_TX_MAX_RATES;
+       hw->max_rate_tries = 18;        /* 9 rates * 2 retries/rate */
+
+       skb_queue_head_init(&mac->ack_wait_queue);
+       mac->ack_pending = 0;
+
+       zd_chip_init(&mac->chip, hw, intf);
+       housekeeping_init(mac);
+       beacon_init(mac);
+       INIT_WORK(&mac->process_intr, zd_process_intr);
+
+       SET_IEEE80211_DEV(hw, &intf->dev);
+       return hw;
+}
+
+#define BEACON_WATCHDOG_DELAY round_jiffies_relative(HZ)
+
+static void beacon_watchdog_handler(struct work_struct *work)
+{
+       struct zd_mac *mac =
+               container_of(work, struct zd_mac, beacon.watchdog_work.work);
+       struct sk_buff *beacon;
+       unsigned long timeout;
+       int interval, period;
+
+       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+               goto rearm;
+       if (mac->type != NL80211_IFTYPE_AP || !mac->vif)
+               goto rearm;
+
+       spin_lock_irq(&mac->lock);
+       interval = mac->beacon.interval;
+       period = mac->beacon.period;
+       timeout = mac->beacon.last_update +
+                       msecs_to_jiffies(interval * 1024 / 1000) * 3;
+       spin_unlock_irq(&mac->lock);
+
+       if (interval > 0 && time_is_before_jiffies(timeout)) {
+               dev_dbg_f(zd_mac_dev(mac), "beacon interrupt stalled, "
+                                          "restarting. "
+                                          "(interval: %d, dtim: %d)\n",
+                                          interval, period);
+
+               zd_chip_disable_hwint(&mac->chip);
+
+               beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+               if (beacon) {
+                       zd_mac_free_cur_beacon(mac);
+
+                       zd_mac_config_beacon(mac->hw, beacon, false);
+               }
+
+               zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
+
+               zd_chip_enable_hwint(&mac->chip);
+
+               spin_lock_irq(&mac->lock);
+               mac->beacon.last_update = jiffies;
+               spin_unlock_irq(&mac->lock);
+       }
+
+rearm:
+       queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
+                          BEACON_WATCHDOG_DELAY);
+}
+
+static void beacon_init(struct zd_mac *mac)
+{
+       INIT_DELAYED_WORK(&mac->beacon.watchdog_work, beacon_watchdog_handler);
+}
+
+static void beacon_enable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+
+       mac->beacon.last_update = jiffies;
+       queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
+                          BEACON_WATCHDOG_DELAY);
+}
+
+static void beacon_disable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+
+       zd_mac_free_cur_beacon(mac);
+}
+
+#define LINK_LED_WORK_DELAY HZ
+
+static void link_led_handler(struct work_struct *work)
+{
+       struct zd_mac *mac =
+               container_of(work, struct zd_mac, housekeeping.link_led_work.work);
+       struct zd_chip *chip = &mac->chip;
+       int is_associated;
+       int r;
+
+       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+               goto requeue;
+
+       spin_lock_irq(&mac->lock);
+       is_associated = mac->associated;
+       spin_unlock_irq(&mac->lock);
+
+       r = zd_chip_control_leds(chip,
+                                is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
+       if (r)
+               dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
+
+requeue:
+       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+                          LINK_LED_WORK_DELAY);
+}
+
+static void housekeeping_init(struct zd_mac *mac)
+{
+       INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler);
+}
+
+static void housekeeping_enable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+                          0);
+}
+
+static void housekeeping_disable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       cancel_delayed_work_sync(&mac->housekeeping.link_led_work);
+       zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
+}
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.h b/drivers/net/wireless/zydas/zd1211rw/zd_mac.h
new file mode 100644 (file)
index 0000000..5a48423
--- /dev/null
@@ -0,0 +1,327 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ZD_MAC_H
+#define _ZD_MAC_H
+
+#include <linux/kernel.h>
+#include <net/mac80211.h>
+
+#include "zd_chip.h"
+
+struct zd_ctrlset {
+       u8     modulation;
+       __le16 tx_length;
+       u8     control;
+       /* stores only the difference to tx_length on ZD1211B */
+       __le16 packet_length;
+       __le16 current_length;
+       u8     service;
+       __le16  next_frame_length;
+} __packed;
+
+#define ZD_CS_RESERVED_SIZE    25
+
+/* The field modulation of struct zd_ctrlset controls the bit rate, the use
+ * of short or long preambles in 802.11b (CCK mode) or the use of 802.11a or
+ * 802.11g in OFDM mode.
+ *
+ * The term zd-rate is used for the combination of the modulation type flag
+ * and the "pure" rate value.
+ */
+#define ZD_PURE_RATE_MASK       0x0f
+#define ZD_MODULATION_TYPE_MASK 0x10
+#define ZD_RATE_MASK            (ZD_PURE_RATE_MASK|ZD_MODULATION_TYPE_MASK)
+#define ZD_PURE_RATE(modulation) ((modulation) & ZD_PURE_RATE_MASK)
+#define ZD_MODULATION_TYPE(modulation) ((modulation) & ZD_MODULATION_TYPE_MASK)
+#define ZD_RATE(modulation) ((modulation) & ZD_RATE_MASK)
+
+/* The two possible modulation types. Notify that 802.11b doesn't use the CCK
+ * codeing for the 1 and 2 MBit/s rate. We stay with the term here to remain
+ * consistent with uses the term at other places.
+ */
+#define ZD_CCK                  0x00
+#define ZD_OFDM                 0x10
+
+/* The ZD1211 firmware uses proprietary encodings of the 802.11b (CCK) rates.
+ * For OFDM the PLCP rate encodings are used. We combine these "pure" rates
+ * with the modulation type flag and call the resulting values zd-rates.
+ */
+#define ZD_CCK_RATE_1M          (ZD_CCK|0x00)
+#define ZD_CCK_RATE_2M          (ZD_CCK|0x01)
+#define ZD_CCK_RATE_5_5M        (ZD_CCK|0x02)
+#define ZD_CCK_RATE_11M         (ZD_CCK|0x03)
+#define ZD_OFDM_RATE_6M         (ZD_OFDM|ZD_OFDM_PLCP_RATE_6M)
+#define ZD_OFDM_RATE_9M         (ZD_OFDM|ZD_OFDM_PLCP_RATE_9M)
+#define ZD_OFDM_RATE_12M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_12M)
+#define ZD_OFDM_RATE_18M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_18M)
+#define ZD_OFDM_RATE_24M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_24M)
+#define ZD_OFDM_RATE_36M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_36M)
+#define ZD_OFDM_RATE_48M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_48M)
+#define ZD_OFDM_RATE_54M        (ZD_OFDM|ZD_OFDM_PLCP_RATE_54M)
+
+/* The bit 5 of the zd_ctrlset modulation field controls the preamble in CCK
+ * mode or the 802.11a/802.11g selection in OFDM mode.
+ */
+#define ZD_CCK_PREA_LONG        0x00
+#define ZD_CCK_PREA_SHORT       0x20
+#define ZD_OFDM_MODE_11G        0x00
+#define ZD_OFDM_MODE_11A        0x20
+
+/* zd_ctrlset control field */
+#define ZD_CS_NEED_RANDOM_BACKOFF      0x01
+#define ZD_CS_NO_ACK                   0x02
+
+#define ZD_CS_FRAME_TYPE_MASK          0x0c
+#define ZD_CS_DATA_FRAME               0x00
+#define ZD_CS_PS_POLL_FRAME            0x04
+#define ZD_CS_MANAGEMENT_FRAME         0x08
+#define ZD_CS_NO_SEQUENCE_CTL_FRAME    0x0c
+
+#define ZD_CS_WAKE_DESTINATION         0x10
+#define ZD_CS_RTS                      0x20
+#define ZD_CS_ENCRYPT                  0x40
+#define ZD_CS_SELF_CTS                 0x80
+
+/* Incoming frames are prepended by a PLCP header */
+#define ZD_PLCP_HEADER_SIZE            5
+
+struct rx_length_info {
+       __le16 length[3];
+       __le16 tag;
+} __packed;
+
+#define RX_LENGTH_INFO_TAG             0x697e
+
+struct rx_status {
+       u8 signal_quality_cck;
+       /* rssi */
+       u8 signal_strength;
+       u8 signal_quality_ofdm;
+       u8 decryption_type;
+       u8 frame_status;
+} __packed;
+
+/* rx_status field decryption_type */
+#define ZD_RX_NO_WEP   0
+#define ZD_RX_WEP64    1
+#define ZD_RX_TKIP     2
+#define ZD_RX_AES      4
+#define ZD_RX_WEP128   5
+#define ZD_RX_WEP256   6
+
+/* rx_status field frame_status */
+#define ZD_RX_FRAME_MODULATION_MASK    0x01
+#define ZD_RX_CCK                      0x00
+#define ZD_RX_OFDM                     0x01
+
+#define ZD_RX_TIMEOUT_ERROR            0x02
+#define ZD_RX_FIFO_OVERRUN_ERROR       0x04
+#define ZD_RX_DECRYPTION_ERROR         0x08
+#define ZD_RX_CRC32_ERROR              0x10
+#define ZD_RX_NO_ADDR1_MATCH_ERROR     0x20
+#define ZD_RX_CRC16_ERROR              0x40
+#define ZD_RX_ERROR                    0x80
+
+struct tx_retry_rate {
+       int count;      /* number of valid element in rate[] array */
+       int rate[10];   /* retry rates, described by an index in zd_rates[] */
+};
+
+struct tx_status {
+       u8 type;        /* must always be 0x01 : USB_INT_TYPE */
+       u8 id;          /* must always be 0xa0 : USB_INT_ID_RETRY_FAILED */
+       u8 rate;
+       u8 pad;
+       u8 mac[ETH_ALEN];
+       u8 retry;
+       u8 failure;
+} __packed;
+
+enum mac_flags {
+       MAC_FIXED_CHANNEL = 0x01,
+};
+
+struct housekeeping {
+       struct delayed_work link_led_work;
+};
+
+struct beacon {
+       struct delayed_work watchdog_work;
+       struct sk_buff *cur_beacon;
+       unsigned long last_update;
+       u16 interval;
+       u8 period;
+};
+
+enum zd_device_flags {
+       ZD_DEVICE_RUNNING,
+};
+
+#define ZD_MAC_STATS_BUFFER_SIZE 16
+
+#define ZD_MAC_MAX_ACK_WAITERS 50
+
+struct zd_mac {
+       struct zd_chip chip;
+       spinlock_t lock;
+       spinlock_t intr_lock;
+       struct ieee80211_hw *hw;
+       struct ieee80211_vif *vif;
+       struct housekeeping housekeeping;
+       struct beacon beacon;
+       struct work_struct set_rts_cts_work;
+       struct work_struct process_intr;
+       struct zd_mc_hash multicast_hash;
+       u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
+       u8 regdomain;
+       u8 default_regdomain;
+       u8 channel;
+       int type;
+       int associated;
+       unsigned long flags;
+       struct sk_buff_head ack_wait_queue;
+       struct ieee80211_channel channels[14];
+       struct ieee80211_rate rates[12];
+       struct ieee80211_supported_band band;
+
+       /* Short preamble (used for RTS/CTS) */
+       unsigned int short_preamble:1;
+
+       /* whether to pass frames with CRC errors to stack */
+       unsigned int pass_failed_fcs:1;
+
+       /* whether to pass control frames to stack */
+       unsigned int pass_ctrl:1;
+
+       /* whether we have received a 802.11 ACK that is pending */
+       unsigned int ack_pending:1;
+
+       /* signal strength of the last 802.11 ACK received */
+       int ack_signal;
+};
+
+#define ZD_REGDOMAIN_FCC       0x10
+#define ZD_REGDOMAIN_IC                0x20
+#define ZD_REGDOMAIN_ETSI      0x30
+#define ZD_REGDOMAIN_SPAIN     0x31
+#define ZD_REGDOMAIN_FRANCE    0x32
+#define ZD_REGDOMAIN_JAPAN_2   0x40
+#define ZD_REGDOMAIN_JAPAN     0x41
+#define ZD_REGDOMAIN_JAPAN_3   0x49
+
+enum {
+       MIN_CHANNEL24 = 1,
+       MAX_CHANNEL24 = 14,
+};
+
+#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
+
+struct ofdm_plcp_header {
+       u8 prefix[3];
+       __le16 service;
+} __packed;
+
+static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
+{
+       return header->prefix[0] & 0xf;
+}
+
+/* The following defines give the encoding of the 4-bit rate field in the
+ * OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to
+ * define the zd-rate values for OFDM.
+ *
+ * See the struct zd_ctrlset definition in zd_mac.h.
+ */
+#define ZD_OFDM_PLCP_RATE_6M   0xb
+#define ZD_OFDM_PLCP_RATE_9M   0xf
+#define ZD_OFDM_PLCP_RATE_12M  0xa
+#define ZD_OFDM_PLCP_RATE_18M  0xe
+#define ZD_OFDM_PLCP_RATE_24M  0x9
+#define ZD_OFDM_PLCP_RATE_36M  0xd
+#define ZD_OFDM_PLCP_RATE_48M  0x8
+#define ZD_OFDM_PLCP_RATE_54M  0xc
+
+struct cck_plcp_header {
+       u8 signal;
+       u8 service;
+       __le16 length;
+       __le16 crc16;
+} __packed;
+
+static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
+{
+       return header->signal;
+}
+
+/* These defines give the encodings of the signal field in the 802.11b PLCP
+ * header. The signal field gives the bit rate of the following packet. Even
+ * if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s
+ * rate to stay consistent with Zydas and our use of the term.
+ *
+ * Notify that these values are *not* used in the zd-rates.
+ */
+#define ZD_CCK_PLCP_SIGNAL_1M  0x0a
+#define ZD_CCK_PLCP_SIGNAL_2M  0x14
+#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
+#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
+
+static inline struct zd_mac *zd_hw_mac(struct ieee80211_hw *hw)
+{
+       return hw->priv;
+}
+
+static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip)
+{
+       return container_of(chip, struct zd_mac, chip);
+}
+
+static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb)
+{
+       return zd_chip_to_mac(zd_usb_to_chip(usb));
+}
+
+static inline u8 *zd_mac_get_perm_addr(struct zd_mac *mac)
+{
+       return mac->hw->wiphy->perm_addr;
+}
+
+#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip))
+
+struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf);
+void zd_mac_clear(struct zd_mac *mac);
+
+int zd_mac_preinit_hw(struct ieee80211_hw *hw);
+int zd_mac_init_hw(struct ieee80211_hw *hw);
+
+int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length);
+void zd_mac_tx_failed(struct urb *urb);
+void zd_mac_tx_to_dev(struct sk_buff *skb, int error);
+
+int zd_op_start(struct ieee80211_hw *hw);
+void zd_op_stop(struct ieee80211_hw *hw);
+int zd_restore_settings(struct zd_mac *mac);
+
+#ifdef DEBUG
+void zd_dump_rx_status(const struct rx_status *status);
+#else
+#define zd_dump_rx_status(status)
+#endif /* DEBUG */
+
+#endif /* _ZD_MAC_H */
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_rf.c b/drivers/net/wireless/zydas/zd1211rw/zd_rf.c
new file mode 100644 (file)
index 0000000..dc179c4
--- /dev/null
@@ -0,0 +1,181 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+
+#include "zd_def.h"
+#include "zd_rf.h"
+#include "zd_mac.h"
+#include "zd_chip.h"
+
+static const char * const rfs[] = {
+       [0]             = "unknown RF0",
+       [1]             = "unknown RF1",
+       [UW2451_RF]     = "UW2451_RF",
+       [UCHIP_RF]      = "UCHIP_RF",
+       [AL2230_RF]     = "AL2230_RF",
+       [AL7230B_RF]    = "AL7230B_RF",
+       [THETA_RF]      = "THETA_RF",
+       [AL2210_RF]     = "AL2210_RF",
+       [MAXIM_NEW_RF]  = "MAXIM_NEW_RF",
+       [UW2453_RF]     = "UW2453_RF",
+       [AL2230S_RF]    = "AL2230S_RF",
+       [RALINK_RF]     = "RALINK_RF",
+       [INTERSIL_RF]   = "INTERSIL_RF",
+       [RF2959_RF]     = "RF2959_RF",
+       [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF",
+       [PHILIPS_RF]    = "PHILIPS_RF",
+};
+
+const char *zd_rf_name(u8 type)
+{
+       if (type & 0xf0)
+               type = 0;
+       return rfs[type];
+}
+
+void zd_rf_init(struct zd_rf *rf)
+{
+       memset(rf, 0, sizeof(*rf));
+
+       /* default to update channel integration, as almost all RF's do want
+        * this */
+       rf->update_channel_int = 1;
+}
+
+void zd_rf_clear(struct zd_rf *rf)
+{
+       if (rf->clear)
+               rf->clear(rf);
+       ZD_MEMCLEAR(rf, sizeof(*rf));
+}
+
+int zd_rf_init_hw(struct zd_rf *rf, u8 type)
+{
+       int r = 0;
+       int t;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       switch (type) {
+       case RF2959_RF:
+               r = zd_rf_init_rf2959(rf);
+               break;
+       case AL2230_RF:
+       case AL2230S_RF:
+               r = zd_rf_init_al2230(rf);
+               break;
+       case AL7230B_RF:
+               r = zd_rf_init_al7230b(rf);
+               break;
+       case MAXIM_NEW_RF:
+       case UW2453_RF:
+               r = zd_rf_init_uw2453(rf);
+               break;
+       default:
+               dev_err(zd_chip_dev(chip),
+                       "RF %s %#x is not supported\n", zd_rf_name(type), type);
+               rf->type = 0;
+               return -ENODEV;
+       }
+
+       if (r)
+               return r;
+
+       rf->type = type;
+
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               return r;
+       t = rf->init_hw(rf);
+       r = zd_chip_unlock_phy_regs(chip);
+       if (t)
+               r = t;
+       return r;
+}
+
+int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size)
+{
+       return scnprintf(buffer, size, "%s", zd_rf_name(rf->type));
+}
+
+int zd_rf_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+
+       ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex));
+       if (channel < MIN_CHANNEL24)
+               return -EINVAL;
+       if (channel > MAX_CHANNEL24)
+               return -EINVAL;
+       dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel);
+
+       r = rf->set_channel(rf, channel);
+       if (r >= 0)
+               rf->channel = channel;
+       return r;
+}
+
+int zd_switch_radio_on(struct zd_rf *rf)
+{
+       int r, t;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               return r;
+       t = rf->switch_radio_on(rf);
+       r = zd_chip_unlock_phy_regs(chip);
+       if (t)
+               r = t;
+       return r;
+}
+
+int zd_switch_radio_off(struct zd_rf *rf)
+{
+       int r, t;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       /* TODO: move phy regs handling to zd_chip */
+       ZD_ASSERT(mutex_is_locked(&chip->mutex));
+       r = zd_chip_lock_phy_regs(chip);
+       if (r)
+               return r;
+       t = rf->switch_radio_off(rf);
+       r = zd_chip_unlock_phy_regs(chip);
+       if (t)
+               r = t;
+       return r;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel)
+{
+       if (!rf->patch_6m_band_edge)
+               return 0;
+
+       return rf->patch_6m_band_edge(rf, channel);
+}
+
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel)
+{
+       return zd_chip_generic_patch_6m_band(zd_rf_to_chip(rf), channel);
+}
+
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_rf.h b/drivers/net/wireless/zydas/zd1211rw/zd_rf.h
new file mode 100644 (file)
index 0000000..8f14e25
--- /dev/null
@@ -0,0 +1,110 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ZD_RF_H
+#define _ZD_RF_H
+
+#define UW2451_RF                      0x2
+#define UCHIP_RF                       0x3
+#define AL2230_RF                      0x4
+#define AL7230B_RF                     0x5     /* a,b,g */
+#define THETA_RF                       0x6
+#define AL2210_RF                      0x7
+#define MAXIM_NEW_RF                   0x8
+#define UW2453_RF                      0x9
+#define AL2230S_RF                     0xa
+#define RALINK_RF                      0xb
+#define INTERSIL_RF                    0xc
+#define RF2959_RF                      0xd
+#define MAXIM_NEW2_RF                  0xe
+#define PHILIPS_RF                     0xf
+
+#define RF_CHANNEL(ch) [(ch)-1]
+
+/* Provides functions of the RF transceiver. */
+
+enum {
+       RF_REG_BITS = 6,
+       RF_VALUE_BITS = 18,
+       RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS,
+};
+
+struct zd_rf {
+       u8 type;
+
+       u8 channel;
+
+       /* whether channel integration and calibration should be updated
+        * defaults to 1 (yes) */
+       u8 update_channel_int:1;
+
+       /* whether ZD_CR47 should be patched from the EEPROM, if the appropriate
+        * flag is set in the POD. The vendor driver suggests that this should
+        * be done for all RF's, but a bug in their code prevents but their
+        * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+       u8 patch_cck_gain:1;
+
+       /* private RF driver data */
+       void *priv;
+
+       /* RF-specific functions */
+       int (*init_hw)(struct zd_rf *rf);
+       int (*set_channel)(struct zd_rf *rf, u8 channel);
+       int (*switch_radio_on)(struct zd_rf *rf);
+       int (*switch_radio_off)(struct zd_rf *rf);
+       int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+       void (*clear)(struct zd_rf *rf);
+};
+
+const char *zd_rf_name(u8 type);
+void zd_rf_init(struct zd_rf *rf);
+void zd_rf_clear(struct zd_rf *rf);
+int zd_rf_init_hw(struct zd_rf *rf, u8 type);
+
+int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size);
+
+int zd_rf_set_channel(struct zd_rf *rf, u8 channel);
+
+int zd_switch_radio_on(struct zd_rf *rf);
+int zd_switch_radio_off(struct zd_rf *rf);
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+       return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+       return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
+/* Functions for individual RF chips */
+
+int zd_rf_init_rf2959(struct zd_rf *rf);
+int zd_rf_init_al2230(struct zd_rf *rf);
+int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
+
+#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zydas/zd1211rw/zd_rf_al2230.c
new file mode 100644 (file)
index 0000000..99aed7d
--- /dev/null
@@ -0,0 +1,443 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF)
+
+static const u32 zd1211_al2230_table[][3] = {
+       RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
+       RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
+       RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, },
+       RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, },
+       RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, },
+       RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, },
+       RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, },
+       RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, },
+       RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
+};
+
+static const u32 zd1211b_al2230_table[][3] = {
+       RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, },
+       RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, },
+       RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, },
+};
+
+static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
+       { ZD_CR240, 0x57 }, { ZD_CR9,   0xe0 },
+};
+
+static const struct zd_ioreq16 ioreqs_init_al2230s[] = {
+       { ZD_CR47,   0x1e }, /* MARK_002 */
+       { ZD_CR106,  0x22 },
+       { ZD_CR107,  0x2a }, /* MARK_002 */
+       { ZD_CR109,  0x13 }, /* MARK_002 */
+       { ZD_CR118,  0xf8 }, /* MARK_002 */
+       { ZD_CR119,  0x12 }, { ZD_CR122,  0xe0 },
+       { ZD_CR128,  0x10 }, /* MARK_001 from 0xe->0x10 */
+       { ZD_CR129,  0x0e }, /* MARK_001 from 0xd->0x0e */
+       { ZD_CR130,  0x10 }, /* MARK_001 from 0xb->0x0d */
+};
+
+static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
+{
+       int r;
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 }, { ZD_CR79,  0x58 },
+               { ZD_CR12,  0xf0 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x58 },
+               { ZD_CR203, 0x06 },
+               { },
+
+               { ZD_CR240, 0x80 },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       /* related to antenna selection? */
+       if (chip->new_phy_layout) {
+               r = zd_iowrite16_locked(chip, 0xe1, ZD_CR9);
+               if (r)
+                       return r;
+       }
+
+       return zd_iowrite16_locked(chip, 0x06, ZD_CR203);
+}
+
+static int zd1211_al2230_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs_init[] = {
+               { ZD_CR15,   0x20 }, { ZD_CR23,   0x40 }, { ZD_CR24,  0x20 },
+               { ZD_CR26,   0x11 }, { ZD_CR28,   0x3e }, { ZD_CR29,  0x00 },
+               { ZD_CR44,   0x33 }, { ZD_CR106,  0x2a }, { ZD_CR107, 0x1a },
+               { ZD_CR109,  0x09 }, { ZD_CR110,  0x27 }, { ZD_CR111, 0x2b },
+               { ZD_CR112,  0x2b }, { ZD_CR119,  0x0a }, { ZD_CR10,  0x89 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR17,   0x28 },
+               { ZD_CR26,   0x93 }, { ZD_CR34,   0x30 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR35,   0x3e },
+               { ZD_CR41,   0x24 }, { ZD_CR44,   0x32 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR46,   0x96 },
+               { ZD_CR47,   0x1e }, { ZD_CR79,   0x58 }, { ZD_CR80,  0x30 },
+               { ZD_CR81,   0x30 }, { ZD_CR87,   0x0a }, { ZD_CR89,  0x04 },
+               { ZD_CR92,   0x0a }, { ZD_CR99,   0x28 }, { ZD_CR100, 0x00 },
+               { ZD_CR101,  0x13 }, { ZD_CR102,  0x27 }, { ZD_CR106, 0x24 },
+               { ZD_CR107,  0x2a }, { ZD_CR109,  0x09 }, { ZD_CR110, 0x13 },
+               { ZD_CR111,  0x1f }, { ZD_CR112,  0x1f }, { ZD_CR113, 0x27 },
+               { ZD_CR114,  0x27 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR115,  0x24 },
+               { ZD_CR116,  0x24 }, { ZD_CR117,  0xf4 }, { ZD_CR118, 0xfc },
+               { ZD_CR119,  0x10 }, { ZD_CR120,  0x4f }, { ZD_CR121, 0x77 },
+               { ZD_CR122,  0xe0 }, { ZD_CR137,  0x88 }, { ZD_CR252, 0xff },
+               { ZD_CR253,  0xff },
+       };
+
+       static const struct zd_ioreq16 ioreqs_pll[] = {
+               /* shdnb(PLL_ON)=0 */
+               { ZD_CR251,  0x2f },
+               /* shdnb(PLL_ON)=1 */
+               { ZD_CR251,  0x3f },
+               { ZD_CR138,  0x28 }, { ZD_CR203,  0x06 },
+       };
+
+       static const u32 rv1[] = {
+               /* Channel 1 */
+               0x03f790,
+               0x033331,
+               0x00000d,
+
+               0x0b3331,
+               0x03b812,
+               0x00fff3,
+       };
+
+       static const u32 rv2[] = {
+               0x000da4,
+               0x0f4dc5, /* fix freq shift, 0x04edc5 */
+               0x0805b6,
+               0x011687,
+               0x000688,
+               0x0403b9, /* external control TX power (ZD_CR31) */
+               0x00dbba,
+               0x00099b,
+               0x0bdffc,
+               0x00000d,
+               0x00500f,
+       };
+
+       static const u32 rv3[] = {
+               0x00d00f,
+               0x004c0f,
+               0x00540f,
+               0x00700f,
+               0x00500f,
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs_init, ARRAY_SIZE(ioreqs_init));
+       if (r)
+               return r;
+
+       if (IS_AL2230S(chip)) {
+               r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
+                       ARRAY_SIZE(ioreqs_init_al2230s));
+               if (r)
+                       return r;
+       }
+
+       r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
+       if (r)
+               return r;
+
+       /* improve band edge for AL2230S */
+       if (IS_AL2230S(chip))
+               r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS);
+       else
+               r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS);
+       if (r)
+               return r;
+
+       r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_pll, ARRAY_SIZE(ioreqs_pll));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int zd1211b_al2230_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs1[] = {
+               { ZD_CR10,  0x89 }, { ZD_CR15,  0x20 },
+               { ZD_CR17,  0x2B }, /* for newest(3rd cut) AL2230 */
+               { ZD_CR23,  0x40 }, { ZD_CR24,  0x20 }, { ZD_CR26,  0x93 },
+               { ZD_CR28,  0x3e }, { ZD_CR29,  0x00 },
+               { ZD_CR33,  0x28 }, /* 5621 */
+               { ZD_CR34,  0x30 },
+               { ZD_CR35,  0x3e }, /* for newest(3rd cut) AL2230 */
+               { ZD_CR41,  0x24 }, { ZD_CR44,  0x32 },
+               { ZD_CR46,  0x99 }, /* for newest(3rd cut) AL2230 */
+               { ZD_CR47,  0x1e },
+
+               /* ZD1211B 05.06.10 */
+               { ZD_CR48,  0x06 }, { ZD_CR49,  0xf9 }, { ZD_CR51,  0x01 },
+               { ZD_CR52,  0x80 }, { ZD_CR53,  0x7e }, { ZD_CR65,  0x00 },
+               { ZD_CR66,  0x00 }, { ZD_CR67,  0x00 }, { ZD_CR68,  0x00 },
+               { ZD_CR69,  0x28 },
+
+               { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 },
+               { ZD_CR87,  0x0a }, { ZD_CR89,  0x04 },
+               { ZD_CR91,  0x00 }, /* 5621 */
+               { ZD_CR92,  0x0a },
+               { ZD_CR98,  0x8d }, /* 4804,  for 1212 new algorithm */
+               { ZD_CR99,  0x00 }, /* 5621 */
+               { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 },
+               { ZD_CR106, 0x24 }, /* for newest(3rd cut) AL2230 */
+               { ZD_CR107, 0x2a },
+               { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */
+               { ZD_CR110, 0x1f }, /* 4804, for 1212 new algorithm */
+               { ZD_CR111, 0x1f }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 },
+               { ZD_CR114, 0x27 },
+               { ZD_CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut)
+                                    * AL2230
+                                    */
+               { ZD_CR116, 0x24 },
+               { ZD_CR117, 0xfa }, /* for 1211b */
+               { ZD_CR118, 0xfa }, /* for 1211b */
+               { ZD_CR119, 0x10 },
+               { ZD_CR120, 0x4f },
+               { ZD_CR121, 0x6c }, /* for 1211b */
+               { ZD_CR122, 0xfc }, /* E0->FC at 4902 */
+               { ZD_CR123, 0x57 }, /* 5623 */
+               { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */
+               { ZD_CR126, 0x6c }, /* 5614 */
+               { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */
+               { ZD_CR137, 0x50 }, /* 5614 */
+               { ZD_CR138, 0xa8 },
+               { ZD_CR144, 0xac }, /* 5621 */
+               { ZD_CR150, 0x0d }, { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 },
+       };
+
+       static const u32 rv1[] = {
+               0x8cccd0,
+               0x481dc0,
+               0xcfff00,
+               0x25a000,
+       };
+
+       static const u32 rv2[] = {
+               /* To improve AL2230 yield, improve phase noise, 4713 */
+               0x25a000,
+               0xa3b2f0,
+
+               0x6da010, /* Reg6 update for MP versio */
+               0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */
+               0x116000,
+               0x9dc020, /* External control TX power (ZD_CR31) */
+               0x5ddb00, /* RegA update for MP version */
+               0xd99000, /* RegB update for MP version */
+               0x3ffbd0, /* RegC update for MP version */
+               0xb00000, /* RegD update for MP version */
+
+               /* improve phase noise and remove phase calibration,4713 */
+               0xf01a00,
+       };
+
+       static const struct zd_ioreq16 ioreqs2[] = {
+               { ZD_CR251, 0x2f }, /* shdnb(PLL_ON)=0 */
+               { ZD_CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
+       };
+
+       static const u32 rv3[] = {
+               /* To improve AL2230 yield, 4713 */
+               0xf01b00,
+               0xf01e00,
+               0xf01a00,
+       };
+
+       static const struct zd_ioreq16 ioreqs3[] = {
+               /* related to 6M band edge patching, happens unconditionally */
+               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
+       };
+
+       r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
+               ARRAY_SIZE(zd1211b_ioreqs_shared_1));
+       if (r)
+               return r;
+       r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
+       if (r)
+               return r;
+
+       if (IS_AL2230S(chip)) {
+               r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s,
+                       ARRAY_SIZE(ioreqs_init_al2230s));
+               if (r)
+                       return r;
+       }
+
+       r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3);
+       if (r)
+               return r;
+       r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1));
+       if (r)
+               return r;
+
+       if (IS_AL2230S(chip))
+               r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS);
+       else
+               r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS);
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2));
+       if (r)
+               return r;
+       r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
+       if (r)
+               return r;
+       r = zd_rfwritev_cr_locked(chip, rv3, ARRAY_SIZE(rv3));
+       if (r)
+               return r;
+       r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
+       if (r)
+               return r;
+       return zd1211b_al2230_finalize_rf(chip);
+}
+
+static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       const u32 *rv = zd1211_al2230_table[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR138, 0x28 },
+               { ZD_CR203, 0x06 },
+       };
+
+       r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS);
+       if (r)
+               return r;
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       const u32 *rv = zd1211b_al2230_table[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
+               ARRAY_SIZE(zd1211b_ioreqs_shared_1));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv, 3);
+       if (r)
+               return r;
+
+       return zd1211b_al2230_finalize_rf(chip);
+}
+
+static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x00 },
+               { ZD_CR251, 0x3f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x00 },
+               { ZD_CR251, 0x7f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int al2230_switch_radio_off(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x04 },
+               { ZD_CR251, 0x2f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_al2230(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       rf->switch_radio_off = al2230_switch_radio_off;
+       if (zd_chip_is_zd1211b(chip)) {
+               rf->init_hw = zd1211b_al2230_init_hw;
+               rf->set_channel = zd1211b_al2230_set_channel;
+               rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
+       } else {
+               rf->init_hw = zd1211_al2230_init_hw;
+               rf->set_channel = zd1211_al2230_set_channel;
+               rf->switch_radio_on = zd1211_al2230_switch_radio_on;
+       }
+       rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+       rf->patch_cck_gain = 1;
+       return 0;
+}
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zydas/zd1211rw/zd_rf_al7230b.c
new file mode 100644 (file)
index 0000000..5fea485
--- /dev/null
@@ -0,0 +1,494 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+static const u32 chan_rv[][2] = {
+       RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 },
+       RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 },
+       RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 },
+       RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 },
+       RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 },
+       RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 },
+       RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 },
+       RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 },
+       RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 },
+       RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 },
+       RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 },
+       RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 },
+       RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 },
+       RF_CHANNEL(14) = { 0x03ec00, 0x866660 },
+};
+
+static const u32 std_rv[] = {
+       0x4ff821,
+       0xc5fbfc,
+       0x21ebfe,
+       0xafd401, /* freq shift 0xaad401 */
+       0x6cf56a,
+       0xe04073,
+       0x193d76,
+       0x9dd844,
+       0x500007,
+       0xd8c010,
+};
+
+static const u32 rv_init1[] = {
+       0x3c9000,
+       0xbfffff,
+       0x700000,
+       0xf15d58,
+};
+
+static const u32 rv_init2[] = {
+       0xf15d59,
+       0xf15d5c,
+       0xf15d58,
+};
+
+static const struct zd_ioreq16 ioreqs_sw[] = {
+       { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
+       { ZD_CR38,  0x38 }, { ZD_CR136, 0xdf },
+};
+
+static int zd1211b_al7230b_finalize(struct zd_chip *chip)
+{
+       int r;
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 }, { ZD_CR79,  0x58 },
+               { ZD_CR12,  0xf0 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x58 },
+               { ZD_CR203, 0x04 },
+               { },
+               { ZD_CR240, 0x80 },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       if (chip->new_phy_layout) {
+               /* antenna selection? */
+               r = zd_iowrite16_locked(chip, 0xe5, ZD_CR9);
+               if (r)
+                       return r;
+       }
+
+       return zd_iowrite16_locked(chip, 0x04, ZD_CR203);
+}
+
+static int zd1211_al7230b_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       /* All of these writes are identical to AL2230 unless otherwise
+        * specified */
+       static const struct zd_ioreq16 ioreqs_1[] = {
+               /* This one is 7230-specific, and happens before the rest */
+               { ZD_CR240,  0x57 },
+               { },
+
+               { ZD_CR15,   0x20 }, { ZD_CR23,   0x40 }, { ZD_CR24,  0x20 },
+               { ZD_CR26,   0x11 }, { ZD_CR28,   0x3e }, { ZD_CR29,  0x00 },
+               { ZD_CR44,   0x33 },
+               /* This value is different for 7230 (was: 0x2a) */
+               { ZD_CR106,  0x22 },
+               { ZD_CR107,  0x1a }, { ZD_CR109,  0x09 }, { ZD_CR110,  0x27 },
+               { ZD_CR111,  0x2b }, { ZD_CR112,  0x2b }, { ZD_CR119,  0x0a },
+               /* This happened further down in AL2230,
+                * and the value changed (was: 0xe0) */
+               { ZD_CR122,  0xfc },
+               { ZD_CR10,   0x89 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR17,   0x28 },
+               { ZD_CR26,   0x93 }, { ZD_CR34,   0x30 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR35,   0x3e },
+               { ZD_CR41,   0x24 }, { ZD_CR44,   0x32 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR46,   0x96 },
+               { ZD_CR47,   0x1e }, { ZD_CR79,   0x58 }, { ZD_CR80,  0x30 },
+               { ZD_CR81,   0x30 }, { ZD_CR87,   0x0a }, { ZD_CR89,  0x04 },
+               { ZD_CR92,   0x0a }, { ZD_CR99,   0x28 },
+               /* This value is different for 7230 (was: 0x00) */
+               { ZD_CR100,  0x02 },
+               { ZD_CR101,  0x13 }, { ZD_CR102,  0x27 },
+               /* This value is different for 7230 (was: 0x24) */
+               { ZD_CR106,  0x22 },
+               /* This value is different for 7230 (was: 0x2a) */
+               { ZD_CR107,  0x3f },
+               { ZD_CR109,  0x09 },
+               /* This value is different for 7230 (was: 0x13) */
+               { ZD_CR110,  0x1f },
+               { ZD_CR111,  0x1f }, { ZD_CR112,  0x1f }, { ZD_CR113, 0x27 },
+               { ZD_CR114,  0x27 },
+               /* for newest (3rd cut) AL2300 */
+               { ZD_CR115,  0x24 },
+               /* This value is different for 7230 (was: 0x24) */
+               { ZD_CR116,  0x3f },
+               /* This value is different for 7230 (was: 0xf4) */
+               { ZD_CR117,  0xfa },
+               { ZD_CR118,  0xfc }, { ZD_CR119,  0x10 }, { ZD_CR120, 0x4f },
+               { ZD_CR121,  0x77 }, { ZD_CR137,  0x88 },
+               /* This one is 7230-specific */
+               { ZD_CR138,  0xa8 },
+               /* This value is different for 7230 (was: 0xff) */
+               { ZD_CR252,  0x34 },
+               /* This value is different for 7230 (was: 0xff) */
+               { ZD_CR253,  0x34 },
+
+               /* PLL_OFF */
+               { ZD_CR251, 0x2f },
+       };
+
+       static const struct zd_ioreq16 ioreqs_2[] = {
+               { ZD_CR251, 0x3f }, /* PLL_ON */
+               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
+               { ZD_CR38,  0x38 }, { ZD_CR136, 0xdf },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, chan_rv[0], ARRAY_SIZE(chan_rv[0]));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv_init1, ARRAY_SIZE(rv_init1));
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv_init2, ARRAY_SIZE(rv_init2));
+       if (r)
+               return r;
+
+       r = zd_iowrite16_locked(chip, 0x06, ZD_CR203);
+       if (r)
+               return r;
+       r = zd_iowrite16_locked(chip, 0x80, ZD_CR240);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+static int zd1211b_al7230b_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs_1[] = {
+               { ZD_CR240, 0x57 }, { ZD_CR9,   0x9 },
+               { },
+               { ZD_CR10,  0x8b }, { ZD_CR15,  0x20 },
+               { ZD_CR17,  0x2B }, /* for newest (3rd cut) AL2230 */
+               { ZD_CR20,  0x10 }, /* 4N25->Stone Request */
+               { ZD_CR23,  0x40 }, { ZD_CR24,  0x20 }, { ZD_CR26,  0x93 },
+               { ZD_CR28,  0x3e }, { ZD_CR29,  0x00 },
+               { ZD_CR33,  0x28 }, /* 5613 */
+               { ZD_CR34,  0x30 },
+               { ZD_CR35,  0x3e }, /* for newest (3rd cut) AL2230 */
+               { ZD_CR41,  0x24 }, { ZD_CR44,  0x32 },
+               { ZD_CR46,  0x99 }, /* for newest (3rd cut) AL2230 */
+               { ZD_CR47,  0x1e },
+
+               /* ZD1215 5610 */
+               { ZD_CR48,  0x00 }, { ZD_CR49,  0x00 }, { ZD_CR51,  0x01 },
+               { ZD_CR52,  0x80 }, { ZD_CR53,  0x7e }, { ZD_CR65,  0x00 },
+               { ZD_CR66,  0x00 }, { ZD_CR67,  0x00 }, { ZD_CR68,  0x00 },
+               { ZD_CR69,  0x28 },
+
+               { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 },
+               { ZD_CR87,  0x0A }, { ZD_CR89,  0x04 },
+               { ZD_CR90,  0x58 }, /* 5112 */
+               { ZD_CR91,  0x00 }, /* 5613 */
+               { ZD_CR92,  0x0a },
+               { ZD_CR98,  0x8d }, /* 4804, for 1212 new algorithm */
+               { ZD_CR99,  0x00 }, { ZD_CR100, 0x02 }, { ZD_CR101, 0x13 },
+               { ZD_CR102, 0x27 },
+               { ZD_CR106, 0x20 }, /* change to 0x24 for AL7230B */
+               { ZD_CR109, 0x13 }, /* 4804, for 1212 new algorithm */
+               { ZD_CR112, 0x1f },
+       };
+
+       static const struct zd_ioreq16 ioreqs_new_phy[] = {
+               { ZD_CR107, 0x28 },
+               { ZD_CR110, 0x1f }, /* 5127, 0x13->0x1f */
+               { ZD_CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */
+               { ZD_CR116, 0x2a }, { ZD_CR118, 0xfa }, { ZD_CR119, 0x12 },
+               { ZD_CR121, 0x6c }, /* 5613 */
+       };
+
+       static const struct zd_ioreq16 ioreqs_old_phy[] = {
+               { ZD_CR107, 0x24 },
+               { ZD_CR110, 0x13 }, /* 5127, 0x13->0x1f */
+               { ZD_CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */
+               { ZD_CR116, 0x24 }, { ZD_CR118, 0xfc }, { ZD_CR119, 0x11 },
+               { ZD_CR121, 0x6a }, /* 5613 */
+       };
+
+       static const struct zd_ioreq16 ioreqs_2[] = {
+               { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x24 },
+               { ZD_CR117, 0xfa }, { ZD_CR120, 0x4f },
+               { ZD_CR122, 0xfc }, /* E0->FCh at 4901 */
+               { ZD_CR123, 0x57 }, /* 5613 */
+               { ZD_CR125, 0xad }, /* 4804, for 1212 new algorithm */
+               { ZD_CR126, 0x6c }, /* 5613 */
+               { ZD_CR127, 0x03 }, /* 4804, for 1212 new algorithm */
+               { ZD_CR130, 0x10 },
+               { ZD_CR131, 0x00 }, /* 5112 */
+               { ZD_CR137, 0x50 }, /* 5613 */
+               { ZD_CR138, 0xa8 }, /* 5112 */
+               { ZD_CR144, 0xac }, /* 5613 */
+               { ZD_CR148, 0x40 }, /* 5112 */
+               { ZD_CR149, 0x40 }, /* 4O07, 50->40 */
+               { ZD_CR150, 0x1a }, /* 5112, 0C->1A */
+               { ZD_CR252, 0x34 }, { ZD_CR253, 0x34 },
+               { ZD_CR251, 0x2f }, /* PLL_OFF */
+       };
+
+       static const struct zd_ioreq16 ioreqs_3[] = {
+               { ZD_CR251, 0x7f }, /* PLL_ON */
+               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 }, { ZD_CR130, 0x10 },
+               { ZD_CR38,  0x38 }, { ZD_CR136, 0xdf },
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
+       if (r)
+               return r;
+
+       if (chip->new_phy_layout)
+               r = zd_iowrite16a_locked(chip, ioreqs_new_phy,
+                       ARRAY_SIZE(ioreqs_new_phy));
+       else
+               r = zd_iowrite16a_locked(chip, ioreqs_old_phy,
+                       ARRAY_SIZE(ioreqs_old_phy));
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, chan_rv[0], ARRAY_SIZE(chan_rv[0]));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv_init1, ARRAY_SIZE(rv_init1));
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_3, ARRAY_SIZE(ioreqs_3));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv_init2, ARRAY_SIZE(rv_init2));
+       if (r)
+               return r;
+
+       return zd1211b_al7230b_finalize(chip);
+}
+
+static int zd1211_al7230b_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       const u32 *rv = chan_rv[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs[] = {
+               /* PLL_ON */
+               { ZD_CR251, 0x3f },
+               { ZD_CR203, 0x06 }, { ZD_CR240, 0x08 },
+       };
+
+       r = zd_iowrite16_locked(chip, 0x57, ZD_CR240);
+       if (r)
+               return r;
+
+       /* PLL_OFF */
+       r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251);
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
+       if (r)
+               return r;
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_sw, ARRAY_SIZE(ioreqs_sw));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv, 2);
+       if (r)
+               return r;
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       const u32 *rv = chan_rv[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       r = zd_iowrite16_locked(chip, 0x57, ZD_CR240);
+       if (r)
+               return r;
+       r = zd_iowrite16_locked(chip, 0xe4, ZD_CR9);
+       if (r)
+               return r;
+
+       /* PLL_OFF */
+       r = zd_iowrite16_locked(chip, 0x2f, ZD_CR251);
+       if (r)
+               return r;
+       r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv));
+       if (r)
+               return r;
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+       r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs_sw, ARRAY_SIZE(ioreqs_sw));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_cr_locked(chip, rv, 2);
+       if (r)
+               return r;
+
+       r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+       if (r)
+               return r;
+
+       r = zd_iowrite16_locked(chip, 0x7f, ZD_CR251);
+       if (r)
+               return r;
+
+       return zd1211b_al7230b_finalize(chip);
+}
+
+static int zd1211_al7230b_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x00 },
+               { ZD_CR251, 0x3f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int zd1211b_al7230b_switch_radio_on(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x00 },
+               { ZD_CR251, 0x7f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int al7230b_switch_radio_off(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x04 },
+               { ZD_CR251, 0x2f },
+       };
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+/* ZD1211B+AL7230B 6m band edge patching differs slightly from other
+ * configurations */
+static int zd1211b_al7230b_patch_6m(struct zd_rf *rf, u8 channel)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR128, 0x14 }, { ZD_CR129, 0x12 },
+       };
+
+       /* FIXME: Channel 11 is not the edge for all regulatory domains. */
+       if (channel == 1) {
+               ioreqs[0].value = 0x0e;
+               ioreqs[1].value = 0x10;
+       } else if (channel == 11) {
+               ioreqs[0].value = 0x10;
+               ioreqs[1].value = 0x10;
+       }
+
+       dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel);
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_al7230b(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       if (zd_chip_is_zd1211b(chip)) {
+               rf->init_hw = zd1211b_al7230b_init_hw;
+               rf->switch_radio_on = zd1211b_al7230b_switch_radio_on;
+               rf->set_channel = zd1211b_al7230b_set_channel;
+               rf->patch_6m_band_edge = zd1211b_al7230b_patch_6m;
+       } else {
+               rf->init_hw = zd1211_al7230b_init_hw;
+               rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
+               rf->set_channel = zd1211_al7230b_set_channel;
+               rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+               rf->patch_cck_gain = 1;
+       }
+
+       rf->switch_radio_off = al7230b_switch_radio_off;
+
+       return 0;
+}
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zydas/zd1211rw/zd_rf_rf2959.c
new file mode 100644 (file)
index 0000000..a93f657
--- /dev/null
@@ -0,0 +1,281 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+static const u32 rf2959_table[][2] = {
+       RF_CHANNEL( 1) = { 0x181979, 0x1e6666 },
+       RF_CHANNEL( 2) = { 0x181989, 0x1e6666 },
+       RF_CHANNEL( 3) = { 0x181999, 0x1e6666 },
+       RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 },
+       RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 },
+       RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 },
+       RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 },
+       RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 },
+       RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 },
+       RF_CHANNEL(10) = { 0x181a09, 0x1e6666 },
+       RF_CHANNEL(11) = { 0x181a19, 0x1e6666 },
+       RF_CHANNEL(12) = { 0x181a29, 0x1e6666 },
+       RF_CHANNEL(13) = { 0x181a39, 0x1e6666 },
+       RF_CHANNEL(14) = { 0x181a60, 0x1c0000 },
+};
+
+#if 0
+static int bits(u32 rw, int from, int to)
+{
+       rw &= ~(0xffffffffU << (to+1));
+       rw >>= from;
+       return rw;
+}
+
+static int bit(u32 rw, int bit)
+{
+       return bits(rw, bit, bit);
+}
+
+static void dump_regwrite(u32 rw)
+{
+       int reg = bits(rw, 18, 22);
+       int rw_flag = bits(rw, 23, 23);
+       PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag);
+
+       switch (reg) {
+       case 0:
+               PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d"
+                      " if_vco_reg_en %d if_vga_en %d",
+                      bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1),
+                      bit(rw, 0));
+               break;
+       case 1:
+               PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d"
+                      " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d"
+                      " ifloopc %d dac1 %d",
+                      bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
+                      bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
+                      bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3));
+               break;
+       case 2:
+               PDEBUG("reg2 IFPLL2 n1 %d num1 %d",
+                      bits(rw, 6, 17), bits(rw, 0, 5));
+               break;
+       case 3:
+               PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17));
+               break;
+       case 4:
+               PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d",
+                      bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
+               break;
+       case 5:
+               PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d"
+                      " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d"
+                      " dac %d",
+                      bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14),
+                      bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10),
+                      bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3));
+               break;
+       case 6:
+               PDEBUG("reg6 RFPLL2 n %d num %d",
+                      bits(rw, 6, 17), bits(rw, 0, 5));
+               break;
+       case 7:
+               PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17));
+               break;
+       case 8:
+               PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d",
+                      bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3));
+               break;
+       case 9:
+               PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d",
+                      bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7),
+                      bits(rw, 0, 2));
+               break;
+       case 10:
+               PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d"
+                      " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d"
+                      " intbiasen %d tybypass %d",
+                      bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14),
+                      bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2),
+                      bit(rw, 1), bit(rw, 0));
+               break;
+       case 11:
+               PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d"
+                       " tx_delay %d",
+                       bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8),
+                       bits(rw, 0, 2));
+               break;
+       case 12:
+               PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d",
+                      bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5));
+               break;
+       case 13:
+               PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d"
+                      " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d"
+                      " rf_biasvco %d",
+                      bit(rw, 17), bit(rw, 16), bit(rw, 15),
+                      bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4),
+                      bits(rw, 0, 2));
+               break;
+       case 14:
+               PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d"
+                      " tx_acal %d tx_pcal %d",
+                      bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8),
+                      bits(rw, 0, 3));
+               break;
+       }
+}
+#endif /* 0 */
+
+static int rf2959_init_hw(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR2,   0x1E }, { ZD_CR9,   0x20 }, { ZD_CR10,  0x89 },
+               { ZD_CR11,  0x00 }, { ZD_CR15,  0xD0 }, { ZD_CR17,  0x68 },
+               { ZD_CR19,  0x4a }, { ZD_CR20,  0x0c }, { ZD_CR21,  0x0E },
+               { ZD_CR23,  0x48 },
+               /* normal size for cca threshold */
+               { ZD_CR24,  0x14 },
+               /* { ZD_CR24,  0x20 }, */
+               { ZD_CR26,  0x90 }, { ZD_CR27,  0x30 }, { ZD_CR29,  0x20 },
+               { ZD_CR31,  0xb2 }, { ZD_CR32,  0x43 }, { ZD_CR33,  0x28 },
+               { ZD_CR38,  0x30 }, { ZD_CR34,  0x0f }, { ZD_CR35,  0xF0 },
+               { ZD_CR41,  0x2a }, { ZD_CR46,  0x7F }, { ZD_CR47,  0x1E },
+               { ZD_CR51,  0xc5 }, { ZD_CR52,  0xc5 }, { ZD_CR53,  0xc5 },
+               { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 },
+               { ZD_CR82,  0x00 }, { ZD_CR83,  0x24 }, { ZD_CR84,  0x04 },
+               { ZD_CR85,  0x00 }, { ZD_CR86,  0x10 }, { ZD_CR87,  0x2A },
+               { ZD_CR88,  0x10 }, { ZD_CR89,  0x24 }, { ZD_CR90,  0x18 },
+               /* { ZD_CR91,  0x18 }, */
+               /* should solve continuous CTS frame problems */
+               { ZD_CR91,  0x00 },
+               { ZD_CR92,  0x0a }, { ZD_CR93,  0x00 }, { ZD_CR94,  0x01 },
+               { ZD_CR95,  0x00 }, { ZD_CR96,  0x40 }, { ZD_CR97,  0x37 },
+               { ZD_CR98,  0x05 }, { ZD_CR99,  0x28 }, { ZD_CR100, 0x00 },
+               { ZD_CR101, 0x13 }, { ZD_CR102, 0x27 }, { ZD_CR103, 0x27 },
+               { ZD_CR104, 0x18 }, { ZD_CR105, 0x12 },
+               /* normal size */
+               { ZD_CR106, 0x1a },
+               /* { ZD_CR106, 0x22 }, */
+               { ZD_CR107, 0x24 }, { ZD_CR108, 0x0a }, { ZD_CR109, 0x13 },
+               { ZD_CR110, 0x2F }, { ZD_CR111, 0x27 }, { ZD_CR112, 0x27 },
+               { ZD_CR113, 0x27 }, { ZD_CR114, 0x27 }, { ZD_CR115, 0x40 },
+               { ZD_CR116, 0x40 }, { ZD_CR117, 0xF0 }, { ZD_CR118, 0xF0 },
+               { ZD_CR119, 0x16 },
+               /* no TX continuation */
+               { ZD_CR122, 0x00 },
+               /* { ZD_CR122, 0xff }, */
+               { ZD_CR127, 0x03 }, { ZD_CR131, 0x08 }, { ZD_CR138, 0x28 },
+               { ZD_CR148, 0x44 }, { ZD_CR150, 0x10 }, { ZD_CR169, 0xBB },
+               { ZD_CR170, 0xBB },
+       };
+
+       static const u32 rv[] = {
+               0x000007,  /* REG0(CFG1) */
+               0x07dd43,  /* REG1(IFPLL1) */
+               0x080959,  /* REG2(IFPLL2) */
+               0x0e6666,
+               0x116a57,  /* REG4 */
+               0x17dd43,  /* REG5 */
+               0x1819f9,  /* REG6 */
+               0x1e6666,
+               0x214554,
+               0x25e7fa,
+               0x27fffa,
+               /* The Zydas driver somehow forgets to set this value. It's
+                * only set for Japan. We are using internal power control
+                * for now.
+                */
+               0x294128, /* internal power */
+               /* 0x28252c, */ /* External control TX power */
+               /* ZD_CR31_CCK, ZD_CR51_6-36M, ZD_CR52_48M, ZD_CR53_54M */
+               0x2c0000,
+               0x300000,
+               0x340000,  /* REG13(0xD) */
+               0x381e0f,  /* REG14(0xE) */
+               /* Bogus, RF2959's data sheet doesn't know register 27, which is
+                * actually referenced here. The commented 0x11 is 17.
+                */
+               0x6c180f,  /* REG27(0x11) */
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int rf2959_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int i, r;
+       const u32 *rv = rf2959_table[channel-1];
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       for (i = 0; i < 2; i++) {
+               r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS);
+               if (r)
+                       return r;
+       }
+       return 0;
+}
+
+static int rf2959_switch_radio_on(struct zd_rf *rf)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR10, 0x89 },
+               { ZD_CR11, 0x00 },
+       };
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int rf2959_switch_radio_off(struct zd_rf *rf)
+{
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR10, 0x15 },
+               { ZD_CR11, 0x81 },
+       };
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_rf2959(struct zd_rf *rf)
+{
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       if (zd_chip_is_zd1211b(chip)) {
+               dev_err(zd_chip_dev(chip),
+                      "RF2959 is currently not supported for ZD1211B"
+                      " devices\n");
+               return -ENODEV;
+       }
+       rf->init_hw = rf2959_init_hw;
+       rf->set_channel = rf2959_set_channel;
+       rf->switch_radio_on = rf2959_switch_radio_on;
+       rf->switch_radio_off = rf2959_switch_radio_off;
+       return 0;
+}
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zydas/zd1211rw/zd_rf_uw2453.c
new file mode 100644 (file)
index 0000000..61b9240
--- /dev/null
@@ -0,0 +1,539 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+       RF_CHANNEL( 1) = 0x47,
+       RF_CHANNEL( 2) = 0x47,
+       RF_CHANNEL( 3) = 0x67,
+       RF_CHANNEL( 4) = 0x67,
+       RF_CHANNEL( 5) = 0x67,
+       RF_CHANNEL( 6) = 0x67,
+       RF_CHANNEL( 7) = 0x57,
+       RF_CHANNEL( 8) = 0x57,
+       RF_CHANNEL( 9) = 0x57,
+       RF_CHANNEL(10) = 0x57,
+       RF_CHANNEL(11) = 0x77,
+       RF_CHANNEL(12) = 0x77,
+       RF_CHANNEL(13) = 0x77,
+       RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+       RF_CHANNEL( 1) = 0x999,
+       RF_CHANNEL( 2) = 0x99b,
+       RF_CHANNEL( 3) = 0x998,
+       RF_CHANNEL( 4) = 0x99a,
+       RF_CHANNEL( 5) = 0x999,
+       RF_CHANNEL( 6) = 0x99b,
+       RF_CHANNEL( 7) = 0x998,
+       RF_CHANNEL( 8) = 0x99a,
+       RF_CHANNEL( 9) = 0x999,
+       RF_CHANNEL(10) = 0x99b,
+       RF_CHANNEL(11) = 0x998,
+       RF_CHANNEL(12) = 0x99a,
+       RF_CHANNEL(13) = 0x999,
+       RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+       { /* table 1 */
+               RF_CHANPAIR( 1,  2) = 0x664d,
+               RF_CHANPAIR( 3,  4) = 0x604d,
+               RF_CHANPAIR( 5,  6) = 0x6675,
+               RF_CHANPAIR( 7,  8) = 0x6475,
+               RF_CHANPAIR( 9, 10) = 0x6655,
+               RF_CHANPAIR(11, 12) = 0x6455,
+               RF_CHANPAIR(13, 14) = 0x6665,
+       },
+       { /* table 2 */
+               RF_CHANPAIR( 1,  2) = 0x666d,
+               RF_CHANPAIR( 3,  4) = 0x606d,
+               RF_CHANPAIR( 5,  6) = 0x664d,
+               RF_CHANPAIR( 7,  8) = 0x644d,
+               RF_CHANPAIR( 9, 10) = 0x6675,
+               RF_CHANPAIR(11, 12) = 0x6475,
+               RF_CHANPAIR(13, 14) = 0x6655,
+       },
+       { /* table 3 */
+               RF_CHANPAIR( 1,  2) = 0x665d,
+               RF_CHANPAIR( 3,  4) = 0x605d,
+               RF_CHANPAIR( 5,  6) = 0x666d,
+               RF_CHANPAIR( 7,  8) = 0x646d,
+               RF_CHANPAIR( 9, 10) = 0x664d,
+               RF_CHANPAIR(11, 12) = 0x644d,
+               RF_CHANPAIR(13, 14) = 0x6675,
+       },
+       { /* table 4 */
+               RF_CHANPAIR( 1,  2) = 0x667d,
+               RF_CHANPAIR( 3,  4) = 0x607d,
+               RF_CHANPAIR( 5,  6) = 0x665d,
+               RF_CHANPAIR( 7,  8) = 0x645d,
+               RF_CHANPAIR( 9, 10) = 0x666d,
+               RF_CHANPAIR(11, 12) = 0x646d,
+               RF_CHANPAIR(13, 14) = 0x664d,
+       },
+       { /* table 5 */
+               RF_CHANPAIR( 1,  2) = 0x6643,
+               RF_CHANPAIR( 3,  4) = 0x6043,
+               RF_CHANPAIR( 5,  6) = 0x667d,
+               RF_CHANPAIR( 7,  8) = 0x647d,
+               RF_CHANPAIR( 9, 10) = 0x665d,
+               RF_CHANPAIR(11, 12) = 0x645d,
+               RF_CHANPAIR(13, 14) = 0x666d,
+       },
+       { /* table 6 */
+               RF_CHANPAIR( 1,  2) = 0x6663,
+               RF_CHANPAIR( 3,  4) = 0x6063,
+               RF_CHANPAIR( 5,  6) = 0x6643,
+               RF_CHANPAIR( 7,  8) = 0x6443,
+               RF_CHANPAIR( 9, 10) = 0x667d,
+               RF_CHANPAIR(11, 12) = 0x647d,
+               RF_CHANPAIR(13, 14) = 0x665d,
+       },
+       { /* table 7 */
+               RF_CHANPAIR( 1,  2) = 0x6653,
+               RF_CHANPAIR( 3,  4) = 0x6053,
+               RF_CHANPAIR( 5,  6) = 0x6663,
+               RF_CHANPAIR( 7,  8) = 0x6463,
+               RF_CHANPAIR( 9, 10) = 0x6643,
+               RF_CHANPAIR(11, 12) = 0x6443,
+               RF_CHANPAIR(13, 14) = 0x667d,
+       },
+       { /* table 8 */
+               RF_CHANPAIR( 1,  2) = 0x6673,
+               RF_CHANPAIR( 3,  4) = 0x6073,
+               RF_CHANPAIR( 5,  6) = 0x6653,
+               RF_CHANPAIR( 7,  8) = 0x6453,
+               RF_CHANPAIR( 9, 10) = 0x6663,
+               RF_CHANPAIR(11, 12) = 0x6463,
+               RF_CHANPAIR(13, 14) = 0x6643,
+       },
+       { /* table 9 */
+               RF_CHANPAIR( 1,  2) = 0x664b,
+               RF_CHANPAIR( 3,  4) = 0x604b,
+               RF_CHANPAIR( 5,  6) = 0x6673,
+               RF_CHANPAIR( 7,  8) = 0x6473,
+               RF_CHANPAIR( 9, 10) = 0x6653,
+               RF_CHANPAIR(11, 12) = 0x6453,
+               RF_CHANPAIR(13, 14) = 0x6663,
+       },
+       { /* table 10 */
+               RF_CHANPAIR( 1,  2) = 0x666b,
+               RF_CHANPAIR( 3,  4) = 0x606b,
+               RF_CHANPAIR( 5,  6) = 0x664b,
+               RF_CHANPAIR( 7,  8) = 0x644b,
+               RF_CHANPAIR( 9, 10) = 0x6673,
+               RF_CHANPAIR(11, 12) = 0x6473,
+               RF_CHANPAIR(13, 14) = 0x6653,
+       },
+       { /* table 11 */
+               RF_CHANPAIR( 1,  2) = 0x665b,
+               RF_CHANPAIR( 3,  4) = 0x605b,
+               RF_CHANPAIR( 5,  6) = 0x666b,
+               RF_CHANPAIR( 7,  8) = 0x646b,
+               RF_CHANPAIR( 9, 10) = 0x664b,
+               RF_CHANPAIR(11, 12) = 0x644b,
+               RF_CHANPAIR(13, 14) = 0x6673,
+       },
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+       RF_CHANNEL( 1) = 0x6847,
+       RF_CHANNEL( 2) = 0x6847,
+       RF_CHANNEL( 3) = 0x6867,
+       RF_CHANNEL( 4) = 0x6867,
+       RF_CHANNEL( 5) = 0x6867,
+       RF_CHANNEL( 6) = 0x6867,
+       RF_CHANNEL( 7) = 0x6857,
+       RF_CHANNEL( 8) = 0x6857,
+       RF_CHANNEL( 9) = 0x6857,
+       RF_CHANNEL(10) = 0x6857,
+       RF_CHANNEL(11) = 0x6877,
+       RF_CHANNEL(12) = 0x6877,
+       RF_CHANNEL(13) = 0x6877,
+       RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+       [0x00] = 0x0e313,
+       [0x01] = 0x0fb13,
+       [0x02] = 0x0e093,
+       [0x03] = 0x0f893,
+       [0x04] = 0x0ea93,
+       [0x05] = 0x1f093,
+       [0x06] = 0x1f493,
+       [0x07] = 0x1f693,
+       [0x08] = 0x1f393,
+       [0x09] = 0x1f35b,
+       [0x0a] = 0x1e6db,
+       [0x0b] = 0x1ff3f,
+       [0x0c] = 0x1ffff,
+       [0x0d] = 0x361d7,
+       [0x0e] = 0x37fbf,
+       [0x0f] = 0x3ff8b,
+       [0x10] = 0x3ff33,
+       [0x11] = 0x3fb3f,
+       [0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+       /* index into synth/VCO config tables where PLL lock was found
+        * -1 means autocal */
+       int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+       bool autocal)
+{
+       int r;
+       int idx = channel - 1;
+       u32 val;
+
+       if (autocal)
+               val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+       else
+               val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+       r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+       if (r)
+               return r;
+
+       return zd_rfwrite_locked(chip,
+               UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+       /* vendor driver always sets these upper bits even though the specs say
+        * they are reserved */
+       u32 val = 0x40000 | value;
+       return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+       static const u32 rv[] = {
+               UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+               UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+               UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+               UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+       };
+
+       return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+       u8 int_value = chip->pwr_int_values[channel - 1];
+
+       if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+               dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+                         "int value %x on channel %d\n", int_value, channel);
+               return 0;
+       }
+
+       return zd_rfwrite_locked(chip,
+               UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+       int i, r;
+       int found_config = -1;
+       u16 intr_status;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR10,  0x89 }, { ZD_CR15,  0x20 },
+               { ZD_CR17,  0x28 }, /* 6112 no change */
+               { ZD_CR23,  0x38 }, { ZD_CR24,  0x20 }, { ZD_CR26,  0x93 },
+               { ZD_CR27,  0x15 }, { ZD_CR28,  0x3e }, { ZD_CR29,  0x00 },
+               { ZD_CR33,  0x28 }, { ZD_CR34,  0x30 },
+               { ZD_CR35,  0x43 }, /* 6112 3e->43 */
+               { ZD_CR41,  0x24 }, { ZD_CR44,  0x32 },
+               { ZD_CR46,  0x92 }, /* 6112 96->92 */
+               { ZD_CR47,  0x1e },
+               { ZD_CR48,  0x04 }, /* 5602 Roger */
+               { ZD_CR49,  0xfa }, { ZD_CR79,  0x58 }, { ZD_CR80,  0x30 },
+               { ZD_CR81,  0x30 }, { ZD_CR87,  0x0a }, { ZD_CR89,  0x04 },
+               { ZD_CR91,  0x00 }, { ZD_CR92,  0x0a }, { ZD_CR98,  0x8d },
+               { ZD_CR99,  0x28 }, { ZD_CR100, 0x02 },
+               { ZD_CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+               { ZD_CR102, 0x27 },
+               { ZD_CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f
+                                    * 6221 1f->1c
+                                    */
+               { ZD_CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+               { ZD_CR109, 0x13 },
+               { ZD_CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+               { ZD_CR111, 0x13 }, { ZD_CR112, 0x1f }, { ZD_CR113, 0x27 },
+               { ZD_CR114, 0x23 }, /* 6221 27->23 */
+               { ZD_CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+               { ZD_CR116, 0x24 }, /* 6220 1c->24 */
+               { ZD_CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+               { ZD_CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+               { ZD_CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+               { ZD_CR120, 0x4f },
+               { ZD_CR121, 0x1f }, /* 6220 4f->1f */
+               { ZD_CR122, 0xf0 }, { ZD_CR123, 0x57 }, { ZD_CR125, 0xad },
+               { ZD_CR126, 0x6c }, { ZD_CR127, 0x03 },
+               { ZD_CR128, 0x14 }, /* 6302 12->11 */
+               { ZD_CR129, 0x12 }, /* 6301 10->0f */
+               { ZD_CR130, 0x10 }, { ZD_CR137, 0x50 }, { ZD_CR138, 0xa8 },
+               { ZD_CR144, 0xac }, { ZD_CR146, 0x20 }, { ZD_CR252, 0xff },
+               { ZD_CR253, 0xff },
+       };
+
+       static const u32 rv[] = {
+               UW2453_REGWRITE(4, 0x2b),    /* configure receiver gain */
+               UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+               UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+               UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+               /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+                * RSSI circuit powered down, reduced RSSI range */
+               UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+               /* synthesizer configuration for channel 1 */
+               UW2453_REGWRITE(1, 0x47),
+               UW2453_REGWRITE(2, 0x999),
+
+               /* disable manual VCO band selection */
+               UW2453_REGWRITE(3, 0x7602),
+
+               /* enable manual VCO band selection, configure current level */
+               UW2453_REGWRITE(3, 0x46063),
+       };
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+       if (r)
+               return r;
+
+       r = uw2453_init_mode(chip);
+       if (r)
+               return r;
+
+       /* Try all standard VCO configuration settings on channel 1 */
+       for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+               /* Configure synthesizer for channel 1 */
+               r = uw2453_synth_set_channel(chip, 1, false);
+               if (r)
+                       return r;
+
+               /* Write VCO config */
+               r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+               if (r)
+                       return r;
+
+               /* ack interrupt event */
+               r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+               if (r)
+                       return r;
+
+               /* check interrupt status */
+               r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+               if (r)
+                       return r;
+
+               if (!(intr_status & 0xf)) {
+                       dev_dbg_f(zd_chip_dev(chip),
+                               "PLL locked on configuration %d\n", i);
+                       found_config = i;
+                       break;
+               }
+       }
+
+       if (found_config == -1) {
+               /* autocal */
+               dev_dbg_f(zd_chip_dev(chip),
+                       "PLL did not lock, using autocal\n");
+
+               r = uw2453_synth_set_channel(chip, 1, true);
+               if (r)
+                       return r;
+
+               r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+               if (r)
+                       return r;
+       }
+
+       /* To match the vendor driver behaviour, we use the configuration after
+        * the one that produced a lock. */
+       UW2453_PRIV(rf)->config = found_config + 1;
+
+       return zd_iowrite16_locked(chip, 0x06, ZD_CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+       int r;
+       u16 vco_cfg;
+       int config = UW2453_PRIV(rf)->config;
+       bool autocal = (config == -1);
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR80,  0x30 }, { ZD_CR81,  0x30 }, { ZD_CR79,  0x58 },
+               { ZD_CR12,  0xf0 }, { ZD_CR77,  0x1b }, { ZD_CR78,  0x58 },
+       };
+
+       r = uw2453_synth_set_channel(chip, channel, autocal);
+       if (r)
+               return r;
+
+       if (autocal)
+               vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+       else
+               vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+       r = uw2453_write_vco_cfg(chip, vco_cfg);
+       if (r)
+               return r;
+
+       r = uw2453_init_mode(chip);
+       if (r)
+               return r;
+
+       r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       if (r)
+               return r;
+
+       r = uw2453_set_tx_gain_level(chip, channel);
+       if (r)
+               return r;
+
+       return zd_iowrite16_locked(chip, 0x06, ZD_CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x00 }, { ZD_CR251, 0x3f },
+       };
+
+       /* enter RXTX mode */
+       r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+       if (r)
+               return r;
+
+       if (zd_chip_is_zd1211b(chip))
+               ioreqs[1].value = 0x7f;
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+       int r;
+       struct zd_chip *chip = zd_rf_to_chip(rf);
+       static const struct zd_ioreq16 ioreqs[] = {
+               { ZD_CR11,  0x04 }, { ZD_CR251, 0x2f },
+       };
+
+       /* enter IDLE mode */
+       /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+       r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+       if (r)
+               return r;
+
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+       kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+       rf->init_hw = uw2453_init_hw;
+       rf->set_channel = uw2453_set_channel;
+       rf->switch_radio_on = uw2453_switch_radio_on;
+       rf->switch_radio_off = uw2453_switch_radio_off;
+       rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+       rf->clear = uw2453_clear;
+       /* we have our own TX integration code */
+       rf->update_channel_int = 0;
+
+       rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+       if (rf->priv == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
new file mode 100644 (file)
index 0000000..a912dc0
--- /dev/null
@@ -0,0 +1,2060 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#include <net/mac80211.h>
+#include <asm/unaligned.h>
+
+#include "zd_def.h"
+#include "zd_mac.h"
+#include "zd_usb.h"
+
+static struct usb_device_id usb_ids[] = {
+       /* ZD1211 */
+       { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x14ea, 0xab10), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x157e, 0x3207), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
+       { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
+       /* ZD1211B */
+       { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x2019, 0xed01), .driver_info = DEVICE_ZD1211B },
+       /* "Driverless" devices that need ejecting */
+       { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
+       { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
+       {}
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip.");
+MODULE_AUTHOR("Ulrich Kunitz");
+MODULE_AUTHOR("Daniel Drake");
+MODULE_VERSION("1.0");
+MODULE_DEVICE_TABLE(usb, usb_ids);
+
+#define FW_ZD1211_PREFIX       "zd1211/zd1211_"
+#define FW_ZD1211B_PREFIX      "zd1211/zd1211b_"
+
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+                           unsigned int count);
+
+/* USB device initialization */
+static void int_urb_complete(struct urb *urb);
+
+static int request_fw_file(
+       const struct firmware **fw, const char *name, struct device *device)
+{
+       int r;
+
+       dev_dbg_f(device, "fw name %s\n", name);
+
+       r = request_firmware(fw, name, device);
+       if (r)
+               dev_err(device,
+                      "Could not load firmware file %s. Error number %d\n",
+                      name, r);
+       return r;
+}
+
+static inline u16 get_bcdDevice(const struct usb_device *udev)
+{
+       return le16_to_cpu(udev->descriptor.bcdDevice);
+}
+
+enum upload_code_flags {
+       REBOOT = 1,
+};
+
+/* Ensures that MAX_TRANSFER_SIZE is even. */
+#define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1)
+
+static int upload_code(struct usb_device *udev,
+       const u8 *data, size_t size, u16 code_offset, int flags)
+{
+       u8 *p;
+       int r;
+
+       /* USB request blocks need "kmalloced" buffers.
+        */
+       p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL);
+       if (!p) {
+               r = -ENOMEM;
+               goto error;
+       }
+
+       size &= ~1;
+       while (size > 0) {
+               size_t transfer_size = size <= MAX_TRANSFER_SIZE ?
+                       size : MAX_TRANSFER_SIZE;
+
+               dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size);
+
+               memcpy(p, data, transfer_size);
+               r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       USB_REQ_FIRMWARE_DOWNLOAD,
+                       USB_DIR_OUT | USB_TYPE_VENDOR,
+                       code_offset, 0, p, transfer_size, 1000 /* ms */);
+               if (r < 0) {
+                       dev_err(&udev->dev,
+                              "USB control request for firmware upload"
+                              " failed. Error number %d\n", r);
+                       goto error;
+               }
+               transfer_size = r & ~1;
+
+               size -= transfer_size;
+               data += transfer_size;
+               code_offset += transfer_size/sizeof(u16);
+       }
+
+       if (flags & REBOOT) {
+               u8 ret;
+
+               /* Use "DMA-aware" buffer. */
+               r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                       USB_REQ_FIRMWARE_CONFIRM,
+                       USB_DIR_IN | USB_TYPE_VENDOR,
+                       0, 0, p, sizeof(ret), 5000 /* ms */);
+               if (r != sizeof(ret)) {
+                       dev_err(&udev->dev,
+                               "control request firmeware confirmation failed."
+                               " Return value %d\n", r);
+                       if (r >= 0)
+                               r = -ENODEV;
+                       goto error;
+               }
+               ret = p[0];
+               if (ret & 0x80) {
+                       dev_err(&udev->dev,
+                               "Internal error while downloading."
+                               " Firmware confirm return value %#04x\n",
+                               (unsigned int)ret);
+                       r = -ENODEV;
+                       goto error;
+               }
+               dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n",
+                       (unsigned int)ret);
+       }
+
+       r = 0;
+error:
+       kfree(p);
+       return r;
+}
+
+static u16 get_word(const void *data, u16 offset)
+{
+       const __le16 *p = data;
+       return le16_to_cpu(p[offset]);
+}
+
+static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size,
+                      const char* postfix)
+{
+       scnprintf(buffer, size, "%s%s",
+               usb->is_zd1211b ?
+                       FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX,
+               postfix);
+       return buffer;
+}
+
+static int handle_version_mismatch(struct zd_usb *usb,
+       const struct firmware *ub_fw)
+{
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       const struct firmware *ur_fw = NULL;
+       int offset;
+       int r = 0;
+       char fw_name[128];
+
+       r = request_fw_file(&ur_fw,
+               get_fw_name(usb, fw_name, sizeof(fw_name), "ur"),
+               &udev->dev);
+       if (r)
+               goto error;
+
+       r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START, REBOOT);
+       if (r)
+               goto error;
+
+       offset = (E2P_BOOT_CODE_OFFSET * sizeof(u16));
+       r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset,
+               E2P_START + E2P_BOOT_CODE_OFFSET, REBOOT);
+
+       /* At this point, the vendor driver downloads the whole firmware
+        * image, hacks around with version IDs, and uploads it again,
+        * completely overwriting the boot code. We do not do this here as
+        * it is not required on any tested devices, and it is suspected to
+        * cause problems. */
+error:
+       release_firmware(ur_fw);
+       return r;
+}
+
+static int upload_firmware(struct zd_usb *usb)
+{
+       int r;
+       u16 fw_bcdDevice;
+       u16 bcdDevice;
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       const struct firmware *ub_fw = NULL;
+       const struct firmware *uph_fw = NULL;
+       char fw_name[128];
+
+       bcdDevice = get_bcdDevice(udev);
+
+       r = request_fw_file(&ub_fw,
+               get_fw_name(usb, fw_name, sizeof(fw_name), "ub"),
+               &udev->dev);
+       if (r)
+               goto error;
+
+       fw_bcdDevice = get_word(ub_fw->data, E2P_DATA_OFFSET);
+
+       if (fw_bcdDevice != bcdDevice) {
+               dev_info(&udev->dev,
+                       "firmware version %#06x and device bootcode version "
+                       "%#06x differ\n", fw_bcdDevice, bcdDevice);
+               if (bcdDevice <= 0x4313)
+                       dev_warn(&udev->dev, "device has old bootcode, please "
+                               "report success or failure\n");
+
+               r = handle_version_mismatch(usb, ub_fw);
+               if (r)
+                       goto error;
+       } else {
+               dev_dbg_f(&udev->dev,
+                       "firmware device id %#06x is equal to the "
+                       "actual device id\n", fw_bcdDevice);
+       }
+
+
+       r = request_fw_file(&uph_fw,
+               get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"),
+               &udev->dev);
+       if (r)
+               goto error;
+
+       r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START, REBOOT);
+       if (r) {
+               dev_err(&udev->dev,
+                       "Could not upload firmware code uph. Error number %d\n",
+                       r);
+       }
+
+       /* FALL-THROUGH */
+error:
+       release_firmware(ub_fw);
+       release_firmware(uph_fw);
+       return r;
+}
+
+MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ur");
+MODULE_FIRMWARE(FW_ZD1211_PREFIX "ur");
+MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ub");
+MODULE_FIRMWARE(FW_ZD1211_PREFIX "ub");
+MODULE_FIRMWARE(FW_ZD1211B_PREFIX "uphr");
+MODULE_FIRMWARE(FW_ZD1211_PREFIX "uphr");
+
+/* Read data from device address space using "firmware interface" which does
+ * not require firmware to be loaded. */
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
+{
+       int r;
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       u8 *buf;
+
+       /* Use "DMA-aware" buffer. */
+       buf = kmalloc(len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+               USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0,
+               buf, len, 5000);
+       if (r < 0) {
+               dev_err(&udev->dev,
+                       "read over firmware interface failed: %d\n", r);
+               goto exit;
+       } else if (r != len) {
+               dev_err(&udev->dev,
+                       "incomplete read over firmware interface: %d/%d\n",
+                       r, len);
+               r = -EIO;
+               goto exit;
+       }
+       r = 0;
+       memcpy(data, buf, len);
+exit:
+       kfree(buf);
+       return r;
+}
+
+#define urb_dev(urb) (&(urb)->dev->dev)
+
+static inline void handle_regs_int_override(struct urb *urb)
+{
+       struct zd_usb *usb = urb->context;
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock(&intr->lock);
+       if (atomic_read(&intr->read_regs_enabled)) {
+               atomic_set(&intr->read_regs_enabled, 0);
+               intr->read_regs_int_overridden = 1;
+               complete(&intr->read_regs.completion);
+       }
+       spin_unlock(&intr->lock);
+}
+
+static inline void handle_regs_int(struct urb *urb)
+{
+       struct zd_usb *usb = urb->context;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       int len;
+       u16 int_num;
+
+       ZD_ASSERT(in_interrupt());
+       spin_lock(&intr->lock);
+
+       int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
+       if (int_num == CR_INTERRUPT) {
+               struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
+               spin_lock(&mac->lock);
+               memcpy(&mac->intr_buffer, urb->transfer_buffer,
+                               USB_MAX_EP_INT_BUFFER);
+               spin_unlock(&mac->lock);
+               schedule_work(&mac->process_intr);
+       } else if (atomic_read(&intr->read_regs_enabled)) {
+               len = urb->actual_length;
+               intr->read_regs.length = urb->actual_length;
+               if (len > sizeof(intr->read_regs.buffer))
+                       len = sizeof(intr->read_regs.buffer);
+
+               memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
+
+               /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
+                * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
+                * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
+                * retry unhandled. Next read-reg command then might catch
+                * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
+                */
+               if (!check_read_regs(usb, intr->read_regs.req,
+                                               intr->read_regs.req_count))
+                       goto out;
+
+               atomic_set(&intr->read_regs_enabled, 0);
+               intr->read_regs_int_overridden = 0;
+               complete(&intr->read_regs.completion);
+
+               goto out;
+       }
+
+out:
+       spin_unlock(&intr->lock);
+
+       /* CR_INTERRUPT might override read_reg too. */
+       if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
+               handle_regs_int_override(urb);
+}
+
+static void int_urb_complete(struct urb *urb)
+{
+       int r;
+       struct usb_int_header *hdr;
+       struct zd_usb *usb;
+       struct zd_usb_interrupt *intr;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+       case -EINVAL:
+       case -ENODEV:
+       case -ENOENT:
+       case -ECONNRESET:
+       case -EPIPE:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               return;
+       default:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               goto resubmit;
+       }
+
+       if (urb->actual_length < sizeof(hdr)) {
+               dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb);
+               goto resubmit;
+       }
+
+       hdr = urb->transfer_buffer;
+       if (hdr->type != USB_INT_TYPE) {
+               dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb);
+               goto resubmit;
+       }
+
+       /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
+        * pending USB_INT_ID_REGS causing read command timeout.
+        */
+       usb = urb->context;
+       intr = &usb->intr;
+       if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
+               handle_regs_int_override(urb);
+
+       switch (hdr->id) {
+       case USB_INT_ID_REGS:
+               handle_regs_int(urb);
+               break;
+       case USB_INT_ID_RETRY_FAILED:
+               zd_mac_tx_failed(urb);
+               break;
+       default:
+               dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb,
+                       (unsigned int)hdr->id);
+               goto resubmit;
+       }
+
+resubmit:
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r) {
+               dev_dbg_f(urb_dev(urb), "error: resubmit urb %p err code %d\n",
+                         urb, r);
+               /* TODO: add worker to reset intr->urb */
+       }
+       return;
+}
+
+static inline int int_urb_interval(struct usb_device *udev)
+{
+       switch (udev->speed) {
+       case USB_SPEED_HIGH:
+               return 4;
+       case USB_SPEED_LOW:
+               return 10;
+       case USB_SPEED_FULL:
+       default:
+               return 1;
+       }
+}
+
+static inline int usb_int_enabled(struct zd_usb *usb)
+{
+       unsigned long flags;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct urb *urb;
+
+       spin_lock_irqsave(&intr->lock, flags);
+       urb = intr->urb;
+       spin_unlock_irqrestore(&intr->lock, flags);
+       return urb != NULL;
+}
+
+int zd_usb_enable_int(struct zd_usb *usb)
+{
+       int r;
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct urb *urb;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb) {
+               r = -ENOMEM;
+               goto out;
+       }
+
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&intr->lock);
+       if (intr->urb) {
+               spin_unlock_irq(&intr->lock);
+               r = 0;
+               goto error_free_urb;
+       }
+       intr->urb = urb;
+       spin_unlock_irq(&intr->lock);
+
+       r = -ENOMEM;
+       intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER,
+                                         GFP_KERNEL, &intr->buffer_dma);
+       if (!intr->buffer) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "couldn't allocate transfer_buffer\n");
+               goto error_set_urb_null;
+       }
+
+       usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN),
+                        intr->buffer, USB_MAX_EP_INT_BUFFER,
+                        int_urb_complete, usb,
+                        intr->interval);
+       urb->transfer_dma = intr->buffer_dma;
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
+       r = usb_submit_urb(urb, GFP_KERNEL);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "Couldn't submit urb. Error number %d\n", r);
+               goto error;
+       }
+
+       return 0;
+error:
+       usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
+                         intr->buffer, intr->buffer_dma);
+error_set_urb_null:
+       spin_lock_irq(&intr->lock);
+       intr->urb = NULL;
+       spin_unlock_irq(&intr->lock);
+error_free_urb:
+       usb_free_urb(urb);
+out:
+       return r;
+}
+
+void zd_usb_disable_int(struct zd_usb *usb)
+{
+       unsigned long flags;
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct urb *urb;
+       void *buffer;
+       dma_addr_t buffer_dma;
+
+       spin_lock_irqsave(&intr->lock, flags);
+       urb = intr->urb;
+       if (!urb) {
+               spin_unlock_irqrestore(&intr->lock, flags);
+               return;
+       }
+       intr->urb = NULL;
+       buffer = intr->buffer;
+       buffer_dma = intr->buffer_dma;
+       intr->buffer = NULL;
+       spin_unlock_irqrestore(&intr->lock, flags);
+
+       usb_kill_urb(urb);
+       dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb);
+       usb_free_urb(urb);
+
+       if (buffer)
+               usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
+                                 buffer, buffer_dma);
+}
+
+static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
+                            unsigned int length)
+{
+       int i;
+       const struct rx_length_info *length_info;
+
+       if (length < sizeof(struct rx_length_info)) {
+               /* It's not a complete packet anyhow. */
+               dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
+                                          length);
+               return;
+       }
+       length_info = (struct rx_length_info *)
+               (buffer + length - sizeof(struct rx_length_info));
+
+       /* It might be that three frames are merged into a single URB
+        * transaction. We have to check for the length info tag.
+        *
+        * While testing we discovered that length_info might be unaligned,
+        * because if USB transactions are merged, the last packet will not
+        * be padded. Unaligned access might also happen if the length_info
+        * structure is not present.
+        */
+       if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG)
+       {
+               unsigned int l, k, n;
+               for (i = 0, l = 0;; i++) {
+                       k = get_unaligned_le16(&length_info->length[i]);
+                       if (k == 0)
+                               return;
+                       n = l+k;
+                       if (n > length)
+                               return;
+                       zd_mac_rx(zd_usb_to_hw(usb), buffer+l, k);
+                       if (i >= 2)
+                               return;
+                       l = (n+3) & ~3;
+               }
+       } else {
+               zd_mac_rx(zd_usb_to_hw(usb), buffer, length);
+       }
+}
+
+static void rx_urb_complete(struct urb *urb)
+{
+       int r;
+       struct zd_usb *usb;
+       struct zd_usb_rx *rx;
+       const u8 *buffer;
+       unsigned int length;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+       case -EINVAL:
+       case -ENODEV:
+       case -ENOENT:
+       case -ECONNRESET:
+       case -EPIPE:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               return;
+       default:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               goto resubmit;
+       }
+
+       buffer = urb->transfer_buffer;
+       length = urb->actual_length;
+       usb = urb->context;
+       rx = &usb->rx;
+
+       tasklet_schedule(&rx->reset_timer_tasklet);
+
+       if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
+               /* If there is an old first fragment, we don't care. */
+               dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
+               ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment));
+               spin_lock(&rx->lock);
+               memcpy(rx->fragment, buffer, length);
+               rx->fragment_length = length;
+               spin_unlock(&rx->lock);
+               goto resubmit;
+       }
+
+       spin_lock(&rx->lock);
+       if (rx->fragment_length > 0) {
+               /* We are on a second fragment, we believe */
+               ZD_ASSERT(length + rx->fragment_length <=
+                         ARRAY_SIZE(rx->fragment));
+               dev_dbg_f(urb_dev(urb), "*** second fragment ***\n");
+               memcpy(rx->fragment+rx->fragment_length, buffer, length);
+               handle_rx_packet(usb, rx->fragment,
+                                rx->fragment_length + length);
+               rx->fragment_length = 0;
+               spin_unlock(&rx->lock);
+       } else {
+               spin_unlock(&rx->lock);
+               handle_rx_packet(usb, buffer, length);
+       }
+
+resubmit:
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r)
+               dev_dbg_f(urb_dev(urb), "urb %p resubmit error %d\n", urb, r);
+}
+
+static struct urb *alloc_rx_urb(struct zd_usb *usb)
+{
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       struct urb *urb;
+       void *buffer;
+
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb)
+               return NULL;
+       buffer = usb_alloc_coherent(udev, USB_MAX_RX_SIZE, GFP_KERNEL,
+                                   &urb->transfer_dma);
+       if (!buffer) {
+               usb_free_urb(urb);
+               return NULL;
+       }
+
+       usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN),
+                         buffer, USB_MAX_RX_SIZE,
+                         rx_urb_complete, usb);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       return urb;
+}
+
+static void free_rx_urb(struct urb *urb)
+{
+       if (!urb)
+               return;
+       usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+                         urb->transfer_buffer, urb->transfer_dma);
+       usb_free_urb(urb);
+}
+
+static int __zd_usb_enable_rx(struct zd_usb *usb)
+{
+       int i, r;
+       struct zd_usb_rx *rx = &usb->rx;
+       struct urb **urbs;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       r = -ENOMEM;
+       urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
+       if (!urbs)
+               goto error;
+       for (i = 0; i < RX_URBS_COUNT; i++) {
+               urbs[i] = alloc_rx_urb(usb);
+               if (!urbs[i])
+                       goto error;
+       }
+
+       ZD_ASSERT(!irqs_disabled());
+       spin_lock_irq(&rx->lock);
+       if (rx->urbs) {
+               spin_unlock_irq(&rx->lock);
+               r = 0;
+               goto error;
+       }
+       rx->urbs = urbs;
+       rx->urbs_count = RX_URBS_COUNT;
+       spin_unlock_irq(&rx->lock);
+
+       for (i = 0; i < RX_URBS_COUNT; i++) {
+               r = usb_submit_urb(urbs[i], GFP_KERNEL);
+               if (r)
+                       goto error_submit;
+       }
+
+       return 0;
+error_submit:
+       for (i = 0; i < RX_URBS_COUNT; i++) {
+               usb_kill_urb(urbs[i]);
+       }
+       spin_lock_irq(&rx->lock);
+       rx->urbs = NULL;
+       rx->urbs_count = 0;
+       spin_unlock_irq(&rx->lock);
+error:
+       if (urbs) {
+               for (i = 0; i < RX_URBS_COUNT; i++)
+                       free_rx_urb(urbs[i]);
+       }
+       return r;
+}
+
+int zd_usb_enable_rx(struct zd_usb *usb)
+{
+       int r;
+       struct zd_usb_rx *rx = &usb->rx;
+
+       mutex_lock(&rx->setup_mutex);
+       r = __zd_usb_enable_rx(usb);
+       mutex_unlock(&rx->setup_mutex);
+
+       zd_usb_reset_rx_idle_timer(usb);
+
+       return r;
+}
+
+static void __zd_usb_disable_rx(struct zd_usb *usb)
+{
+       int i;
+       unsigned long flags;
+       struct urb **urbs;
+       unsigned int count;
+       struct zd_usb_rx *rx = &usb->rx;
+
+       spin_lock_irqsave(&rx->lock, flags);
+       urbs = rx->urbs;
+       count = rx->urbs_count;
+       spin_unlock_irqrestore(&rx->lock, flags);
+       if (!urbs)
+               return;
+
+       for (i = 0; i < count; i++) {
+               usb_kill_urb(urbs[i]);
+               free_rx_urb(urbs[i]);
+       }
+       kfree(urbs);
+
+       spin_lock_irqsave(&rx->lock, flags);
+       rx->urbs = NULL;
+       rx->urbs_count = 0;
+       spin_unlock_irqrestore(&rx->lock, flags);
+}
+
+void zd_usb_disable_rx(struct zd_usb *usb)
+{
+       struct zd_usb_rx *rx = &usb->rx;
+
+       mutex_lock(&rx->setup_mutex);
+       __zd_usb_disable_rx(usb);
+       mutex_unlock(&rx->setup_mutex);
+
+       tasklet_kill(&rx->reset_timer_tasklet);
+       cancel_delayed_work_sync(&rx->idle_work);
+}
+
+static void zd_usb_reset_rx(struct zd_usb *usb)
+{
+       bool do_reset;
+       struct zd_usb_rx *rx = &usb->rx;
+       unsigned long flags;
+
+       mutex_lock(&rx->setup_mutex);
+
+       spin_lock_irqsave(&rx->lock, flags);
+       do_reset = rx->urbs != NULL;
+       spin_unlock_irqrestore(&rx->lock, flags);
+
+       if (do_reset) {
+               __zd_usb_disable_rx(usb);
+               __zd_usb_enable_rx(usb);
+       }
+
+       mutex_unlock(&rx->setup_mutex);
+
+       if (do_reset)
+               zd_usb_reset_rx_idle_timer(usb);
+}
+
+/**
+ * zd_usb_disable_tx - disable transmission
+ * @usb: the zd1211rw-private USB structure
+ *
+ * Frees all URBs in the free list and marks the transmission as disabled.
+ */
+void zd_usb_disable_tx(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+       unsigned long flags;
+
+       atomic_set(&tx->enabled, 0);
+
+       /* kill all submitted tx-urbs */
+       usb_kill_anchored_urbs(&tx->submitted);
+
+       spin_lock_irqsave(&tx->lock, flags);
+       WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
+       WARN_ON(tx->submitted_urbs != 0);
+       tx->submitted_urbs = 0;
+       spin_unlock_irqrestore(&tx->lock, flags);
+
+       /* The stopped state is ignored, relying on ieee80211_wake_queues()
+        * in a potentionally following zd_usb_enable_tx().
+        */
+}
+
+/**
+ * zd_usb_enable_tx - enables transmission
+ * @usb: a &struct zd_usb pointer
+ *
+ * This function enables transmission and prepares the &zd_usb_tx data
+ * structure.
+ */
+void zd_usb_enable_tx(struct zd_usb *usb)
+{
+       unsigned long flags;
+       struct zd_usb_tx *tx = &usb->tx;
+
+       spin_lock_irqsave(&tx->lock, flags);
+       atomic_set(&tx->enabled, 1);
+       tx->submitted_urbs = 0;
+       ieee80211_wake_queues(zd_usb_to_hw(usb));
+       tx->stopped = 0;
+       spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static void tx_dec_submitted_urbs(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tx->lock, flags);
+       --tx->submitted_urbs;
+       if (tx->stopped && tx->submitted_urbs <= ZD_USB_TX_LOW) {
+               ieee80211_wake_queues(zd_usb_to_hw(usb));
+               tx->stopped = 0;
+       }
+       spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static void tx_inc_submitted_urbs(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tx->lock, flags);
+       ++tx->submitted_urbs;
+       if (!tx->stopped && tx->submitted_urbs > ZD_USB_TX_HIGH) {
+               ieee80211_stop_queues(zd_usb_to_hw(usb));
+               tx->stopped = 1;
+       }
+       spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+/**
+ * tx_urb_complete - completes the execution of an URB
+ * @urb: a URB
+ *
+ * This function is called if the URB has been transferred to a device or an
+ * error has happened.
+ */
+static void tx_urb_complete(struct urb *urb)
+{
+       int r;
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *info;
+       struct zd_usb *usb;
+       struct zd_usb_tx *tx;
+
+       skb = (struct sk_buff *)urb->context;
+       info = IEEE80211_SKB_CB(skb);
+       /*
+        * grab 'usb' pointer before handing off the skb (since
+        * it might be freed by zd_mac_tx_to_dev or mac80211)
+        */
+       usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
+       tx = &usb->tx;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+       case -EINVAL:
+       case -ENODEV:
+       case -ENOENT:
+       case -ECONNRESET:
+       case -EPIPE:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               break;
+       default:
+               dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+               goto resubmit;
+       }
+free_urb:
+       skb_unlink(skb, &usb->tx.submitted_skbs);
+       zd_mac_tx_to_dev(skb, urb->status);
+       usb_free_urb(urb);
+       tx_dec_submitted_urbs(usb);
+       return;
+resubmit:
+       usb_anchor_urb(urb, &tx->submitted);
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r) {
+               usb_unanchor_urb(urb);
+               dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
+               goto free_urb;
+       }
+}
+
+/**
+ * zd_usb_tx: initiates transfer of a frame of the device
+ *
+ * @usb: the zd1211rw-private USB structure
+ * @skb: a &struct sk_buff pointer
+ *
+ * This function tranmits a frame to the device. It doesn't wait for
+ * completion. The frame must contain the control set and have all the
+ * control set information available.
+ *
+ * The function returns 0 if the transfer has been successfully initiated.
+ */
+int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
+{
+       int r;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct usb_device *udev = zd_usb_to_usbdev(usb);
+       struct urb *urb;
+       struct zd_usb_tx *tx = &usb->tx;
+
+       if (!atomic_read(&tx->enabled)) {
+               r = -ENOENT;
+               goto out;
+       }
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               r = -ENOMEM;
+               goto out;
+       }
+
+       usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
+                         skb->data, skb->len, tx_urb_complete, skb);
+
+       info->rate_driver_data[1] = (void *)jiffies;
+       skb_queue_tail(&tx->submitted_skbs, skb);
+       usb_anchor_urb(urb, &tx->submitted);
+
+       r = usb_submit_urb(urb, GFP_ATOMIC);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r);
+               usb_unanchor_urb(urb);
+               skb_unlink(skb, &tx->submitted_skbs);
+               goto error;
+       }
+       tx_inc_submitted_urbs(usb);
+       return 0;
+error:
+       usb_free_urb(urb);
+out:
+       return r;
+}
+
+static bool zd_tx_timeout(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+       struct sk_buff_head *q = &tx->submitted_skbs;
+       struct sk_buff *skb, *skbnext;
+       struct ieee80211_tx_info *info;
+       unsigned long flags, trans_start;
+       bool have_timedout = false;
+
+       spin_lock_irqsave(&q->lock, flags);
+       skb_queue_walk_safe(q, skb, skbnext) {
+               info = IEEE80211_SKB_CB(skb);
+               trans_start = (unsigned long)info->rate_driver_data[1];
+
+               if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) {
+                       have_timedout = true;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&q->lock, flags);
+
+       return have_timedout;
+}
+
+static void zd_tx_watchdog_handler(struct work_struct *work)
+{
+       struct zd_usb *usb =
+               container_of(work, struct zd_usb, tx.watchdog_work.work);
+       struct zd_usb_tx *tx = &usb->tx;
+
+       if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled)
+               goto out;
+       if (!zd_tx_timeout(usb))
+               goto out;
+
+       /* TX halted, try reset */
+       dev_warn(zd_usb_dev(usb), "TX-stall detected, resetting device...");
+
+       usb_queue_reset_device(usb->intf);
+
+       /* reset will stop this worker, don't rearm */
+       return;
+out:
+       queue_delayed_work(zd_workqueue, &tx->watchdog_work,
+                          ZD_TX_WATCHDOG_INTERVAL);
+}
+
+void zd_tx_watchdog_enable(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+
+       if (!tx->watchdog_enabled) {
+               dev_dbg_f(zd_usb_dev(usb), "\n");
+               queue_delayed_work(zd_workqueue, &tx->watchdog_work,
+                                  ZD_TX_WATCHDOG_INTERVAL);
+               tx->watchdog_enabled = 1;
+       }
+}
+
+void zd_tx_watchdog_disable(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+
+       if (tx->watchdog_enabled) {
+               dev_dbg_f(zd_usb_dev(usb), "\n");
+               tx->watchdog_enabled = 0;
+               cancel_delayed_work_sync(&tx->watchdog_work);
+       }
+}
+
+static void zd_rx_idle_timer_handler(struct work_struct *work)
+{
+       struct zd_usb *usb =
+               container_of(work, struct zd_usb, rx.idle_work.work);
+       struct zd_mac *mac = zd_usb_to_mac(usb);
+
+       if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+               return;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       /* 30 seconds since last rx, reset rx */
+       zd_usb_reset_rx(usb);
+}
+
+static void zd_usb_reset_rx_idle_timer_tasklet(unsigned long param)
+{
+       struct zd_usb *usb = (struct zd_usb *)param;
+
+       zd_usb_reset_rx_idle_timer(usb);
+}
+
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
+{
+       struct zd_usb_rx *rx = &usb->rx;
+
+       mod_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
+}
+
+static inline void init_usb_interrupt(struct zd_usb *usb)
+{
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock_init(&intr->lock);
+       intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
+       init_completion(&intr->read_regs.completion);
+       atomic_set(&intr->read_regs_enabled, 0);
+       intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
+}
+
+static inline void init_usb_rx(struct zd_usb *usb)
+{
+       struct zd_usb_rx *rx = &usb->rx;
+
+       spin_lock_init(&rx->lock);
+       mutex_init(&rx->setup_mutex);
+       if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
+               rx->usb_packet_size = 512;
+       } else {
+               rx->usb_packet_size = 64;
+       }
+       ZD_ASSERT(rx->fragment_length == 0);
+       INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
+       rx->reset_timer_tasklet.func = zd_usb_reset_rx_idle_timer_tasklet;
+       rx->reset_timer_tasklet.data = (unsigned long)usb;
+}
+
+static inline void init_usb_tx(struct zd_usb *usb)
+{
+       struct zd_usb_tx *tx = &usb->tx;
+
+       spin_lock_init(&tx->lock);
+       atomic_set(&tx->enabled, 0);
+       tx->stopped = 0;
+       skb_queue_head_init(&tx->submitted_skbs);
+       init_usb_anchor(&tx->submitted);
+       tx->submitted_urbs = 0;
+       tx->watchdog_enabled = 0;
+       INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler);
+}
+
+void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
+                struct usb_interface *intf)
+{
+       memset(usb, 0, sizeof(*usb));
+       usb->intf = usb_get_intf(intf);
+       usb_set_intfdata(usb->intf, hw);
+       init_usb_anchor(&usb->submitted_cmds);
+       init_usb_interrupt(usb);
+       init_usb_tx(usb);
+       init_usb_rx(usb);
+}
+
+void zd_usb_clear(struct zd_usb *usb)
+{
+       usb_set_intfdata(usb->intf, NULL);
+       usb_put_intf(usb->intf);
+       ZD_MEMCLEAR(usb, sizeof(*usb));
+       /* FIXME: usb_interrupt, usb_tx, usb_rx? */
+}
+
+static const char *speed(enum usb_device_speed speed)
+{
+       switch (speed) {
+       case USB_SPEED_LOW:
+               return "low";
+       case USB_SPEED_FULL:
+               return "full";
+       case USB_SPEED_HIGH:
+               return "high";
+       default:
+               return "unknown speed";
+       }
+}
+
+static int scnprint_id(struct usb_device *udev, char *buffer, size_t size)
+{
+       return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s",
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               get_bcdDevice(udev),
+               speed(udev->speed));
+}
+
+int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size)
+{
+       struct usb_device *udev = interface_to_usbdev(usb->intf);
+       return scnprint_id(udev, buffer, size);
+}
+
+#ifdef DEBUG
+static void print_id(struct usb_device *udev)
+{
+       char buffer[40];
+
+       scnprint_id(udev, buffer, sizeof(buffer));
+       buffer[sizeof(buffer)-1] = 0;
+       dev_dbg_f(&udev->dev, "%s\n", buffer);
+}
+#else
+#define print_id(udev) do { } while (0)
+#endif
+
+static int eject_installer(struct usb_interface *intf)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_host_interface *iface_desc = &intf->altsetting[0];
+       struct usb_endpoint_descriptor *endpoint;
+       unsigned char *cmd;
+       u8 bulk_out_ep;
+       int r;
+
+       /* Find bulk out endpoint */
+       for (r = 1; r >= 0; r--) {
+               endpoint = &iface_desc->endpoint[r].desc;
+               if (usb_endpoint_dir_out(endpoint) &&
+                   usb_endpoint_xfer_bulk(endpoint)) {
+                       bulk_out_ep = endpoint->bEndpointAddress;
+                       break;
+               }
+       }
+       if (r == -1) {
+               dev_err(&udev->dev,
+                       "zd1211rw: Could not find bulk out endpoint\n");
+               return -ENODEV;
+       }
+
+       cmd = kzalloc(31, GFP_KERNEL);
+       if (cmd == NULL)
+               return -ENODEV;
+
+       /* USB bulk command block */
+       cmd[0] = 0x55;  /* bulk command signature */
+       cmd[1] = 0x53;  /* bulk command signature */
+       cmd[2] = 0x42;  /* bulk command signature */
+       cmd[3] = 0x43;  /* bulk command signature */
+       cmd[14] = 6;    /* command length */
+
+       cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */
+       cmd[19] = 0x2;  /* eject disc */
+
+       dev_info(&udev->dev, "Ejecting virtual installer media...\n");
+       r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
+               cmd, 31, NULL, 2000);
+       kfree(cmd);
+       if (r)
+               return r;
+
+       /* At this point, the device disconnects and reconnects with the real
+        * ID numbers. */
+
+       usb_set_intfdata(intf, NULL);
+       return 0;
+}
+
+int zd_usb_init_hw(struct zd_usb *usb)
+{
+       int r;
+       struct zd_mac *mac = zd_usb_to_mac(usb);
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       r = upload_firmware(usb);
+       if (r) {
+               dev_err(zd_usb_dev(usb),
+                      "couldn't load firmware. Error number %d\n", r);
+               return r;
+       }
+
+       r = usb_reset_configuration(zd_usb_to_usbdev(usb));
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "couldn't reset configuration. Error number %d\n", r);
+               return r;
+       }
+
+       r = zd_mac_init_hw(mac->hw);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "couldn't initialize mac. Error number %d\n", r);
+               return r;
+       }
+
+       usb->initialized = 1;
+       return 0;
+}
+
+static int probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       int r;
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct zd_usb *usb;
+       struct ieee80211_hw *hw = NULL;
+
+       print_id(udev);
+
+       if (id->driver_info & DEVICE_INSTALLER)
+               return eject_installer(intf);
+
+       switch (udev->speed) {
+       case USB_SPEED_LOW:
+       case USB_SPEED_FULL:
+       case USB_SPEED_HIGH:
+               break;
+       default:
+               dev_dbg_f(&intf->dev, "Unknown USB speed\n");
+               r = -ENODEV;
+               goto error;
+       }
+
+       r = usb_reset_device(udev);
+       if (r) {
+               dev_err(&intf->dev,
+                       "couldn't reset usb device. Error number %d\n", r);
+               goto error;
+       }
+
+       hw = zd_mac_alloc_hw(intf);
+       if (hw == NULL) {
+               r = -ENOMEM;
+               goto error;
+       }
+
+       usb = &zd_hw_mac(hw)->chip.usb;
+       usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
+
+       r = zd_mac_preinit_hw(hw);
+       if (r) {
+               dev_dbg_f(&intf->dev,
+                        "couldn't initialize mac. Error number %d\n", r);
+               goto error;
+       }
+
+       r = ieee80211_register_hw(hw);
+       if (r) {
+               dev_dbg_f(&intf->dev,
+                        "couldn't register device. Error number %d\n", r);
+               goto error;
+       }
+
+       dev_dbg_f(&intf->dev, "successful\n");
+       dev_info(&intf->dev, "%s\n", wiphy_name(hw->wiphy));
+       return 0;
+error:
+       usb_reset_device(interface_to_usbdev(intf));
+       if (hw) {
+               zd_mac_clear(zd_hw_mac(hw));
+               ieee80211_free_hw(hw);
+       }
+       return r;
+}
+
+static void disconnect(struct usb_interface *intf)
+{
+       struct ieee80211_hw *hw = zd_intf_to_hw(intf);
+       struct zd_mac *mac;
+       struct zd_usb *usb;
+
+       /* Either something really bad happened, or we're just dealing with
+        * a DEVICE_INSTALLER. */
+       if (hw == NULL)
+               return;
+
+       mac = zd_hw_mac(hw);
+       usb = &mac->chip.usb;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       ieee80211_unregister_hw(hw);
+
+       /* Just in case something has gone wrong! */
+       zd_usb_disable_tx(usb);
+       zd_usb_disable_rx(usb);
+       zd_usb_disable_int(usb);
+
+       /* If the disconnect has been caused by a removal of the
+        * driver module, the reset allows reloading of the driver. If the
+        * reset will not be executed here, the upload of the firmware in the
+        * probe function caused by the reloading of the driver will fail.
+        */
+       usb_reset_device(interface_to_usbdev(intf));
+
+       zd_mac_clear(mac);
+       ieee80211_free_hw(hw);
+       dev_dbg(&intf->dev, "disconnected\n");
+}
+
+static void zd_usb_resume(struct zd_usb *usb)
+{
+       struct zd_mac *mac = zd_usb_to_mac(usb);
+       int r;
+
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       r = zd_op_start(zd_usb_to_hw(usb));
+       if (r < 0) {
+               dev_warn(zd_usb_dev(usb), "Device resume failed "
+                        "with error code %d. Retrying...\n", r);
+               if (usb->was_running)
+                       set_bit(ZD_DEVICE_RUNNING, &mac->flags);
+               usb_queue_reset_device(usb->intf);
+               return;
+       }
+
+       if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
+               r = zd_restore_settings(mac);
+               if (r < 0) {
+                       dev_dbg(zd_usb_dev(usb),
+                               "failed to restore settings, %d\n", r);
+                       return;
+               }
+       }
+}
+
+static void zd_usb_stop(struct zd_usb *usb)
+{
+       dev_dbg_f(zd_usb_dev(usb), "\n");
+
+       zd_op_stop(zd_usb_to_hw(usb));
+
+       zd_usb_disable_tx(usb);
+       zd_usb_disable_rx(usb);
+       zd_usb_disable_int(usb);
+
+       usb->initialized = 0;
+}
+
+static int pre_reset(struct usb_interface *intf)
+{
+       struct ieee80211_hw *hw = usb_get_intfdata(intf);
+       struct zd_mac *mac;
+       struct zd_usb *usb;
+
+       if (!hw || intf->condition != USB_INTERFACE_BOUND)
+               return 0;
+
+       mac = zd_hw_mac(hw);
+       usb = &mac->chip.usb;
+
+       usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags);
+
+       zd_usb_stop(usb);
+
+       mutex_lock(&mac->chip.mutex);
+       return 0;
+}
+
+static int post_reset(struct usb_interface *intf)
+{
+       struct ieee80211_hw *hw = usb_get_intfdata(intf);
+       struct zd_mac *mac;
+       struct zd_usb *usb;
+
+       if (!hw || intf->condition != USB_INTERFACE_BOUND)
+               return 0;
+
+       mac = zd_hw_mac(hw);
+       usb = &mac->chip.usb;
+
+       mutex_unlock(&mac->chip.mutex);
+
+       if (usb->was_running)
+               zd_usb_resume(usb);
+       return 0;
+}
+
+static struct usb_driver driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = usb_ids,
+       .probe          = probe,
+       .disconnect     = disconnect,
+       .pre_reset      = pre_reset,
+       .post_reset     = post_reset,
+       .disable_hub_initiated_lpm = 1,
+};
+
+struct workqueue_struct *zd_workqueue;
+
+static int __init usb_init(void)
+{
+       int r;
+
+       pr_debug("%s usb_init()\n", driver.name);
+
+       zd_workqueue = create_singlethread_workqueue(driver.name);
+       if (zd_workqueue == NULL) {
+               printk(KERN_ERR "%s couldn't create workqueue\n", driver.name);
+               return -ENOMEM;
+       }
+
+       r = usb_register(&driver);
+       if (r) {
+               destroy_workqueue(zd_workqueue);
+               printk(KERN_ERR "%s usb_register() failed. Error number %d\n",
+                      driver.name, r);
+               return r;
+       }
+
+       pr_debug("%s initialized\n", driver.name);
+       return 0;
+}
+
+static void __exit usb_exit(void)
+{
+       pr_debug("%s usb_exit()\n", driver.name);
+       usb_deregister(&driver);
+       destroy_workqueue(zd_workqueue);
+}
+
+module_init(usb_init);
+module_exit(usb_exit);
+
+static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len,
+                             int *actual_length, int timeout)
+{
+       /* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in
+        * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint
+        * descriptor.
+        */
+       struct usb_host_endpoint *ep;
+       unsigned int pipe;
+
+       pipe = usb_sndintpipe(udev, EP_REGS_OUT);
+       ep = usb_pipe_endpoint(udev, pipe);
+       if (!ep)
+               return -EINVAL;
+
+       if (usb_endpoint_xfer_int(&ep->desc)) {
+               return usb_interrupt_msg(udev, pipe, data, len,
+                                        actual_length, timeout);
+       } else {
+               pipe = usb_sndbulkpipe(udev, EP_REGS_OUT);
+               return usb_bulk_msg(udev, pipe, data, len, actual_length,
+                                   timeout);
+       }
+}
+
+static int usb_int_regs_length(unsigned int count)
+{
+       return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
+}
+
+static void prepare_read_regs_int(struct zd_usb *usb,
+                                 struct usb_req_read_regs *req,
+                                 unsigned int count)
+{
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock_irq(&intr->lock);
+       atomic_set(&intr->read_regs_enabled, 1);
+       intr->read_regs.req = req;
+       intr->read_regs.req_count = count;
+       reinit_completion(&intr->read_regs.completion);
+       spin_unlock_irq(&intr->lock);
+}
+
+static void disable_read_regs_int(struct zd_usb *usb)
+{
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock_irq(&intr->lock);
+       atomic_set(&intr->read_regs_enabled, 0);
+       spin_unlock_irq(&intr->lock);
+}
+
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+                           unsigned int count)
+{
+       int i;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct read_regs_int *rr = &intr->read_regs;
+       struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+       /* The created block size seems to be larger than expected.
+        * However results appear to be correct.
+        */
+       if (rr->length < usb_int_regs_length(count)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: actual length %d less than expected %d\n",
+                        rr->length, usb_int_regs_length(count));
+               return false;
+       }
+
+       if (rr->length > sizeof(rr->buffer)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: actual length %d exceeds buffer size %zu\n",
+                        rr->length, sizeof(rr->buffer));
+               return false;
+       }
+
+       for (i = 0; i < count; i++) {
+               struct reg_data *rd = &regs->regs[i];
+               if (rd->addr != req->addr[i]) {
+                       dev_dbg_f(zd_usb_dev(usb),
+                                "rd[%d] addr %#06hx expected %#06hx\n", i,
+                                le16_to_cpu(rd->addr),
+                                le16_to_cpu(req->addr[i]));
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static int get_results(struct zd_usb *usb, u16 *values,
+                      struct usb_req_read_regs *req, unsigned int count,
+                      bool *retry)
+{
+       int r;
+       int i;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct read_regs_int *rr = &intr->read_regs;
+       struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+       spin_lock_irq(&intr->lock);
+
+       r = -EIO;
+
+       /* Read failed because firmware bug? */
+       *retry = !!intr->read_regs_int_overridden;
+       if (*retry)
+               goto error_unlock;
+
+       if (!check_read_regs(usb, req, count)) {
+               dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
+               goto error_unlock;
+       }
+
+       for (i = 0; i < count; i++) {
+               struct reg_data *rd = &regs->regs[i];
+               values[i] = le16_to_cpu(rd->value);
+       }
+
+       r = 0;
+error_unlock:
+       spin_unlock_irq(&intr->lock);
+       return r;
+}
+
+int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
+                    const zd_addr_t *addresses, unsigned int count)
+{
+       int r, i, req_len, actual_req_len, try_count = 0;
+       struct usb_device *udev;
+       struct usb_req_read_regs *req = NULL;
+       unsigned long timeout;
+       bool retry = false;
+
+       if (count < 1) {
+               dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
+               return -EINVAL;
+       }
+       if (count > USB_MAX_IOREAD16_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: count %u exceeds possible max %u\n",
+                        count, USB_MAX_IOREAD16_COUNT);
+               return -EINVAL;
+       }
+       if (in_atomic()) {
+               dev_dbg_f(zd_usb_dev(usb),
+                        "error: io in atomic context not supported\n");
+               return -EWOULDBLOCK;
+       }
+       if (!usb_int_enabled(usb)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                         "error: usb interrupt not enabled\n");
+               return -EWOULDBLOCK;
+       }
+
+       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+       BUILD_BUG_ON(sizeof(struct usb_req_read_regs) + USB_MAX_IOREAD16_COUNT *
+                    sizeof(__le16) > sizeof(usb->req_buf));
+       BUG_ON(sizeof(struct usb_req_read_regs) + count * sizeof(__le16) >
+              sizeof(usb->req_buf));
+
+       req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
+       req = (void *)usb->req_buf;
+
+       req->id = cpu_to_le16(USB_REQ_READ_REGS);
+       for (i = 0; i < count; i++)
+               req->addr[i] = cpu_to_le16((u16)addresses[i]);
+
+retry_read:
+       try_count++;
+       udev = zd_usb_to_usbdev(usb);
+       prepare_read_regs_int(usb, req, count);
+       r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in zd_ep_regs_out_msg(). Error number %d\n", r);
+               goto error;
+       }
+       if (req_len != actual_req_len) {
+               dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n"
+                       " req_len %d != actual_req_len %d\n",
+                       req_len, actual_req_len);
+               r = -EIO;
+               goto error;
+       }
+
+       timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion,
+                                             msecs_to_jiffies(50));
+       if (!timeout) {
+               disable_read_regs_int(usb);
+               dev_dbg_f(zd_usb_dev(usb), "read timed out\n");
+               r = -ETIMEDOUT;
+               goto error;
+       }
+
+       r = get_results(usb, values, req, count, &retry);
+       if (retry && try_count < 20) {
+               dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
+                               try_count);
+               goto retry_read;
+       }
+error:
+       return r;
+}
+
+static void iowrite16v_urb_complete(struct urb *urb)
+{
+       struct zd_usb *usb = urb->context;
+
+       if (urb->status && !usb->cmd_error)
+               usb->cmd_error = urb->status;
+
+       if (!usb->cmd_error &&
+                       urb->actual_length != urb->transfer_buffer_length)
+               usb->cmd_error = -EIO;
+}
+
+static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
+{
+       int r = 0;
+       struct urb *urb = usb->urb_async_waiting;
+
+       if (!urb)
+               return 0;
+
+       usb->urb_async_waiting = NULL;
+
+       if (!last)
+               urb->transfer_flags |= URB_NO_INTERRUPT;
+
+       usb_anchor_urb(urb, &usb->submitted_cmds);
+       r = usb_submit_urb(urb, GFP_KERNEL);
+       if (r) {
+               usb_unanchor_urb(urb);
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in usb_submit_urb(). Error number %d\n", r);
+               goto error;
+       }
+
+       /* fall-through with r == 0 */
+error:
+       usb_free_urb(urb);
+       return r;
+}
+
+void zd_usb_iowrite16v_async_start(struct zd_usb *usb)
+{
+       ZD_ASSERT(usb_anchor_empty(&usb->submitted_cmds));
+       ZD_ASSERT(usb->urb_async_waiting == NULL);
+       ZD_ASSERT(!usb->in_async);
+
+       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+
+       usb->in_async = 1;
+       usb->cmd_error = 0;
+       usb->urb_async_waiting = NULL;
+}
+
+int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout)
+{
+       int r;
+
+       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+       ZD_ASSERT(usb->in_async);
+
+       /* Submit last iowrite16v URB */
+       r = zd_submit_waiting_urb(usb, true);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in zd_submit_waiting_usb(). "
+                       "Error number %d\n", r);
+
+               usb_kill_anchored_urbs(&usb->submitted_cmds);
+               goto error;
+       }
+
+       if (timeout)
+               timeout = usb_wait_anchor_empty_timeout(&usb->submitted_cmds,
+                                                       timeout);
+       if (!timeout) {
+               usb_kill_anchored_urbs(&usb->submitted_cmds);
+               if (usb->cmd_error == -ENOENT) {
+                       dev_dbg_f(zd_usb_dev(usb), "timed out");
+                       r = -ETIMEDOUT;
+                       goto error;
+               }
+       }
+
+       r = usb->cmd_error;
+error:
+       usb->in_async = 0;
+       return r;
+}
+
+int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+                           unsigned int count)
+{
+       int r;
+       struct usb_device *udev;
+       struct usb_req_write_regs *req = NULL;
+       int i, req_len;
+       struct urb *urb;
+       struct usb_host_endpoint *ep;
+
+       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+       ZD_ASSERT(usb->in_async);
+
+       if (count == 0)
+               return 0;
+       if (count > USB_MAX_IOWRITE16_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: count %u exceeds possible max %u\n",
+                       count, USB_MAX_IOWRITE16_COUNT);
+               return -EINVAL;
+       }
+       if (in_atomic()) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: io in atomic context not supported\n");
+               return -EWOULDBLOCK;
+       }
+
+       udev = zd_usb_to_usbdev(usb);
+
+       ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT));
+       if (!ep)
+               return -ENOENT;
+
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb)
+               return -ENOMEM;
+
+       req_len = sizeof(struct usb_req_write_regs) +
+                 count * sizeof(struct reg_data);
+       req = kmalloc(req_len, GFP_KERNEL);
+       if (!req) {
+               r = -ENOMEM;
+               goto error;
+       }
+
+       req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
+       for (i = 0; i < count; i++) {
+               struct reg_data *rw  = &req->reg_writes[i];
+               rw->addr = cpu_to_le16((u16)ioreqs[i].addr);
+               rw->value = cpu_to_le16(ioreqs[i].value);
+       }
+
+       /* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode
+        * endpoint is bulk. Select correct type URB by endpoint descriptor.
+        */
+       if (usb_endpoint_xfer_int(&ep->desc))
+               usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
+                                req, req_len, iowrite16v_urb_complete, usb,
+                                ep->desc.bInterval);
+       else
+               usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
+                                 req, req_len, iowrite16v_urb_complete, usb);
+
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       /* Submit previous URB */
+       r = zd_submit_waiting_urb(usb, false);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in zd_submit_waiting_usb(). "
+                       "Error number %d\n", r);
+               goto error;
+       }
+
+       /* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs
+        * of currect batch except for very last.
+        */
+       usb->urb_async_waiting = urb;
+       return 0;
+error:
+       usb_free_urb(urb);
+       return r;
+}
+
+int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+                       unsigned int count)
+{
+       int r;
+
+       zd_usb_iowrite16v_async_start(usb);
+       r = zd_usb_iowrite16v_async(usb, ioreqs, count);
+       if (r) {
+               zd_usb_iowrite16v_async_end(usb, 0);
+               return r;
+       }
+       return zd_usb_iowrite16v_async_end(usb, 50 /* ms */);
+}
+
+int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
+{
+       int r;
+       struct usb_device *udev;
+       struct usb_req_rfwrite *req = NULL;
+       int i, req_len, actual_req_len;
+       u16 bit_value_template;
+
+       if (in_atomic()) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: io in atomic context not supported\n");
+               return -EWOULDBLOCK;
+       }
+       if (bits < USB_MIN_RFWRITE_BIT_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: bits %d are smaller than"
+                       " USB_MIN_RFWRITE_BIT_COUNT %d\n",
+                       bits, USB_MIN_RFWRITE_BIT_COUNT);
+               return -EINVAL;
+       }
+       if (bits > USB_MAX_RFWRITE_BIT_COUNT) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n",
+                       bits, USB_MAX_RFWRITE_BIT_COUNT);
+               return -EINVAL;
+       }
+#ifdef DEBUG
+       if (value & (~0UL << bits)) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error: value %#09x has bits >= %d set\n",
+                       value, bits);
+               return -EINVAL;
+       }
+#endif /* DEBUG */
+
+       dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits);
+
+       r = zd_usb_ioread16(usb, &bit_value_template, ZD_CR203);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error %d: Couldn't read ZD_CR203\n", r);
+               return r;
+       }
+       bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
+
+       ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+       BUILD_BUG_ON(sizeof(struct usb_req_rfwrite) +
+                    USB_MAX_RFWRITE_BIT_COUNT * sizeof(__le16) >
+                    sizeof(usb->req_buf));
+       BUG_ON(sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16) >
+              sizeof(usb->req_buf));
+
+       req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
+       req = (void *)usb->req_buf;
+
+       req->id = cpu_to_le16(USB_REQ_WRITE_RF);
+       /* 1: 3683a, but not used in ZYDAS driver */
+       req->value = cpu_to_le16(2);
+       req->bits = cpu_to_le16(bits);
+
+       for (i = 0; i < bits; i++) {
+               u16 bv = bit_value_template;
+               if (value & (1 << (bits-1-i)))
+                       bv |= RF_DATA;
+               req->bit_values[i] = cpu_to_le16(bv);
+       }
+
+       udev = zd_usb_to_usbdev(usb);
+       r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
+       if (r) {
+               dev_dbg_f(zd_usb_dev(usb),
+                       "error in zd_ep_regs_out_msg(). Error number %d\n", r);
+               goto out;
+       }
+       if (req_len != actual_req_len) {
+               dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()"
+                       " req_len %d != actual_req_len %d\n",
+                       req_len, actual_req_len);
+               r = -EIO;
+               goto out;
+       }
+
+       /* FALL-THROUGH with r == 0 */
+out:
+       return r;
+}
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_usb.h b/drivers/net/wireless/zydas/zd1211rw/zd_usb.h
new file mode 100644 (file)
index 0000000..a9075f2
--- /dev/null
@@ -0,0 +1,292 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ZD_USB_H
+#define _ZD_USB_H
+
+#include <linux/completion.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+
+#include "zd_def.h"
+
+#define ZD_USB_TX_HIGH  5
+#define ZD_USB_TX_LOW   2
+
+#define ZD_TX_TIMEOUT          (HZ * 5)
+#define ZD_TX_WATCHDOG_INTERVAL        round_jiffies_relative(HZ)
+#define ZD_RX_IDLE_INTERVAL    round_jiffies_relative(30 * HZ)
+
+enum devicetype {
+       DEVICE_ZD1211  = 0,
+       DEVICE_ZD1211B = 1,
+       DEVICE_INSTALLER = 2,
+};
+
+enum endpoints {
+       EP_CTRL     = 0,
+       EP_DATA_OUT = 1,
+       EP_DATA_IN  = 2,
+       EP_INT_IN   = 3,
+       EP_REGS_OUT = 4,
+};
+
+enum {
+       USB_MAX_TRANSFER_SIZE           = 4096, /* bytes */
+       /* FIXME: The original driver uses this value. We have to check,
+        * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be
+        * used if one combined frame is split over two USB transactions.
+        */
+       USB_MAX_RX_SIZE                 = 4800, /* bytes */
+       USB_MAX_IOWRITE16_COUNT         = 15,
+       USB_MAX_IOWRITE32_COUNT         = USB_MAX_IOWRITE16_COUNT/2,
+       USB_MAX_IOREAD16_COUNT          = 15,
+       USB_MAX_IOREAD32_COUNT          = USB_MAX_IOREAD16_COUNT/2,
+       USB_MIN_RFWRITE_BIT_COUNT       = 16,
+       USB_MAX_RFWRITE_BIT_COUNT       = 28,
+       USB_MAX_EP_INT_BUFFER           = 64,
+       USB_ZD1211B_BCD_DEVICE          = 0x4810,
+};
+
+enum control_requests {
+       USB_REQ_WRITE_REGS              = 0x21,
+       USB_REQ_READ_REGS               = 0x22,
+       USB_REQ_WRITE_RF                = 0x23,
+       USB_REQ_PROG_FLASH              = 0x24,
+       USB_REQ_EEPROM_START            = 0x0128, /* ? request is a byte */
+       USB_REQ_EEPROM_MID              = 0x28,
+       USB_REQ_EEPROM_END              = 0x0228, /* ? request is a byte */
+       USB_REQ_FIRMWARE_DOWNLOAD       = 0x30,
+       USB_REQ_FIRMWARE_CONFIRM        = 0x31,
+       USB_REQ_FIRMWARE_READ_DATA      = 0x32,
+};
+
+struct usb_req_read_regs {
+       __le16 id;
+       __le16 addr[0];
+} __packed;
+
+struct reg_data {
+       __le16 addr;
+       __le16 value;
+} __packed;
+
+struct usb_req_write_regs {
+       __le16 id;
+       struct reg_data reg_writes[0];
+} __packed;
+
+enum {
+       RF_IF_LE = 0x02,
+       RF_CLK   = 0x04,
+       RF_DATA  = 0x08,
+};
+
+struct usb_req_rfwrite {
+       __le16 id;
+       __le16 value;
+       /* 1: 3683a */
+       /* 2: other (default) */
+       __le16 bits;
+       /* RF2595: 24 */
+       __le16 bit_values[0];
+       /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
+} __packed;
+
+/* USB interrupt */
+
+enum usb_int_id {
+       USB_INT_TYPE                    = 0x01,
+       USB_INT_ID_REGS                 = 0x90,
+       USB_INT_ID_RETRY_FAILED         = 0xa0,
+};
+
+enum usb_int_flags {
+       USB_INT_READ_REGS_EN            = 0x01,
+};
+
+struct usb_int_header {
+       u8 type;        /* must always be 1 */
+       u8 id;
+} __packed;
+
+struct usb_int_regs {
+       struct usb_int_header hdr;
+       struct reg_data regs[0];
+} __packed;
+
+struct usb_int_retry_fail {
+       struct usb_int_header hdr;
+       u8 new_rate;
+       u8 _dummy;
+       u8 addr[ETH_ALEN];
+       u8 ibss_wakeup_dest;
+} __packed;
+
+struct read_regs_int {
+       struct completion completion;
+       struct usb_req_read_regs *req;
+       unsigned int req_count;
+       /* Stores the USB int structure and contains the USB address of the
+        * first requested register before request.
+        */
+       u8 buffer[USB_MAX_EP_INT_BUFFER];
+       int length;
+       __le16 cr_int_addr;
+};
+
+struct zd_ioreq16 {
+       zd_addr_t addr;
+       u16 value;
+};
+
+struct zd_ioreq32 {
+       zd_addr_t addr;
+       u32 value;
+};
+
+struct zd_usb_interrupt {
+       struct read_regs_int read_regs;
+       spinlock_t lock;
+       struct urb *urb;
+       void *buffer;
+       dma_addr_t buffer_dma;
+       int interval;
+       atomic_t read_regs_enabled;
+       u8 read_regs_int_overridden:1;
+};
+
+static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
+{
+       return (struct usb_int_regs *)intr->read_regs.buffer;
+}
+
+#define RX_URBS_COUNT 5
+
+struct zd_usb_rx {
+       spinlock_t lock;
+       struct mutex setup_mutex;
+       struct delayed_work idle_work;
+       struct tasklet_struct reset_timer_tasklet;
+       u8 fragment[2 * USB_MAX_RX_SIZE];
+       unsigned int fragment_length;
+       unsigned int usb_packet_size;
+       struct urb **urbs;
+       int urbs_count;
+};
+
+/**
+ * struct zd_usb_tx - structure used for transmitting frames
+ * @enabled: atomic enabled flag, indicates whether tx is enabled
+ * @lock: lock for transmission
+ * @submitted: anchor for URBs sent to device
+ * @submitted_urbs: atomic integer that counts the URBs having sent to the
+ *     device, which haven't been completed
+ * @stopped: indicates whether higher level tx queues are stopped
+ */
+struct zd_usb_tx {
+       atomic_t enabled;
+       spinlock_t lock;
+       struct delayed_work watchdog_work;
+       struct sk_buff_head submitted_skbs;
+       struct usb_anchor submitted;
+       int submitted_urbs;
+       u8 stopped:1, watchdog_enabled:1;
+};
+
+/* Contains the usb parts. The structure doesn't require a lock because intf
+ * will not be changed after initialization.
+ */
+struct zd_usb {
+       struct zd_usb_interrupt intr;
+       struct zd_usb_rx rx;
+       struct zd_usb_tx tx;
+       struct usb_interface *intf;
+       struct usb_anchor submitted_cmds;
+       struct urb *urb_async_waiting;
+       int cmd_error;
+       u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */
+       u8 is_zd1211b:1, initialized:1, was_running:1, in_async:1;
+};
+
+#define zd_usb_dev(usb) (&usb->intf->dev)
+
+static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb)
+{
+       return interface_to_usbdev(usb->intf);
+}
+
+static inline struct ieee80211_hw *zd_intf_to_hw(struct usb_interface *intf)
+{
+       return usb_get_intfdata(intf);
+}
+
+static inline struct ieee80211_hw *zd_usb_to_hw(struct zd_usb *usb)
+{
+       return zd_intf_to_hw(usb->intf);
+}
+
+void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
+                struct usb_interface *intf);
+int zd_usb_init_hw(struct zd_usb *usb);
+void zd_usb_clear(struct zd_usb *usb);
+
+int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
+
+void zd_tx_watchdog_enable(struct zd_usb *usb);
+void zd_tx_watchdog_disable(struct zd_usb *usb);
+
+int zd_usb_enable_int(struct zd_usb *usb);
+void zd_usb_disable_int(struct zd_usb *usb);
+
+int zd_usb_enable_rx(struct zd_usb *usb);
+void zd_usb_disable_rx(struct zd_usb *usb);
+
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb);
+
+void zd_usb_enable_tx(struct zd_usb *usb);
+void zd_usb_disable_tx(struct zd_usb *usb);
+
+int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb);
+
+int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
+                const zd_addr_t *addresses, unsigned int count);
+
+static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value,
+                             const zd_addr_t addr)
+{
+       return zd_usb_ioread16v(usb, value, &addr, 1);
+}
+
+void zd_usb_iowrite16v_async_start(struct zd_usb *usb);
+int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout);
+int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+                           unsigned int count);
+int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+                     unsigned int count);
+
+int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
+
+int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len);
+
+extern struct workqueue_struct *zd_workqueue;
+
+#endif /* _ZD_USB_H */