diff options
22 files changed, 6911 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 30ec235e6935..fa9d2c4edc93 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
| @@ -550,6 +550,7 @@ config USB_ZD1201 | |||
| 550 | 550 | ||
| 551 | source "drivers/net/wireless/hostap/Kconfig" | 551 | source "drivers/net/wireless/hostap/Kconfig" |
| 552 | source "drivers/net/wireless/bcm43xx/Kconfig" | 552 | source "drivers/net/wireless/bcm43xx/Kconfig" |
| 553 | source "drivers/net/wireless/zd1211rw/Kconfig" | ||
| 553 | 554 | ||
| 554 | # yes, this works even when no drivers are selected | 555 | # yes, this works even when no drivers are selected |
| 555 | config NET_WIRELESS | 556 | config NET_WIRELESS |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 512603de309a..c613af17a159 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
| @@ -36,6 +36,7 @@ obj-$(CONFIG_PRISM54) += prism54/ | |||
| 36 | 36 | ||
| 37 | obj-$(CONFIG_HOSTAP) += hostap/ | 37 | obj-$(CONFIG_HOSTAP) += hostap/ |
| 38 | obj-$(CONFIG_BCM43XX) += bcm43xx/ | 38 | obj-$(CONFIG_BCM43XX) += bcm43xx/ |
| 39 | obj-$(CONFIG_ZD1211RW) += zd1211rw/ | ||
| 39 | 40 | ||
| 40 | # 16-bit wireless PCMCIA client drivers | 41 | # 16-bit wireless PCMCIA client drivers |
| 41 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o | 42 | obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o |
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig new file mode 100644 index 000000000000..66ed55bc5460 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/Kconfig | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | config ZD1211RW | ||
| 2 | tristate "ZyDAS ZD1211/ZD1211B USB-wireless support" | ||
| 3 | depends on USB && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL | ||
| 4 | select FW_LOADER | ||
| 5 | ---help--- | ||
| 6 | This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless | ||
| 7 | chip, present in many USB-wireless adapters. | ||
| 8 | |||
| 9 | Device firmware is required alongside this driver. You can download the | ||
| 10 | firmware distribution from http://zd1211.ath.cx/get-firmware | ||
| 11 | |||
| 12 | config ZD1211RW_DEBUG | ||
| 13 | bool "ZyDAS ZD1211 debugging" | ||
| 14 | depends on ZD1211RW | ||
| 15 | ---help--- | ||
| 16 | ZD1211 debugging messages. Choosing Y will result in additional debug | ||
| 17 | messages being saved to your kernel logs, which may help debug any | ||
| 18 | problems. | ||
| 19 | |||
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile new file mode 100644 index 000000000000..500314fc74d2 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/Makefile | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | obj-$(CONFIG_ZD1211RW) += zd1211rw.o | ||
| 2 | |||
| 3 | zd1211rw-objs := zd_chip.o zd_ieee80211.o \ | ||
| 4 | zd_mac.o zd_netdev.o \ | ||
| 5 | zd_rf_al2230.o zd_rf_rf2959.o \ | ||
| 6 | zd_rf.o zd_usb.o zd_util.o | ||
| 7 | |||
| 8 | ifeq ($(CONFIG_ZD1211RW_DEBUG),y) | ||
| 9 | EXTRA_CFLAGS += -DDEBUG | ||
| 10 | endif | ||
| 11 | |||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c new file mode 100644 index 000000000000..efc9c4bd826f --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
| @@ -0,0 +1,1615 @@ | |||
| 1 | /* zd_chip.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* This file implements all the hardware specific functions for the ZD1211 | ||
| 19 | * and ZD1211B chips. Support for the ZD1211B was possible after Timothy | ||
| 20 | * Legge sent me a ZD1211B device. Thank you Tim. -- Uli | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | |||
| 26 | #include "zd_def.h" | ||
| 27 | #include "zd_chip.h" | ||
| 28 | #include "zd_ieee80211.h" | ||
| 29 | #include "zd_mac.h" | ||
| 30 | #include "zd_rf.h" | ||
| 31 | #include "zd_util.h" | ||
| 32 | |||
| 33 | void zd_chip_init(struct zd_chip *chip, | ||
| 34 | struct net_device *netdev, | ||
| 35 | struct usb_interface *intf) | ||
| 36 | { | ||
| 37 | memset(chip, 0, sizeof(*chip)); | ||
| 38 | mutex_init(&chip->mutex); | ||
| 39 | zd_usb_init(&chip->usb, netdev, intf); | ||
| 40 | zd_rf_init(&chip->rf); | ||
| 41 | } | ||
| 42 | |||
| 43 | void zd_chip_clear(struct zd_chip *chip) | ||
| 44 | { | ||
| 45 | mutex_lock(&chip->mutex); | ||
| 46 | zd_usb_clear(&chip->usb); | ||
| 47 | zd_rf_clear(&chip->rf); | ||
| 48 | mutex_unlock(&chip->mutex); | ||
| 49 | mutex_destroy(&chip->mutex); | ||
| 50 | memset(chip, 0, sizeof(*chip)); | ||
| 51 | } | ||
| 52 | |||
| 53 | static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) | ||
| 54 | { | ||
| 55 | return scnprintf(buffer, size, "%02x-%02x-%02x", | ||
| 56 | addr[0], addr[1], addr[2]); | ||
| 57 | } | ||
| 58 | |||
| 59 | /* Prints an identifier line, which will support debugging. */ | ||
| 60 | static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) | ||
| 61 | { | ||
| 62 | int i = 0; | ||
| 63 | |||
| 64 | i = scnprintf(buffer, size, "zd1211%s chip ", | ||
| 65 | chip->is_zd1211b ? "b" : ""); | ||
| 66 | i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); | ||
| 67 | i += scnprintf(buffer+i, size-i, " "); | ||
| 68 | i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); | ||
| 69 | i += scnprintf(buffer+i, size-i, " "); | ||
| 70 | i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); | ||
| 71 | i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type, | ||
| 72 | chip->patch_cck_gain ? 'g' : '-', | ||
| 73 | chip->patch_cr157 ? '7' : '-', | ||
| 74 | chip->patch_6m_band_edge ? '6' : '-'); | ||
| 75 | return i; | ||
| 76 | } | ||
| 77 | |||
| 78 | static void print_id(struct zd_chip *chip) | ||
| 79 | { | ||
| 80 | char buffer[80]; | ||
| 81 | |||
| 82 | scnprint_id(chip, buffer, sizeof(buffer)); | ||
| 83 | buffer[sizeof(buffer)-1] = 0; | ||
| 84 | dev_info(zd_chip_dev(chip), "%s\n", buffer); | ||
| 85 | } | ||
| 86 | |||
| 87 | /* Read a variable number of 32-bit values. Parameter count is not allowed to | ||
| 88 | * exceed USB_MAX_IOREAD32_COUNT. | ||
| 89 | */ | ||
| 90 | int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr, | ||
| 91 | unsigned int count) | ||
| 92 | { | ||
| 93 | int r; | ||
| 94 | int i; | ||
| 95 | zd_addr_t *a16 = (zd_addr_t *)NULL; | ||
| 96 | u16 *v16; | ||
| 97 | unsigned int count16; | ||
| 98 | |||
| 99 | if (count > USB_MAX_IOREAD32_COUNT) | ||
| 100 | return -EINVAL; | ||
| 101 | |||
| 102 | /* Allocate a single memory block for values and addresses. */ | ||
| 103 | count16 = 2*count; | ||
| 104 | a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), | ||
| 105 | GFP_NOFS); | ||
| 106 | if (!a16) { | ||
| 107 | dev_dbg_f(zd_chip_dev(chip), | ||
| 108 | "error ENOMEM in allocation of a16\n"); | ||
| 109 | r = -ENOMEM; | ||
| 110 | goto out; | ||
| 111 | } | ||
| 112 | v16 = (u16 *)(a16 + count16); | ||
| 113 | |||
| 114 | for (i = 0; i < count; i++) { | ||
| 115 | int j = 2*i; | ||
| 116 | /* We read the high word always first. */ | ||
| 117 | a16[j] = zd_inc_word(addr[i]); | ||
| 118 | a16[j+1] = addr[i]; | ||
| 119 | } | ||
| 120 | |||
| 121 | r = zd_ioread16v_locked(chip, v16, a16, count16); | ||
| 122 | if (r) { | ||
| 123 | dev_dbg_f(zd_chip_dev(chip), | ||
| 124 | "error: zd_ioread16v_locked. Error number %d\n", r); | ||
| 125 | goto out; | ||
| 126 | } | ||
| 127 | |||
| 128 | for (i = 0; i < count; i++) { | ||
| 129 | int j = 2*i; | ||
| 130 | values[i] = (v16[j] << 16) | v16[j+1]; | ||
| 131 | } | ||
| 132 | |||
| 133 | out: | ||
| 134 | kfree((void *)a16); | ||
| 135 | return r; | ||
| 136 | } | ||
| 137 | |||
| 138 | int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
| 139 | unsigned int count) | ||
| 140 | { | ||
| 141 | int i, j, r; | ||
| 142 | struct zd_ioreq16 *ioreqs16; | ||
| 143 | unsigned int count16; | ||
| 144 | |||
| 145 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 146 | |||
| 147 | if (count == 0) | ||
| 148 | return 0; | ||
| 149 | if (count > USB_MAX_IOWRITE32_COUNT) | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | /* Allocate a single memory block for values and addresses. */ | ||
| 153 | count16 = 2*count; | ||
| 154 | ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_NOFS); | ||
| 155 | if (!ioreqs16) { | ||
| 156 | r = -ENOMEM; | ||
| 157 | dev_dbg_f(zd_chip_dev(chip), | ||
| 158 | "error %d in ioreqs16 allocation\n", r); | ||
| 159 | goto out; | ||
| 160 | } | ||
| 161 | |||
| 162 | for (i = 0; i < count; i++) { | ||
| 163 | j = 2*i; | ||
| 164 | /* We write the high word always first. */ | ||
| 165 | ioreqs16[j].value = ioreqs[i].value >> 16; | ||
| 166 | ioreqs16[j].addr = zd_inc_word(ioreqs[i].addr); | ||
| 167 | ioreqs16[j+1].value = ioreqs[i].value; | ||
| 168 | ioreqs16[j+1].addr = ioreqs[i].addr; | ||
| 169 | } | ||
| 170 | |||
| 171 | r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16); | ||
| 172 | #ifdef DEBUG | ||
| 173 | if (r) { | ||
| 174 | dev_dbg_f(zd_chip_dev(chip), | ||
| 175 | "error %d in zd_usb_write16v\n", r); | ||
| 176 | } | ||
| 177 | #endif /* DEBUG */ | ||
| 178 | out: | ||
| 179 | kfree(ioreqs16); | ||
| 180 | return r; | ||
| 181 | } | ||
| 182 | |||
| 183 | int zd_iowrite16a_locked(struct zd_chip *chip, | ||
| 184 | const struct zd_ioreq16 *ioreqs, unsigned int count) | ||
| 185 | { | ||
| 186 | int r; | ||
| 187 | unsigned int i, j, t, max; | ||
| 188 | |||
| 189 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 190 | for (i = 0; i < count; i += j + t) { | ||
| 191 | t = 0; | ||
| 192 | max = count-i; | ||
| 193 | if (max > USB_MAX_IOWRITE16_COUNT) | ||
| 194 | max = USB_MAX_IOWRITE16_COUNT; | ||
| 195 | for (j = 0; j < max; j++) { | ||
| 196 | if (!ioreqs[i+j].addr) { | ||
| 197 | t = 1; | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j); | ||
| 203 | if (r) { | ||
| 204 | dev_dbg_f(zd_chip_dev(chip), | ||
| 205 | "error zd_usb_iowrite16v. Error number %d\n", | ||
| 206 | r); | ||
| 207 | return r; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | /* Writes a variable number of 32 bit registers. The functions will split | ||
| 215 | * that in several USB requests. A split can be forced by inserting an IO | ||
| 216 | * request with an zero address field. | ||
| 217 | */ | ||
| 218 | int zd_iowrite32a_locked(struct zd_chip *chip, | ||
| 219 | const struct zd_ioreq32 *ioreqs, unsigned int count) | ||
| 220 | { | ||
| 221 | int r; | ||
| 222 | unsigned int i, j, t, max; | ||
| 223 | |||
| 224 | for (i = 0; i < count; i += j + t) { | ||
| 225 | t = 0; | ||
| 226 | max = count-i; | ||
| 227 | if (max > USB_MAX_IOWRITE32_COUNT) | ||
| 228 | max = USB_MAX_IOWRITE32_COUNT; | ||
| 229 | for (j = 0; j < max; j++) { | ||
| 230 | if (!ioreqs[i+j].addr) { | ||
| 231 | t = 1; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | r = _zd_iowrite32v_locked(chip, &ioreqs[i], j); | ||
| 237 | if (r) { | ||
| 238 | dev_dbg_f(zd_chip_dev(chip), | ||
| 239 | "error _zd_iowrite32v_locked." | ||
| 240 | " Error number %d\n", r); | ||
| 241 | return r; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value) | ||
| 249 | { | ||
| 250 | int r; | ||
| 251 | |||
| 252 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
| 253 | mutex_lock(&chip->mutex); | ||
| 254 | r = zd_ioread16_locked(chip, value, addr); | ||
| 255 | mutex_unlock(&chip->mutex); | ||
| 256 | return r; | ||
| 257 | } | ||
| 258 | |||
| 259 | int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value) | ||
| 260 | { | ||
| 261 | int r; | ||
| 262 | |||
| 263 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
| 264 | mutex_lock(&chip->mutex); | ||
| 265 | r = zd_ioread32_locked(chip, value, addr); | ||
| 266 | mutex_unlock(&chip->mutex); | ||
| 267 | return r; | ||
| 268 | } | ||
| 269 | |||
| 270 | int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value) | ||
| 271 | { | ||
| 272 | int r; | ||
| 273 | |||
| 274 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
| 275 | mutex_lock(&chip->mutex); | ||
| 276 | r = zd_iowrite16_locked(chip, value, addr); | ||
| 277 | mutex_unlock(&chip->mutex); | ||
| 278 | return r; | ||
| 279 | } | ||
| 280 | |||
| 281 | int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value) | ||
| 282 | { | ||
| 283 | int r; | ||
| 284 | |||
| 285 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
| 286 | mutex_lock(&chip->mutex); | ||
| 287 | r = zd_iowrite32_locked(chip, value, addr); | ||
| 288 | mutex_unlock(&chip->mutex); | ||
| 289 | return r; | ||
| 290 | } | ||
| 291 | |||
| 292 | int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, | ||
| 293 | u32 *values, unsigned int count) | ||
| 294 | { | ||
| 295 | int r; | ||
| 296 | |||
| 297 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
| 298 | mutex_lock(&chip->mutex); | ||
| 299 | r = zd_ioread32v_locked(chip, values, addresses, count); | ||
| 300 | mutex_unlock(&chip->mutex); | ||
| 301 | return r; | ||
| 302 | } | ||
| 303 | |||
| 304 | int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
| 305 | unsigned int count) | ||
| 306 | { | ||
| 307 | int r; | ||
| 308 | |||
| 309 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); | ||
| 310 | mutex_lock(&chip->mutex); | ||
| 311 | r = zd_iowrite32a_locked(chip, ioreqs, count); | ||
| 312 | mutex_unlock(&chip->mutex); | ||
| 313 | return r; | ||
| 314 | } | ||
| 315 | |||
| 316 | static int read_pod(struct zd_chip *chip, u8 *rf_type) | ||
| 317 | { | ||
| 318 | int r; | ||
| 319 | u32 value; | ||
| 320 | |||
| 321 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 322 | r = zd_ioread32_locked(chip, &value, E2P_POD); | ||
| 323 | if (r) | ||
| 324 | goto error; | ||
| 325 | dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value); | ||
| 326 | |||
| 327 | /* FIXME: AL2230 handling (Bit 7 in POD) */ | ||
| 328 | *rf_type = value & 0x0f; | ||
| 329 | chip->pa_type = (value >> 16) & 0x0f; | ||
| 330 | chip->patch_cck_gain = (value >> 8) & 0x1; | ||
| 331 | chip->patch_cr157 = (value >> 13) & 0x1; | ||
| 332 | chip->patch_6m_band_edge = (value >> 21) & 0x1; | ||
| 333 | |||
| 334 | dev_dbg_f(zd_chip_dev(chip), | ||
| 335 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " | ||
| 336 | "patch 6M %d\n", | ||
| 337 | zd_rf_name(*rf_type), *rf_type, | ||
| 338 | chip->pa_type, chip->patch_cck_gain, | ||
| 339 | chip->patch_cr157, chip->patch_6m_band_edge); | ||
| 340 | return 0; | ||
| 341 | error: | ||
| 342 | *rf_type = 0; | ||
| 343 | chip->pa_type = 0; | ||
| 344 | chip->patch_cck_gain = 0; | ||
| 345 | chip->patch_cr157 = 0; | ||
| 346 | chip->patch_6m_band_edge = 0; | ||
| 347 | return r; | ||
| 348 | } | ||
| 349 | |||
| 350 | static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr, | ||
| 351 | const zd_addr_t *addr) | ||
| 352 | { | ||
| 353 | int r; | ||
| 354 | u32 parts[2]; | ||
| 355 | |||
| 356 | r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2); | ||
| 357 | if (r) { | ||
| 358 | dev_dbg_f(zd_chip_dev(chip), | ||
| 359 | "error: couldn't read e2p macs. Error number %d\n", r); | ||
| 360 | return r; | ||
| 361 | } | ||
| 362 | |||
| 363 | mac_addr[0] = parts[0]; | ||
| 364 | mac_addr[1] = parts[0] >> 8; | ||
| 365 | mac_addr[2] = parts[0] >> 16; | ||
| 366 | mac_addr[3] = parts[0] >> 24; | ||
| 367 | mac_addr[4] = parts[1]; | ||
| 368 | mac_addr[5] = parts[1] >> 8; | ||
| 369 | |||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int read_e2p_mac_addr(struct zd_chip *chip) | ||
| 374 | { | ||
| 375 | static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; | ||
| 376 | |||
| 377 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 378 | return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr); | ||
| 379 | } | ||
| 380 | |||
| 381 | /* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and | ||
| 382 | * CR_MAC_ADDR_P2 must be overwritten | ||
| 383 | */ | ||
| 384 | void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr) | ||
| 385 | { | ||
| 386 | mutex_lock(&chip->mutex); | ||
| 387 | memcpy(mac_addr, chip->e2p_mac, ETH_ALEN); | ||
| 388 | mutex_unlock(&chip->mutex); | ||
| 389 | } | ||
| 390 | |||
| 391 | static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr) | ||
| 392 | { | ||
| 393 | static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 }; | ||
| 394 | return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr); | ||
| 395 | } | ||
| 396 | |||
| 397 | int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr) | ||
| 398 | { | ||
| 399 | int r; | ||
| 400 | |||
| 401 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 402 | mutex_lock(&chip->mutex); | ||
| 403 | r = read_mac_addr(chip, mac_addr); | ||
| 404 | mutex_unlock(&chip->mutex); | ||
| 405 | return r; | ||
| 406 | } | ||
| 407 | |||
| 408 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) | ||
| 409 | { | ||
| 410 | int r; | ||
| 411 | struct zd_ioreq32 reqs[2] = { | ||
| 412 | [0] = { .addr = CR_MAC_ADDR_P1 }, | ||
| 413 | [1] = { .addr = CR_MAC_ADDR_P2 }, | ||
| 414 | }; | ||
| 415 | |||
| 416 | reqs[0].value = (mac_addr[3] << 24) | ||
| 417 | | (mac_addr[2] << 16) | ||
| 418 | | (mac_addr[1] << 8) | ||
| 419 | | mac_addr[0]; | ||
| 420 | reqs[1].value = (mac_addr[5] << 8) | ||
| 421 | | mac_addr[4]; | ||
| 422 | |||
| 423 | dev_dbg_f(zd_chip_dev(chip), | ||
| 424 | "mac addr " MAC_FMT "\n", MAC_ARG(mac_addr)); | ||
| 425 | |||
| 426 | mutex_lock(&chip->mutex); | ||
| 427 | r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); | ||
| 428 | #ifdef DEBUG | ||
| 429 | { | ||
| 430 | u8 tmp[ETH_ALEN]; | ||
| 431 | read_mac_addr(chip, tmp); | ||
| 432 | } | ||
| 433 | #endif /* DEBUG */ | ||
| 434 | mutex_unlock(&chip->mutex); | ||
| 435 | return r; | ||
| 436 | } | ||
| 437 | |||
| 438 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain) | ||
| 439 | { | ||
| 440 | int r; | ||
| 441 | u32 value; | ||
| 442 | |||
| 443 | mutex_lock(&chip->mutex); | ||
| 444 | r = zd_ioread32_locked(chip, &value, E2P_SUBID); | ||
| 445 | mutex_unlock(&chip->mutex); | ||
| 446 | if (r) | ||
| 447 | return r; | ||
| 448 | |||
| 449 | *regdomain = value >> 16; | ||
| 450 | dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain); | ||
| 451 | |||
| 452 | return 0; | ||
| 453 | } | ||
| 454 | |||
| 455 | static int read_values(struct zd_chip *chip, u8 *values, size_t count, | ||
| 456 | zd_addr_t e2p_addr, u32 guard) | ||
| 457 | { | ||
| 458 | int r; | ||
| 459 | int i; | ||
| 460 | u32 v; | ||
| 461 | |||
| 462 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 463 | for (i = 0;;) { | ||
| 464 | r = zd_ioread32_locked(chip, &v, e2p_addr+i/2); | ||
| 465 | if (r) | ||
| 466 | return r; | ||
| 467 | v -= guard; | ||
| 468 | if (i+4 < count) { | ||
| 469 | values[i++] = v; | ||
| 470 | values[i++] = v >> 8; | ||
| 471 | values[i++] = v >> 16; | ||
| 472 | values[i++] = v >> 24; | ||
| 473 | continue; | ||
| 474 | } | ||
| 475 | for (;i < count; i++) | ||
| 476 | values[i] = v >> (8*(i%3)); | ||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 481 | static int read_pwr_cal_values(struct zd_chip *chip) | ||
| 482 | { | ||
| 483 | return read_values(chip, chip->pwr_cal_values, | ||
| 484 | E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1, | ||
| 485 | 0); | ||
| 486 | } | ||
| 487 | |||
| 488 | static int read_pwr_int_values(struct zd_chip *chip) | ||
| 489 | { | ||
| 490 | return read_values(chip, chip->pwr_int_values, | ||
| 491 | E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1, | ||
| 492 | E2P_PWR_INT_GUARD); | ||
| 493 | } | ||
| 494 | |||
| 495 | static int read_ofdm_cal_values(struct zd_chip *chip) | ||
| 496 | { | ||
| 497 | int r; | ||
| 498 | int i; | ||
| 499 | static const zd_addr_t addresses[] = { | ||
| 500 | E2P_36M_CAL_VALUE1, | ||
| 501 | E2P_48M_CAL_VALUE1, | ||
| 502 | E2P_54M_CAL_VALUE1, | ||
| 503 | }; | ||
| 504 | |||
| 505 | for (i = 0; i < 3; i++) { | ||
| 506 | r = read_values(chip, chip->ofdm_cal_values[i], | ||
| 507 | E2P_CHANNEL_COUNT, addresses[i], 0); | ||
| 508 | if (r) | ||
| 509 | return r; | ||
| 510 | } | ||
| 511 | return 0; | ||
| 512 | } | ||
| 513 | |||
| 514 | static int read_cal_int_tables(struct zd_chip *chip) | ||
| 515 | { | ||
| 516 | int r; | ||
| 517 | |||
| 518 | r = read_pwr_cal_values(chip); | ||
| 519 | if (r) | ||
| 520 | return r; | ||
| 521 | r = read_pwr_int_values(chip); | ||
| 522 | if (r) | ||
| 523 | return r; | ||
| 524 | r = read_ofdm_cal_values(chip); | ||
| 525 | if (r) | ||
| 526 | return r; | ||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | /* phy means physical registers */ | ||
| 531 | int zd_chip_lock_phy_regs(struct zd_chip *chip) | ||
| 532 | { | ||
| 533 | int r; | ||
| 534 | u32 tmp; | ||
| 535 | |||
| 536 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 537 | r = zd_ioread32_locked(chip, &tmp, CR_REG1); | ||
| 538 | if (r) { | ||
| 539 | dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r); | ||
| 540 | return r; | ||
| 541 | } | ||
| 542 | |||
| 543 | dev_dbg_f(zd_chip_dev(chip), | ||
| 544 | "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp & ~UNLOCK_PHY_REGS); | ||
| 545 | tmp &= ~UNLOCK_PHY_REGS; | ||
| 546 | |||
| 547 | r = zd_iowrite32_locked(chip, tmp, CR_REG1); | ||
| 548 | if (r) | ||
| 549 | dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); | ||
| 550 | return r; | ||
| 551 | } | ||
| 552 | |||
| 553 | int zd_chip_unlock_phy_regs(struct zd_chip *chip) | ||
| 554 | { | ||
| 555 | int r; | ||
| 556 | u32 tmp; | ||
| 557 | |||
| 558 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 559 | r = zd_ioread32_locked(chip, &tmp, CR_REG1); | ||
| 560 | if (r) { | ||
| 561 | dev_err(zd_chip_dev(chip), | ||
| 562 | "error ioread32(CR_REG1): %d\n", r); | ||
| 563 | return r; | ||
| 564 | } | ||
| 565 | |||
| 566 | dev_dbg_f(zd_chip_dev(chip), | ||
| 567 | "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp | UNLOCK_PHY_REGS); | ||
| 568 | tmp |= UNLOCK_PHY_REGS; | ||
| 569 | |||
| 570 | r = zd_iowrite32_locked(chip, tmp, CR_REG1); | ||
| 571 | if (r) | ||
| 572 | dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); | ||
| 573 | return r; | ||
| 574 | } | ||
| 575 | |||
| 576 | /* CR157 can be optionally patched by the EEPROM */ | ||
| 577 | static int patch_cr157(struct zd_chip *chip) | ||
| 578 | { | ||
| 579 | int r; | ||
| 580 | u32 value; | ||
| 581 | |||
| 582 | if (!chip->patch_cr157) | ||
| 583 | return 0; | ||
| 584 | |||
| 585 | r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); | ||
| 586 | if (r) | ||
| 587 | return r; | ||
| 588 | |||
| 589 | dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); | ||
| 590 | return zd_iowrite32_locked(chip, value >> 8, CR157); | ||
| 591 | } | ||
| 592 | |||
| 593 | /* | ||
| 594 | * 6M band edge can be optionally overwritten for certain RF's | ||
| 595 | * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge | ||
| 596 | * bit (for AL2230, AL2230S) | ||
| 597 | */ | ||
| 598 | static int patch_6m_band_edge(struct zd_chip *chip, int channel) | ||
| 599 | { | ||
| 600 | struct zd_ioreq16 ioreqs[] = { | ||
| 601 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
| 602 | { CR47, 0x1e }, | ||
| 603 | }; | ||
| 604 | |||
| 605 | if (!chip->patch_6m_band_edge || !chip->rf.patch_6m_band_edge) | ||
| 606 | return 0; | ||
| 607 | |||
| 608 | /* FIXME: Channel 11 is not the edge for all regulatory domains. */ | ||
| 609 | if (channel == 1 || channel == 11) | ||
| 610 | ioreqs[0].value = 0x12; | ||
| 611 | |||
| 612 | dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel); | ||
| 613 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 614 | } | ||
| 615 | |||
| 616 | static int zd1211_hw_reset_phy(struct zd_chip *chip) | ||
| 617 | { | ||
| 618 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 619 | { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, | ||
| 620 | { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, | ||
| 621 | { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, | ||
| 622 | { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, | ||
| 623 | { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, | ||
| 624 | { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, | ||
| 625 | { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, | ||
| 626 | { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, | ||
| 627 | { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, | ||
| 628 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, | ||
| 629 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, | ||
| 630 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, | ||
| 631 | { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, | ||
| 632 | { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, | ||
| 633 | { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, | ||
| 634 | { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, | ||
| 635 | { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, | ||
| 636 | { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, | ||
| 637 | { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, | ||
| 638 | { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, | ||
| 639 | { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, | ||
| 640 | { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, | ||
| 641 | { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, | ||
| 642 | { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, | ||
| 643 | { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, | ||
| 644 | { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, | ||
| 645 | { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, | ||
| 646 | { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, | ||
| 647 | { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, | ||
| 648 | { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, | ||
| 649 | { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, | ||
| 650 | { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, | ||
| 651 | { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, | ||
| 652 | { }, | ||
| 653 | { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, | ||
| 654 | { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, | ||
| 655 | { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, | ||
| 656 | { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, | ||
| 657 | { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, | ||
| 658 | { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, | ||
| 659 | { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, | ||
| 660 | { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, | ||
| 661 | { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, | ||
| 662 | { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, | ||
| 663 | { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, | ||
| 664 | { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, | ||
| 665 | { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, | ||
| 666 | { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, | ||
| 667 | { CR123, 0x27 }, { CR125, 0xaa }, { CR127, 0x03 }, | ||
| 668 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
| 669 | { CR131, 0x0C }, { CR136, 0xdf }, { CR137, 0x40 }, | ||
| 670 | { CR138, 0xa0 }, { CR139, 0xb0 }, { CR140, 0x99 }, | ||
| 671 | { CR141, 0x82 }, { CR142, 0x54 }, { CR143, 0x1c }, | ||
| 672 | { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x4c }, | ||
| 673 | { CR149, 0x50 }, { CR150, 0x0e }, { CR151, 0x18 }, | ||
| 674 | { CR160, 0xfe }, { CR161, 0xee }, { CR162, 0xaa }, | ||
| 675 | { CR163, 0xfa }, { CR164, 0xfa }, { CR165, 0xea }, | ||
| 676 | { CR166, 0xbe }, { CR167, 0xbe }, { CR168, 0x6a }, | ||
| 677 | { CR169, 0xba }, { CR170, 0xba }, { CR171, 0xba }, | ||
| 678 | /* Note: CR204 must lead the CR203 */ | ||
| 679 | { CR204, 0x7d }, | ||
| 680 | { }, | ||
| 681 | { CR203, 0x30 }, | ||
| 682 | }; | ||
| 683 | |||
| 684 | int r, t; | ||
| 685 | |||
| 686 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 687 | |||
| 688 | r = zd_chip_lock_phy_regs(chip); | ||
| 689 | if (r) | ||
| 690 | goto out; | ||
| 691 | |||
| 692 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 693 | if (r) | ||
| 694 | goto unlock; | ||
| 695 | |||
| 696 | r = patch_cr157(chip); | ||
| 697 | unlock: | ||
| 698 | t = zd_chip_unlock_phy_regs(chip); | ||
| 699 | if (t && !r) | ||
| 700 | r = t; | ||
| 701 | out: | ||
| 702 | return r; | ||
| 703 | } | ||
| 704 | |||
| 705 | static int zd1211b_hw_reset_phy(struct zd_chip *chip) | ||
| 706 | { | ||
| 707 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 708 | { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, | ||
| 709 | { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, | ||
| 710 | { CR10, 0x81 }, | ||
| 711 | /* power control { { CR11, 1 << 6 }, */ | ||
| 712 | { CR11, 0x00 }, | ||
| 713 | { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, | ||
| 714 | { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, | ||
| 715 | { CR18, 0x0a }, { CR19, 0x48 }, | ||
| 716 | { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ | ||
| 717 | { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, | ||
| 718 | { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, | ||
| 719 | { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, | ||
| 720 | { CR30, 0x49 }, /* jointly decoder, no ASIC */ | ||
| 721 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, | ||
| 722 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, | ||
| 723 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, | ||
| 724 | { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, | ||
| 725 | { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, | ||
| 726 | { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, | ||
| 727 | { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, | ||
| 728 | { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, | ||
| 729 | { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, | ||
| 730 | { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, | ||
| 731 | { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, | ||
| 732 | { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, | ||
| 733 | { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, | ||
| 734 | { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, | ||
| 735 | { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, | ||
| 736 | { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, | ||
| 737 | { CR94, 0x01 }, | ||
| 738 | { CR95, 0x20 }, /* ZD1211B */ | ||
| 739 | { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, | ||
| 740 | { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, | ||
| 741 | { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, | ||
| 742 | { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, | ||
| 743 | { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, | ||
| 744 | { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, | ||
| 745 | { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, | ||
| 746 | { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, | ||
| 747 | { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, | ||
| 748 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
| 749 | { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, | ||
| 750 | { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, | ||
| 751 | { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, | ||
| 752 | { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, | ||
| 753 | { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ | ||
| 754 | { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ | ||
| 755 | { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, | ||
| 756 | { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, | ||
| 757 | { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, | ||
| 758 | { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, | ||
| 759 | { CR170, 0xba }, { CR171, 0xba }, | ||
| 760 | /* Note: CR204 must lead the CR203 */ | ||
| 761 | { CR204, 0x7d }, | ||
| 762 | {}, | ||
| 763 | { CR203, 0x30 }, | ||
| 764 | }; | ||
| 765 | |||
| 766 | int r, t; | ||
| 767 | |||
| 768 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 769 | |||
| 770 | r = zd_chip_lock_phy_regs(chip); | ||
| 771 | if (r) | ||
| 772 | goto out; | ||
| 773 | |||
| 774 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 775 | if (r) | ||
| 776 | goto unlock; | ||
| 777 | |||
| 778 | r = patch_cr157(chip); | ||
| 779 | unlock: | ||
| 780 | t = zd_chip_unlock_phy_regs(chip); | ||
| 781 | if (t && !r) | ||
| 782 | r = t; | ||
| 783 | out: | ||
| 784 | return r; | ||
| 785 | } | ||
| 786 | |||
| 787 | static int hw_reset_phy(struct zd_chip *chip) | ||
| 788 | { | ||
| 789 | return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) : | ||
| 790 | zd1211_hw_reset_phy(chip); | ||
| 791 | } | ||
| 792 | |||
| 793 | static int zd1211_hw_init_hmac(struct zd_chip *chip) | ||
| 794 | { | ||
| 795 | static const struct zd_ioreq32 ioreqs[] = { | ||
| 796 | { CR_ACK_TIMEOUT_EXT, 0x20 }, | ||
| 797 | { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, | ||
| 798 | { CR_ZD1211_RETRY_MAX, 0x2 }, | ||
| 799 | { CR_SNIFFER_ON, 0 }, | ||
| 800 | { CR_RX_FILTER, AP_RX_FILTER }, | ||
| 801 | { CR_GROUP_HASH_P1, 0x00 }, | ||
| 802 | { CR_GROUP_HASH_P2, 0x80000000 }, | ||
| 803 | { CR_REG1, 0xa4 }, | ||
| 804 | { CR_ADDA_PWR_DWN, 0x7f }, | ||
| 805 | { CR_BCN_PLCP_CFG, 0x00f00401 }, | ||
| 806 | { CR_PHY_DELAY, 0x00 }, | ||
| 807 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | ||
| 808 | { CR_ADDA_PWR_DWN, 0x00 }, | ||
| 809 | { CR_ACK_TIME_80211, 0x100 }, | ||
| 810 | { CR_IFS_VALUE, 0x547c032 }, | ||
| 811 | { CR_RX_PE_DELAY, 0x70 }, | ||
| 812 | { CR_PS_CTRL, 0x10000000 }, | ||
| 813 | { CR_RTS_CTS_RATE, 0x02030203 }, | ||
| 814 | { CR_RX_THRESHOLD, 0x000c0640 }, | ||
| 815 | { CR_AFTER_PNP, 0x1 }, | ||
| 816 | { CR_WEP_PROTECT, 0x114 }, | ||
| 817 | }; | ||
| 818 | |||
| 819 | int r; | ||
| 820 | |||
| 821 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 822 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 823 | r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 824 | #ifdef DEBUG | ||
| 825 | if (r) { | ||
| 826 | dev_err(zd_chip_dev(chip), | ||
| 827 | "error in zd_iowrite32a_locked. Error number %d\n", r); | ||
| 828 | } | ||
| 829 | #endif /* DEBUG */ | ||
| 830 | return r; | ||
| 831 | } | ||
| 832 | |||
| 833 | static int zd1211b_hw_init_hmac(struct zd_chip *chip) | ||
| 834 | { | ||
| 835 | static const struct zd_ioreq32 ioreqs[] = { | ||
| 836 | { CR_ACK_TIMEOUT_EXT, 0x20 }, | ||
| 837 | { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, | ||
| 838 | { CR_ZD1211B_RETRY_MAX, 0x02020202 }, | ||
| 839 | { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f }, | ||
| 840 | { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f }, | ||
| 841 | { CR_ZD1211B_TX_PWR_CTL2, 0x003f001f }, | ||
| 842 | { CR_ZD1211B_TX_PWR_CTL1, 0x001f000f }, | ||
| 843 | { CR_ZD1211B_AIFS_CTL1, 0x00280028 }, | ||
| 844 | { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, | ||
| 845 | { CR_ZD1211B_TXOP, 0x01800824 }, | ||
| 846 | { CR_SNIFFER_ON, 0 }, | ||
| 847 | { CR_RX_FILTER, AP_RX_FILTER }, | ||
| 848 | { CR_GROUP_HASH_P1, 0x00 }, | ||
| 849 | { CR_GROUP_HASH_P2, 0x80000000 }, | ||
| 850 | { CR_REG1, 0xa4 }, | ||
| 851 | { CR_ADDA_PWR_DWN, 0x7f }, | ||
| 852 | { CR_BCN_PLCP_CFG, 0x00f00401 }, | ||
| 853 | { CR_PHY_DELAY, 0x00 }, | ||
| 854 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | ||
| 855 | { CR_ADDA_PWR_DWN, 0x00 }, | ||
| 856 | { CR_ACK_TIME_80211, 0x100 }, | ||
| 857 | { CR_IFS_VALUE, 0x547c032 }, | ||
| 858 | { CR_RX_PE_DELAY, 0x70 }, | ||
| 859 | { CR_PS_CTRL, 0x10000000 }, | ||
| 860 | { CR_RTS_CTS_RATE, 0x02030203 }, | ||
| 861 | { CR_RX_THRESHOLD, 0x000c0640 }, | ||
| 862 | { CR_AFTER_PNP, 0x1 }, | ||
| 863 | { CR_WEP_PROTECT, 0x114 }, | ||
| 864 | }; | ||
| 865 | |||
| 866 | int r; | ||
| 867 | |||
| 868 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 869 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 870 | r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 871 | if (r) { | ||
| 872 | dev_dbg_f(zd_chip_dev(chip), | ||
| 873 | "error in zd_iowrite32a_locked. Error number %d\n", r); | ||
| 874 | } | ||
| 875 | return r; | ||
| 876 | } | ||
| 877 | |||
| 878 | static int hw_init_hmac(struct zd_chip *chip) | ||
| 879 | { | ||
| 880 | return chip->is_zd1211b ? | ||
| 881 | zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); | ||
| 882 | } | ||
| 883 | |||
| 884 | struct aw_pt_bi { | ||
| 885 | u32 atim_wnd_period; | ||
| 886 | u32 pre_tbtt; | ||
| 887 | u32 beacon_interval; | ||
| 888 | }; | ||
| 889 | |||
| 890 | static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | ||
| 891 | { | ||
| 892 | int r; | ||
| 893 | static const zd_addr_t aw_pt_bi_addr[] = | ||
| 894 | { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL }; | ||
| 895 | u32 values[3]; | ||
| 896 | |||
| 897 | r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr, | ||
| 898 | ARRAY_SIZE(aw_pt_bi_addr)); | ||
| 899 | if (r) { | ||
| 900 | memset(s, 0, sizeof(*s)); | ||
| 901 | return r; | ||
| 902 | } | ||
| 903 | |||
| 904 | s->atim_wnd_period = values[0]; | ||
| 905 | s->pre_tbtt = values[1]; | ||
| 906 | s->beacon_interval = values[2]; | ||
| 907 | dev_dbg_f(zd_chip_dev(chip), "aw %u pt %u bi %u\n", | ||
| 908 | s->atim_wnd_period, s->pre_tbtt, s->beacon_interval); | ||
| 909 | return 0; | ||
| 910 | } | ||
| 911 | |||
| 912 | static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | ||
| 913 | { | ||
| 914 | struct zd_ioreq32 reqs[3]; | ||
| 915 | |||
| 916 | if (s->beacon_interval <= 5) | ||
| 917 | s->beacon_interval = 5; | ||
| 918 | if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval) | ||
| 919 | s->pre_tbtt = s->beacon_interval - 1; | ||
| 920 | if (s->atim_wnd_period >= s->pre_tbtt) | ||
| 921 | s->atim_wnd_period = s->pre_tbtt - 1; | ||
| 922 | |||
| 923 | reqs[0].addr = CR_ATIM_WND_PERIOD; | ||
| 924 | reqs[0].value = s->atim_wnd_period; | ||
| 925 | reqs[1].addr = CR_PRE_TBTT; | ||
| 926 | reqs[1].value = s->pre_tbtt; | ||
| 927 | reqs[2].addr = CR_BCN_INTERVAL; | ||
| 928 | reqs[2].value = s->beacon_interval; | ||
| 929 | |||
| 930 | dev_dbg_f(zd_chip_dev(chip), | ||
| 931 | "aw %u pt %u bi %u\n", s->atim_wnd_period, s->pre_tbtt, | ||
| 932 | s->beacon_interval); | ||
| 933 | return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); | ||
| 934 | } | ||
| 935 | |||
| 936 | |||
| 937 | static int set_beacon_interval(struct zd_chip *chip, u32 interval) | ||
| 938 | { | ||
| 939 | int r; | ||
| 940 | struct aw_pt_bi s; | ||
| 941 | |||
| 942 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 943 | r = get_aw_pt_bi(chip, &s); | ||
| 944 | if (r) | ||
| 945 | return r; | ||
| 946 | s.beacon_interval = interval; | ||
| 947 | return set_aw_pt_bi(chip, &s); | ||
| 948 | } | ||
| 949 | |||
| 950 | int zd_set_beacon_interval(struct zd_chip *chip, u32 interval) | ||
| 951 | { | ||
| 952 | int r; | ||
| 953 | |||
| 954 | mutex_lock(&chip->mutex); | ||
| 955 | r = set_beacon_interval(chip, interval); | ||
| 956 | mutex_unlock(&chip->mutex); | ||
| 957 | return r; | ||
| 958 | } | ||
| 959 | |||
| 960 | static int hw_init(struct zd_chip *chip) | ||
| 961 | { | ||
| 962 | int r; | ||
| 963 | |||
| 964 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 965 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 966 | r = hw_reset_phy(chip); | ||
| 967 | if (r) | ||
| 968 | return r; | ||
| 969 | |||
| 970 | r = hw_init_hmac(chip); | ||
| 971 | if (r) | ||
| 972 | return r; | ||
| 973 | r = set_beacon_interval(chip, 100); | ||
| 974 | if (r) | ||
| 975 | return r; | ||
| 976 | return 0; | ||
| 977 | } | ||
| 978 | |||
| 979 | #ifdef DEBUG | ||
| 980 | static int dump_cr(struct zd_chip *chip, const zd_addr_t addr, | ||
| 981 | const char *addr_string) | ||
| 982 | { | ||
| 983 | int r; | ||
| 984 | u32 value; | ||
| 985 | |||
| 986 | r = zd_ioread32_locked(chip, &value, addr); | ||
| 987 | if (r) { | ||
| 988 | dev_dbg_f(zd_chip_dev(chip), | ||
| 989 | "error reading %s. Error number %d\n", addr_string, r); | ||
| 990 | return r; | ||
| 991 | } | ||
| 992 | |||
| 993 | dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n", | ||
| 994 | addr_string, (unsigned int)value); | ||
| 995 | return 0; | ||
| 996 | } | ||
| 997 | |||
| 998 | static int test_init(struct zd_chip *chip) | ||
| 999 | { | ||
| 1000 | int r; | ||
| 1001 | |||
| 1002 | r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP"); | ||
| 1003 | if (r) | ||
| 1004 | return r; | ||
| 1005 | r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN"); | ||
| 1006 | if (r) | ||
| 1007 | return r; | ||
| 1008 | return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT"); | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | static void dump_fw_registers(struct zd_chip *chip) | ||
| 1012 | { | ||
| 1013 | static const zd_addr_t addr[4] = { | ||
| 1014 | FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE, | ||
| 1015 | FW_LINK_STATUS | ||
| 1016 | }; | ||
| 1017 | |||
| 1018 | int r; | ||
| 1019 | u16 values[4]; | ||
| 1020 | |||
| 1021 | r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr, | ||
| 1022 | ARRAY_SIZE(addr)); | ||
| 1023 | if (r) { | ||
| 1024 | dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n", | ||
| 1025 | r); | ||
| 1026 | return; | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]); | ||
| 1030 | dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]); | ||
| 1031 | dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]); | ||
| 1032 | dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]); | ||
| 1033 | } | ||
| 1034 | #endif /* DEBUG */ | ||
| 1035 | |||
| 1036 | static int print_fw_version(struct zd_chip *chip) | ||
| 1037 | { | ||
| 1038 | int r; | ||
| 1039 | u16 version; | ||
| 1040 | |||
| 1041 | r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER); | ||
| 1042 | if (r) | ||
| 1043 | return r; | ||
| 1044 | |||
| 1045 | dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); | ||
| 1046 | return 0; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std) | ||
| 1050 | { | ||
| 1051 | u32 rates; | ||
| 1052 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 1053 | /* This sets the mandatory rates, which only depend from the standard | ||
| 1054 | * that the device is supporting. Until further notice we should try | ||
| 1055 | * to support 802.11g also for full speed USB. | ||
| 1056 | */ | ||
| 1057 | switch (std) { | ||
| 1058 | case IEEE80211B: | ||
| 1059 | rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M; | ||
| 1060 | break; | ||
| 1061 | case IEEE80211G: | ||
| 1062 | rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M| | ||
| 1063 | CR_RATE_6M|CR_RATE_12M|CR_RATE_24M; | ||
| 1064 | break; | ||
| 1065 | default: | ||
| 1066 | return -EINVAL; | ||
| 1067 | } | ||
| 1068 | return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | int zd_chip_enable_hwint(struct zd_chip *chip) | ||
| 1072 | { | ||
| 1073 | int r; | ||
| 1074 | |||
| 1075 | mutex_lock(&chip->mutex); | ||
| 1076 | r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT); | ||
| 1077 | mutex_unlock(&chip->mutex); | ||
| 1078 | return r; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | static int disable_hwint(struct zd_chip *chip) | ||
| 1082 | { | ||
| 1083 | return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | int zd_chip_disable_hwint(struct zd_chip *chip) | ||
| 1087 | { | ||
| 1088 | int r; | ||
| 1089 | |||
| 1090 | mutex_lock(&chip->mutex); | ||
| 1091 | r = disable_hwint(chip); | ||
| 1092 | mutex_unlock(&chip->mutex); | ||
| 1093 | return r; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) | ||
| 1097 | { | ||
| 1098 | int r; | ||
| 1099 | u8 rf_type; | ||
| 1100 | |||
| 1101 | dev_dbg_f(zd_chip_dev(chip), "\n"); | ||
| 1102 | |||
| 1103 | mutex_lock(&chip->mutex); | ||
| 1104 | chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0; | ||
| 1105 | |||
| 1106 | #ifdef DEBUG | ||
| 1107 | r = test_init(chip); | ||
| 1108 | if (r) | ||
| 1109 | goto out; | ||
| 1110 | #endif | ||
| 1111 | r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP); | ||
| 1112 | if (r) | ||
| 1113 | goto out; | ||
| 1114 | |||
| 1115 | r = zd_usb_init_hw(&chip->usb); | ||
| 1116 | if (r) | ||
| 1117 | goto out; | ||
| 1118 | |||
| 1119 | /* GPI is always disabled, also in the other driver. | ||
| 1120 | */ | ||
| 1121 | r = zd_iowrite32_locked(chip, 0, CR_GPI_EN); | ||
| 1122 | if (r) | ||
| 1123 | goto out; | ||
| 1124 | r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX); | ||
| 1125 | if (r) | ||
| 1126 | goto out; | ||
| 1127 | /* Currently we support IEEE 802.11g for full and high speed USB. | ||
| 1128 | * It might be discussed, whether we should suppport pure b mode for | ||
| 1129 | * full speed USB. | ||
| 1130 | */ | ||
| 1131 | r = set_mandatory_rates(chip, IEEE80211G); | ||
| 1132 | if (r) | ||
| 1133 | goto out; | ||
| 1134 | /* Disabling interrupts is certainly a smart thing here. | ||
| 1135 | */ | ||
| 1136 | r = disable_hwint(chip); | ||
| 1137 | if (r) | ||
| 1138 | goto out; | ||
| 1139 | r = read_pod(chip, &rf_type); | ||
| 1140 | if (r) | ||
| 1141 | goto out; | ||
| 1142 | r = hw_init(chip); | ||
| 1143 | if (r) | ||
| 1144 | goto out; | ||
| 1145 | r = zd_rf_init_hw(&chip->rf, rf_type); | ||
| 1146 | if (r) | ||
| 1147 | goto out; | ||
| 1148 | |||
| 1149 | r = print_fw_version(chip); | ||
| 1150 | if (r) | ||
| 1151 | goto out; | ||
| 1152 | |||
| 1153 | #ifdef DEBUG | ||
| 1154 | dump_fw_registers(chip); | ||
| 1155 | r = test_init(chip); | ||
| 1156 | if (r) | ||
| 1157 | goto out; | ||
| 1158 | #endif /* DEBUG */ | ||
| 1159 | |||
| 1160 | r = read_e2p_mac_addr(chip); | ||
| 1161 | if (r) | ||
| 1162 | goto out; | ||
| 1163 | |||
| 1164 | r = read_cal_int_tables(chip); | ||
| 1165 | if (r) | ||
| 1166 | goto out; | ||
| 1167 | |||
| 1168 | print_id(chip); | ||
| 1169 | out: | ||
| 1170 | mutex_unlock(&chip->mutex); | ||
| 1171 | return r; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | static int update_pwr_int(struct zd_chip *chip, u8 channel) | ||
| 1175 | { | ||
| 1176 | u8 value = chip->pwr_int_values[channel - 1]; | ||
| 1177 | dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n", | ||
| 1178 | channel, value); | ||
| 1179 | return zd_iowrite32_locked(chip, value, CR31); | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | static int update_pwr_cal(struct zd_chip *chip, u8 channel) | ||
| 1183 | { | ||
| 1184 | u8 value = chip->pwr_cal_values[channel-1]; | ||
| 1185 | dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n", | ||
| 1186 | channel, value); | ||
| 1187 | return zd_iowrite32_locked(chip, value, CR68); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | static int update_ofdm_cal(struct zd_chip *chip, u8 channel) | ||
| 1191 | { | ||
| 1192 | struct zd_ioreq32 ioreqs[3]; | ||
| 1193 | |||
| 1194 | ioreqs[0].addr = CR67; | ||
| 1195 | ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; | ||
| 1196 | ioreqs[1].addr = CR66; | ||
| 1197 | ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; | ||
| 1198 | ioreqs[2].addr = CR65; | ||
| 1199 | ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; | ||
| 1200 | |||
| 1201 | dev_dbg_f(zd_chip_dev(chip), | ||
| 1202 | "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n", | ||
| 1203 | channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value); | ||
| 1204 | return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | static int update_channel_integration_and_calibration(struct zd_chip *chip, | ||
| 1208 | u8 channel) | ||
| 1209 | { | ||
| 1210 | int r; | ||
| 1211 | |||
| 1212 | r = update_pwr_int(chip, channel); | ||
| 1213 | if (r) | ||
| 1214 | return r; | ||
| 1215 | if (chip->is_zd1211b) { | ||
| 1216 | static const struct zd_ioreq32 ioreqs[] = { | ||
| 1217 | { CR69, 0x28 }, | ||
| 1218 | {}, | ||
| 1219 | { CR69, 0x2a }, | ||
| 1220 | }; | ||
| 1221 | |||
| 1222 | r = update_ofdm_cal(chip, channel); | ||
| 1223 | if (r) | ||
| 1224 | return r; | ||
| 1225 | r = update_pwr_cal(chip, channel); | ||
| 1226 | if (r) | ||
| 1227 | return r; | ||
| 1228 | r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 1229 | if (r) | ||
| 1230 | return r; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | return 0; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | /* The CCK baseband gain can be optionally patched by the EEPROM */ | ||
| 1237 | static int patch_cck_gain(struct zd_chip *chip) | ||
| 1238 | { | ||
| 1239 | int r; | ||
| 1240 | u32 value; | ||
| 1241 | |||
| 1242 | if (!chip->patch_cck_gain) | ||
| 1243 | return 0; | ||
| 1244 | |||
| 1245 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 1246 | r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); | ||
| 1247 | if (r) | ||
| 1248 | return r; | ||
| 1249 | dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); | ||
| 1250 | return zd_iowrite32_locked(chip, value & 0xff, CR47); | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | int zd_chip_set_channel(struct zd_chip *chip, u8 channel) | ||
| 1254 | { | ||
| 1255 | int r, t; | ||
| 1256 | |||
| 1257 | mutex_lock(&chip->mutex); | ||
| 1258 | r = zd_chip_lock_phy_regs(chip); | ||
| 1259 | if (r) | ||
| 1260 | goto out; | ||
| 1261 | r = zd_rf_set_channel(&chip->rf, channel); | ||
| 1262 | if (r) | ||
| 1263 | goto unlock; | ||
| 1264 | r = update_channel_integration_and_calibration(chip, channel); | ||
| 1265 | if (r) | ||
| 1266 | goto unlock; | ||
| 1267 | r = patch_cck_gain(chip); | ||
| 1268 | if (r) | ||
| 1269 | goto unlock; | ||
| 1270 | r = patch_6m_band_edge(chip, channel); | ||
| 1271 | if (r) | ||
| 1272 | goto unlock; | ||
| 1273 | r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS); | ||
| 1274 | unlock: | ||
| 1275 | t = zd_chip_unlock_phy_regs(chip); | ||
| 1276 | if (t && !r) | ||
| 1277 | r = t; | ||
| 1278 | out: | ||
| 1279 | mutex_unlock(&chip->mutex); | ||
| 1280 | return r; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | u8 zd_chip_get_channel(struct zd_chip *chip) | ||
| 1284 | { | ||
| 1285 | u8 channel; | ||
| 1286 | |||
| 1287 | mutex_lock(&chip->mutex); | ||
| 1288 | channel = chip->rf.channel; | ||
| 1289 | mutex_unlock(&chip->mutex); | ||
| 1290 | return channel; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | static u16 led_mask(int led) | ||
| 1294 | { | ||
| 1295 | switch (led) { | ||
| 1296 | case 1: | ||
| 1297 | return LED1; | ||
| 1298 | case 2: | ||
| 1299 | return LED2; | ||
| 1300 | default: | ||
| 1301 | return 0; | ||
| 1302 | } | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | static int read_led_reg(struct zd_chip *chip, u16 *status) | ||
| 1306 | { | ||
| 1307 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 1308 | return zd_ioread16_locked(chip, status, CR_LED); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static int write_led_reg(struct zd_chip *chip, u16 status) | ||
| 1312 | { | ||
| 1313 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 1314 | return zd_iowrite16_locked(chip, status, CR_LED); | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status) | ||
| 1318 | { | ||
| 1319 | int r, ret; | ||
| 1320 | u16 mask = led_mask(led); | ||
| 1321 | u16 reg; | ||
| 1322 | |||
| 1323 | if (!mask) | ||
| 1324 | return -EINVAL; | ||
| 1325 | mutex_lock(&chip->mutex); | ||
| 1326 | r = read_led_reg(chip, ®); | ||
| 1327 | if (r) | ||
| 1328 | return r; | ||
| 1329 | switch (status) { | ||
| 1330 | case LED_STATUS: | ||
| 1331 | return (reg & mask) ? LED_ON : LED_OFF; | ||
| 1332 | case LED_OFF: | ||
| 1333 | reg &= ~mask; | ||
| 1334 | ret = LED_OFF; | ||
| 1335 | break; | ||
| 1336 | case LED_FLIP: | ||
| 1337 | reg ^= mask; | ||
| 1338 | ret = (reg&mask) ? LED_ON : LED_OFF; | ||
| 1339 | break; | ||
| 1340 | case LED_ON: | ||
| 1341 | reg |= mask; | ||
| 1342 | ret = LED_ON; | ||
| 1343 | break; | ||
| 1344 | default: | ||
| 1345 | return -EINVAL; | ||
| 1346 | } | ||
| 1347 | r = write_led_reg(chip, reg); | ||
| 1348 | if (r) { | ||
| 1349 | ret = r; | ||
| 1350 | goto out; | ||
| 1351 | } | ||
| 1352 | out: | ||
| 1353 | mutex_unlock(&chip->mutex); | ||
| 1354 | return r; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | int zd_chip_led_flip(struct zd_chip *chip, int led, | ||
| 1358 | const unsigned int *phases_msecs, unsigned int count) | ||
| 1359 | { | ||
| 1360 | int i, r; | ||
| 1361 | enum led_status status; | ||
| 1362 | |||
| 1363 | r = zd_chip_led_status(chip, led, LED_STATUS); | ||
| 1364 | if (r) | ||
| 1365 | return r; | ||
| 1366 | status = r; | ||
| 1367 | for (i = 0; i < count; i++) { | ||
| 1368 | r = zd_chip_led_status(chip, led, LED_FLIP); | ||
| 1369 | if (r < 0) | ||
| 1370 | goto out; | ||
| 1371 | msleep(phases_msecs[i]); | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | out: | ||
| 1375 | zd_chip_led_status(chip, led, status); | ||
| 1376 | return r; | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) | ||
| 1380 | { | ||
| 1381 | int r; | ||
| 1382 | |||
| 1383 | if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) | ||
| 1384 | return -EINVAL; | ||
| 1385 | |||
| 1386 | mutex_lock(&chip->mutex); | ||
| 1387 | r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); | ||
| 1388 | mutex_unlock(&chip->mutex); | ||
| 1389 | return r; | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) | ||
| 1393 | { | ||
| 1394 | static const u16 constants[] = { | ||
| 1395 | 715, 655, 585, 540, 470, 410, 360, 315, | ||
| 1396 | 270, 235, 205, 175, 150, 125, 105, 85, | ||
| 1397 | 65, 50, 40, 25, 15 | ||
| 1398 | }; | ||
| 1399 | |||
| 1400 | int i; | ||
| 1401 | u32 x; | ||
| 1402 | |||
| 1403 | /* It seems that their quality parameter is somehow per signal | ||
| 1404 | * and is now transferred per bit. | ||
| 1405 | */ | ||
| 1406 | switch (rate) { | ||
| 1407 | case ZD_OFDM_RATE_6M: | ||
| 1408 | case ZD_OFDM_RATE_12M: | ||
| 1409 | case ZD_OFDM_RATE_24M: | ||
| 1410 | size *= 2; | ||
| 1411 | break; | ||
| 1412 | case ZD_OFDM_RATE_9M: | ||
| 1413 | case ZD_OFDM_RATE_18M: | ||
| 1414 | case ZD_OFDM_RATE_36M: | ||
| 1415 | case ZD_OFDM_RATE_54M: | ||
| 1416 | size *= 4; | ||
| 1417 | size /= 3; | ||
| 1418 | break; | ||
| 1419 | case ZD_OFDM_RATE_48M: | ||
| 1420 | size *= 3; | ||
| 1421 | size /= 2; | ||
| 1422 | break; | ||
| 1423 | default: | ||
| 1424 | return -EINVAL; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | x = (10000 * status_quality)/size; | ||
| 1428 | for (i = 0; i < ARRAY_SIZE(constants); i++) { | ||
| 1429 | if (x > constants[i]) | ||
| 1430 | break; | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | return i; | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | static unsigned int log10times100(unsigned int x) | ||
| 1437 | { | ||
| 1438 | static const u8 log10[] = { | ||
| 1439 | 0, | ||
| 1440 | 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, | ||
| 1441 | 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, | ||
| 1442 | 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, | ||
| 1443 | 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, | ||
| 1444 | 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, | ||
| 1445 | 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, | ||
| 1446 | 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, | ||
| 1447 | 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, | ||
| 1448 | 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, | ||
| 1449 | 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, | ||
| 1450 | 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, | ||
| 1451 | 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, | ||
| 1452 | 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, | ||
| 1453 | 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, | ||
| 1454 | 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, | ||
| 1455 | 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, | ||
| 1456 | 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, | ||
| 1457 | 223, 223, 223, 224, 224, 224, 224, | ||
| 1458 | }; | ||
| 1459 | |||
| 1460 | return x < ARRAY_SIZE(log10) ? log10[x] : 225; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | enum { | ||
| 1464 | MAX_CCK_EVM_DB = 45, | ||
| 1465 | }; | ||
| 1466 | |||
| 1467 | static int cck_evm_db(u8 status_quality) | ||
| 1468 | { | ||
| 1469 | return (20 * log10times100(status_quality)) / 100; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | static int cck_snr_db(u8 status_quality) | ||
| 1473 | { | ||
| 1474 | int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); | ||
| 1475 | ZD_ASSERT(r >= 0); | ||
| 1476 | return r; | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | static int rx_qual_db(const void *rx_frame, unsigned int size, | ||
| 1480 | const struct rx_status *status) | ||
| 1481 | { | ||
| 1482 | return (status->frame_status&ZD_RX_OFDM) ? | ||
| 1483 | ofdm_qual_db(status->signal_quality_ofdm, | ||
| 1484 | zd_ofdm_plcp_header_rate(rx_frame), | ||
| 1485 | size) : | ||
| 1486 | cck_snr_db(status->signal_quality_cck); | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
| 1490 | const struct rx_status *status) | ||
| 1491 | { | ||
| 1492 | int r = rx_qual_db(rx_frame, size, status); | ||
| 1493 | if (r < 0) | ||
| 1494 | r = 0; | ||
| 1495 | r = (r * 100) / 14; | ||
| 1496 | if (r > 100) | ||
| 1497 | r = 100; | ||
| 1498 | return r; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | u8 zd_rx_strength_percent(u8 rssi) | ||
| 1502 | { | ||
| 1503 | int r = (rssi*100) / 30; | ||
| 1504 | if (r > 100) | ||
| 1505 | r = 100; | ||
| 1506 | return (u8) r; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status) | ||
| 1510 | { | ||
| 1511 | static const u16 ofdm_rates[] = { | ||
| 1512 | [ZD_OFDM_RATE_6M] = 60, | ||
| 1513 | [ZD_OFDM_RATE_9M] = 90, | ||
| 1514 | [ZD_OFDM_RATE_12M] = 120, | ||
| 1515 | [ZD_OFDM_RATE_18M] = 180, | ||
| 1516 | [ZD_OFDM_RATE_24M] = 240, | ||
| 1517 | [ZD_OFDM_RATE_36M] = 360, | ||
| 1518 | [ZD_OFDM_RATE_48M] = 480, | ||
| 1519 | [ZD_OFDM_RATE_54M] = 540, | ||
| 1520 | }; | ||
| 1521 | u16 rate; | ||
| 1522 | if (status->frame_status & ZD_RX_OFDM) { | ||
| 1523 | u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame); | ||
| 1524 | rate = ofdm_rates[ofdm_rate & 0xf]; | ||
| 1525 | } else { | ||
| 1526 | u8 cck_rate = zd_cck_plcp_header_rate(rx_frame); | ||
| 1527 | switch (cck_rate) { | ||
| 1528 | case ZD_CCK_SIGNAL_1M: | ||
| 1529 | rate = 10; | ||
| 1530 | break; | ||
| 1531 | case ZD_CCK_SIGNAL_2M: | ||
| 1532 | rate = 20; | ||
| 1533 | break; | ||
| 1534 | case ZD_CCK_SIGNAL_5M5: | ||
| 1535 | rate = 55; | ||
| 1536 | break; | ||
| 1537 | case ZD_CCK_SIGNAL_11M: | ||
| 1538 | rate = 110; | ||
| 1539 | break; | ||
| 1540 | default: | ||
| 1541 | rate = 0; | ||
| 1542 | } | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | return rate; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | int zd_chip_switch_radio_on(struct zd_chip *chip) | ||
| 1549 | { | ||
| 1550 | int r; | ||
| 1551 | |||
| 1552 | mutex_lock(&chip->mutex); | ||
| 1553 | r = zd_switch_radio_on(&chip->rf); | ||
| 1554 | mutex_unlock(&chip->mutex); | ||
| 1555 | return r; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | int zd_chip_switch_radio_off(struct zd_chip *chip) | ||
| 1559 | { | ||
| 1560 | int r; | ||
| 1561 | |||
| 1562 | mutex_lock(&chip->mutex); | ||
| 1563 | r = zd_switch_radio_off(&chip->rf); | ||
| 1564 | mutex_unlock(&chip->mutex); | ||
| 1565 | return r; | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | int zd_chip_enable_int(struct zd_chip *chip) | ||
| 1569 | { | ||
| 1570 | int r; | ||
| 1571 | |||
| 1572 | mutex_lock(&chip->mutex); | ||
| 1573 | r = zd_usb_enable_int(&chip->usb); | ||
| 1574 | mutex_unlock(&chip->mutex); | ||
| 1575 | return r; | ||
| 1576 | } | ||
| 1577 | |||
| 1578 | void zd_chip_disable_int(struct zd_chip *chip) | ||
| 1579 | { | ||
| 1580 | mutex_lock(&chip->mutex); | ||
| 1581 | zd_usb_disable_int(&chip->usb); | ||
| 1582 | mutex_unlock(&chip->mutex); | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | int zd_chip_enable_rx(struct zd_chip *chip) | ||
| 1586 | { | ||
| 1587 | int r; | ||
| 1588 | |||
| 1589 | mutex_lock(&chip->mutex); | ||
| 1590 | r = zd_usb_enable_rx(&chip->usb); | ||
| 1591 | mutex_unlock(&chip->mutex); | ||
| 1592 | return r; | ||
| 1593 | } | ||
| 1594 | |||
| 1595 | void zd_chip_disable_rx(struct zd_chip *chip) | ||
| 1596 | { | ||
| 1597 | mutex_lock(&chip->mutex); | ||
| 1598 | zd_usb_disable_rx(&chip->usb); | ||
| 1599 | mutex_unlock(&chip->mutex); | ||
| 1600 | } | ||
| 1601 | |||
| 1602 | int zd_rfwritev_locked(struct zd_chip *chip, | ||
| 1603 | const u32* values, unsigned int count, u8 bits) | ||
| 1604 | { | ||
| 1605 | int r; | ||
| 1606 | unsigned int i; | ||
| 1607 | |||
| 1608 | for (i = 0; i < count; i++) { | ||
| 1609 | r = zd_rfwrite_locked(chip, values[i], bits); | ||
| 1610 | if (r) | ||
| 1611 | return r; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | return 0; | ||
| 1615 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h new file mode 100644 index 000000000000..805121093ab5 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
| @@ -0,0 +1,825 @@ | |||
| 1 | /* zd_chip.h | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_CHIP_H | ||
| 19 | #define _ZD_CHIP_H | ||
| 20 | |||
| 21 | #include "zd_types.h" | ||
| 22 | #include "zd_rf.h" | ||
| 23 | #include "zd_usb.h" | ||
| 24 | |||
| 25 | /* Header for the Media Access Controller (MAC) and the Baseband Processor | ||
| 26 | * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and | ||
| 27 | * adds a processor for handling the USB protocol. | ||
| 28 | */ | ||
| 29 | |||
| 30 | /* 8-bit hardware registers */ | ||
| 31 | #define CR0 CTL_REG(0x0000) | ||
| 32 | #define CR1 CTL_REG(0x0004) | ||
| 33 | #define CR2 CTL_REG(0x0008) | ||
| 34 | #define CR3 CTL_REG(0x000C) | ||
| 35 | |||
| 36 | #define CR5 CTL_REG(0x0010) | ||
| 37 | /* bit 5: if set short preamble used | ||
| 38 | * bit 6: filter band - Japan channel 14 on, else off | ||
| 39 | */ | ||
| 40 | #define CR6 CTL_REG(0x0014) | ||
| 41 | #define CR7 CTL_REG(0x0018) | ||
| 42 | #define CR8 CTL_REG(0x001C) | ||
| 43 | |||
| 44 | #define CR4 CTL_REG(0x0020) | ||
| 45 | |||
| 46 | #define CR9 CTL_REG(0x0024) | ||
| 47 | /* bit 2: antenna switch (together with CR10) */ | ||
| 48 | #define CR10 CTL_REG(0x0028) | ||
| 49 | /* bit 1: antenna switch (together with CR9) | ||
| 50 | * RF2959 controls with CR11 radion on and off | ||
| 51 | */ | ||
| 52 | #define CR11 CTL_REG(0x002C) | ||
| 53 | /* bit 6: TX power control for OFDM | ||
| 54 | * RF2959 controls with CR10 radio on and off | ||
| 55 | */ | ||
| 56 | #define CR12 CTL_REG(0x0030) | ||
| 57 | #define CR13 CTL_REG(0x0034) | ||
| 58 | #define CR14 CTL_REG(0x0038) | ||
| 59 | #define CR15 CTL_REG(0x003C) | ||
| 60 | #define CR16 CTL_REG(0x0040) | ||
| 61 | #define CR17 CTL_REG(0x0044) | ||
| 62 | #define CR18 CTL_REG(0x0048) | ||
| 63 | #define CR19 CTL_REG(0x004C) | ||
| 64 | #define CR20 CTL_REG(0x0050) | ||
| 65 | #define CR21 CTL_REG(0x0054) | ||
| 66 | #define CR22 CTL_REG(0x0058) | ||
| 67 | #define CR23 CTL_REG(0x005C) | ||
| 68 | #define CR24 CTL_REG(0x0060) /* CCA threshold */ | ||
| 69 | #define CR25 CTL_REG(0x0064) | ||
| 70 | #define CR26 CTL_REG(0x0068) | ||
| 71 | #define CR27 CTL_REG(0x006C) | ||
| 72 | #define CR28 CTL_REG(0x0070) | ||
| 73 | #define CR29 CTL_REG(0x0074) | ||
| 74 | #define CR30 CTL_REG(0x0078) | ||
| 75 | #define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ | ||
| 76 | #define CR32 CTL_REG(0x0080) | ||
| 77 | #define CR33 CTL_REG(0x0084) | ||
| 78 | #define CR34 CTL_REG(0x0088) | ||
| 79 | #define CR35 CTL_REG(0x008C) | ||
| 80 | #define CR36 CTL_REG(0x0090) | ||
| 81 | #define CR37 CTL_REG(0x0094) | ||
| 82 | #define CR38 CTL_REG(0x0098) | ||
| 83 | #define CR39 CTL_REG(0x009C) | ||
| 84 | #define CR40 CTL_REG(0x00A0) | ||
| 85 | #define CR41 CTL_REG(0x00A4) | ||
| 86 | #define CR42 CTL_REG(0x00A8) | ||
| 87 | #define CR43 CTL_REG(0x00AC) | ||
| 88 | #define CR44 CTL_REG(0x00B0) | ||
| 89 | #define CR45 CTL_REG(0x00B4) | ||
| 90 | #define CR46 CTL_REG(0x00B8) | ||
| 91 | #define CR47 CTL_REG(0x00BC) /* CCK baseband gain | ||
| 92 | * (patch value might be in EEPROM) | ||
| 93 | */ | ||
| 94 | #define CR48 CTL_REG(0x00C0) | ||
| 95 | #define CR49 CTL_REG(0x00C4) | ||
| 96 | #define CR50 CTL_REG(0x00C8) | ||
| 97 | #define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ | ||
| 98 | #define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ | ||
| 99 | #define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ | ||
| 100 | #define CR54 CTL_REG(0x00D8) | ||
| 101 | #define CR55 CTL_REG(0x00DC) | ||
| 102 | #define CR56 CTL_REG(0x00E0) | ||
| 103 | #define CR57 CTL_REG(0x00E4) | ||
| 104 | #define CR58 CTL_REG(0x00E8) | ||
| 105 | #define CR59 CTL_REG(0x00EC) | ||
| 106 | #define CR60 CTL_REG(0x00F0) | ||
| 107 | #define CR61 CTL_REG(0x00F4) | ||
| 108 | #define CR62 CTL_REG(0x00F8) | ||
| 109 | #define CR63 CTL_REG(0x00FC) | ||
| 110 | #define CR64 CTL_REG(0x0100) | ||
| 111 | #define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ | ||
| 112 | #define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ | ||
| 113 | #define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ | ||
| 114 | #define CR68 CTL_REG(0x0110) /* CCK calibration */ | ||
| 115 | #define CR69 CTL_REG(0x0114) | ||
| 116 | #define CR70 CTL_REG(0x0118) | ||
| 117 | #define CR71 CTL_REG(0x011C) | ||
| 118 | #define CR72 CTL_REG(0x0120) | ||
| 119 | #define CR73 CTL_REG(0x0124) | ||
| 120 | #define CR74 CTL_REG(0x0128) | ||
| 121 | #define CR75 CTL_REG(0x012C) | ||
| 122 | #define CR76 CTL_REG(0x0130) | ||
| 123 | #define CR77 CTL_REG(0x0134) | ||
| 124 | #define CR78 CTL_REG(0x0138) | ||
| 125 | #define CR79 CTL_REG(0x013C) | ||
| 126 | #define CR80 CTL_REG(0x0140) | ||
| 127 | #define CR81 CTL_REG(0x0144) | ||
| 128 | #define CR82 CTL_REG(0x0148) | ||
| 129 | #define CR83 CTL_REG(0x014C) | ||
| 130 | #define CR84 CTL_REG(0x0150) | ||
| 131 | #define CR85 CTL_REG(0x0154) | ||
| 132 | #define CR86 CTL_REG(0x0158) | ||
| 133 | #define CR87 CTL_REG(0x015C) | ||
| 134 | #define CR88 CTL_REG(0x0160) | ||
| 135 | #define CR89 CTL_REG(0x0164) | ||
| 136 | #define CR90 CTL_REG(0x0168) | ||
| 137 | #define CR91 CTL_REG(0x016C) | ||
| 138 | #define CR92 CTL_REG(0x0170) | ||
| 139 | #define CR93 CTL_REG(0x0174) | ||
| 140 | #define CR94 CTL_REG(0x0178) | ||
| 141 | #define CR95 CTL_REG(0x017C) | ||
| 142 | #define CR96 CTL_REG(0x0180) | ||
| 143 | #define CR97 CTL_REG(0x0184) | ||
| 144 | #define CR98 CTL_REG(0x0188) | ||
| 145 | #define CR99 CTL_REG(0x018C) | ||
| 146 | #define CR100 CTL_REG(0x0190) | ||
| 147 | #define CR101 CTL_REG(0x0194) | ||
| 148 | #define CR102 CTL_REG(0x0198) | ||
| 149 | #define CR103 CTL_REG(0x019C) | ||
| 150 | #define CR104 CTL_REG(0x01A0) | ||
| 151 | #define CR105 CTL_REG(0x01A4) | ||
| 152 | #define CR106 CTL_REG(0x01A8) | ||
| 153 | #define CR107 CTL_REG(0x01AC) | ||
| 154 | #define CR108 CTL_REG(0x01B0) | ||
| 155 | #define CR109 CTL_REG(0x01B4) | ||
| 156 | #define CR110 CTL_REG(0x01B8) | ||
| 157 | #define CR111 CTL_REG(0x01BC) | ||
| 158 | #define CR112 CTL_REG(0x01C0) | ||
| 159 | #define CR113 CTL_REG(0x01C4) | ||
| 160 | #define CR114 CTL_REG(0x01C8) | ||
| 161 | #define CR115 CTL_REG(0x01CC) | ||
| 162 | #define CR116 CTL_REG(0x01D0) | ||
| 163 | #define CR117 CTL_REG(0x01D4) | ||
| 164 | #define CR118 CTL_REG(0x01D8) | ||
| 165 | #define CR119 CTL_REG(0x01DC) | ||
| 166 | #define CR120 CTL_REG(0x01E0) | ||
| 167 | #define CR121 CTL_REG(0x01E4) | ||
| 168 | #define CR122 CTL_REG(0x01E8) | ||
| 169 | #define CR123 CTL_REG(0x01EC) | ||
| 170 | #define CR124 CTL_REG(0x01F0) | ||
| 171 | #define CR125 CTL_REG(0x01F4) | ||
| 172 | #define CR126 CTL_REG(0x01F8) | ||
| 173 | #define CR127 CTL_REG(0x01FC) | ||
| 174 | #define CR128 CTL_REG(0x0200) | ||
| 175 | #define CR129 CTL_REG(0x0204) | ||
| 176 | #define CR130 CTL_REG(0x0208) | ||
| 177 | #define CR131 CTL_REG(0x020C) | ||
| 178 | #define CR132 CTL_REG(0x0210) | ||
| 179 | #define CR133 CTL_REG(0x0214) | ||
| 180 | #define CR134 CTL_REG(0x0218) | ||
| 181 | #define CR135 CTL_REG(0x021C) | ||
| 182 | #define CR136 CTL_REG(0x0220) | ||
| 183 | #define CR137 CTL_REG(0x0224) | ||
| 184 | #define CR138 CTL_REG(0x0228) | ||
| 185 | #define CR139 CTL_REG(0x022C) | ||
| 186 | #define CR140 CTL_REG(0x0230) | ||
| 187 | #define CR141 CTL_REG(0x0234) | ||
| 188 | #define CR142 CTL_REG(0x0238) | ||
| 189 | #define CR143 CTL_REG(0x023C) | ||
| 190 | #define CR144 CTL_REG(0x0240) | ||
| 191 | #define CR145 CTL_REG(0x0244) | ||
| 192 | #define CR146 CTL_REG(0x0248) | ||
| 193 | #define CR147 CTL_REG(0x024C) | ||
| 194 | #define CR148 CTL_REG(0x0250) | ||
| 195 | #define CR149 CTL_REG(0x0254) | ||
| 196 | #define CR150 CTL_REG(0x0258) | ||
| 197 | #define CR151 CTL_REG(0x025C) | ||
| 198 | #define CR152 CTL_REG(0x0260) | ||
| 199 | #define CR153 CTL_REG(0x0264) | ||
| 200 | #define CR154 CTL_REG(0x0268) | ||
| 201 | #define CR155 CTL_REG(0x026C) | ||
| 202 | #define CR156 CTL_REG(0x0270) | ||
| 203 | #define CR157 CTL_REG(0x0274) | ||
| 204 | #define CR158 CTL_REG(0x0278) | ||
| 205 | #define CR159 CTL_REG(0x027C) | ||
| 206 | #define CR160 CTL_REG(0x0280) | ||
| 207 | #define CR161 CTL_REG(0x0284) | ||
| 208 | #define CR162 CTL_REG(0x0288) | ||
| 209 | #define CR163 CTL_REG(0x028C) | ||
| 210 | #define CR164 CTL_REG(0x0290) | ||
| 211 | #define CR165 CTL_REG(0x0294) | ||
| 212 | #define CR166 CTL_REG(0x0298) | ||
| 213 | #define CR167 CTL_REG(0x029C) | ||
| 214 | #define CR168 CTL_REG(0x02A0) | ||
| 215 | #define CR169 CTL_REG(0x02A4) | ||
| 216 | #define CR170 CTL_REG(0x02A8) | ||
| 217 | #define CR171 CTL_REG(0x02AC) | ||
| 218 | #define CR172 CTL_REG(0x02B0) | ||
| 219 | #define CR173 CTL_REG(0x02B4) | ||
| 220 | #define CR174 CTL_REG(0x02B8) | ||
| 221 | #define CR175 CTL_REG(0x02BC) | ||
| 222 | #define CR176 CTL_REG(0x02C0) | ||
| 223 | #define CR177 CTL_REG(0x02C4) | ||
| 224 | #define CR178 CTL_REG(0x02C8) | ||
| 225 | #define CR179 CTL_REG(0x02CC) | ||
| 226 | #define CR180 CTL_REG(0x02D0) | ||
| 227 | #define CR181 CTL_REG(0x02D4) | ||
| 228 | #define CR182 CTL_REG(0x02D8) | ||
| 229 | #define CR183 CTL_REG(0x02DC) | ||
| 230 | #define CR184 CTL_REG(0x02E0) | ||
| 231 | #define CR185 CTL_REG(0x02E4) | ||
| 232 | #define CR186 CTL_REG(0x02E8) | ||
| 233 | #define CR187 CTL_REG(0x02EC) | ||
| 234 | #define CR188 CTL_REG(0x02F0) | ||
| 235 | #define CR189 CTL_REG(0x02F4) | ||
| 236 | #define CR190 CTL_REG(0x02F8) | ||
| 237 | #define CR191 CTL_REG(0x02FC) | ||
| 238 | #define CR192 CTL_REG(0x0300) | ||
| 239 | #define CR193 CTL_REG(0x0304) | ||
| 240 | #define CR194 CTL_REG(0x0308) | ||
| 241 | #define CR195 CTL_REG(0x030C) | ||
| 242 | #define CR196 CTL_REG(0x0310) | ||
| 243 | #define CR197 CTL_REG(0x0314) | ||
| 244 | #define CR198 CTL_REG(0x0318) | ||
| 245 | #define CR199 CTL_REG(0x031C) | ||
| 246 | #define CR200 CTL_REG(0x0320) | ||
| 247 | #define CR201 CTL_REG(0x0324) | ||
| 248 | #define CR202 CTL_REG(0x0328) | ||
| 249 | #define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ | ||
| 250 | #define CR204 CTL_REG(0x0330) | ||
| 251 | #define CR205 CTL_REG(0x0334) | ||
| 252 | #define CR206 CTL_REG(0x0338) | ||
| 253 | #define CR207 CTL_REG(0x033C) | ||
| 254 | #define CR208 CTL_REG(0x0340) | ||
| 255 | #define CR209 CTL_REG(0x0344) | ||
| 256 | #define CR210 CTL_REG(0x0348) | ||
| 257 | #define CR211 CTL_REG(0x034C) | ||
| 258 | #define CR212 CTL_REG(0x0350) | ||
| 259 | #define CR213 CTL_REG(0x0354) | ||
| 260 | #define CR214 CTL_REG(0x0358) | ||
| 261 | #define CR215 CTL_REG(0x035C) | ||
| 262 | #define CR216 CTL_REG(0x0360) | ||
| 263 | #define CR217 CTL_REG(0x0364) | ||
| 264 | #define CR218 CTL_REG(0x0368) | ||
| 265 | #define CR219 CTL_REG(0x036C) | ||
| 266 | #define CR220 CTL_REG(0x0370) | ||
| 267 | #define CR221 CTL_REG(0x0374) | ||
| 268 | #define CR222 CTL_REG(0x0378) | ||
| 269 | #define CR223 CTL_REG(0x037C) | ||
| 270 | #define CR224 CTL_REG(0x0380) | ||
| 271 | #define CR225 CTL_REG(0x0384) | ||
| 272 | #define CR226 CTL_REG(0x0388) | ||
| 273 | #define CR227 CTL_REG(0x038C) | ||
| 274 | #define CR228 CTL_REG(0x0390) | ||
| 275 | #define CR229 CTL_REG(0x0394) | ||
| 276 | #define CR230 CTL_REG(0x0398) | ||
| 277 | #define CR231 CTL_REG(0x039C) | ||
| 278 | #define CR232 CTL_REG(0x03A0) | ||
| 279 | #define CR233 CTL_REG(0x03A4) | ||
| 280 | #define CR234 CTL_REG(0x03A8) | ||
| 281 | #define CR235 CTL_REG(0x03AC) | ||
| 282 | #define CR236 CTL_REG(0x03B0) | ||
| 283 | |||
| 284 | #define CR240 CTL_REG(0x03C0) | ||
| 285 | /* bit 7: host-controlled RF register writes | ||
| 286 | * CR241-CR245: for hardware controlled writing of RF bits, not needed for | ||
| 287 | * USB | ||
| 288 | */ | ||
| 289 | #define CR241 CTL_REG(0x03C4) | ||
| 290 | #define CR242 CTL_REG(0x03C8) | ||
| 291 | #define CR243 CTL_REG(0x03CC) | ||
| 292 | #define CR244 CTL_REG(0x03D0) | ||
| 293 | #define CR245 CTL_REG(0x03D4) | ||
| 294 | |||
| 295 | #define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of | ||
| 296 | * Airoha RFs AL2230 and AL7230B | ||
| 297 | */ | ||
| 298 | #define CR252 CTL_REG(0x03F0) | ||
| 299 | #define CR253 CTL_REG(0x03F4) | ||
| 300 | #define CR254 CTL_REG(0x03F8) | ||
| 301 | #define CR255 CTL_REG(0x03FC) | ||
| 302 | |||
| 303 | #define CR_MAX_PHY_REG 255 | ||
| 304 | |||
| 305 | /* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211 | ||
| 306 | * driver. | ||
| 307 | */ | ||
| 308 | |||
| 309 | #define CR_RF_IF_CLK CTL_REG(0x0400) | ||
| 310 | #define CR_RF_IF_DATA CTL_REG(0x0404) | ||
| 311 | #define CR_PE1_PE2 CTL_REG(0x0408) | ||
| 312 | #define CR_PE2_DLY CTL_REG(0x040C) | ||
| 313 | #define CR_LE1 CTL_REG(0x0410) | ||
| 314 | #define CR_LE2 CTL_REG(0x0414) | ||
| 315 | /* Seems to enable/disable GPI (General Purpose IO?) */ | ||
| 316 | #define CR_GPI_EN CTL_REG(0x0418) | ||
| 317 | #define CR_RADIO_PD CTL_REG(0x042C) | ||
| 318 | #define CR_RF2948_PD CTL_REG(0x042C) | ||
| 319 | #define CR_ENABLE_PS_MANUAL_AGC CTL_REG(0x043C) | ||
| 320 | #define CR_CONFIG_PHILIPS CTL_REG(0x0440) | ||
| 321 | #define CR_SA2400_SER_AP CTL_REG(0x0444) | ||
| 322 | #define CR_I2C_WRITE CTL_REG(0x0444) | ||
| 323 | #define CR_SA2400_SER_RP CTL_REG(0x0448) | ||
| 324 | #define CR_RADIO_PE CTL_REG(0x0458) | ||
| 325 | #define CR_RST_BUS_MASTER CTL_REG(0x045C) | ||
| 326 | #define CR_RFCFG CTL_REG(0x0464) | ||
| 327 | #define CR_HSTSCHG CTL_REG(0x046C) | ||
| 328 | #define CR_PHY_ON CTL_REG(0x0474) | ||
| 329 | #define CR_RX_DELAY CTL_REG(0x0478) | ||
| 330 | #define CR_RX_PE_DELAY CTL_REG(0x047C) | ||
| 331 | #define CR_GPIO_1 CTL_REG(0x0490) | ||
| 332 | #define CR_GPIO_2 CTL_REG(0x0494) | ||
| 333 | #define CR_EncryBufMux CTL_REG(0x04A8) | ||
| 334 | #define CR_PS_CTRL CTL_REG(0x0500) | ||
| 335 | #define CR_ADDA_PWR_DWN CTL_REG(0x0504) | ||
| 336 | #define CR_ADDA_MBIAS_WARMTIME CTL_REG(0x0508) | ||
| 337 | #define CR_MAC_PS_STATE CTL_REG(0x050C) | ||
| 338 | |||
| 339 | #define CR_INTERRUPT CTL_REG(0x0510) | ||
| 340 | #define INT_TX_COMPLETE 0x00000001 | ||
| 341 | #define INT_RX_COMPLETE 0x00000002 | ||
| 342 | #define INT_RETRY_FAIL 0x00000004 | ||
| 343 | #define INT_WAKEUP 0x00000008 | ||
| 344 | #define INT_DTIM_NOTIFY 0x00000020 | ||
| 345 | #define INT_CFG_NEXT_BCN 0x00000040 | ||
| 346 | #define INT_BUS_ABORT 0x00000080 | ||
| 347 | #define INT_TX_FIFO_READY 0x00000100 | ||
| 348 | #define INT_UART 0x00000200 | ||
| 349 | #define INT_TX_COMPLETE_EN 0x00010000 | ||
| 350 | #define INT_RX_COMPLETE_EN 0x00020000 | ||
| 351 | #define INT_RETRY_FAIL_EN 0x00040000 | ||
| 352 | #define INT_WAKEUP_EN 0x00080000 | ||
| 353 | #define INT_DTIM_NOTIFY_EN 0x00200000 | ||
| 354 | #define INT_CFG_NEXT_BCN_EN 0x00400000 | ||
| 355 | #define INT_BUS_ABORT_EN 0x00800000 | ||
| 356 | #define INT_TX_FIFO_READY_EN 0x01000000 | ||
| 357 | #define INT_UART_EN 0x02000000 | ||
| 358 | |||
| 359 | #define CR_TSF_LOW_PART CTL_REG(0x0514) | ||
| 360 | #define CR_TSF_HIGH_PART CTL_REG(0x0518) | ||
| 361 | |||
| 362 | /* Following three values are in time units (1024us) | ||
| 363 | * Following condition must be met: | ||
| 364 | * atim < tbtt < bcn | ||
| 365 | */ | ||
| 366 | #define CR_ATIM_WND_PERIOD CTL_REG(0x051C) | ||
| 367 | #define CR_BCN_INTERVAL CTL_REG(0x0520) | ||
| 368 | #define CR_PRE_TBTT CTL_REG(0x0524) | ||
| 369 | /* in units of TU(1024us) */ | ||
| 370 | |||
| 371 | /* for UART support */ | ||
| 372 | #define CR_UART_RBR_THR_DLL CTL_REG(0x0540) | ||
| 373 | #define CR_UART_DLM_IER CTL_REG(0x0544) | ||
| 374 | #define CR_UART_IIR_FCR CTL_REG(0x0548) | ||
| 375 | #define CR_UART_LCR CTL_REG(0x054c) | ||
| 376 | #define CR_UART_MCR CTL_REG(0x0550) | ||
| 377 | #define CR_UART_LSR CTL_REG(0x0554) | ||
| 378 | #define CR_UART_MSR CTL_REG(0x0558) | ||
| 379 | #define CR_UART_ECR CTL_REG(0x055c) | ||
| 380 | #define CR_UART_STATUS CTL_REG(0x0560) | ||
| 381 | |||
| 382 | #define CR_PCI_TX_ADDR_P1 CTL_REG(0x0600) | ||
| 383 | #define CR_PCI_TX_AddR_P2 CTL_REG(0x0604) | ||
| 384 | #define CR_PCI_RX_AddR_P1 CTL_REG(0x0608) | ||
| 385 | #define CR_PCI_RX_AddR_P2 CTL_REG(0x060C) | ||
| 386 | |||
| 387 | /* must be overwritten if custom MAC address will be used */ | ||
| 388 | #define CR_MAC_ADDR_P1 CTL_REG(0x0610) | ||
| 389 | #define CR_MAC_ADDR_P2 CTL_REG(0x0614) | ||
| 390 | #define CR_BSSID_P1 CTL_REG(0x0618) | ||
| 391 | #define CR_BSSID_P2 CTL_REG(0x061C) | ||
| 392 | #define CR_BCN_PLCP_CFG CTL_REG(0x0620) | ||
| 393 | #define CR_GROUP_HASH_P1 CTL_REG(0x0624) | ||
| 394 | #define CR_GROUP_HASH_P2 CTL_REG(0x0628) | ||
| 395 | #define CR_RX_TIMEOUT CTL_REG(0x062C) | ||
| 396 | |||
| 397 | /* Basic rates supported by the BSS. When producing ACK or CTS messages, the | ||
| 398 | * device will use a rate in this table that is less than or equal to the rate | ||
| 399 | * of the incoming frame which prompted the response */ | ||
| 400 | #define CR_BASIC_RATE_TBL CTL_REG(0x0630) | ||
| 401 | #define CR_RATE_1M 0x0001 /* 802.11b */ | ||
| 402 | #define CR_RATE_2M 0x0002 /* 802.11b */ | ||
| 403 | #define CR_RATE_5_5M 0x0004 /* 802.11b */ | ||
| 404 | #define CR_RATE_11M 0x0008 /* 802.11b */ | ||
| 405 | #define CR_RATE_6M 0x0100 /* 802.11g */ | ||
| 406 | #define CR_RATE_9M 0x0200 /* 802.11g */ | ||
| 407 | #define CR_RATE_12M 0x0400 /* 802.11g */ | ||
| 408 | #define CR_RATE_18M 0x0800 /* 802.11g */ | ||
| 409 | #define CR_RATE_24M 0x1000 /* 802.11g */ | ||
| 410 | #define CR_RATE_36M 0x2000 /* 802.11g */ | ||
| 411 | #define CR_RATE_48M 0x4000 /* 802.11g */ | ||
| 412 | #define CR_RATE_54M 0x8000 /* 802.11g */ | ||
| 413 | #define CR_RATES_80211G 0xff00 | ||
| 414 | #define CR_RATES_80211B 0x000f | ||
| 415 | |||
| 416 | /* Mandatory rates required in the BSS. When producing ACK or CTS messages, if | ||
| 417 | * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will | ||
| 418 | * look for a rate in this table that is less than or equal to the rate of | ||
| 419 | * the incoming frame. */ | ||
| 420 | #define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) | ||
| 421 | #define CR_RTS_CTS_RATE CTL_REG(0x0638) | ||
| 422 | |||
| 423 | #define CR_WEP_PROTECT CTL_REG(0x063C) | ||
| 424 | #define CR_RX_THRESHOLD CTL_REG(0x0640) | ||
| 425 | |||
| 426 | /* register for controlling the LEDS */ | ||
| 427 | #define CR_LED CTL_REG(0x0644) | ||
| 428 | /* masks for controlling LEDs */ | ||
| 429 | #define LED1 0x0100 | ||
| 430 | #define LED2 0x0200 | ||
| 431 | |||
| 432 | /* Seems to indicate that the configuration is over. | ||
| 433 | */ | ||
| 434 | #define CR_AFTER_PNP CTL_REG(0x0648) | ||
| 435 | #define CR_ACK_TIME_80211 CTL_REG(0x0658) | ||
| 436 | |||
| 437 | #define CR_RX_OFFSET CTL_REG(0x065c) | ||
| 438 | |||
| 439 | #define CR_PHY_DELAY CTL_REG(0x066C) | ||
| 440 | #define CR_BCN_FIFO CTL_REG(0x0670) | ||
| 441 | #define CR_SNIFFER_ON CTL_REG(0x0674) | ||
| 442 | |||
| 443 | #define CR_ENCRYPTION_TYPE CTL_REG(0x0678) | ||
| 444 | #define NO_WEP 0 | ||
| 445 | #define WEP64 1 | ||
| 446 | #define WEP128 5 | ||
| 447 | #define WEP256 6 | ||
| 448 | #define ENC_SNIFFER 8 | ||
| 449 | |||
| 450 | #define CR_ZD1211_RETRY_MAX CTL_REG(0x067C) | ||
| 451 | |||
| 452 | #define CR_REG1 CTL_REG(0x0680) | ||
| 453 | /* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical | ||
| 454 | * registers, so one could argue it is a LOCK bit. But calling it | ||
| 455 | * LOCK_PHY_REGS makes it confusing. | ||
| 456 | */ | ||
| 457 | #define UNLOCK_PHY_REGS 0x0080 | ||
| 458 | |||
| 459 | #define CR_DEVICE_STATE CTL_REG(0x0684) | ||
| 460 | #define CR_UNDERRUN_CNT CTL_REG(0x0688) | ||
| 461 | |||
| 462 | #define CR_RX_FILTER CTL_REG(0x068c) | ||
| 463 | #define RX_FILTER_ASSOC_RESPONSE 0x0002 | ||
| 464 | #define RX_FILTER_PROBE_RESPONSE 0x0020 | ||
| 465 | #define RX_FILTER_BEACON 0x0100 | ||
| 466 | #define RX_FILTER_AUTH 0x0800 | ||
| 467 | /* Sniff modus sets filter to 0xfffff */ | ||
| 468 | |||
| 469 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) | ||
| 470 | #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) | ||
| 471 | #define CR_IFS_VALUE CTL_REG(0x0698) | ||
| 472 | #define CR_RX_TIME_OUT CTL_REG(0x069C) | ||
| 473 | #define CR_TOTAL_RX_FRM CTL_REG(0x06A0) | ||
| 474 | #define CR_CRC32_CNT CTL_REG(0x06A4) | ||
| 475 | #define CR_CRC16_CNT CTL_REG(0x06A8) | ||
| 476 | #define CR_DECRYPTION_ERR_UNI CTL_REG(0x06AC) | ||
| 477 | #define CR_RX_FIFO_OVERRUN CTL_REG(0x06B0) | ||
| 478 | |||
| 479 | #define CR_DECRYPTION_ERR_MUL CTL_REG(0x06BC) | ||
| 480 | |||
| 481 | #define CR_NAV_CNT CTL_REG(0x06C4) | ||
| 482 | #define CR_NAV_CCA CTL_REG(0x06C8) | ||
| 483 | #define CR_RETRY_CNT CTL_REG(0x06CC) | ||
| 484 | |||
| 485 | #define CR_READ_TCB_ADDR CTL_REG(0x06E8) | ||
| 486 | #define CR_READ_RFD_ADDR CTL_REG(0x06EC) | ||
| 487 | #define CR_CWMIN_CWMAX CTL_REG(0x06F0) | ||
| 488 | #define CR_TOTAL_TX_FRM CTL_REG(0x06F4) | ||
| 489 | |||
| 490 | /* CAM: Continuous Access Mode (power management) */ | ||
| 491 | #define CR_CAM_MODE CTL_REG(0x0700) | ||
| 492 | #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) | ||
| 493 | #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) | ||
| 494 | #define CR_CAM_ADDRESS CTL_REG(0x070C) | ||
| 495 | #define CR_CAM_DATA CTL_REG(0x0710) | ||
| 496 | |||
| 497 | #define CR_ROMDIR CTL_REG(0x0714) | ||
| 498 | |||
| 499 | #define CR_DECRY_ERR_FLG_LOW CTL_REG(0x0714) | ||
| 500 | #define CR_DECRY_ERR_FLG_HIGH CTL_REG(0x0718) | ||
| 501 | |||
| 502 | #define CR_WEPKEY0 CTL_REG(0x0720) | ||
| 503 | #define CR_WEPKEY1 CTL_REG(0x0724) | ||
| 504 | #define CR_WEPKEY2 CTL_REG(0x0728) | ||
| 505 | #define CR_WEPKEY3 CTL_REG(0x072C) | ||
| 506 | #define CR_WEPKEY4 CTL_REG(0x0730) | ||
| 507 | #define CR_WEPKEY5 CTL_REG(0x0734) | ||
| 508 | #define CR_WEPKEY6 CTL_REG(0x0738) | ||
| 509 | #define CR_WEPKEY7 CTL_REG(0x073C) | ||
| 510 | #define CR_WEPKEY8 CTL_REG(0x0740) | ||
| 511 | #define CR_WEPKEY9 CTL_REG(0x0744) | ||
| 512 | #define CR_WEPKEY10 CTL_REG(0x0748) | ||
| 513 | #define CR_WEPKEY11 CTL_REG(0x074C) | ||
| 514 | #define CR_WEPKEY12 CTL_REG(0x0750) | ||
| 515 | #define CR_WEPKEY13 CTL_REG(0x0754) | ||
| 516 | #define CR_WEPKEY14 CTL_REG(0x0758) | ||
| 517 | #define CR_WEPKEY15 CTL_REG(0x075c) | ||
| 518 | #define CR_TKIP_MODE CTL_REG(0x0760) | ||
| 519 | |||
| 520 | #define CR_EEPROM_PROTECT0 CTL_REG(0x0758) | ||
| 521 | #define CR_EEPROM_PROTECT1 CTL_REG(0x075C) | ||
| 522 | |||
| 523 | #define CR_DBG_FIFO_RD CTL_REG(0x0800) | ||
| 524 | #define CR_DBG_SELECT CTL_REG(0x0804) | ||
| 525 | #define CR_FIFO_Length CTL_REG(0x0808) | ||
| 526 | |||
| 527 | |||
| 528 | #define CR_RSSI_MGC CTL_REG(0x0810) | ||
| 529 | |||
| 530 | #define CR_PON CTL_REG(0x0818) | ||
| 531 | #define CR_RX_ON CTL_REG(0x081C) | ||
| 532 | #define CR_TX_ON CTL_REG(0x0820) | ||
| 533 | #define CR_CHIP_EN CTL_REG(0x0824) | ||
| 534 | #define CR_LO_SW CTL_REG(0x0828) | ||
| 535 | #define CR_TXRX_SW CTL_REG(0x082C) | ||
| 536 | #define CR_S_MD CTL_REG(0x0830) | ||
| 537 | |||
| 538 | #define CR_USB_DEBUG_PORT CTL_REG(0x0888) | ||
| 539 | |||
| 540 | #define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00) | ||
| 541 | #define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04) | ||
| 542 | #define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08) | ||
| 543 | #define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c) | ||
| 544 | #define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10) | ||
| 545 | #define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14) | ||
| 546 | #define CR_ZD1211B_TXOP CTL_REG(0x0b20) | ||
| 547 | #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) | ||
| 548 | |||
| 549 | #define AP_RX_FILTER 0x0400feff | ||
| 550 | #define STA_RX_FILTER 0x0000ffff | ||
| 551 | |||
| 552 | #define CWIN_SIZE 0x007f043f | ||
| 553 | |||
| 554 | |||
| 555 | #define HWINT_ENABLED 0x004f0000 | ||
| 556 | #define HWINT_DISABLED 0 | ||
| 557 | |||
| 558 | #define E2P_PWR_INT_GUARD 8 | ||
| 559 | #define E2P_CHANNEL_COUNT 14 | ||
| 560 | |||
| 561 | /* If you compare this addresses with the ZYDAS orignal driver, please notify | ||
| 562 | * that we use word mapping for the EEPROM. | ||
| 563 | */ | ||
| 564 | |||
| 565 | /* | ||
| 566 | * Upper 16 bit contains the regulatory domain. | ||
| 567 | */ | ||
| 568 | #define E2P_SUBID E2P_REG(0x00) | ||
| 569 | #define E2P_POD E2P_REG(0x02) | ||
| 570 | #define E2P_MAC_ADDR_P1 E2P_REG(0x04) | ||
| 571 | #define E2P_MAC_ADDR_P2 E2P_REG(0x06) | ||
| 572 | #define E2P_PWR_CAL_VALUE1 E2P_REG(0x08) | ||
| 573 | #define E2P_PWR_CAL_VALUE2 E2P_REG(0x0a) | ||
| 574 | #define E2P_PWR_CAL_VALUE3 E2P_REG(0x0c) | ||
| 575 | #define E2P_PWR_CAL_VALUE4 E2P_REG(0x0e) | ||
| 576 | #define E2P_PWR_INT_VALUE1 E2P_REG(0x10) | ||
| 577 | #define E2P_PWR_INT_VALUE2 E2P_REG(0x12) | ||
| 578 | #define E2P_PWR_INT_VALUE3 E2P_REG(0x14) | ||
| 579 | #define E2P_PWR_INT_VALUE4 E2P_REG(0x16) | ||
| 580 | |||
| 581 | /* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30) | ||
| 582 | * also only 11 channels. */ | ||
| 583 | #define E2P_ALLOWED_CHANNEL E2P_REG(0x18) | ||
| 584 | |||
| 585 | #define E2P_PHY_REG E2P_REG(0x1a) | ||
| 586 | #define E2P_DEVICE_VER E2P_REG(0x20) | ||
| 587 | #define E2P_36M_CAL_VALUE1 E2P_REG(0x28) | ||
| 588 | #define E2P_36M_CAL_VALUE2 E2P_REG(0x2a) | ||
| 589 | #define E2P_36M_CAL_VALUE3 E2P_REG(0x2c) | ||
| 590 | #define E2P_36M_CAL_VALUE4 E2P_REG(0x2e) | ||
| 591 | #define E2P_11A_INT_VALUE1 E2P_REG(0x30) | ||
| 592 | #define E2P_11A_INT_VALUE2 E2P_REG(0x32) | ||
| 593 | #define E2P_11A_INT_VALUE3 E2P_REG(0x34) | ||
| 594 | #define E2P_11A_INT_VALUE4 E2P_REG(0x36) | ||
| 595 | #define E2P_48M_CAL_VALUE1 E2P_REG(0x38) | ||
| 596 | #define E2P_48M_CAL_VALUE2 E2P_REG(0x3a) | ||
| 597 | #define E2P_48M_CAL_VALUE3 E2P_REG(0x3c) | ||
| 598 | #define E2P_48M_CAL_VALUE4 E2P_REG(0x3e) | ||
| 599 | #define E2P_48M_INT_VALUE1 E2P_REG(0x40) | ||
| 600 | #define E2P_48M_INT_VALUE2 E2P_REG(0x42) | ||
| 601 | #define E2P_48M_INT_VALUE3 E2P_REG(0x44) | ||
| 602 | #define E2P_48M_INT_VALUE4 E2P_REG(0x46) | ||
| 603 | #define E2P_54M_CAL_VALUE1 E2P_REG(0x48) /* ??? */ | ||
| 604 | #define E2P_54M_CAL_VALUE2 E2P_REG(0x4a) | ||
| 605 | #define E2P_54M_CAL_VALUE3 E2P_REG(0x4c) | ||
| 606 | #define E2P_54M_CAL_VALUE4 E2P_REG(0x4e) | ||
| 607 | #define E2P_54M_INT_VALUE1 E2P_REG(0x50) | ||
| 608 | #define E2P_54M_INT_VALUE2 E2P_REG(0x52) | ||
| 609 | #define E2P_54M_INT_VALUE3 E2P_REG(0x54) | ||
| 610 | #define E2P_54M_INT_VALUE4 E2P_REG(0x56) | ||
| 611 | |||
| 612 | /* All 16 bit values */ | ||
| 613 | #define FW_FIRMWARE_VER FW_REG(0) | ||
| 614 | /* non-zero if USB high speed connection */ | ||
| 615 | #define FW_USB_SPEED FW_REG(1) | ||
| 616 | #define FW_FIX_TX_RATE FW_REG(2) | ||
| 617 | /* Seems to be able to control LEDs over the firmware */ | ||
| 618 | #define FW_LINK_STATUS FW_REG(3) | ||
| 619 | #define FW_SOFT_RESET FW_REG(4) | ||
| 620 | #define FW_FLASH_CHK FW_REG(5) | ||
| 621 | |||
| 622 | enum { | ||
| 623 | CR_BASE_OFFSET = 0x9000, | ||
| 624 | FW_START_OFFSET = 0xee00, | ||
| 625 | FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d, | ||
| 626 | EEPROM_START_OFFSET = 0xf800, | ||
| 627 | EEPROM_SIZE = 0x800, /* words */ | ||
| 628 | LOAD_CODE_SIZE = 0xe, /* words */ | ||
| 629 | LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ | ||
| 630 | EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, | ||
| 631 | E2P_BASE_OFFSET = EEPROM_START_OFFSET + | ||
| 632 | EEPROM_REGS_OFFSET, | ||
| 633 | }; | ||
| 634 | |||
| 635 | #define FW_REG_TABLE_ADDR USB_ADDR(FW_START_OFFSET + 0x1d) | ||
| 636 | |||
| 637 | enum { | ||
| 638 | /* indices for ofdm_cal_values */ | ||
| 639 | OFDM_36M_INDEX = 0, | ||
| 640 | OFDM_48M_INDEX = 1, | ||
| 641 | OFDM_54M_INDEX = 2, | ||
| 642 | }; | ||
| 643 | |||
| 644 | struct zd_chip { | ||
| 645 | struct zd_usb usb; | ||
| 646 | struct zd_rf rf; | ||
| 647 | struct mutex mutex; | ||
| 648 | u8 e2p_mac[ETH_ALEN]; | ||
| 649 | /* EepSetPoint in the vendor driver */ | ||
| 650 | u8 pwr_cal_values[E2P_CHANNEL_COUNT]; | ||
| 651 | /* integration values in the vendor driver */ | ||
| 652 | u8 pwr_int_values[E2P_CHANNEL_COUNT]; | ||
| 653 | /* SetPointOFDM in the vendor driver */ | ||
| 654 | u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; | ||
| 655 | u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, | ||
| 656 | is_zd1211b:1; | ||
| 657 | }; | ||
| 658 | |||
| 659 | static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) | ||
| 660 | { | ||
| 661 | return container_of(usb, struct zd_chip, usb); | ||
| 662 | } | ||
| 663 | |||
| 664 | static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf) | ||
| 665 | { | ||
| 666 | return container_of(rf, struct zd_chip, rf); | ||
| 667 | } | ||
| 668 | |||
| 669 | #define zd_chip_dev(chip) (&(chip)->usb.intf->dev) | ||
| 670 | |||
| 671 | void zd_chip_init(struct zd_chip *chip, | ||
| 672 | struct net_device *netdev, | ||
| 673 | struct usb_interface *intf); | ||
| 674 | void zd_chip_clear(struct zd_chip *chip); | ||
| 675 | int zd_chip_init_hw(struct zd_chip *chip, u8 device_type); | ||
| 676 | int zd_chip_reset(struct zd_chip *chip); | ||
| 677 | |||
| 678 | static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values, | ||
| 679 | const zd_addr_t *addresses, | ||
| 680 | unsigned int count) | ||
| 681 | { | ||
| 682 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 683 | return zd_usb_ioread16v(&chip->usb, values, addresses, count); | ||
| 684 | } | ||
| 685 | |||
| 686 | static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value, | ||
| 687 | const zd_addr_t addr) | ||
| 688 | { | ||
| 689 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 690 | return zd_usb_ioread16(&chip->usb, value, addr); | ||
| 691 | } | ||
| 692 | |||
| 693 | int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, | ||
| 694 | const zd_addr_t *addresses, unsigned int count); | ||
| 695 | |||
| 696 | static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value, | ||
| 697 | const zd_addr_t addr) | ||
| 698 | { | ||
| 699 | return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1); | ||
| 700 | } | ||
| 701 | |||
| 702 | static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value, | ||
| 703 | zd_addr_t addr) | ||
| 704 | { | ||
| 705 | struct zd_ioreq16 ioreq; | ||
| 706 | |||
| 707 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 708 | ioreq.addr = addr; | ||
| 709 | ioreq.value = value; | ||
| 710 | |||
| 711 | return zd_usb_iowrite16v(&chip->usb, &ioreq, 1); | ||
| 712 | } | ||
| 713 | |||
| 714 | int zd_iowrite16a_locked(struct zd_chip *chip, | ||
| 715 | const struct zd_ioreq16 *ioreqs, unsigned int count); | ||
| 716 | |||
| 717 | int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
| 718 | unsigned int count); | ||
| 719 | |||
| 720 | static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value, | ||
| 721 | zd_addr_t addr) | ||
| 722 | { | ||
| 723 | struct zd_ioreq32 ioreq; | ||
| 724 | |||
| 725 | ioreq.addr = addr; | ||
| 726 | ioreq.value = value; | ||
| 727 | |||
| 728 | return _zd_iowrite32v_locked(chip, &ioreq, 1); | ||
| 729 | } | ||
| 730 | |||
| 731 | int zd_iowrite32a_locked(struct zd_chip *chip, | ||
| 732 | const struct zd_ioreq32 *ioreqs, unsigned int count); | ||
| 733 | |||
| 734 | static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits) | ||
| 735 | { | ||
| 736 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 737 | return zd_usb_rfwrite(&chip->usb, value, bits); | ||
| 738 | } | ||
| 739 | |||
| 740 | int zd_rfwritev_locked(struct zd_chip *chip, | ||
| 741 | const u32* values, unsigned int count, u8 bits); | ||
| 742 | |||
| 743 | /* Locking functions for reading and writing registers. | ||
| 744 | * The different parameters are intentional. | ||
| 745 | */ | ||
| 746 | int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value); | ||
| 747 | int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value); | ||
| 748 | int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value); | ||
| 749 | int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value); | ||
| 750 | int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, | ||
| 751 | u32 *values, unsigned int count); | ||
| 752 | int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | ||
| 753 | unsigned int count); | ||
| 754 | |||
| 755 | int zd_chip_set_channel(struct zd_chip *chip, u8 channel); | ||
| 756 | static inline u8 _zd_chip_get_channel(struct zd_chip *chip) | ||
| 757 | { | ||
| 758 | return chip->rf.channel; | ||
| 759 | } | ||
| 760 | u8 zd_chip_get_channel(struct zd_chip *chip); | ||
| 761 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); | ||
| 762 | void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr); | ||
| 763 | int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr); | ||
| 764 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); | ||
| 765 | int zd_chip_switch_radio_on(struct zd_chip *chip); | ||
| 766 | int zd_chip_switch_radio_off(struct zd_chip *chip); | ||
| 767 | int zd_chip_enable_int(struct zd_chip *chip); | ||
| 768 | void zd_chip_disable_int(struct zd_chip *chip); | ||
| 769 | int zd_chip_enable_rx(struct zd_chip *chip); | ||
| 770 | void zd_chip_disable_rx(struct zd_chip *chip); | ||
| 771 | int zd_chip_enable_hwint(struct zd_chip *chip); | ||
| 772 | int zd_chip_disable_hwint(struct zd_chip *chip); | ||
| 773 | |||
| 774 | static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) | ||
| 775 | { | ||
| 776 | return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); | ||
| 777 | } | ||
| 778 | |||
| 779 | static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type) | ||
| 780 | { | ||
| 781 | return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type); | ||
| 782 | } | ||
| 783 | |||
| 784 | static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates) | ||
| 785 | { | ||
| 786 | return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); | ||
| 787 | } | ||
| 788 | |||
| 789 | int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); | ||
| 790 | |||
| 791 | static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter) | ||
| 792 | { | ||
| 793 | return zd_iowrite32(chip, CR_RX_FILTER, filter); | ||
| 794 | } | ||
| 795 | |||
| 796 | int zd_chip_lock_phy_regs(struct zd_chip *chip); | ||
| 797 | int zd_chip_unlock_phy_regs(struct zd_chip *chip); | ||
| 798 | |||
| 799 | enum led_status { | ||
| 800 | LED_OFF = 0, | ||
| 801 | LED_ON = 1, | ||
| 802 | LED_FLIP = 2, | ||
| 803 | LED_STATUS = 3, | ||
| 804 | }; | ||
| 805 | |||
| 806 | int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status); | ||
| 807 | int zd_chip_led_flip(struct zd_chip *chip, int led, | ||
| 808 | const unsigned int *phases_msecs, unsigned int count); | ||
| 809 | |||
| 810 | int zd_set_beacon_interval(struct zd_chip *chip, u32 interval); | ||
| 811 | |||
| 812 | static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) | ||
| 813 | { | ||
| 814 | return zd_ioread32(chip, CR_BCN_INTERVAL, interval); | ||
| 815 | } | ||
| 816 | |||
| 817 | struct rx_status; | ||
| 818 | |||
| 819 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
| 820 | const struct rx_status *status); | ||
| 821 | u8 zd_rx_strength_percent(u8 rssi); | ||
| 822 | |||
| 823 | u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status); | ||
| 824 | |||
| 825 | #endif /* _ZD_CHIP_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h new file mode 100644 index 000000000000..465906812fc4 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_def.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* zd_def.h | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_DEF_H | ||
| 19 | #define _ZD_DEF_H | ||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/stringify.h> | ||
| 23 | #include <linux/device.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | |||
| 26 | #define dev_printk_f(level, dev, fmt, args...) \ | ||
| 27 | dev_printk(level, dev, "%s() " fmt, __func__, ##args) | ||
| 28 | |||
| 29 | #ifdef DEBUG | ||
| 30 | # define dev_dbg_f(dev, fmt, args...) \ | ||
| 31 | dev_printk_f(KERN_DEBUG, dev, fmt, ## args) | ||
| 32 | #else | ||
| 33 | # define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) | ||
| 34 | #endif /* DEBUG */ | ||
| 35 | |||
| 36 | #ifdef DEBUG | ||
| 37 | # define ZD_ASSERT(x) \ | ||
| 38 | do { \ | ||
| 39 | if (!(x)) { \ | ||
| 40 | pr_debug("%s:%d ASSERT %s VIOLATED!\n", \ | ||
| 41 | __FILE__, __LINE__, __stringify(x)); \ | ||
| 42 | } \ | ||
| 43 | } while (0) | ||
| 44 | #else | ||
| 45 | # define ZD_ASSERT(x) do { } while (0) | ||
| 46 | #endif | ||
| 47 | |||
| 48 | #endif /* _ZD_DEF_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c new file mode 100644 index 000000000000..66905f7b61ff --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | /* zd_ieee80211.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | /* | ||
| 19 | * A lot of this code is generic and should be moved into the upper layers | ||
| 20 | * at some point. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/errno.h> | ||
| 24 | #include <linux/wireless.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <net/ieee80211.h> | ||
| 27 | |||
| 28 | #include "zd_def.h" | ||
| 29 | #include "zd_ieee80211.h" | ||
| 30 | #include "zd_mac.h" | ||
| 31 | |||
| 32 | static const struct channel_range channel_ranges[] = { | ||
| 33 | [0] = { 0, 0}, | ||
| 34 | [ZD_REGDOMAIN_FCC] = { 1, 12}, | ||
| 35 | [ZD_REGDOMAIN_IC] = { 1, 12}, | ||
| 36 | [ZD_REGDOMAIN_ETSI] = { 1, 14}, | ||
| 37 | [ZD_REGDOMAIN_JAPAN] = { 1, 14}, | ||
| 38 | [ZD_REGDOMAIN_SPAIN] = { 1, 14}, | ||
| 39 | [ZD_REGDOMAIN_FRANCE] = { 1, 14}, | ||
| 40 | [ZD_REGDOMAIN_JAPAN_ADD] = {14, 15}, | ||
| 41 | }; | ||
| 42 | |||
| 43 | const struct channel_range *zd_channel_range(u8 regdomain) | ||
| 44 | { | ||
| 45 | if (regdomain >= ARRAY_SIZE(channel_ranges)) | ||
| 46 | regdomain = 0; | ||
| 47 | return &channel_ranges[regdomain]; | ||
| 48 | } | ||
| 49 | |||
| 50 | int zd_regdomain_supports_channel(u8 regdomain, u8 channel) | ||
| 51 | { | ||
| 52 | const struct channel_range *range = zd_channel_range(regdomain); | ||
| 53 | return range->start <= channel && channel < range->end; | ||
| 54 | } | ||
| 55 | |||
| 56 | int zd_regdomain_supported(u8 regdomain) | ||
| 57 | { | ||
| 58 | const struct channel_range *range = zd_channel_range(regdomain); | ||
| 59 | return range->start != 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | /* Stores channel frequencies in MHz. */ | ||
| 63 | static const u16 channel_frequencies[] = { | ||
| 64 | 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, | ||
| 65 | 2452, 2457, 2462, 2467, 2472, 2484, | ||
| 66 | }; | ||
| 67 | |||
| 68 | #define NUM_CHANNELS ARRAY_SIZE(channel_frequencies) | ||
| 69 | |||
| 70 | static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz) | ||
| 71 | { | ||
| 72 | u32 factor; | ||
| 73 | |||
| 74 | freq->e = 0; | ||
| 75 | if (mhz >= 1000000000U) { | ||
| 76 | pr_debug("zd1211 mhz %u to large\n", mhz); | ||
| 77 | freq->m = 0; | ||
| 78 | return -EINVAL; | ||
| 79 | } | ||
| 80 | |||
| 81 | factor = 1000; | ||
| 82 | while (mhz >= factor) { | ||
| 83 | |||
| 84 | freq->e += 1; | ||
| 85 | factor *= 10; | ||
| 86 | } | ||
| 87 | |||
| 88 | factor /= 1000U; | ||
| 89 | freq->m = mhz * (1000000U/factor) + hz/factor; | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | int zd_channel_to_freq(struct iw_freq *freq, u8 channel) | ||
| 95 | { | ||
| 96 | if (channel > NUM_CHANNELS) { | ||
| 97 | freq->m = 0; | ||
| 98 | freq->e = 0; | ||
| 99 | return -EINVAL; | ||
| 100 | } | ||
| 101 | if (!channel) { | ||
| 102 | freq->m = 0; | ||
| 103 | freq->e = 0; | ||
| 104 | return -EINVAL; | ||
| 105 | } | ||
| 106 | return compute_freq(freq, channel_frequencies[channel-1], 0); | ||
| 107 | } | ||
| 108 | |||
| 109 | static int freq_to_mhz(const struct iw_freq *freq) | ||
| 110 | { | ||
| 111 | u32 factor; | ||
| 112 | int e; | ||
| 113 | |||
| 114 | /* Such high frequencies are not supported. */ | ||
| 115 | if (freq->e > 6) | ||
| 116 | return -EINVAL; | ||
| 117 | |||
| 118 | factor = 1; | ||
| 119 | for (e = freq->e; e > 0; --e) { | ||
| 120 | factor *= 10; | ||
| 121 | } | ||
| 122 | factor = 1000000U / factor; | ||
| 123 | |||
| 124 | if (freq->m % factor) { | ||
| 125 | return -EINVAL; | ||
| 126 | } | ||
| 127 | |||
| 128 | return freq->m / factor; | ||
| 129 | } | ||
| 130 | |||
| 131 | int zd_find_channel(u8 *channel, const struct iw_freq *freq) | ||
| 132 | { | ||
| 133 | int i, r; | ||
| 134 | u32 mhz; | ||
| 135 | |||
| 136 | if (!(freq->flags & IW_FREQ_FIXED)) | ||
| 137 | return 0; | ||
| 138 | |||
| 139 | if (freq->m < 1000) { | ||
| 140 | if (freq->m > NUM_CHANNELS || freq->m == 0) | ||
| 141 | return -EINVAL; | ||
| 142 | *channel = freq->m; | ||
| 143 | return 1; | ||
| 144 | } | ||
| 145 | |||
| 146 | r = freq_to_mhz(freq); | ||
| 147 | if (r < 0) | ||
| 148 | return r; | ||
| 149 | mhz = r; | ||
| 150 | |||
| 151 | for (i = 0; i < NUM_CHANNELS; i++) { | ||
| 152 | if (mhz == channel_frequencies[i]) { | ||
| 153 | *channel = i+1; | ||
| 154 | return 1; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | return -EINVAL; | ||
| 159 | } | ||
| 160 | |||
| 161 | int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain) | ||
| 162 | { | ||
| 163 | struct ieee80211_geo geo; | ||
| 164 | const struct channel_range *range; | ||
| 165 | int i; | ||
| 166 | u8 channel; | ||
| 167 | |||
| 168 | dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)), | ||
| 169 | "regdomain %#04x\n", regdomain); | ||
| 170 | |||
| 171 | range = zd_channel_range(regdomain); | ||
| 172 | if (range->start == 0) { | ||
| 173 | dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)), | ||
| 174 | "zd1211 regdomain %#04x not supported\n", | ||
| 175 | regdomain); | ||
| 176 | return -EINVAL; | ||
| 177 | } | ||
| 178 | |||
| 179 | memset(&geo, 0, sizeof(geo)); | ||
| 180 | |||
| 181 | for (i = 0, channel = range->start; channel < range->end; channel++) { | ||
| 182 | struct ieee80211_channel *chan = &geo.bg[i++]; | ||
| 183 | chan->freq = channel_frequencies[channel - 1]; | ||
| 184 | chan->channel = channel; | ||
| 185 | } | ||
| 186 | |||
| 187 | geo.bg_channels = i; | ||
| 188 | memcpy(geo.name, "XX ", 4); | ||
| 189 | ieee80211_set_geo(ieee, &geo); | ||
| 190 | return 0; | ||
| 191 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h new file mode 100644 index 000000000000..36329890dfec --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | #ifndef _ZD_IEEE80211_H | ||
| 2 | #define _ZD_IEEE80211_H | ||
| 3 | |||
| 4 | #include <net/ieee80211.h> | ||
| 5 | #include "zd_types.h" | ||
| 6 | |||
| 7 | /* Additional definitions from the standards. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define ZD_REGDOMAIN_FCC 0x10 | ||
| 11 | #define ZD_REGDOMAIN_IC 0x20 | ||
| 12 | #define ZD_REGDOMAIN_ETSI 0x30 | ||
| 13 | #define ZD_REGDOMAIN_SPAIN 0x31 | ||
| 14 | #define ZD_REGDOMAIN_FRANCE 0x32 | ||
| 15 | #define ZD_REGDOMAIN_JAPAN_ADD 0x40 | ||
| 16 | #define ZD_REGDOMAIN_JAPAN 0x41 | ||
| 17 | |||
| 18 | enum { | ||
| 19 | MIN_CHANNEL24 = 1, | ||
| 20 | MAX_CHANNEL24 = 14, | ||
| 21 | }; | ||
| 22 | |||
| 23 | struct channel_range { | ||
| 24 | u8 start; | ||
| 25 | u8 end; /* exclusive (channel must be less than end) */ | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct iw_freq; | ||
| 29 | |||
| 30 | int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain); | ||
| 31 | |||
| 32 | const struct channel_range *zd_channel_range(u8 regdomain); | ||
| 33 | int zd_regdomain_supports_channel(u8 regdomain, u8 channel); | ||
| 34 | int zd_regdomain_supported(u8 regdomain); | ||
| 35 | |||
| 36 | /* for 2.4 GHz band */ | ||
| 37 | int zd_channel_to_freq(struct iw_freq *freq, u8 channel); | ||
| 38 | int zd_find_channel(u8 *channel, const struct iw_freq *freq); | ||
| 39 | |||
| 40 | #define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80 | ||
| 41 | |||
| 42 | struct ofdm_plcp_header { | ||
| 43 | u8 prefix[3]; | ||
| 44 | __le16 service; | ||
| 45 | } __attribute__((packed)); | ||
| 46 | |||
| 47 | static inline u8 zd_ofdm_plcp_header_rate( | ||
| 48 | const struct ofdm_plcp_header *header) | ||
| 49 | { | ||
| 50 | return header->prefix[0] & 0xf; | ||
| 51 | } | ||
| 52 | |||
| 53 | #define ZD_OFDM_RATE_6M 0xb | ||
| 54 | #define ZD_OFDM_RATE_9M 0xf | ||
| 55 | #define ZD_OFDM_RATE_12M 0xa | ||
| 56 | #define ZD_OFDM_RATE_18M 0xe | ||
| 57 | #define ZD_OFDM_RATE_24M 0x9 | ||
| 58 | #define ZD_OFDM_RATE_36M 0xd | ||
| 59 | #define ZD_OFDM_RATE_48M 0x8 | ||
| 60 | #define ZD_OFDM_RATE_54M 0xc | ||
| 61 | |||
| 62 | struct cck_plcp_header { | ||
| 63 | u8 signal; | ||
| 64 | u8 service; | ||
| 65 | __le16 length; | ||
| 66 | __le16 crc16; | ||
| 67 | } __attribute__((packed)); | ||
| 68 | |||
| 69 | static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header) | ||
| 70 | { | ||
| 71 | return header->signal; | ||
| 72 | } | ||
| 73 | |||
| 74 | #define ZD_CCK_SIGNAL_1M 0x0a | ||
| 75 | #define ZD_CCK_SIGNAL_2M 0x14 | ||
| 76 | #define ZD_CCK_SIGNAL_5M5 0x37 | ||
| 77 | #define ZD_CCK_SIGNAL_11M 0x6e | ||
| 78 | |||
| 79 | enum ieee80211_std { | ||
| 80 | IEEE80211B = 0x01, | ||
| 81 | IEEE80211A = 0x02, | ||
| 82 | IEEE80211G = 0x04, | ||
| 83 | }; | ||
| 84 | |||
| 85 | #endif /* _ZD_IEEE80211_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c new file mode 100644 index 000000000000..bbe067ec7de1 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
| @@ -0,0 +1,1055 @@ | |||
| 1 | /* zd_mac.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/wireless.h> | ||
| 21 | #include <linux/usb.h> | ||
| 22 | #include <linux/jiffies.h> | ||
| 23 | #include <net/ieee80211_radiotap.h> | ||
| 24 | |||
| 25 | #include "zd_def.h" | ||
| 26 | #include "zd_chip.h" | ||
| 27 | #include "zd_mac.h" | ||
| 28 | #include "zd_ieee80211.h" | ||
| 29 | #include "zd_netdev.h" | ||
| 30 | #include "zd_rf.h" | ||
| 31 | #include "zd_util.h" | ||
| 32 | |||
| 33 | static void ieee_init(struct ieee80211_device *ieee); | ||
| 34 | static void softmac_init(struct ieee80211softmac_device *sm); | ||
| 35 | |||
| 36 | int zd_mac_init(struct zd_mac *mac, | ||
| 37 | struct net_device *netdev, | ||
| 38 | struct usb_interface *intf) | ||
| 39 | { | ||
| 40 | struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev); | ||
| 41 | |||
| 42 | memset(mac, 0, sizeof(*mac)); | ||
| 43 | spin_lock_init(&mac->lock); | ||
| 44 | mac->netdev = netdev; | ||
| 45 | |||
| 46 | ieee_init(ieee); | ||
| 47 | softmac_init(ieee80211_priv(netdev)); | ||
| 48 | zd_chip_init(&mac->chip, netdev, intf); | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int reset_channel(struct zd_mac *mac) | ||
| 53 | { | ||
| 54 | int r; | ||
| 55 | unsigned long flags; | ||
| 56 | const struct channel_range *range; | ||
| 57 | |||
| 58 | spin_lock_irqsave(&mac->lock, flags); | ||
| 59 | range = zd_channel_range(mac->regdomain); | ||
| 60 | if (!range->start) { | ||
| 61 | r = -EINVAL; | ||
| 62 | goto out; | ||
| 63 | } | ||
| 64 | mac->requested_channel = range->start; | ||
| 65 | r = 0; | ||
| 66 | out: | ||
| 67 | spin_unlock_irqrestore(&mac->lock, flags); | ||
| 68 | return r; | ||
| 69 | } | ||
| 70 | |||
| 71 | int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) | ||
| 72 | { | ||
| 73 | int r; | ||
| 74 | struct zd_chip *chip = &mac->chip; | ||
| 75 | u8 addr[ETH_ALEN]; | ||
| 76 | u8 default_regdomain; | ||
| 77 | |||
| 78 | r = zd_chip_enable_int(chip); | ||
| 79 | if (r) | ||
| 80 | goto out; | ||
| 81 | r = zd_chip_init_hw(chip, device_type); | ||
| 82 | if (r) | ||
| 83 | goto disable_int; | ||
| 84 | |||
| 85 | zd_get_e2p_mac_addr(chip, addr); | ||
| 86 | r = zd_write_mac_addr(chip, addr); | ||
| 87 | if (r) | ||
| 88 | goto disable_int; | ||
| 89 | ZD_ASSERT(!irqs_disabled()); | ||
| 90 | spin_lock_irq(&mac->lock); | ||
| 91 | memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); | ||
| 92 | spin_unlock_irq(&mac->lock); | ||
| 93 | |||
| 94 | r = zd_read_regdomain(chip, &default_regdomain); | ||
| 95 | if (r) | ||
| 96 | goto disable_int; | ||
| 97 | if (!zd_regdomain_supported(default_regdomain)) { | ||
| 98 | dev_dbg_f(zd_mac_dev(mac), | ||
| 99 | "Regulatory Domain %#04x is not supported.\n", | ||
| 100 | default_regdomain); | ||
| 101 | r = -EINVAL; | ||
| 102 | goto disable_int; | ||
| 103 | } | ||
| 104 | spin_lock_irq(&mac->lock); | ||
| 105 | mac->regdomain = mac->default_regdomain = default_regdomain; | ||
| 106 | spin_unlock_irq(&mac->lock); | ||
| 107 | r = reset_channel(mac); | ||
| 108 | if (r) | ||
| 109 | goto disable_int; | ||
| 110 | |||
| 111 | r = zd_set_encryption_type(chip, NO_WEP); | ||
| 112 | if (r) | ||
| 113 | goto disable_int; | ||
| 114 | |||
| 115 | r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain); | ||
| 116 | if (r) | ||
| 117 | goto disable_int; | ||
| 118 | |||
| 119 | r = 0; | ||
| 120 | disable_int: | ||
| 121 | zd_chip_disable_int(chip); | ||
| 122 | out: | ||
| 123 | return r; | ||
| 124 | } | ||
| 125 | |||
| 126 | void zd_mac_clear(struct zd_mac *mac) | ||
| 127 | { | ||
| 128 | /* Aquire the lock. */ | ||
| 129 | spin_lock(&mac->lock); | ||
| 130 | spin_unlock(&mac->lock); | ||
| 131 | zd_chip_clear(&mac->chip); | ||
| 132 | memset(mac, 0, sizeof(*mac)); | ||
| 133 | } | ||
| 134 | |||
| 135 | static int reset_mode(struct zd_mac *mac) | ||
| 136 | { | ||
| 137 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
| 138 | struct zd_ioreq32 ioreqs[3] = { | ||
| 139 | { CR_RX_FILTER, RX_FILTER_BEACON|RX_FILTER_PROBE_RESPONSE| | ||
| 140 | RX_FILTER_AUTH|RX_FILTER_ASSOC_RESPONSE }, | ||
| 141 | { CR_SNIFFER_ON, 0U }, | ||
| 142 | { CR_ENCRYPTION_TYPE, NO_WEP }, | ||
| 143 | }; | ||
| 144 | |||
| 145 | if (ieee->iw_mode == IW_MODE_MONITOR) { | ||
| 146 | ioreqs[0].value = 0xffffffff; | ||
| 147 | ioreqs[1].value = 0x1; | ||
| 148 | ioreqs[2].value = ENC_SNIFFER; | ||
| 149 | } | ||
| 150 | |||
| 151 | return zd_iowrite32a(&mac->chip, ioreqs, 3); | ||
| 152 | } | ||
| 153 | |||
| 154 | int zd_mac_open(struct net_device *netdev) | ||
| 155 | { | ||
| 156 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 157 | struct zd_chip *chip = &mac->chip; | ||
| 158 | int r; | ||
| 159 | |||
| 160 | r = zd_chip_enable_int(chip); | ||
| 161 | if (r < 0) | ||
| 162 | goto out; | ||
| 163 | |||
| 164 | r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); | ||
| 165 | if (r < 0) | ||
| 166 | goto disable_int; | ||
| 167 | r = reset_mode(mac); | ||
| 168 | if (r) | ||
| 169 | goto disable_int; | ||
| 170 | r = zd_chip_switch_radio_on(chip); | ||
| 171 | if (r < 0) | ||
| 172 | goto disable_int; | ||
| 173 | r = zd_chip_set_channel(chip, mac->requested_channel); | ||
| 174 | if (r < 0) | ||
| 175 | goto disable_radio; | ||
| 176 | r = zd_chip_enable_rx(chip); | ||
| 177 | if (r < 0) | ||
| 178 | goto disable_radio; | ||
| 179 | r = zd_chip_enable_hwint(chip); | ||
| 180 | if (r < 0) | ||
| 181 | goto disable_rx; | ||
| 182 | |||
| 183 | ieee80211softmac_start(netdev); | ||
| 184 | return 0; | ||
| 185 | disable_rx: | ||
| 186 | zd_chip_disable_rx(chip); | ||
| 187 | disable_radio: | ||
| 188 | zd_chip_switch_radio_off(chip); | ||
| 189 | disable_int: | ||
| 190 | zd_chip_disable_int(chip); | ||
| 191 | out: | ||
| 192 | return r; | ||
| 193 | } | ||
| 194 | |||
| 195 | int zd_mac_stop(struct net_device *netdev) | ||
| 196 | { | ||
| 197 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 198 | struct zd_chip *chip = &mac->chip; | ||
| 199 | |||
| 200 | /* | ||
| 201 | * The order here deliberately is a little different from the open() | ||
| 202 | * method, since we need to make sure there is no opportunity for RX | ||
| 203 | * frames to be processed by softmac after we have stopped it. | ||
| 204 | */ | ||
| 205 | |||
| 206 | zd_chip_disable_rx(chip); | ||
| 207 | ieee80211softmac_stop(netdev); | ||
| 208 | |||
| 209 | zd_chip_disable_hwint(chip); | ||
| 210 | zd_chip_switch_radio_off(chip); | ||
| 211 | zd_chip_disable_int(chip); | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | int zd_mac_set_mac_address(struct net_device *netdev, void *p) | ||
| 217 | { | ||
| 218 | int r; | ||
| 219 | unsigned long flags; | ||
| 220 | struct sockaddr *addr = p; | ||
| 221 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 222 | struct zd_chip *chip = &mac->chip; | ||
| 223 | |||
| 224 | if (!is_valid_ether_addr(addr->sa_data)) | ||
| 225 | return -EADDRNOTAVAIL; | ||
| 226 | |||
| 227 | dev_dbg_f(zd_mac_dev(mac), | ||
| 228 | "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data)); | ||
| 229 | |||
| 230 | r = zd_write_mac_addr(chip, addr->sa_data); | ||
| 231 | if (r) | ||
| 232 | return r; | ||
| 233 | |||
| 234 | spin_lock_irqsave(&mac->lock, flags); | ||
| 235 | memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN); | ||
| 236 | spin_unlock_irqrestore(&mac->lock, flags); | ||
| 237 | |||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain) | ||
| 242 | { | ||
| 243 | int r; | ||
| 244 | u8 channel; | ||
| 245 | |||
| 246 | ZD_ASSERT(!irqs_disabled()); | ||
| 247 | spin_lock_irq(&mac->lock); | ||
| 248 | if (regdomain == 0) { | ||
| 249 | regdomain = mac->default_regdomain; | ||
| 250 | } | ||
| 251 | if (!zd_regdomain_supported(regdomain)) { | ||
| 252 | spin_unlock_irq(&mac->lock); | ||
| 253 | return -EINVAL; | ||
| 254 | } | ||
| 255 | mac->regdomain = regdomain; | ||
| 256 | channel = mac->requested_channel; | ||
| 257 | spin_unlock_irq(&mac->lock); | ||
| 258 | |||
| 259 | r = zd_geo_init(zd_mac_to_ieee80211(mac), regdomain); | ||
| 260 | if (r) | ||
| 261 | return r; | ||
| 262 | if (!zd_regdomain_supports_channel(regdomain, channel)) { | ||
| 263 | r = reset_channel(mac); | ||
| 264 | if (r) | ||
| 265 | return r; | ||
| 266 | } | ||
| 267 | |||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | |||
| 271 | u8 zd_mac_get_regdomain(struct zd_mac *mac) | ||
| 272 | { | ||
| 273 | unsigned long flags; | ||
| 274 | u8 regdomain; | ||
| 275 | |||
| 276 | spin_lock_irqsave(&mac->lock, flags); | ||
| 277 | regdomain = mac->regdomain; | ||
| 278 | spin_unlock_irqrestore(&mac->lock, flags); | ||
| 279 | return regdomain; | ||
| 280 | } | ||
| 281 | |||
| 282 | static void set_channel(struct net_device *netdev, u8 channel) | ||
| 283 | { | ||
| 284 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 285 | |||
| 286 | dev_dbg_f(zd_mac_dev(mac), "channel %d\n", channel); | ||
| 287 | |||
| 288 | zd_chip_set_channel(&mac->chip, channel); | ||
| 289 | } | ||
| 290 | |||
| 291 | /* TODO: Should not work in Managed mode. */ | ||
| 292 | int zd_mac_request_channel(struct zd_mac *mac, u8 channel) | ||
| 293 | { | ||
| 294 | unsigned long lock_flags; | ||
| 295 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
| 296 | |||
| 297 | if (ieee->iw_mode == IW_MODE_INFRA) | ||
| 298 | return -EPERM; | ||
| 299 | |||
| 300 | spin_lock_irqsave(&mac->lock, lock_flags); | ||
| 301 | if (!zd_regdomain_supports_channel(mac->regdomain, channel)) { | ||
| 302 | spin_unlock_irqrestore(&mac->lock, lock_flags); | ||
| 303 | return -EINVAL; | ||
| 304 | } | ||
| 305 | mac->requested_channel = channel; | ||
| 306 | spin_unlock_irqrestore(&mac->lock, lock_flags); | ||
| 307 | if (netif_running(mac->netdev)) | ||
| 308 | return zd_chip_set_channel(&mac->chip, channel); | ||
| 309 | else | ||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags) | ||
| 314 | { | ||
| 315 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
| 316 | |||
| 317 | *channel = zd_chip_get_channel(&mac->chip); | ||
| 318 | if (ieee->iw_mode != IW_MODE_INFRA) { | ||
| 319 | spin_lock_irq(&mac->lock); | ||
| 320 | *flags = *channel == mac->requested_channel ? | ||
| 321 | MAC_FIXED_CHANNEL : 0; | ||
| 322 | spin_unlock(&mac->lock); | ||
| 323 | } else { | ||
| 324 | *flags = 0; | ||
| 325 | } | ||
| 326 | dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags); | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | /* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ | ||
| 331 | static u8 cs_typed_rate(u8 cs_rate) | ||
| 332 | { | ||
| 333 | static const u8 typed_rates[16] = { | ||
| 334 | [ZD_CS_CCK_RATE_1M] = ZD_CS_CCK|ZD_CS_CCK_RATE_1M, | ||
| 335 | [ZD_CS_CCK_RATE_2M] = ZD_CS_CCK|ZD_CS_CCK_RATE_2M, | ||
| 336 | [ZD_CS_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M, | ||
| 337 | [ZD_CS_CCK_RATE_11M] = ZD_CS_CCK|ZD_CS_CCK_RATE_11M, | ||
| 338 | [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, | ||
| 339 | [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, | ||
| 340 | [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, | ||
| 341 | [ZD_OFDM_RATE_18M] = ZD_CS_OFDM|ZD_OFDM_RATE_18M, | ||
| 342 | [ZD_OFDM_RATE_24M] = ZD_CS_OFDM|ZD_OFDM_RATE_24M, | ||
| 343 | [ZD_OFDM_RATE_36M] = ZD_CS_OFDM|ZD_OFDM_RATE_36M, | ||
| 344 | [ZD_OFDM_RATE_48M] = ZD_CS_OFDM|ZD_OFDM_RATE_48M, | ||
| 345 | [ZD_OFDM_RATE_54M] = ZD_CS_OFDM|ZD_OFDM_RATE_54M, | ||
| 346 | }; | ||
| 347 | |||
| 348 | ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); | ||
| 349 | return typed_rates[cs_rate & ZD_CS_RATE_MASK]; | ||
| 350 | } | ||
| 351 | |||
| 352 | /* Fallback to lowest rate, if rate is unknown. */ | ||
| 353 | static u8 rate_to_cs_rate(u8 rate) | ||
| 354 | { | ||
| 355 | switch (rate) { | ||
| 356 | case IEEE80211_CCK_RATE_2MB: | ||
| 357 | return ZD_CS_CCK_RATE_2M; | ||
| 358 | case IEEE80211_CCK_RATE_5MB: | ||
| 359 | return ZD_CS_CCK_RATE_5_5M; | ||
| 360 | case IEEE80211_CCK_RATE_11MB: | ||
| 361 | return ZD_CS_CCK_RATE_11M; | ||
| 362 | case IEEE80211_OFDM_RATE_6MB: | ||
| 363 | return ZD_OFDM_RATE_6M; | ||
| 364 | case IEEE80211_OFDM_RATE_9MB: | ||
| 365 | return ZD_OFDM_RATE_9M; | ||
| 366 | case IEEE80211_OFDM_RATE_12MB: | ||
| 367 | return ZD_OFDM_RATE_12M; | ||
| 368 | case IEEE80211_OFDM_RATE_18MB: | ||
| 369 | return ZD_OFDM_RATE_18M; | ||
| 370 | case IEEE80211_OFDM_RATE_24MB: | ||
| 371 | return ZD_OFDM_RATE_24M; | ||
| 372 | case IEEE80211_OFDM_RATE_36MB: | ||
| 373 | return ZD_OFDM_RATE_36M; | ||
| 374 | case IEEE80211_OFDM_RATE_48MB: | ||
| 375 | return ZD_OFDM_RATE_48M; | ||
| 376 | case IEEE80211_OFDM_RATE_54MB: | ||
| 377 | return ZD_OFDM_RATE_54M; | ||
| 378 | } | ||
| 379 | return ZD_CS_CCK_RATE_1M; | ||
| 380 | } | ||
| 381 | |||
| 382 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode) | ||
| 383 | { | ||
| 384 | struct ieee80211_device *ieee; | ||
| 385 | |||
| 386 | switch (mode) { | ||
| 387 | case IW_MODE_AUTO: | ||
| 388 | case IW_MODE_ADHOC: | ||
| 389 | case IW_MODE_INFRA: | ||
| 390 | mac->netdev->type = ARPHRD_ETHER; | ||
| 391 | break; | ||
| 392 | case IW_MODE_MONITOR: | ||
| 393 | mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
| 394 | break; | ||
| 395 | default: | ||
| 396 | dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode); | ||
| 397 | return -EINVAL; | ||
| 398 | } | ||
| 399 | |||
| 400 | ieee = zd_mac_to_ieee80211(mac); | ||
| 401 | ZD_ASSERT(!irqs_disabled()); | ||
| 402 | spin_lock_irq(&ieee->lock); | ||
| 403 | ieee->iw_mode = mode; | ||
| 404 | spin_unlock_irq(&ieee->lock); | ||
| 405 | |||
| 406 | if (netif_running(mac->netdev)) | ||
| 407 | return reset_mode(mac); | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | |||
| 412 | int zd_mac_get_mode(struct zd_mac *mac, u32 *mode) | ||
| 413 | { | ||
| 414 | unsigned long flags; | ||
| 415 | struct ieee80211_device *ieee; | ||
| 416 | |||
| 417 | ieee = zd_mac_to_ieee80211(mac); | ||
| 418 | spin_lock_irqsave(&ieee->lock, flags); | ||
| 419 | *mode = ieee->iw_mode; | ||
| 420 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) | ||
| 425 | { | ||
| 426 | int i; | ||
| 427 | const struct channel_range *channel_range; | ||
| 428 | u8 regdomain; | ||
| 429 | |||
| 430 | memset(range, 0, sizeof(*range)); | ||
| 431 | |||
| 432 | /* FIXME: Not so important and depends on the mode. For 802.11g | ||
| 433 | * usually this value is used. It seems to be that Bit/s number is | ||
| 434 | * given here. | ||
| 435 | */ | ||
| 436 | range->throughput = 27 * 1000 * 1000; | ||
| 437 | |||
| 438 | range->max_qual.qual = 100; | ||
| 439 | range->max_qual.level = 100; | ||
| 440 | |||
| 441 | /* FIXME: Needs still to be tuned. */ | ||
| 442 | range->avg_qual.qual = 71; | ||
| 443 | range->avg_qual.level = 80; | ||
| 444 | |||
| 445 | /* FIXME: depends on standard? */ | ||
| 446 | range->min_rts = 256; | ||
| 447 | range->max_rts = 2346; | ||
| 448 | |||
| 449 | range->min_frag = MIN_FRAG_THRESHOLD; | ||
| 450 | range->max_frag = MAX_FRAG_THRESHOLD; | ||
| 451 | |||
| 452 | range->max_encoding_tokens = WEP_KEYS; | ||
| 453 | range->num_encoding_sizes = 2; | ||
| 454 | range->encoding_size[0] = 5; | ||
| 455 | range->encoding_size[1] = WEP_KEY_LEN; | ||
| 456 | |||
| 457 | range->we_version_compiled = WIRELESS_EXT; | ||
| 458 | range->we_version_source = 20; | ||
| 459 | |||
| 460 | ZD_ASSERT(!irqs_disabled()); | ||
| 461 | spin_lock_irq(&mac->lock); | ||
| 462 | regdomain = mac->regdomain; | ||
| 463 | spin_unlock_irq(&mac->lock); | ||
| 464 | channel_range = zd_channel_range(regdomain); | ||
| 465 | |||
| 466 | range->num_channels = channel_range->end - channel_range->start; | ||
| 467 | range->old_num_channels = range->num_channels; | ||
| 468 | range->num_frequency = range->num_channels; | ||
| 469 | range->old_num_frequency = range->num_frequency; | ||
| 470 | |||
| 471 | for (i = 0; i < range->num_frequency; i++) { | ||
| 472 | struct iw_freq *freq = &range->freq[i]; | ||
| 473 | freq->i = channel_range->start + i; | ||
| 474 | zd_channel_to_freq(freq, freq->i); | ||
| 475 | } | ||
| 476 | |||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) | ||
| 481 | { | ||
| 482 | static const u8 rate_divisor[] = { | ||
| 483 | [ZD_CS_CCK_RATE_1M] = 1, | ||
| 484 | [ZD_CS_CCK_RATE_2M] = 2, | ||
| 485 | [ZD_CS_CCK_RATE_5_5M] = 11, /* bits must be doubled */ | ||
| 486 | [ZD_CS_CCK_RATE_11M] = 11, | ||
| 487 | [ZD_OFDM_RATE_6M] = 6, | ||
| 488 | [ZD_OFDM_RATE_9M] = 9, | ||
| 489 | [ZD_OFDM_RATE_12M] = 12, | ||
| 490 | [ZD_OFDM_RATE_18M] = 18, | ||
| 491 | [ZD_OFDM_RATE_24M] = 24, | ||
| 492 | [ZD_OFDM_RATE_36M] = 36, | ||
| 493 | [ZD_OFDM_RATE_48M] = 48, | ||
| 494 | [ZD_OFDM_RATE_54M] = 54, | ||
| 495 | }; | ||
| 496 | |||
| 497 | u32 bits = (u32)tx_length * 8; | ||
| 498 | u32 divisor; | ||
| 499 | |||
| 500 | divisor = rate_divisor[cs_rate]; | ||
| 501 | if (divisor == 0) | ||
| 502 | return -EINVAL; | ||
| 503 | |||
| 504 | switch (cs_rate) { | ||
| 505 | case ZD_CS_CCK_RATE_5_5M: | ||
| 506 | bits = (2*bits) + 10; /* round up to the next integer */ | ||
| 507 | break; | ||
| 508 | case ZD_CS_CCK_RATE_11M: | ||
| 509 | if (service) { | ||
| 510 | u32 t = bits % 11; | ||
| 511 | *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; | ||
| 512 | if (0 < t && t <= 3) { | ||
| 513 | *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION; | ||
| 514 | } | ||
| 515 | } | ||
| 516 | bits += 10; /* round up to the next integer */ | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | |||
| 520 | return bits/divisor; | ||
| 521 | } | ||
| 522 | |||
| 523 | enum { | ||
| 524 | R2M_SHORT_PREAMBLE = 0x01, | ||
| 525 | R2M_11A = 0x02, | ||
| 526 | }; | ||
| 527 | |||
| 528 | static u8 cs_rate_to_modulation(u8 cs_rate, int flags) | ||
| 529 | { | ||
| 530 | u8 modulation; | ||
| 531 | |||
| 532 | modulation = cs_typed_rate(cs_rate); | ||
| 533 | if (flags & R2M_SHORT_PREAMBLE) { | ||
| 534 | switch (ZD_CS_RATE(modulation)) { | ||
| 535 | case ZD_CS_CCK_RATE_2M: | ||
| 536 | case ZD_CS_CCK_RATE_5_5M: | ||
| 537 | case ZD_CS_CCK_RATE_11M: | ||
| 538 | modulation |= ZD_CS_CCK_PREA_SHORT; | ||
| 539 | return modulation; | ||
| 540 | } | ||
| 541 | } | ||
| 542 | if (flags & R2M_11A) { | ||
| 543 | if (ZD_CS_TYPE(modulation) == ZD_CS_OFDM) | ||
| 544 | modulation |= ZD_CS_OFDM_MODE_11A; | ||
| 545 | } | ||
| 546 | return modulation; | ||
| 547 | } | ||
| 548 | |||
| 549 | static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, | ||
| 550 | struct ieee80211_hdr_4addr *hdr) | ||
| 551 | { | ||
| 552 | struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); | ||
| 553 | u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); | ||
| 554 | u8 rate, cs_rate; | ||
| 555 | int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; | ||
| 556 | |||
| 557 | /* FIXME: 802.11a? short preamble? */ | ||
| 558 | rate = ieee80211softmac_suggest_txrate(softmac, | ||
| 559 | is_multicast_ether_addr(hdr->addr1), is_mgt); | ||
| 560 | |||
| 561 | cs_rate = rate_to_cs_rate(rate); | ||
| 562 | cs->modulation = cs_rate_to_modulation(cs_rate, 0); | ||
| 563 | } | ||
| 564 | |||
| 565 | static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | ||
| 566 | struct ieee80211_hdr_4addr *header) | ||
| 567 | { | ||
| 568 | unsigned int tx_length = le16_to_cpu(cs->tx_length); | ||
| 569 | u16 fctl = le16_to_cpu(header->frame_ctl); | ||
| 570 | u16 ftype = WLAN_FC_GET_TYPE(fctl); | ||
| 571 | u16 stype = WLAN_FC_GET_STYPE(fctl); | ||
| 572 | |||
| 573 | /* | ||
| 574 | * CONTROL: | ||
| 575 | * - start at 0x00 | ||
| 576 | * - if fragment 0, enable bit 0 | ||
| 577 | * - if backoff needed, enable bit 0 | ||
| 578 | * - if burst (backoff not needed) disable bit 0 | ||
| 579 | * - if multicast, enable bit 1 | ||
| 580 | * - if PS-POLL frame, enable bit 2 | ||
| 581 | * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable | ||
| 582 | * bit 4 (FIXME: wtf) | ||
| 583 | * - if frag_len > RTS threshold, set bit 5 as long if it isnt | ||
| 584 | * multicast or mgt | ||
| 585 | * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit | ||
| 586 | * 7 | ||
| 587 | */ | ||
| 588 | |||
| 589 | cs->control = 0; | ||
| 590 | |||
| 591 | /* First fragment */ | ||
| 592 | if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0) | ||
| 593 | cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; | ||
| 594 | |||
| 595 | /* Multicast */ | ||
| 596 | if (is_multicast_ether_addr(header->addr1)) | ||
| 597 | cs->control |= ZD_CS_MULTICAST; | ||
| 598 | |||
| 599 | /* PS-POLL */ | ||
| 600 | if (stype == IEEE80211_STYPE_PSPOLL) | ||
| 601 | cs->control |= ZD_CS_PS_POLL_FRAME; | ||
| 602 | |||
| 603 | if (!is_multicast_ether_addr(header->addr1) && | ||
| 604 | ftype != IEEE80211_FTYPE_MGMT && | ||
| 605 | tx_length > zd_netdev_ieee80211(mac->netdev)->rts) | ||
| 606 | { | ||
| 607 | /* FIXME: check the logic */ | ||
| 608 | if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) { | ||
| 609 | /* 802.11g */ | ||
| 610 | cs->control |= ZD_CS_SELF_CTS; | ||
| 611 | } else { /* 802.11b */ | ||
| 612 | cs->control |= ZD_CS_RTS; | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | /* FIXME: Management frame? */ | ||
| 617 | } | ||
| 618 | |||
| 619 | static int fill_ctrlset(struct zd_mac *mac, | ||
| 620 | struct ieee80211_txb *txb, | ||
| 621 | int frag_num) | ||
| 622 | { | ||
| 623 | int r; | ||
| 624 | struct sk_buff *skb = txb->fragments[frag_num]; | ||
| 625 | struct ieee80211_hdr_4addr *hdr = | ||
| 626 | (struct ieee80211_hdr_4addr *) skb->data; | ||
| 627 | unsigned int frag_len = skb->len + IEEE80211_FCS_LEN; | ||
| 628 | unsigned int next_frag_len; | ||
| 629 | unsigned int packet_length; | ||
| 630 | struct zd_ctrlset *cs = (struct zd_ctrlset *) | ||
| 631 | skb_push(skb, sizeof(struct zd_ctrlset)); | ||
| 632 | |||
| 633 | if (frag_num+1 < txb->nr_frags) { | ||
| 634 | next_frag_len = txb->fragments[frag_num+1]->len + | ||
| 635 | IEEE80211_FCS_LEN; | ||
| 636 | } else { | ||
| 637 | next_frag_len = 0; | ||
| 638 | } | ||
| 639 | ZD_ASSERT(frag_len <= 0xffff); | ||
| 640 | ZD_ASSERT(next_frag_len <= 0xffff); | ||
| 641 | |||
| 642 | cs_set_modulation(mac, cs, hdr); | ||
| 643 | |||
| 644 | cs->tx_length = cpu_to_le16(frag_len); | ||
| 645 | |||
| 646 | cs_set_control(mac, cs, hdr); | ||
| 647 | |||
| 648 | packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; | ||
| 649 | ZD_ASSERT(packet_length <= 0xffff); | ||
| 650 | /* ZD1211B: Computing the length difference this way, gives us | ||
| 651 | * flexibility to compute the packet length. | ||
| 652 | */ | ||
| 653 | cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ? | ||
| 654 | packet_length - frag_len : packet_length); | ||
| 655 | |||
| 656 | /* | ||
| 657 | * CURRENT LENGTH: | ||
| 658 | * - transmit frame length in microseconds | ||
| 659 | * - seems to be derived from frame length | ||
| 660 | * - see Cal_Us_Service() in zdinlinef.h | ||
| 661 | * - if macp->bTxBurstEnable is enabled, then multiply by 4 | ||
| 662 | * - bTxBurstEnable is never set in the vendor driver | ||
| 663 | * | ||
| 664 | * SERVICE: | ||
| 665 | * - "for PLCP configuration" | ||
| 666 | * - always 0 except in some situations at 802.11b 11M | ||
| 667 | * - see line 53 of zdinlinef.h | ||
| 668 | */ | ||
| 669 | cs->service = 0; | ||
| 670 | r = zd_calc_tx_length_us(&cs->service, ZD_CS_RATE(cs->modulation), | ||
| 671 | le16_to_cpu(cs->tx_length)); | ||
| 672 | if (r < 0) | ||
| 673 | return r; | ||
| 674 | cs->current_length = cpu_to_le16(r); | ||
| 675 | |||
| 676 | if (next_frag_len == 0) { | ||
| 677 | cs->next_frame_length = 0; | ||
| 678 | } else { | ||
| 679 | r = zd_calc_tx_length_us(NULL, ZD_CS_RATE(cs->modulation), | ||
| 680 | next_frag_len); | ||
| 681 | if (r < 0) | ||
| 682 | return r; | ||
| 683 | cs->next_frame_length = cpu_to_le16(r); | ||
| 684 | } | ||
| 685 | |||
| 686 | return 0; | ||
| 687 | } | ||
| 688 | |||
| 689 | static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri) | ||
| 690 | { | ||
| 691 | int i, r; | ||
| 692 | |||
| 693 | for (i = 0; i < txb->nr_frags; i++) { | ||
| 694 | struct sk_buff *skb = txb->fragments[i]; | ||
| 695 | |||
| 696 | r = fill_ctrlset(mac, txb, i); | ||
| 697 | if (r) | ||
| 698 | return r; | ||
| 699 | r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len); | ||
| 700 | if (r) | ||
| 701 | return r; | ||
| 702 | } | ||
| 703 | |||
| 704 | /* FIXME: shouldn't this be handled by the upper layers? */ | ||
| 705 | mac->netdev->trans_start = jiffies; | ||
| 706 | |||
| 707 | ieee80211_txb_free(txb); | ||
| 708 | return 0; | ||
| 709 | } | ||
| 710 | |||
| 711 | struct zd_rt_hdr { | ||
| 712 | struct ieee80211_radiotap_header rt_hdr; | ||
| 713 | u8 rt_flags; | ||
| 714 | u16 rt_channel; | ||
| 715 | u16 rt_chbitmask; | ||
| 716 | u16 rt_rate; | ||
| 717 | }; | ||
| 718 | |||
| 719 | static void fill_rt_header(void *buffer, struct zd_mac *mac, | ||
| 720 | const struct ieee80211_rx_stats *stats, | ||
| 721 | const struct rx_status *status) | ||
| 722 | { | ||
| 723 | struct zd_rt_hdr *hdr = buffer; | ||
| 724 | |||
| 725 | hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
| 726 | hdr->rt_hdr.it_pad = 0; | ||
| 727 | hdr->rt_hdr.it_len = cpu_to_le16(sizeof(struct zd_rt_hdr)); | ||
| 728 | hdr->rt_hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
| 729 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
| 730 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
| 731 | |||
| 732 | hdr->rt_flags = 0; | ||
| 733 | if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256)) | ||
| 734 | hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP; | ||
| 735 | |||
| 736 | /* FIXME: 802.11a */ | ||
| 737 | hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz( | ||
| 738 | _zd_chip_get_channel(&mac->chip))); | ||
| 739 | hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ | | ||
| 740 | ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) == | ||
| 741 | ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK)); | ||
| 742 | |||
| 743 | hdr->rt_rate = stats->rate / 5; | ||
| 744 | } | ||
| 745 | |||
| 746 | /* Returns 1 if the data packet is for us and 0 otherwise. */ | ||
| 747 | static int is_data_packet_for_us(struct ieee80211_device *ieee, | ||
| 748 | struct ieee80211_hdr_4addr *hdr) | ||
| 749 | { | ||
| 750 | struct net_device *netdev = ieee->dev; | ||
| 751 | u16 fc = le16_to_cpu(hdr->frame_ctl); | ||
| 752 | |||
| 753 | ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA); | ||
| 754 | |||
| 755 | switch (ieee->iw_mode) { | ||
| 756 | case IW_MODE_ADHOC: | ||
| 757 | if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 || | ||
| 758 | memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0) | ||
| 759 | return 0; | ||
| 760 | break; | ||
| 761 | case IW_MODE_AUTO: | ||
| 762 | case IW_MODE_INFRA: | ||
| 763 | if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != | ||
| 764 | IEEE80211_FCTL_FROMDS || | ||
| 765 | memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0) | ||
| 766 | return 0; | ||
| 767 | break; | ||
| 768 | default: | ||
| 769 | ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR); | ||
| 770 | return 0; | ||
| 771 | } | ||
| 772 | |||
| 773 | return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || | ||
| 774 | is_multicast_ether_addr(hdr->addr1) || | ||
| 775 | (netdev->flags & IFF_PROMISC); | ||
| 776 | } | ||
| 777 | |||
| 778 | /* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0 | ||
| 779 | * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is | ||
| 780 | * called here. | ||
| 781 | * | ||
| 782 | * It has been based on ieee80211_rx_any. | ||
| 783 | */ | ||
| 784 | static int filter_rx(struct ieee80211_device *ieee, | ||
| 785 | const u8 *buffer, unsigned int length, | ||
| 786 | struct ieee80211_rx_stats *stats) | ||
| 787 | { | ||
| 788 | struct ieee80211_hdr_4addr *hdr; | ||
| 789 | u16 fc; | ||
| 790 | |||
| 791 | if (ieee->iw_mode == IW_MODE_MONITOR) | ||
| 792 | return 1; | ||
| 793 | |||
| 794 | hdr = (struct ieee80211_hdr_4addr *)buffer; | ||
| 795 | fc = le16_to_cpu(hdr->frame_ctl); | ||
| 796 | if ((fc & IEEE80211_FCTL_VERS) != 0) | ||
| 797 | return -EINVAL; | ||
| 798 | |||
| 799 | switch (WLAN_FC_GET_TYPE(fc)) { | ||
| 800 | case IEEE80211_FTYPE_MGMT: | ||
| 801 | if (length < sizeof(struct ieee80211_hdr_3addr)) | ||
| 802 | return -EINVAL; | ||
| 803 | ieee80211_rx_mgt(ieee, hdr, stats); | ||
| 804 | return 0; | ||
| 805 | case IEEE80211_FTYPE_CTL: | ||
| 806 | /* Ignore invalid short buffers */ | ||
| 807 | return 0; | ||
| 808 | case IEEE80211_FTYPE_DATA: | ||
| 809 | if (length < sizeof(struct ieee80211_hdr_3addr)) | ||
| 810 | return -EINVAL; | ||
| 811 | return is_data_packet_for_us(ieee, hdr); | ||
| 812 | } | ||
| 813 | |||
| 814 | return -EINVAL; | ||
| 815 | } | ||
| 816 | |||
| 817 | static void update_qual_rssi(struct zd_mac *mac, u8 qual_percent, u8 rssi) | ||
| 818 | { | ||
| 819 | unsigned long flags; | ||
| 820 | |||
| 821 | spin_lock_irqsave(&mac->lock, flags); | ||
| 822 | mac->qual_average = (7 * mac->qual_average + qual_percent) / 8; | ||
| 823 | mac->rssi_average = (7 * mac->rssi_average + rssi) / 8; | ||
| 824 | spin_unlock_irqrestore(&mac->lock, flags); | ||
| 825 | } | ||
| 826 | |||
| 827 | static int fill_rx_stats(struct ieee80211_rx_stats *stats, | ||
| 828 | const struct rx_status **pstatus, | ||
| 829 | struct zd_mac *mac, | ||
| 830 | const u8 *buffer, unsigned int length) | ||
| 831 | { | ||
| 832 | const struct rx_status *status; | ||
| 833 | |||
| 834 | *pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status)); | ||
| 835 | if (status->frame_status & ZD_RX_ERROR) { | ||
| 836 | /* FIXME: update? */ | ||
| 837 | return -EINVAL; | ||
| 838 | } | ||
| 839 | memset(stats, 0, sizeof(struct ieee80211_rx_stats)); | ||
| 840 | stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN + | ||
| 841 | + sizeof(struct rx_status)); | ||
| 842 | /* FIXME: 802.11a */ | ||
| 843 | stats->freq = IEEE80211_24GHZ_BAND; | ||
| 844 | stats->received_channel = _zd_chip_get_channel(&mac->chip); | ||
| 845 | stats->rssi = zd_rx_strength_percent(status->signal_strength); | ||
| 846 | stats->signal = zd_rx_qual_percent(buffer, | ||
| 847 | length - sizeof(struct rx_status), | ||
| 848 | status); | ||
| 849 | stats->mask = IEEE80211_STATMASK_RSSI | IEEE80211_STATMASK_SIGNAL; | ||
| 850 | stats->rate = zd_rx_rate(buffer, status); | ||
| 851 | if (stats->rate) | ||
| 852 | stats->mask |= IEEE80211_STATMASK_RATE; | ||
| 853 | |||
| 854 | update_qual_rssi(mac, stats->signal, stats->rssi); | ||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | |||
| 858 | int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) | ||
| 859 | { | ||
| 860 | int r; | ||
| 861 | struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); | ||
| 862 | struct ieee80211_rx_stats stats; | ||
| 863 | const struct rx_status *status; | ||
| 864 | struct sk_buff *skb; | ||
| 865 | |||
| 866 | if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN + | ||
| 867 | IEEE80211_FCS_LEN + sizeof(struct rx_status)) | ||
| 868 | return -EINVAL; | ||
| 869 | |||
| 870 | r = fill_rx_stats(&stats, &status, mac, buffer, length); | ||
| 871 | if (r) | ||
| 872 | return r; | ||
| 873 | |||
| 874 | length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+ | ||
| 875 | sizeof(struct rx_status); | ||
| 876 | buffer += ZD_PLCP_HEADER_SIZE; | ||
| 877 | |||
| 878 | r = filter_rx(ieee, buffer, length, &stats); | ||
| 879 | if (r <= 0) | ||
| 880 | return r; | ||
| 881 | |||
| 882 | skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length); | ||
| 883 | if (!skb) | ||
| 884 | return -ENOMEM; | ||
| 885 | if (ieee->iw_mode == IW_MODE_MONITOR) | ||
| 886 | fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac, | ||
| 887 | &stats, status); | ||
| 888 | memcpy(skb_put(skb, length), buffer, length); | ||
| 889 | |||
| 890 | r = ieee80211_rx(ieee, skb, &stats); | ||
| 891 | if (!r) { | ||
| 892 | ZD_ASSERT(in_irq()); | ||
| 893 | dev_kfree_skb_irq(skb); | ||
| 894 | } | ||
| 895 | return 0; | ||
| 896 | } | ||
| 897 | |||
| 898 | static int netdev_tx(struct ieee80211_txb *txb, struct net_device *netdev, | ||
| 899 | int pri) | ||
| 900 | { | ||
| 901 | return zd_mac_tx(zd_netdev_mac(netdev), txb, pri); | ||
| 902 | } | ||
| 903 | |||
| 904 | static void set_security(struct net_device *netdev, | ||
| 905 | struct ieee80211_security *sec) | ||
| 906 | { | ||
| 907 | struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev); | ||
| 908 | struct ieee80211_security *secinfo = &ieee->sec; | ||
| 909 | int keyidx; | ||
| 910 | |||
| 911 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n"); | ||
| 912 | |||
| 913 | for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) | ||
| 914 | if (sec->flags & (1<<keyidx)) { | ||
| 915 | secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx]; | ||
| 916 | secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; | ||
| 917 | memcpy(secinfo->keys[keyidx], sec->keys[keyidx], | ||
| 918 | SCM_KEY_LEN); | ||
| 919 | } | ||
| 920 | |||
| 921 | if (sec->flags & SEC_ACTIVE_KEY) { | ||
| 922 | secinfo->active_key = sec->active_key; | ||
| 923 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
| 924 | " .active_key = %d\n", sec->active_key); | ||
| 925 | } | ||
| 926 | if (sec->flags & SEC_UNICAST_GROUP) { | ||
| 927 | secinfo->unicast_uses_group = sec->unicast_uses_group; | ||
| 928 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
| 929 | " .unicast_uses_group = %d\n", | ||
| 930 | sec->unicast_uses_group); | ||
| 931 | } | ||
| 932 | if (sec->flags & SEC_LEVEL) { | ||
| 933 | secinfo->level = sec->level; | ||
| 934 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
| 935 | " .level = %d\n", sec->level); | ||
| 936 | } | ||
| 937 | if (sec->flags & SEC_ENABLED) { | ||
| 938 | secinfo->enabled = sec->enabled; | ||
| 939 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
| 940 | " .enabled = %d\n", sec->enabled); | ||
| 941 | } | ||
| 942 | if (sec->flags & SEC_ENCRYPT) { | ||
| 943 | secinfo->encrypt = sec->encrypt; | ||
| 944 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
| 945 | " .encrypt = %d\n", sec->encrypt); | ||
| 946 | } | ||
| 947 | if (sec->flags & SEC_AUTH_MODE) { | ||
| 948 | secinfo->auth_mode = sec->auth_mode; | ||
| 949 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), | ||
| 950 | " .auth_mode = %d\n", sec->auth_mode); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 954 | static void ieee_init(struct ieee80211_device *ieee) | ||
| 955 | { | ||
| 956 | ieee->mode = IEEE_B | IEEE_G; | ||
| 957 | ieee->freq_band = IEEE80211_24GHZ_BAND; | ||
| 958 | ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION; | ||
| 959 | ieee->tx_headroom = sizeof(struct zd_ctrlset); | ||
| 960 | ieee->set_security = set_security; | ||
| 961 | ieee->hard_start_xmit = netdev_tx; | ||
| 962 | |||
| 963 | /* Software encryption/decryption for now */ | ||
| 964 | ieee->host_build_iv = 0; | ||
| 965 | ieee->host_encrypt = 1; | ||
| 966 | ieee->host_decrypt = 1; | ||
| 967 | |||
| 968 | /* FIXME: default to managed mode, until ieee80211 and zd1211rw can | ||
| 969 | * correctly support AUTO */ | ||
| 970 | ieee->iw_mode = IW_MODE_INFRA; | ||
| 971 | } | ||
| 972 | |||
| 973 | static void softmac_init(struct ieee80211softmac_device *sm) | ||
| 974 | { | ||
| 975 | sm->set_channel = set_channel; | ||
| 976 | } | ||
| 977 | |||
| 978 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) | ||
| 979 | { | ||
| 980 | struct zd_mac *mac = zd_netdev_mac(ndev); | ||
| 981 | struct iw_statistics *iw_stats = &mac->iw_stats; | ||
| 982 | |||
| 983 | memset(iw_stats, 0, sizeof(struct iw_statistics)); | ||
| 984 | /* We are not setting the status, because ieee->state is not updated | ||
| 985 | * at all and this driver doesn't track authentication state. | ||
| 986 | */ | ||
| 987 | spin_lock_irq(&mac->lock); | ||
| 988 | iw_stats->qual.qual = mac->qual_average; | ||
| 989 | iw_stats->qual.level = mac->rssi_average; | ||
| 990 | iw_stats->qual.updated = IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED| | ||
| 991 | IW_QUAL_NOISE_INVALID; | ||
| 992 | spin_unlock_irq(&mac->lock); | ||
| 993 | /* TODO: update counter */ | ||
| 994 | return iw_stats; | ||
| 995 | } | ||
| 996 | |||
| 997 | #ifdef DEBUG | ||
| 998 | static const char* decryption_types[] = { | ||
| 999 | [ZD_RX_NO_WEP] = "none", | ||
| 1000 | [ZD_RX_WEP64] = "WEP64", | ||
| 1001 | [ZD_RX_TKIP] = "TKIP", | ||
| 1002 | [ZD_RX_AES] = "AES", | ||
| 1003 | [ZD_RX_WEP128] = "WEP128", | ||
| 1004 | [ZD_RX_WEP256] = "WEP256", | ||
| 1005 | }; | ||
| 1006 | |||
| 1007 | static const char *decryption_type_string(u8 type) | ||
| 1008 | { | ||
| 1009 | const char *s; | ||
| 1010 | |||
| 1011 | if (type < ARRAY_SIZE(decryption_types)) { | ||
| 1012 | s = decryption_types[type]; | ||
| 1013 | } else { | ||
| 1014 | s = NULL; | ||
| 1015 | } | ||
| 1016 | return s ? s : "unknown"; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | static int is_ofdm(u8 frame_status) | ||
| 1020 | { | ||
| 1021 | return (frame_status & ZD_RX_OFDM); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | void zd_dump_rx_status(const struct rx_status *status) | ||
| 1025 | { | ||
| 1026 | const char* modulation; | ||
| 1027 | u8 quality; | ||
| 1028 | |||
| 1029 | if (is_ofdm(status->frame_status)) { | ||
| 1030 | modulation = "ofdm"; | ||
| 1031 | quality = status->signal_quality_ofdm; | ||
| 1032 | } else { | ||
| 1033 | modulation = "cck"; | ||
| 1034 | quality = status->signal_quality_cck; | ||
| 1035 | } | ||
| 1036 | pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n", | ||
| 1037 | modulation, status->signal_strength, quality, | ||
| 1038 | decryption_type_string(status->decryption_type)); | ||
| 1039 | if (status->frame_status & ZD_RX_ERROR) { | ||
| 1040 | pr_debug("rx error %s%s%s%s%s%s\n", | ||
| 1041 | (status->frame_status & ZD_RX_TIMEOUT_ERROR) ? | ||
| 1042 | "timeout " : "", | ||
| 1043 | (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ? | ||
| 1044 | "fifo " : "", | ||
| 1045 | (status->frame_status & ZD_RX_DECRYPTION_ERROR) ? | ||
| 1046 | "decryption " : "", | ||
| 1047 | (status->frame_status & ZD_RX_CRC32_ERROR) ? | ||
| 1048 | "crc32 " : "", | ||
| 1049 | (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ? | ||
| 1050 | "addr1 " : "", | ||
| 1051 | (status->frame_status & ZD_RX_CRC16_ERROR) ? | ||
| 1052 | "crc16" : ""); | ||
| 1053 | } | ||
| 1054 | } | ||
| 1055 | #endif /* DEBUG */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h new file mode 100644 index 000000000000..71e382c589ee --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /* zd_mac.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_MAC_H | ||
| 19 | #define _ZD_MAC_H | ||
| 20 | |||
| 21 | #include <linux/wireless.h> | ||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <net/ieee80211.h> | ||
| 24 | #include <net/ieee80211softmac.h> | ||
| 25 | |||
| 26 | #include "zd_chip.h" | ||
| 27 | #include "zd_netdev.h" | ||
| 28 | |||
| 29 | struct zd_ctrlset { | ||
| 30 | u8 modulation; | ||
| 31 | __le16 tx_length; | ||
| 32 | u8 control; | ||
| 33 | /* stores only the difference to tx_length on ZD1211B */ | ||
| 34 | __le16 packet_length; | ||
| 35 | __le16 current_length; | ||
| 36 | u8 service; | ||
| 37 | __le16 next_frame_length; | ||
| 38 | } __attribute__((packed)); | ||
| 39 | |||
| 40 | #define ZD_CS_RESERVED_SIZE 25 | ||
| 41 | |||
| 42 | /* zd_crtlset field modulation */ | ||
| 43 | #define ZD_CS_RATE_MASK 0x0f | ||
| 44 | #define ZD_CS_TYPE_MASK 0x10 | ||
| 45 | #define ZD_CS_RATE(modulation) ((modulation) & ZD_CS_RATE_MASK) | ||
| 46 | #define ZD_CS_TYPE(modulation) ((modulation) & ZD_CS_TYPE_MASK) | ||
| 47 | |||
| 48 | #define ZD_CS_CCK 0x00 | ||
| 49 | #define ZD_CS_OFDM 0x10 | ||
| 50 | |||
| 51 | #define ZD_CS_CCK_RATE_1M 0x00 | ||
| 52 | #define ZD_CS_CCK_RATE_2M 0x01 | ||
| 53 | #define ZD_CS_CCK_RATE_5_5M 0x02 | ||
| 54 | #define ZD_CS_CCK_RATE_11M 0x03 | ||
| 55 | /* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*. | ||
| 56 | */ | ||
| 57 | |||
| 58 | /* bit 5 is preamble (when in CCK mode), or a/g selection (when in OFDM mode) */ | ||
| 59 | #define ZD_CS_CCK_PREA_LONG 0x00 | ||
| 60 | #define ZD_CS_CCK_PREA_SHORT 0x20 | ||
| 61 | #define ZD_CS_OFDM_MODE_11G 0x00 | ||
| 62 | #define ZD_CS_OFDM_MODE_11A 0x20 | ||
| 63 | |||
| 64 | /* zd_ctrlset control field */ | ||
| 65 | #define ZD_CS_NEED_RANDOM_BACKOFF 0x01 | ||
| 66 | #define ZD_CS_MULTICAST 0x02 | ||
| 67 | |||
| 68 | #define ZD_CS_FRAME_TYPE_MASK 0x0c | ||
| 69 | #define ZD_CS_DATA_FRAME 0x00 | ||
| 70 | #define ZD_CS_PS_POLL_FRAME 0x04 | ||
| 71 | #define ZD_CS_MANAGEMENT_FRAME 0x08 | ||
| 72 | #define ZD_CS_NO_SEQUENCE_CTL_FRAME 0x0c | ||
| 73 | |||
| 74 | #define ZD_CS_WAKE_DESTINATION 0x10 | ||
| 75 | #define ZD_CS_RTS 0x20 | ||
| 76 | #define ZD_CS_ENCRYPT 0x40 | ||
| 77 | #define ZD_CS_SELF_CTS 0x80 | ||
| 78 | |||
| 79 | /* Incoming frames are prepended by a PLCP header */ | ||
| 80 | #define ZD_PLCP_HEADER_SIZE 5 | ||
| 81 | |||
| 82 | struct rx_length_info { | ||
| 83 | __le16 length[3]; | ||
| 84 | __le16 tag; | ||
| 85 | } __attribute__((packed)); | ||
| 86 | |||
| 87 | #define RX_LENGTH_INFO_TAG 0x697e | ||
| 88 | |||
| 89 | struct rx_status { | ||
| 90 | /* rssi */ | ||
| 91 | u8 signal_strength; | ||
| 92 | u8 signal_quality_cck; | ||
| 93 | u8 signal_quality_ofdm; | ||
| 94 | u8 decryption_type; | ||
| 95 | u8 frame_status; | ||
| 96 | } __attribute__((packed)); | ||
| 97 | |||
| 98 | /* rx_status field decryption_type */ | ||
| 99 | #define ZD_RX_NO_WEP 0 | ||
| 100 | #define ZD_RX_WEP64 1 | ||
| 101 | #define ZD_RX_TKIP 2 | ||
| 102 | #define ZD_RX_AES 4 | ||
| 103 | #define ZD_RX_WEP128 5 | ||
| 104 | #define ZD_RX_WEP256 6 | ||
| 105 | |||
| 106 | /* rx_status field frame_status */ | ||
| 107 | #define ZD_RX_FRAME_MODULATION_MASK 0x01 | ||
| 108 | #define ZD_RX_CCK 0x00 | ||
| 109 | #define ZD_RX_OFDM 0x01 | ||
| 110 | |||
| 111 | #define ZD_RX_TIMEOUT_ERROR 0x02 | ||
| 112 | #define ZD_RX_FIFO_OVERRUN_ERROR 0x04 | ||
| 113 | #define ZD_RX_DECRYPTION_ERROR 0x08 | ||
| 114 | #define ZD_RX_CRC32_ERROR 0x10 | ||
| 115 | #define ZD_RX_NO_ADDR1_MATCH_ERROR 0x20 | ||
| 116 | #define ZD_RX_CRC16_ERROR 0x40 | ||
| 117 | #define ZD_RX_ERROR 0x80 | ||
| 118 | |||
| 119 | enum mac_flags { | ||
| 120 | MAC_FIXED_CHANNEL = 0x01, | ||
| 121 | }; | ||
| 122 | |||
| 123 | struct zd_mac { | ||
| 124 | struct net_device *netdev; | ||
| 125 | struct zd_chip chip; | ||
| 126 | spinlock_t lock; | ||
| 127 | /* Unlocked reading possible */ | ||
| 128 | struct iw_statistics iw_stats; | ||
| 129 | u8 qual_average; | ||
| 130 | u8 rssi_average; | ||
| 131 | u8 regdomain; | ||
| 132 | u8 default_regdomain; | ||
| 133 | u8 requested_channel; | ||
| 134 | }; | ||
| 135 | |||
| 136 | static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) | ||
| 137 | { | ||
| 138 | return zd_netdev_ieee80211(mac->netdev); | ||
| 139 | } | ||
| 140 | |||
| 141 | static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev) | ||
| 142 | { | ||
| 143 | return ieee80211softmac_priv(netdev); | ||
| 144 | } | ||
| 145 | |||
| 146 | static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip) | ||
| 147 | { | ||
| 148 | return container_of(chip, struct zd_mac, chip); | ||
| 149 | } | ||
| 150 | |||
| 151 | static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb) | ||
| 152 | { | ||
| 153 | return zd_chip_to_mac(zd_usb_to_chip(usb)); | ||
| 154 | } | ||
| 155 | |||
| 156 | #define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip)) | ||
| 157 | |||
| 158 | int zd_mac_init(struct zd_mac *mac, | ||
| 159 | struct net_device *netdev, | ||
| 160 | struct usb_interface *intf); | ||
| 161 | void zd_mac_clear(struct zd_mac *mac); | ||
| 162 | |||
| 163 | int zd_mac_init_hw(struct zd_mac *mac, u8 device_type); | ||
| 164 | |||
| 165 | int zd_mac_open(struct net_device *netdev); | ||
| 166 | int zd_mac_stop(struct net_device *netdev); | ||
| 167 | int zd_mac_set_mac_address(struct net_device *dev, void *p); | ||
| 168 | |||
| 169 | int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length); | ||
| 170 | |||
| 171 | int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain); | ||
| 172 | u8 zd_mac_get_regdomain(struct zd_mac *zd_mac); | ||
| 173 | |||
| 174 | int zd_mac_request_channel(struct zd_mac *mac, u8 channel); | ||
| 175 | int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags); | ||
| 176 | |||
| 177 | int zd_mac_set_mode(struct zd_mac *mac, u32 mode); | ||
| 178 | int zd_mac_get_mode(struct zd_mac *mac, u32 *mode); | ||
| 179 | |||
| 180 | int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range); | ||
| 181 | |||
| 182 | struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev); | ||
| 183 | |||
| 184 | #ifdef DEBUG | ||
| 185 | void zd_dump_rx_status(const struct rx_status *status); | ||
| 186 | #else | ||
| 187 | #define zd_dump_rx_status(status) | ||
| 188 | #endif /* DEBUG */ | ||
| 189 | |||
| 190 | #endif /* _ZD_MAC_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c new file mode 100644 index 000000000000..9df232c2c863 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_netdev.c | |||
| @@ -0,0 +1,267 @@ | |||
| 1 | /* zd_netdev.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/etherdevice.h> | ||
| 20 | #include <linux/skbuff.h> | ||
| 21 | #include <net/ieee80211.h> | ||
| 22 | #include <net/ieee80211softmac.h> | ||
| 23 | #include <net/ieee80211softmac_wx.h> | ||
| 24 | #include <net/iw_handler.h> | ||
| 25 | |||
| 26 | #include "zd_def.h" | ||
| 27 | #include "zd_netdev.h" | ||
| 28 | #include "zd_mac.h" | ||
| 29 | #include "zd_ieee80211.h" | ||
| 30 | |||
| 31 | /* Region 0 means reset regdomain to default. */ | ||
| 32 | static int zd_set_regdomain(struct net_device *netdev, | ||
| 33 | struct iw_request_info *info, | ||
| 34 | union iwreq_data *req, char *extra) | ||
| 35 | { | ||
| 36 | const u8 *regdomain = (u8 *)req; | ||
| 37 | return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain); | ||
| 38 | } | ||
| 39 | |||
| 40 | static int zd_get_regdomain(struct net_device *netdev, | ||
| 41 | struct iw_request_info *info, | ||
| 42 | union iwreq_data *req, char *extra) | ||
| 43 | { | ||
| 44 | u8 *regdomain = (u8 *)req; | ||
| 45 | if (!regdomain) | ||
| 46 | return -EINVAL; | ||
| 47 | *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev)); | ||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | |||
| 51 | static const struct iw_priv_args zd_priv_args[] = { | ||
| 52 | { | ||
| 53 | .cmd = ZD_PRIV_SET_REGDOMAIN, | ||
| 54 | .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, | ||
| 55 | .name = "set_regdomain", | ||
| 56 | }, | ||
| 57 | { | ||
| 58 | .cmd = ZD_PRIV_GET_REGDOMAIN, | ||
| 59 | .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, | ||
| 60 | .name = "get_regdomain", | ||
| 61 | }, | ||
| 62 | }; | ||
| 63 | |||
| 64 | #define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV] | ||
| 65 | |||
| 66 | static const iw_handler zd_priv_handler[] = { | ||
| 67 | PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain, | ||
| 68 | PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain, | ||
| 69 | }; | ||
| 70 | |||
| 71 | static int iw_get_name(struct net_device *netdev, | ||
| 72 | struct iw_request_info *info, | ||
| 73 | union iwreq_data *req, char *extra) | ||
| 74 | { | ||
| 75 | /* FIXME: check whether 802.11a will also supported, add also | ||
| 76 | * zd1211B, if we support it. | ||
| 77 | */ | ||
| 78 | strlcpy(req->name, "802.11g zd1211", IFNAMSIZ); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int iw_set_freq(struct net_device *netdev, | ||
| 83 | struct iw_request_info *info, | ||
| 84 | union iwreq_data *req, char *extra) | ||
| 85 | { | ||
| 86 | int r; | ||
| 87 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 88 | struct iw_freq *freq = &req->freq; | ||
| 89 | u8 channel; | ||
| 90 | |||
| 91 | r = zd_find_channel(&channel, freq); | ||
| 92 | if (r < 0) | ||
| 93 | return r; | ||
| 94 | r = zd_mac_request_channel(mac, channel); | ||
| 95 | return r; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int iw_get_freq(struct net_device *netdev, | ||
| 99 | struct iw_request_info *info, | ||
| 100 | union iwreq_data *req, char *extra) | ||
| 101 | { | ||
| 102 | int r; | ||
| 103 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 104 | struct iw_freq *freq = &req->freq; | ||
| 105 | u8 channel; | ||
| 106 | u8 flags; | ||
| 107 | |||
| 108 | r = zd_mac_get_channel(mac, &channel, &flags); | ||
| 109 | if (r) | ||
| 110 | return r; | ||
| 111 | |||
| 112 | freq->flags = (flags & MAC_FIXED_CHANNEL) ? | ||
| 113 | IW_FREQ_FIXED : IW_FREQ_AUTO; | ||
| 114 | dev_dbg_f(zd_mac_dev(mac), "channel %s\n", | ||
| 115 | (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto"); | ||
| 116 | return zd_channel_to_freq(freq, channel); | ||
| 117 | } | ||
| 118 | |||
| 119 | static int iw_set_mode(struct net_device *netdev, | ||
| 120 | struct iw_request_info *info, | ||
| 121 | union iwreq_data *req, char *extra) | ||
| 122 | { | ||
| 123 | return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode); | ||
| 124 | } | ||
| 125 | |||
| 126 | static int iw_get_mode(struct net_device *netdev, | ||
| 127 | struct iw_request_info *info, | ||
| 128 | union iwreq_data *req, char *extra) | ||
| 129 | { | ||
| 130 | return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode); | ||
| 131 | } | ||
| 132 | |||
| 133 | static int iw_get_range(struct net_device *netdev, | ||
| 134 | struct iw_request_info *info, | ||
| 135 | union iwreq_data *req, char *extra) | ||
| 136 | { | ||
| 137 | struct iw_range *range = (struct iw_range *)extra; | ||
| 138 | |||
| 139 | dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n"); | ||
| 140 | req->data.length = sizeof(*range); | ||
| 141 | return zd_mac_get_range(zd_netdev_mac(netdev), range); | ||
| 142 | } | ||
| 143 | |||
| 144 | static int iw_set_encode(struct net_device *netdev, | ||
| 145 | struct iw_request_info *info, | ||
| 146 | union iwreq_data *data, | ||
| 147 | char *extra) | ||
| 148 | { | ||
| 149 | return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info, | ||
| 150 | data, extra); | ||
| 151 | } | ||
| 152 | |||
| 153 | static int iw_get_encode(struct net_device *netdev, | ||
| 154 | struct iw_request_info *info, | ||
| 155 | union iwreq_data *data, | ||
| 156 | char *extra) | ||
| 157 | { | ||
| 158 | return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info, | ||
| 159 | data, extra); | ||
| 160 | } | ||
| 161 | |||
| 162 | static int iw_set_encodeext(struct net_device *netdev, | ||
| 163 | struct iw_request_info *info, | ||
| 164 | union iwreq_data *data, | ||
| 165 | char *extra) | ||
| 166 | { | ||
| 167 | return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info, | ||
| 168 | data, extra); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int iw_get_encodeext(struct net_device *netdev, | ||
| 172 | struct iw_request_info *info, | ||
| 173 | union iwreq_data *data, | ||
| 174 | char *extra) | ||
| 175 | { | ||
| 176 | return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info, | ||
| 177 | data, extra); | ||
| 178 | } | ||
| 179 | |||
| 180 | #define WX(x) [(x)-SIOCIWFIRST] | ||
| 181 | |||
| 182 | static const iw_handler zd_standard_iw_handlers[] = { | ||
| 183 | WX(SIOCGIWNAME) = iw_get_name, | ||
| 184 | WX(SIOCSIWFREQ) = iw_set_freq, | ||
| 185 | WX(SIOCGIWFREQ) = iw_get_freq, | ||
| 186 | WX(SIOCSIWMODE) = iw_set_mode, | ||
| 187 | WX(SIOCGIWMODE) = iw_get_mode, | ||
| 188 | WX(SIOCGIWRANGE) = iw_get_range, | ||
| 189 | WX(SIOCSIWENCODE) = iw_set_encode, | ||
| 190 | WX(SIOCGIWENCODE) = iw_get_encode, | ||
| 191 | WX(SIOCSIWENCODEEXT) = iw_set_encodeext, | ||
| 192 | WX(SIOCGIWENCODEEXT) = iw_get_encodeext, | ||
| 193 | WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, | ||
| 194 | WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, | ||
| 195 | WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, | ||
| 196 | WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, | ||
| 197 | WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, | ||
| 198 | WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, | ||
| 199 | WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, | ||
| 200 | WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, | ||
| 201 | WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, | ||
| 202 | WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, | ||
| 203 | WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, | ||
| 204 | WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, | ||
| 205 | WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme, | ||
| 206 | }; | ||
| 207 | |||
| 208 | static const struct iw_handler_def iw_handler_def = { | ||
| 209 | .standard = zd_standard_iw_handlers, | ||
| 210 | .num_standard = ARRAY_SIZE(zd_standard_iw_handlers), | ||
| 211 | .private = zd_priv_handler, | ||
| 212 | .num_private = ARRAY_SIZE(zd_priv_handler), | ||
| 213 | .private_args = zd_priv_args, | ||
| 214 | .num_private_args = ARRAY_SIZE(zd_priv_args), | ||
| 215 | .get_wireless_stats = zd_mac_get_wireless_stats, | ||
| 216 | }; | ||
| 217 | |||
| 218 | struct net_device *zd_netdev_alloc(struct usb_interface *intf) | ||
| 219 | { | ||
| 220 | int r; | ||
| 221 | struct net_device *netdev; | ||
| 222 | struct zd_mac *mac; | ||
| 223 | |||
| 224 | netdev = alloc_ieee80211softmac(sizeof(struct zd_mac)); | ||
| 225 | if (!netdev) { | ||
| 226 | dev_dbg_f(&intf->dev, "out of memory\n"); | ||
| 227 | return NULL; | ||
| 228 | } | ||
| 229 | |||
| 230 | mac = zd_netdev_mac(netdev); | ||
| 231 | r = zd_mac_init(mac, netdev, intf); | ||
| 232 | if (r) { | ||
| 233 | usb_set_intfdata(intf, NULL); | ||
| 234 | free_ieee80211(netdev); | ||
| 235 | return NULL; | ||
| 236 | } | ||
| 237 | |||
| 238 | SET_MODULE_OWNER(netdev); | ||
| 239 | SET_NETDEV_DEV(netdev, &intf->dev); | ||
| 240 | |||
| 241 | dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags); | ||
| 242 | dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features); | ||
| 243 | |||
| 244 | netdev->open = zd_mac_open; | ||
| 245 | netdev->stop = zd_mac_stop; | ||
| 246 | /* netdev->get_stats = */ | ||
| 247 | /* netdev->set_multicast_list = */ | ||
| 248 | netdev->set_mac_address = zd_mac_set_mac_address; | ||
| 249 | netdev->wireless_handlers = &iw_handler_def; | ||
| 250 | /* netdev->ethtool_ops = */ | ||
| 251 | |||
| 252 | return netdev; | ||
| 253 | } | ||
| 254 | |||
| 255 | void zd_netdev_free(struct net_device *netdev) | ||
| 256 | { | ||
| 257 | if (!netdev) | ||
| 258 | return; | ||
| 259 | |||
| 260 | zd_mac_clear(zd_netdev_mac(netdev)); | ||
| 261 | free_ieee80211(netdev); | ||
| 262 | } | ||
| 263 | |||
| 264 | void zd_netdev_disconnect(struct net_device *netdev) | ||
| 265 | { | ||
| 266 | unregister_netdev(netdev); | ||
| 267 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.h b/drivers/net/wireless/zd1211rw/zd_netdev.h new file mode 100644 index 000000000000..374a957073c1 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_netdev.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* zd_netdev.h: Header for net device related functions. | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_NETDEV_H | ||
| 19 | #define _ZD_NETDEV_H | ||
| 20 | |||
| 21 | #include <linux/usb.h> | ||
| 22 | #include <linux/netdevice.h> | ||
| 23 | #include <net/ieee80211.h> | ||
| 24 | |||
| 25 | #define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV) | ||
| 26 | #define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1) | ||
| 27 | |||
| 28 | static inline struct ieee80211_device *zd_netdev_ieee80211( | ||
| 29 | struct net_device *ndev) | ||
| 30 | { | ||
| 31 | return netdev_priv(ndev); | ||
| 32 | } | ||
| 33 | |||
| 34 | static inline struct net_device *zd_ieee80211_to_netdev( | ||
| 35 | struct ieee80211_device *ieee) | ||
| 36 | { | ||
| 37 | return ieee->dev; | ||
| 38 | } | ||
| 39 | |||
| 40 | struct net_device *zd_netdev_alloc(struct usb_interface *intf); | ||
| 41 | void zd_netdev_free(struct net_device *netdev); | ||
| 42 | |||
| 43 | void zd_netdev_disconnect(struct net_device *netdev); | ||
| 44 | |||
| 45 | #endif /* _ZD_NETDEV_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c new file mode 100644 index 000000000000..d3770d2c61bc --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf.c | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | /* zd_rf.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/errno.h> | ||
| 19 | #include <linux/string.h> | ||
| 20 | |||
| 21 | #include "zd_def.h" | ||
| 22 | #include "zd_rf.h" | ||
| 23 | #include "zd_ieee80211.h" | ||
| 24 | #include "zd_chip.h" | ||
| 25 | |||
| 26 | static const char *rfs[] = { | ||
| 27 | [0] = "unknown RF0", | ||
| 28 | [1] = "unknown RF1", | ||
| 29 | [UW2451_RF] = "UW2451_RF", | ||
| 30 | [UCHIP_RF] = "UCHIP_RF", | ||
| 31 | [AL2230_RF] = "AL2230_RF", | ||
| 32 | [AL7230B_RF] = "AL7230B_RF", | ||
| 33 | [THETA_RF] = "THETA_RF", | ||
| 34 | [AL2210_RF] = "AL2210_RF", | ||
| 35 | [MAXIM_NEW_RF] = "MAXIM_NEW_RF", | ||
| 36 | [UW2453_RF] = "UW2453_RF", | ||
| 37 | [AL2230S_RF] = "AL2230S_RF", | ||
| 38 | [RALINK_RF] = "RALINK_RF", | ||
| 39 | [INTERSIL_RF] = "INTERSIL_RF", | ||
| 40 | [RF2959_RF] = "RF2959_RF", | ||
| 41 | [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF", | ||
| 42 | [PHILIPS_RF] = "PHILIPS_RF", | ||
| 43 | }; | ||
| 44 | |||
| 45 | const char *zd_rf_name(u8 type) | ||
| 46 | { | ||
| 47 | if (type & 0xf0) | ||
| 48 | type = 0; | ||
| 49 | return rfs[type]; | ||
| 50 | } | ||
| 51 | |||
| 52 | void zd_rf_init(struct zd_rf *rf) | ||
| 53 | { | ||
| 54 | memset(rf, 0, sizeof(*rf)); | ||
| 55 | } | ||
| 56 | |||
| 57 | void zd_rf_clear(struct zd_rf *rf) | ||
| 58 | { | ||
| 59 | memset(rf, 0, sizeof(*rf)); | ||
| 60 | } | ||
| 61 | |||
| 62 | int zd_rf_init_hw(struct zd_rf *rf, u8 type) | ||
| 63 | { | ||
| 64 | int r, t; | ||
| 65 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 66 | |||
| 67 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 68 | switch (type) { | ||
| 69 | case RF2959_RF: | ||
| 70 | r = zd_rf_init_rf2959(rf); | ||
| 71 | if (r) | ||
| 72 | return r; | ||
| 73 | break; | ||
| 74 | case AL2230_RF: | ||
| 75 | r = zd_rf_init_al2230(rf); | ||
| 76 | if (r) | ||
| 77 | return r; | ||
| 78 | break; | ||
| 79 | default: | ||
| 80 | dev_err(zd_chip_dev(chip), | ||
| 81 | "RF %s %#x is not supported\n", zd_rf_name(type), type); | ||
| 82 | rf->type = 0; | ||
| 83 | return -ENODEV; | ||
| 84 | } | ||
| 85 | |||
| 86 | rf->type = type; | ||
| 87 | |||
| 88 | r = zd_chip_lock_phy_regs(chip); | ||
| 89 | if (r) | ||
| 90 | return r; | ||
| 91 | t = rf->init_hw(rf); | ||
| 92 | r = zd_chip_unlock_phy_regs(chip); | ||
| 93 | if (t) | ||
| 94 | r = t; | ||
| 95 | return r; | ||
| 96 | } | ||
| 97 | |||
| 98 | int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size) | ||
| 99 | { | ||
| 100 | return scnprintf(buffer, size, "%s", zd_rf_name(rf->type)); | ||
| 101 | } | ||
| 102 | |||
| 103 | int zd_rf_set_channel(struct zd_rf *rf, u8 channel) | ||
| 104 | { | ||
| 105 | int r; | ||
| 106 | |||
| 107 | ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); | ||
| 108 | if (channel < MIN_CHANNEL24) | ||
| 109 | return -EINVAL; | ||
| 110 | if (channel > MAX_CHANNEL24) | ||
| 111 | return -EINVAL; | ||
| 112 | dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); | ||
| 113 | |||
| 114 | r = rf->set_channel(rf, channel); | ||
| 115 | if (r >= 0) | ||
| 116 | rf->channel = channel; | ||
| 117 | return r; | ||
| 118 | } | ||
| 119 | |||
| 120 | int zd_switch_radio_on(struct zd_rf *rf) | ||
| 121 | { | ||
| 122 | int r, t; | ||
| 123 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 124 | |||
| 125 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 126 | r = zd_chip_lock_phy_regs(chip); | ||
| 127 | if (r) | ||
| 128 | return r; | ||
| 129 | t = rf->switch_radio_on(rf); | ||
| 130 | r = zd_chip_unlock_phy_regs(chip); | ||
| 131 | if (t) | ||
| 132 | r = t; | ||
| 133 | return r; | ||
| 134 | } | ||
| 135 | |||
| 136 | int zd_switch_radio_off(struct zd_rf *rf) | ||
| 137 | { | ||
| 138 | int r, t; | ||
| 139 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 140 | |||
| 141 | /* TODO: move phy regs handling to zd_chip */ | ||
| 142 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 143 | r = zd_chip_lock_phy_regs(chip); | ||
| 144 | if (r) | ||
| 145 | return r; | ||
| 146 | t = rf->switch_radio_off(rf); | ||
| 147 | r = zd_chip_unlock_phy_regs(chip); | ||
| 148 | if (t) | ||
| 149 | r = t; | ||
| 150 | return r; | ||
| 151 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h new file mode 100644 index 000000000000..ea30f693fcc8 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf.h | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | /* zd_rf.h | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_RF_H | ||
| 19 | #define _ZD_RF_H | ||
| 20 | |||
| 21 | #include "zd_types.h" | ||
| 22 | |||
| 23 | #define UW2451_RF 0x2 | ||
| 24 | #define UCHIP_RF 0x3 | ||
| 25 | #define AL2230_RF 0x4 | ||
| 26 | #define AL7230B_RF 0x5 /* a,b,g */ | ||
| 27 | #define THETA_RF 0x6 | ||
| 28 | #define AL2210_RF 0x7 | ||
| 29 | #define MAXIM_NEW_RF 0x8 | ||
| 30 | #define UW2453_RF 0x9 | ||
| 31 | #define AL2230S_RF 0xa | ||
| 32 | #define RALINK_RF 0xb | ||
| 33 | #define INTERSIL_RF 0xc | ||
| 34 | #define RF2959_RF 0xd | ||
| 35 | #define MAXIM_NEW2_RF 0xe | ||
| 36 | #define PHILIPS_RF 0xf | ||
| 37 | |||
| 38 | #define RF_CHANNEL(ch) [(ch)-1] | ||
| 39 | |||
| 40 | /* Provides functions of the RF transceiver. */ | ||
| 41 | |||
| 42 | enum { | ||
| 43 | RF_REG_BITS = 6, | ||
| 44 | RF_VALUE_BITS = 18, | ||
| 45 | RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS, | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct zd_rf { | ||
| 49 | u8 type; | ||
| 50 | |||
| 51 | u8 channel; | ||
| 52 | /* | ||
| 53 | * Whether this RF should patch the 6M band edge | ||
| 54 | * (assuming E2P_POD agrees) | ||
| 55 | */ | ||
| 56 | u8 patch_6m_band_edge:1; | ||
| 57 | |||
| 58 | /* RF-specific functions */ | ||
| 59 | int (*init_hw)(struct zd_rf *rf); | ||
| 60 | int (*set_channel)(struct zd_rf *rf, u8 channel); | ||
| 61 | int (*switch_radio_on)(struct zd_rf *rf); | ||
| 62 | int (*switch_radio_off)(struct zd_rf *rf); | ||
| 63 | }; | ||
| 64 | |||
| 65 | const char *zd_rf_name(u8 type); | ||
| 66 | void zd_rf_init(struct zd_rf *rf); | ||
| 67 | void zd_rf_clear(struct zd_rf *rf); | ||
| 68 | int zd_rf_init_hw(struct zd_rf *rf, u8 type); | ||
| 69 | |||
| 70 | int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size); | ||
| 71 | |||
| 72 | int zd_rf_set_channel(struct zd_rf *rf, u8 channel); | ||
| 73 | |||
| 74 | int zd_switch_radio_on(struct zd_rf *rf); | ||
| 75 | int zd_switch_radio_off(struct zd_rf *rf); | ||
| 76 | |||
| 77 | /* Functions for individual RF chips */ | ||
| 78 | |||
| 79 | int zd_rf_init_rf2959(struct zd_rf *rf); | ||
| 80 | int zd_rf_init_al2230(struct zd_rf *rf); | ||
| 81 | |||
| 82 | #endif /* _ZD_RF_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c new file mode 100644 index 000000000000..0948b25f660d --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c | |||
| @@ -0,0 +1,308 @@ | |||
| 1 | /* zd_rf_al2230.c: Functions for the AL2230 RF controller | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | |||
| 20 | #include "zd_rf.h" | ||
| 21 | #include "zd_usb.h" | ||
| 22 | #include "zd_chip.h" | ||
| 23 | |||
| 24 | static const u32 al2230_table[][3] = { | ||
| 25 | RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, | ||
| 26 | RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, | ||
| 27 | RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, | ||
| 28 | RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, }, | ||
| 29 | RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, }, | ||
| 30 | RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, }, | ||
| 31 | RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, }, | ||
| 32 | RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, }, | ||
| 33 | RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, }, | ||
| 34 | RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, }, | ||
| 35 | RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, }, | ||
| 36 | RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, }, | ||
| 37 | RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, }, | ||
| 38 | RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, | ||
| 39 | }; | ||
| 40 | |||
| 41 | static int zd1211_al2230_init_hw(struct zd_rf *rf) | ||
| 42 | { | ||
| 43 | int r; | ||
| 44 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 45 | |||
| 46 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 47 | { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, | ||
| 48 | { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, | ||
| 49 | { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, | ||
| 50 | { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, | ||
| 51 | { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, | ||
| 52 | /* for newest (3rd cut) AL2300 */ | ||
| 53 | { CR17, 0x28 }, | ||
| 54 | { CR26, 0x93 }, { CR34, 0x30 }, | ||
| 55 | /* for newest (3rd cut) AL2300 */ | ||
| 56 | { CR35, 0x3e }, | ||
| 57 | { CR41, 0x24 }, { CR44, 0x32 }, | ||
| 58 | /* for newest (3rd cut) AL2300 */ | ||
| 59 | { CR46, 0x96 }, | ||
| 60 | { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, | ||
| 61 | { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, | ||
| 62 | { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, | ||
| 63 | { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, | ||
| 64 | { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, | ||
| 65 | { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, | ||
| 66 | { CR114, 0x27 }, | ||
| 67 | /* for newest (3rd cut) AL2300 */ | ||
| 68 | { CR115, 0x24 }, | ||
| 69 | { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, | ||
| 70 | { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, | ||
| 71 | { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, | ||
| 72 | { CR253, 0xff }, | ||
| 73 | |||
| 74 | /* These following happen separately in the vendor driver */ | ||
| 75 | { }, | ||
| 76 | |||
| 77 | /* shdnb(PLL_ON)=0 */ | ||
| 78 | { CR251, 0x2f }, | ||
| 79 | /* shdnb(PLL_ON)=1 */ | ||
| 80 | { CR251, 0x3f }, | ||
| 81 | { CR138, 0x28 }, { CR203, 0x06 }, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static const u32 rv[] = { | ||
| 85 | /* Channel 1 */ | ||
| 86 | 0x03f790, | ||
| 87 | 0x033331, | ||
| 88 | 0x00000d, | ||
| 89 | |||
| 90 | 0x0b3331, | ||
| 91 | 0x03b812, | ||
| 92 | 0x00fff3, | ||
| 93 | 0x000da4, | ||
| 94 | 0x0f4dc5, /* fix freq shift, 0x04edc5 */ | ||
| 95 | 0x0805b6, | ||
| 96 | 0x011687, | ||
| 97 | 0x000688, | ||
| 98 | 0x0403b9, /* external control TX power (CR31) */ | ||
| 99 | 0x00dbba, | ||
| 100 | 0x00099b, | ||
| 101 | 0x0bdffc, | ||
| 102 | 0x00000d, | ||
| 103 | 0x00500f, | ||
| 104 | |||
| 105 | /* These writes happen separately in the vendor driver */ | ||
| 106 | 0x00d00f, | ||
| 107 | 0x004c0f, | ||
| 108 | 0x00540f, | ||
| 109 | 0x00700f, | ||
| 110 | 0x00500f, | ||
| 111 | }; | ||
| 112 | |||
| 113 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 114 | if (r) | ||
| 115 | return r; | ||
| 116 | |||
| 117 | r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); | ||
| 118 | if (r) | ||
| 119 | return r; | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static int zd1211b_al2230_init_hw(struct zd_rf *rf) | ||
| 125 | { | ||
| 126 | int r; | ||
| 127 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 128 | |||
| 129 | static const struct zd_ioreq16 ioreqs1[] = { | ||
| 130 | { CR10, 0x89 }, { CR15, 0x20 }, | ||
| 131 | { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ | ||
| 132 | { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, | ||
| 133 | { CR28, 0x3e }, { CR29, 0x00 }, | ||
| 134 | { CR33, 0x28 }, /* 5621 */ | ||
| 135 | { CR34, 0x30 }, | ||
| 136 | { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ | ||
| 137 | { CR41, 0x24 }, { CR44, 0x32 }, | ||
| 138 | { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ | ||
| 139 | { CR47, 0x1e }, | ||
| 140 | |||
| 141 | /* ZD1211B 05.06.10 */ | ||
| 142 | { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, | ||
| 143 | { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, | ||
| 144 | { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, | ||
| 145 | { CR69, 0x28 }, | ||
| 146 | |||
| 147 | { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, | ||
| 148 | { CR87, 0x0a }, { CR89, 0x04 }, | ||
| 149 | { CR91, 0x00 }, /* 5621 */ | ||
| 150 | { CR92, 0x0a }, | ||
| 151 | { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ | ||
| 152 | { CR99, 0x00 }, /* 5621 */ | ||
| 153 | { CR101, 0x13 }, { CR102, 0x27 }, | ||
| 154 | { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ | ||
| 155 | { CR107, 0x2a }, | ||
| 156 | { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ | ||
| 157 | { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ | ||
| 158 | { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, | ||
| 159 | { CR114, 0x27 }, | ||
| 160 | { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ | ||
| 161 | { CR116, 0x24 }, | ||
| 162 | { CR117, 0xfa }, /* for 1211b */ | ||
| 163 | { CR118, 0xfa }, /* for 1211b */ | ||
| 164 | { CR119, 0x10 }, | ||
| 165 | { CR120, 0x4f }, | ||
| 166 | { CR121, 0x6c }, /* for 1211b */ | ||
| 167 | { CR122, 0xfc }, /* E0->FC at 4902 */ | ||
| 168 | { CR123, 0x57 }, /* 5623 */ | ||
| 169 | { CR125, 0xad }, /* 4804, for 1212 new algorithm */ | ||
| 170 | { CR126, 0x6c }, /* 5614 */ | ||
| 171 | { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ | ||
| 172 | { CR137, 0x50 }, /* 5614 */ | ||
| 173 | { CR138, 0xa8 }, | ||
| 174 | { CR144, 0xac }, /* 5621 */ | ||
| 175 | { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 }, | ||
| 176 | }; | ||
| 177 | |||
| 178 | static const u32 rv1[] = { | ||
| 179 | /* channel 1 */ | ||
| 180 | 0x03f790, | ||
| 181 | 0x033331, | ||
| 182 | 0x00000d, | ||
| 183 | |||
| 184 | 0x0b3331, | ||
| 185 | 0x03b812, | ||
| 186 | 0x00fff3, | ||
| 187 | 0x0005a4, | ||
| 188 | 0x0f4dc5, /* fix freq shift 0x044dc5 */ | ||
| 189 | 0x0805b6, | ||
| 190 | 0x0146c7, | ||
| 191 | 0x000688, | ||
| 192 | 0x0403b9, /* External control TX power (CR31) */ | ||
| 193 | 0x00dbba, | ||
| 194 | 0x00099b, | ||
| 195 | 0x0bdffc, | ||
| 196 | 0x00000d, | ||
| 197 | 0x00580f, | ||
| 198 | }; | ||
| 199 | |||
| 200 | static const struct zd_ioreq16 ioreqs2[] = { | ||
| 201 | { CR47, 0x1e }, { CR_RFCFG, 0x03 }, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static const u32 rv2[] = { | ||
| 205 | 0x00880f, | ||
| 206 | 0x00080f, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static const struct zd_ioreq16 ioreqs3[] = { | ||
| 210 | { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f }, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const u32 rv3[] = { | ||
| 214 | 0x00d80f, | ||
| 215 | 0x00780f, | ||
| 216 | 0x00580f, | ||
| 217 | }; | ||
| 218 | |||
| 219 | static const struct zd_ioreq16 ioreqs4[] = { | ||
| 220 | { CR138, 0x28 }, { CR203, 0x06 }, | ||
| 221 | }; | ||
| 222 | |||
| 223 | r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); | ||
| 224 | if (r) | ||
| 225 | return r; | ||
| 226 | r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS); | ||
| 227 | if (r) | ||
| 228 | return r; | ||
| 229 | r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); | ||
| 230 | if (r) | ||
| 231 | return r; | ||
| 232 | r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS); | ||
| 233 | if (r) | ||
| 234 | return r; | ||
| 235 | r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); | ||
| 236 | if (r) | ||
| 237 | return r; | ||
| 238 | r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS); | ||
| 239 | if (r) | ||
| 240 | return r; | ||
| 241 | return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4)); | ||
| 242 | } | ||
| 243 | |||
| 244 | static int al2230_set_channel(struct zd_rf *rf, u8 channel) | ||
| 245 | { | ||
| 246 | int r; | ||
| 247 | const u32 *rv = al2230_table[channel-1]; | ||
| 248 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 249 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 250 | { CR138, 0x28 }, | ||
| 251 | { CR203, 0x06 }, | ||
| 252 | }; | ||
| 253 | |||
| 254 | r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); | ||
| 255 | if (r) | ||
| 256 | return r; | ||
| 257 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 258 | } | ||
| 259 | |||
| 260 | static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) | ||
| 261 | { | ||
| 262 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 263 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 264 | { CR11, 0x00 }, | ||
| 265 | { CR251, 0x3f }, | ||
| 266 | }; | ||
| 267 | |||
| 268 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 269 | } | ||
| 270 | |||
| 271 | static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf) | ||
| 272 | { | ||
| 273 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 274 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 275 | { CR11, 0x00 }, | ||
| 276 | { CR251, 0x7f }, | ||
| 277 | }; | ||
| 278 | |||
| 279 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 280 | } | ||
| 281 | |||
| 282 | static int al2230_switch_radio_off(struct zd_rf *rf) | ||
| 283 | { | ||
| 284 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 285 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 286 | { CR11, 0x04 }, | ||
| 287 | { CR251, 0x2f }, | ||
| 288 | }; | ||
| 289 | |||
| 290 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 291 | } | ||
| 292 | |||
| 293 | int zd_rf_init_al2230(struct zd_rf *rf) | ||
| 294 | { | ||
| 295 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 296 | |||
| 297 | rf->set_channel = al2230_set_channel; | ||
| 298 | rf->switch_radio_off = al2230_switch_radio_off; | ||
| 299 | if (chip->is_zd1211b) { | ||
| 300 | rf->init_hw = zd1211b_al2230_init_hw; | ||
| 301 | rf->switch_radio_on = zd1211b_al2230_switch_radio_on; | ||
| 302 | } else { | ||
| 303 | rf->init_hw = zd1211_al2230_init_hw; | ||
| 304 | rf->switch_radio_on = zd1211_al2230_switch_radio_on; | ||
| 305 | } | ||
| 306 | rf->patch_6m_band_edge = 1; | ||
| 307 | return 0; | ||
| 308 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c new file mode 100644 index 000000000000..58247271cc24 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c | |||
| @@ -0,0 +1,279 @@ | |||
| 1 | /* zd_rf_rfmd.c: Functions for the RFMD RF controller | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | |||
| 20 | #include "zd_rf.h" | ||
| 21 | #include "zd_usb.h" | ||
| 22 | #include "zd_chip.h" | ||
| 23 | |||
| 24 | static u32 rf2959_table[][2] = { | ||
| 25 | RF_CHANNEL( 1) = { 0x181979, 0x1e6666 }, | ||
| 26 | RF_CHANNEL( 2) = { 0x181989, 0x1e6666 }, | ||
| 27 | RF_CHANNEL( 3) = { 0x181999, 0x1e6666 }, | ||
| 28 | RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 }, | ||
| 29 | RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 }, | ||
| 30 | RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 }, | ||
| 31 | RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 }, | ||
| 32 | RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 }, | ||
| 33 | RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 }, | ||
| 34 | RF_CHANNEL(10) = { 0x181a09, 0x1e6666 }, | ||
| 35 | RF_CHANNEL(11) = { 0x181a19, 0x1e6666 }, | ||
| 36 | RF_CHANNEL(12) = { 0x181a29, 0x1e6666 }, | ||
| 37 | RF_CHANNEL(13) = { 0x181a39, 0x1e6666 }, | ||
| 38 | RF_CHANNEL(14) = { 0x181a60, 0x1c0000 }, | ||
| 39 | }; | ||
| 40 | |||
| 41 | #if 0 | ||
| 42 | static int bits(u32 rw, int from, int to) | ||
| 43 | { | ||
| 44 | rw &= ~(0xffffffffU << (to+1)); | ||
| 45 | rw >>= from; | ||
| 46 | return rw; | ||
| 47 | } | ||
| 48 | |||
| 49 | static int bit(u32 rw, int bit) | ||
| 50 | { | ||
| 51 | return bits(rw, bit, bit); | ||
| 52 | } | ||
| 53 | |||
| 54 | static void dump_regwrite(u32 rw) | ||
| 55 | { | ||
| 56 | int reg = bits(rw, 18, 22); | ||
| 57 | int rw_flag = bits(rw, 23, 23); | ||
| 58 | PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag); | ||
| 59 | |||
| 60 | switch (reg) { | ||
| 61 | case 0: | ||
| 62 | PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d" | ||
| 63 | " if_vco_reg_en %d if_vga_en %d", | ||
| 64 | bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1), | ||
| 65 | bit(rw, 0)); | ||
| 66 | break; | ||
| 67 | case 1: | ||
| 68 | PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d" | ||
| 69 | " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d" | ||
| 70 | " ifloopc %d dac1 %d", | ||
| 71 | bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), | ||
| 72 | bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), | ||
| 73 | bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3)); | ||
| 74 | break; | ||
| 75 | case 2: | ||
| 76 | PDEBUG("reg2 IFPLL2 n1 %d num1 %d", | ||
| 77 | bits(rw, 6, 17), bits(rw, 0, 5)); | ||
| 78 | break; | ||
| 79 | case 3: | ||
| 80 | PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17)); | ||
| 81 | break; | ||
| 82 | case 4: | ||
| 83 | PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d", | ||
| 84 | bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); | ||
| 85 | break; | ||
| 86 | case 5: | ||
| 87 | PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d" | ||
| 88 | " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d" | ||
| 89 | " dac %d", | ||
| 90 | bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), | ||
| 91 | bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), | ||
| 92 | bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3)); | ||
| 93 | break; | ||
| 94 | case 6: | ||
| 95 | PDEBUG("reg6 RFPLL2 n %d num %d", | ||
| 96 | bits(rw, 6, 17), bits(rw, 0, 5)); | ||
| 97 | break; | ||
| 98 | case 7: | ||
| 99 | PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17)); | ||
| 100 | break; | ||
| 101 | case 8: | ||
| 102 | PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d", | ||
| 103 | bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); | ||
| 104 | break; | ||
| 105 | case 9: | ||
| 106 | PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d", | ||
| 107 | bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7), | ||
| 108 | bits(rw, 0, 2)); | ||
| 109 | break; | ||
| 110 | case 10: | ||
| 111 | PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d" | ||
| 112 | " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d" | ||
| 113 | " intbiasen %d tybypass %d", | ||
| 114 | bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14), | ||
| 115 | bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2), | ||
| 116 | bit(rw, 1), bit(rw, 0)); | ||
| 117 | break; | ||
| 118 | case 11: | ||
| 119 | PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d" | ||
| 120 | " tx_delay %d", | ||
| 121 | bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8), | ||
| 122 | bits(rw, 0, 2)); | ||
| 123 | break; | ||
| 124 | case 12: | ||
| 125 | PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d", | ||
| 126 | bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5)); | ||
| 127 | break; | ||
| 128 | case 13: | ||
| 129 | PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d" | ||
| 130 | " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d" | ||
| 131 | " rf_biasvco %d", | ||
| 132 | bit(rw, 17), bit(rw, 16), bit(rw, 15), | ||
| 133 | bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4), | ||
| 134 | bits(rw, 0, 2)); | ||
| 135 | break; | ||
| 136 | case 14: | ||
| 137 | PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d" | ||
| 138 | " tx_acal %d tx_pcal %d", | ||
| 139 | bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8), | ||
| 140 | bits(rw, 0, 3)); | ||
| 141 | break; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | #endif /* 0 */ | ||
| 145 | |||
| 146 | static int rf2959_init_hw(struct zd_rf *rf) | ||
| 147 | { | ||
| 148 | int r; | ||
| 149 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 150 | |||
| 151 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 152 | { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, | ||
| 153 | { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, | ||
| 154 | { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, | ||
| 155 | { CR23, 0x48 }, | ||
| 156 | /* normal size for cca threshold */ | ||
| 157 | { CR24, 0x14 }, | ||
| 158 | /* { CR24, 0x20 }, */ | ||
| 159 | { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, | ||
| 160 | { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, | ||
| 161 | { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, | ||
| 162 | { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, | ||
| 163 | { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, | ||
| 164 | { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, | ||
| 165 | { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, | ||
| 166 | { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, | ||
| 167 | { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, | ||
| 168 | /* { CR91, 0x18 }, */ | ||
| 169 | /* should solve continous CTS frame problems */ | ||
| 170 | { CR91, 0x00 }, | ||
| 171 | { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, | ||
| 172 | { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, | ||
| 173 | { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, | ||
| 174 | { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, | ||
| 175 | { CR104, 0x18 }, { CR105, 0x12 }, | ||
| 176 | /* normal size */ | ||
| 177 | { CR106, 0x1a }, | ||
| 178 | /* { CR106, 0x22 }, */ | ||
| 179 | { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, | ||
| 180 | { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, | ||
| 181 | { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, | ||
| 182 | { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, | ||
| 183 | { CR119, 0x16 }, | ||
| 184 | /* no TX continuation */ | ||
| 185 | { CR122, 0x00 }, | ||
| 186 | /* { CR122, 0xff }, */ | ||
| 187 | { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, | ||
| 188 | { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, | ||
| 189 | { CR170, 0xBB }, | ||
| 190 | }; | ||
| 191 | |||
| 192 | static const u32 rv[] = { | ||
| 193 | 0x000007, /* REG0(CFG1) */ | ||
| 194 | 0x07dd43, /* REG1(IFPLL1) */ | ||
| 195 | 0x080959, /* REG2(IFPLL2) */ | ||
| 196 | 0x0e6666, | ||
| 197 | 0x116a57, /* REG4 */ | ||
| 198 | 0x17dd43, /* REG5 */ | ||
| 199 | 0x1819f9, /* REG6 */ | ||
| 200 | 0x1e6666, | ||
| 201 | 0x214554, | ||
| 202 | 0x25e7fa, | ||
| 203 | 0x27fffa, | ||
| 204 | /* The Zydas driver somehow forgets to set this value. It's | ||
| 205 | * only set for Japan. We are using internal power control | ||
| 206 | * for now. | ||
| 207 | */ | ||
| 208 | 0x294128, /* internal power */ | ||
| 209 | /* 0x28252c, */ /* External control TX power */ | ||
| 210 | /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ | ||
| 211 | 0x2c0000, | ||
| 212 | 0x300000, | ||
| 213 | 0x340000, /* REG13(0xD) */ | ||
| 214 | 0x381e0f, /* REG14(0xE) */ | ||
| 215 | /* Bogus, RF2959's data sheet doesn't know register 27, which is | ||
| 216 | * actually referenced here. The commented 0x11 is 17. | ||
| 217 | */ | ||
| 218 | 0x6c180f, /* REG27(0x11) */ | ||
| 219 | }; | ||
| 220 | |||
| 221 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 222 | if (r) | ||
| 223 | return r; | ||
| 224 | |||
| 225 | return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); | ||
| 226 | } | ||
| 227 | |||
| 228 | static int rf2959_set_channel(struct zd_rf *rf, u8 channel) | ||
| 229 | { | ||
| 230 | int i, r; | ||
| 231 | u32 *rv = rf2959_table[channel-1]; | ||
| 232 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 233 | |||
| 234 | for (i = 0; i < 2; i++) { | ||
| 235 | r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS); | ||
| 236 | if (r) | ||
| 237 | return r; | ||
| 238 | } | ||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static int rf2959_switch_radio_on(struct zd_rf *rf) | ||
| 243 | { | ||
| 244 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 245 | { CR10, 0x89 }, | ||
| 246 | { CR11, 0x00 }, | ||
| 247 | }; | ||
| 248 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 249 | |||
| 250 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 251 | } | ||
| 252 | |||
| 253 | static int rf2959_switch_radio_off(struct zd_rf *rf) | ||
| 254 | { | ||
| 255 | static const struct zd_ioreq16 ioreqs[] = { | ||
| 256 | { CR10, 0x15 }, | ||
| 257 | { CR11, 0x81 }, | ||
| 258 | }; | ||
| 259 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 260 | |||
| 261 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
| 262 | } | ||
| 263 | |||
| 264 | int zd_rf_init_rf2959(struct zd_rf *rf) | ||
| 265 | { | ||
| 266 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
| 267 | |||
| 268 | if (chip->is_zd1211b) { | ||
| 269 | dev_err(zd_chip_dev(chip), | ||
| 270 | "RF2959 is currently not supported for ZD1211B" | ||
| 271 | " devices\n"); | ||
| 272 | return -ENODEV; | ||
| 273 | } | ||
| 274 | rf->init_hw = rf2959_init_hw; | ||
| 275 | rf->set_channel = rf2959_set_channel; | ||
| 276 | rf->switch_radio_on = rf2959_switch_radio_on; | ||
| 277 | rf->switch_radio_off = rf2959_switch_radio_off; | ||
| 278 | return 0; | ||
| 279 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_types.h b/drivers/net/wireless/zd1211rw/zd_types.h new file mode 100644 index 000000000000..0155a1584ed3 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_types.h | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | /* zd_types.h | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_TYPES_H | ||
| 19 | #define _ZD_TYPES_H | ||
| 20 | |||
| 21 | #include <linux/types.h> | ||
| 22 | |||
| 23 | /* We have three register spaces mapped into the overall USB address space of | ||
| 24 | * 64K words (16-bit values). There is the control register space of | ||
| 25 | * double-word registers, the eeprom register space and the firmware register | ||
| 26 | * space. The control register space is byte mapped, the others are word | ||
| 27 | * mapped. | ||
| 28 | * | ||
| 29 | * For that reason, we are using byte offsets for control registers and word | ||
| 30 | * offsets for everything else. | ||
| 31 | */ | ||
| 32 | |||
| 33 | typedef u32 __nocast zd_addr_t; | ||
| 34 | |||
| 35 | enum { | ||
| 36 | ADDR_BASE_MASK = 0xff000000, | ||
| 37 | ADDR_OFFSET_MASK = 0x0000ffff, | ||
| 38 | ADDR_ZERO_MASK = 0x00ff0000, | ||
| 39 | NULL_BASE = 0x00000000, | ||
| 40 | USB_BASE = 0x01000000, | ||
| 41 | CR_BASE = 0x02000000, | ||
| 42 | CR_MAX_OFFSET = 0x0b30, | ||
| 43 | E2P_BASE = 0x03000000, | ||
| 44 | E2P_MAX_OFFSET = 0x007e, | ||
| 45 | FW_BASE = 0x04000000, | ||
| 46 | FW_MAX_OFFSET = 0x0005, | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK) | ||
| 50 | #define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK) | ||
| 51 | |||
| 52 | #define ZD_ADDR(base, offset) \ | ||
| 53 | ((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK))) | ||
| 54 | |||
| 55 | #define ZD_NULL_ADDR ((zd_addr_t)0) | ||
| 56 | #define USB_REG(offset) ZD_ADDR(USB_BASE, offset) /* word addressing */ | ||
| 57 | #define CTL_REG(offset) ZD_ADDR(CR_BASE, offset) /* byte addressing */ | ||
| 58 | #define E2P_REG(offset) ZD_ADDR(E2P_BASE, offset) /* word addressing */ | ||
| 59 | #define FW_REG(offset) ZD_ADDR(FW_BASE, offset) /* word addressing */ | ||
| 60 | |||
| 61 | static inline zd_addr_t zd_inc_word(zd_addr_t addr) | ||
| 62 | { | ||
| 63 | u32 base = ZD_ADDR_BASE(addr); | ||
| 64 | u32 offset = ZD_OFFSET(addr); | ||
| 65 | |||
| 66 | offset += base == CR_BASE ? 2 : 1; | ||
| 67 | |||
| 68 | return base | offset; | ||
| 69 | } | ||
| 70 | |||
| 71 | #endif /* _ZD_TYPES_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c new file mode 100644 index 000000000000..ce1cb2c6aa8d --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
| @@ -0,0 +1,1316 @@ | |||
| 1 | /* zd_usb.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <asm/unaligned.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/firmware.h> | ||
| 22 | #include <linux/device.h> | ||
| 23 | #include <linux/errno.h> | ||
| 24 | #include <linux/skbuff.h> | ||
| 25 | #include <linux/usb.h> | ||
| 26 | #include <net/ieee80211.h> | ||
| 27 | |||
| 28 | #include "zd_def.h" | ||
| 29 | #include "zd_netdev.h" | ||
| 30 | #include "zd_mac.h" | ||
| 31 | #include "zd_usb.h" | ||
| 32 | #include "zd_util.h" | ||
| 33 | |||
| 34 | static struct usb_device_id usb_ids[] = { | ||
| 35 | /* ZD1211 */ | ||
| 36 | { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, | ||
| 37 | { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, | ||
| 38 | { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, | ||
| 39 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, | ||
| 40 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, | ||
| 41 | { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, | ||
| 42 | /* ZD1211B */ | ||
| 43 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | ||
| 44 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, | ||
| 45 | {} | ||
| 46 | }; | ||
| 47 | |||
| 48 | MODULE_LICENSE("GPL"); | ||
| 49 | MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip."); | ||
| 50 | MODULE_AUTHOR("Ulrich Kunitz"); | ||
| 51 | MODULE_AUTHOR("Daniel Drake"); | ||
| 52 | MODULE_VERSION("1.0"); | ||
| 53 | MODULE_DEVICE_TABLE(usb, usb_ids); | ||
| 54 | |||
| 55 | #define FW_ZD1211_PREFIX "zd1211/zd1211_" | ||
| 56 | #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" | ||
| 57 | |||
| 58 | /* register address handling */ | ||
| 59 | |||
| 60 | #ifdef DEBUG | ||
| 61 | static int check_addr(struct zd_usb *usb, zd_addr_t addr) | ||
| 62 | { | ||
| 63 | u32 base = ZD_ADDR_BASE(addr); | ||
| 64 | u32 offset = ZD_OFFSET(addr); | ||
| 65 | |||
| 66 | if ((u32)addr & ADDR_ZERO_MASK) | ||
| 67 | goto invalid_address; | ||
| 68 | switch (base) { | ||
| 69 | case USB_BASE: | ||
| 70 | break; | ||
| 71 | case CR_BASE: | ||
| 72 | if (offset > CR_MAX_OFFSET) { | ||
| 73 | dev_dbg(zd_usb_dev(usb), | ||
| 74 | "CR offset %#010x larger than" | ||
| 75 | " CR_MAX_OFFSET %#10x\n", | ||
| 76 | offset, CR_MAX_OFFSET); | ||
| 77 | goto invalid_address; | ||
| 78 | } | ||
| 79 | if (offset & 1) { | ||
| 80 | dev_dbg(zd_usb_dev(usb), | ||
| 81 | "CR offset %#010x is not a multiple of 2\n", | ||
| 82 | offset); | ||
| 83 | goto invalid_address; | ||
| 84 | } | ||
| 85 | break; | ||
| 86 | case E2P_BASE: | ||
| 87 | if (offset > E2P_MAX_OFFSET) { | ||
| 88 | dev_dbg(zd_usb_dev(usb), | ||
| 89 | "E2P offset %#010x larger than" | ||
| 90 | " E2P_MAX_OFFSET %#010x\n", | ||
| 91 | offset, E2P_MAX_OFFSET); | ||
| 92 | goto invalid_address; | ||
| 93 | } | ||
| 94 | break; | ||
| 95 | case FW_BASE: | ||
| 96 | if (!usb->fw_base_offset) { | ||
| 97 | dev_dbg(zd_usb_dev(usb), | ||
| 98 | "ERROR: fw base offset has not been set\n"); | ||
| 99 | return -EAGAIN; | ||
| 100 | } | ||
| 101 | if (offset > FW_MAX_OFFSET) { | ||
| 102 | dev_dbg(zd_usb_dev(usb), | ||
| 103 | "FW offset %#10x is larger than" | ||
| 104 | " FW_MAX_OFFSET %#010x\n", | ||
| 105 | offset, FW_MAX_OFFSET); | ||
| 106 | goto invalid_address; | ||
| 107 | } | ||
| 108 | break; | ||
| 109 | default: | ||
| 110 | dev_dbg(zd_usb_dev(usb), | ||
| 111 | "address has unsupported base %#010x\n", addr); | ||
| 112 | goto invalid_address; | ||
| 113 | } | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | invalid_address: | ||
| 117 | dev_dbg(zd_usb_dev(usb), | ||
| 118 | "ERROR: invalid address: %#010x\n", addr); | ||
| 119 | return -EINVAL; | ||
| 120 | } | ||
| 121 | #endif /* DEBUG */ | ||
| 122 | |||
| 123 | static u16 usb_addr(struct zd_usb *usb, zd_addr_t addr) | ||
| 124 | { | ||
| 125 | u32 base; | ||
| 126 | u16 offset; | ||
| 127 | |||
| 128 | base = ZD_ADDR_BASE(addr); | ||
| 129 | offset = ZD_OFFSET(addr); | ||
| 130 | |||
| 131 | ZD_ASSERT(check_addr(usb, addr) == 0); | ||
| 132 | |||
| 133 | switch (base) { | ||
| 134 | case CR_BASE: | ||
| 135 | offset += CR_BASE_OFFSET; | ||
| 136 | break; | ||
| 137 | case E2P_BASE: | ||
| 138 | offset += E2P_BASE_OFFSET; | ||
| 139 | break; | ||
| 140 | case FW_BASE: | ||
| 141 | offset += usb->fw_base_offset; | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | |||
| 145 | return offset; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* USB device initialization */ | ||
| 149 | |||
| 150 | static int request_fw_file( | ||
| 151 | const struct firmware **fw, const char *name, struct device *device) | ||
| 152 | { | ||
| 153 | int r; | ||
| 154 | |||
| 155 | dev_dbg_f(device, "fw name %s\n", name); | ||
| 156 | |||
| 157 | r = request_firmware(fw, name, device); | ||
| 158 | if (r) | ||
| 159 | dev_err(device, | ||
| 160 | "Could not load firmware file %s. Error number %d\n", | ||
| 161 | name, r); | ||
| 162 | return r; | ||
| 163 | } | ||
| 164 | |||
| 165 | static inline u16 get_bcdDevice(const struct usb_device *udev) | ||
| 166 | { | ||
| 167 | return le16_to_cpu(udev->descriptor.bcdDevice); | ||
| 168 | } | ||
| 169 | |||
| 170 | enum upload_code_flags { | ||
| 171 | REBOOT = 1, | ||
| 172 | }; | ||
| 173 | |||
| 174 | /* Ensures that MAX_TRANSFER_SIZE is even. */ | ||
| 175 | #define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1) | ||
| 176 | |||
| 177 | static int upload_code(struct usb_device *udev, | ||
| 178 | const u8 *data, size_t size, u16 code_offset, int flags) | ||
| 179 | { | ||
| 180 | u8 *p; | ||
| 181 | int r; | ||
| 182 | |||
| 183 | /* USB request blocks need "kmalloced" buffers. | ||
| 184 | */ | ||
| 185 | p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL); | ||
| 186 | if (!p) { | ||
| 187 | dev_err(&udev->dev, "out of memory\n"); | ||
| 188 | r = -ENOMEM; | ||
| 189 | goto error; | ||
| 190 | } | ||
| 191 | |||
| 192 | size &= ~1; | ||
| 193 | while (size > 0) { | ||
| 194 | size_t transfer_size = size <= MAX_TRANSFER_SIZE ? | ||
| 195 | size : MAX_TRANSFER_SIZE; | ||
| 196 | |||
| 197 | dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size); | ||
| 198 | |||
| 199 | memcpy(p, data, transfer_size); | ||
| 200 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 201 | USB_REQ_FIRMWARE_DOWNLOAD, | ||
| 202 | USB_DIR_OUT | USB_TYPE_VENDOR, | ||
| 203 | code_offset, 0, p, transfer_size, 1000 /* ms */); | ||
| 204 | if (r < 0) { | ||
| 205 | dev_err(&udev->dev, | ||
| 206 | "USB control request for firmware upload" | ||
| 207 | " failed. Error number %d\n", r); | ||
| 208 | goto error; | ||
| 209 | } | ||
| 210 | transfer_size = r & ~1; | ||
| 211 | |||
| 212 | size -= transfer_size; | ||
| 213 | data += transfer_size; | ||
| 214 | code_offset += transfer_size/sizeof(u16); | ||
| 215 | } | ||
| 216 | |||
| 217 | if (flags & REBOOT) { | ||
| 218 | u8 ret; | ||
| 219 | |||
| 220 | r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
| 221 | USB_REQ_FIRMWARE_CONFIRM, | ||
| 222 | USB_DIR_IN | USB_TYPE_VENDOR, | ||
| 223 | 0, 0, &ret, sizeof(ret), 5000 /* ms */); | ||
| 224 | if (r != sizeof(ret)) { | ||
| 225 | dev_err(&udev->dev, | ||
| 226 | "control request firmeware confirmation failed." | ||
| 227 | " Return value %d\n", r); | ||
| 228 | if (r >= 0) | ||
| 229 | r = -ENODEV; | ||
| 230 | goto error; | ||
| 231 | } | ||
| 232 | if (ret & 0x80) { | ||
| 233 | dev_err(&udev->dev, | ||
| 234 | "Internal error while downloading." | ||
| 235 | " Firmware confirm return value %#04x\n", | ||
| 236 | (unsigned int)ret); | ||
| 237 | r = -ENODEV; | ||
| 238 | goto error; | ||
| 239 | } | ||
| 240 | dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n", | ||
| 241 | (unsigned int)ret); | ||
| 242 | } | ||
| 243 | |||
| 244 | r = 0; | ||
| 245 | error: | ||
| 246 | kfree(p); | ||
| 247 | return r; | ||
| 248 | } | ||
| 249 | |||
| 250 | static u16 get_word(const void *data, u16 offset) | ||
| 251 | { | ||
| 252 | const __le16 *p = data; | ||
| 253 | return le16_to_cpu(p[offset]); | ||
| 254 | } | ||
| 255 | |||
| 256 | static char *get_fw_name(char *buffer, size_t size, u8 device_type, | ||
| 257 | const char* postfix) | ||
| 258 | { | ||
| 259 | scnprintf(buffer, size, "%s%s", | ||
| 260 | device_type == DEVICE_ZD1211B ? | ||
| 261 | FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, | ||
| 262 | postfix); | ||
| 263 | return buffer; | ||
| 264 | } | ||
| 265 | |||
| 266 | static int upload_firmware(struct usb_device *udev, u8 device_type) | ||
| 267 | { | ||
| 268 | int r; | ||
| 269 | u16 fw_bcdDevice; | ||
| 270 | u16 bcdDevice; | ||
| 271 | const struct firmware *ub_fw = NULL; | ||
| 272 | const struct firmware *uph_fw = NULL; | ||
| 273 | char fw_name[128]; | ||
| 274 | |||
| 275 | bcdDevice = get_bcdDevice(udev); | ||
| 276 | |||
| 277 | r = request_fw_file(&ub_fw, | ||
| 278 | get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"), | ||
| 279 | &udev->dev); | ||
| 280 | if (r) | ||
| 281 | goto error; | ||
| 282 | |||
| 283 | fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); | ||
| 284 | |||
| 285 | /* FIXME: do we have any reason to perform the kludge that the vendor | ||
| 286 | * driver does when there is a version mismatch? (their driver uploads | ||
| 287 | * different firmwares and stuff) | ||
| 288 | */ | ||
| 289 | if (fw_bcdDevice != bcdDevice) { | ||
| 290 | dev_info(&udev->dev, | ||
| 291 | "firmware device id %#06x and actual device id " | ||
| 292 | "%#06x differ, continuing anyway\n", | ||
| 293 | fw_bcdDevice, bcdDevice); | ||
| 294 | } else { | ||
| 295 | dev_dbg_f(&udev->dev, | ||
| 296 | "firmware device id %#06x is equal to the " | ||
| 297 | "actual device id\n", fw_bcdDevice); | ||
| 298 | } | ||
| 299 | |||
| 300 | |||
| 301 | r = request_fw_file(&uph_fw, | ||
| 302 | get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"), | ||
| 303 | &udev->dev); | ||
| 304 | if (r) | ||
| 305 | goto error; | ||
| 306 | |||
| 307 | r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START_OFFSET, | ||
| 308 | REBOOT); | ||
| 309 | if (r) { | ||
| 310 | dev_err(&udev->dev, | ||
| 311 | "Could not upload firmware code uph. Error number %d\n", | ||
| 312 | r); | ||
| 313 | } | ||
| 314 | |||
| 315 | /* FALL-THROUGH */ | ||
| 316 | error: | ||
| 317 | release_firmware(ub_fw); | ||
| 318 | release_firmware(uph_fw); | ||
| 319 | return r; | ||
| 320 | } | ||
| 321 | |||
| 322 | static void disable_read_regs_int(struct zd_usb *usb) | ||
| 323 | { | ||
| 324 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 325 | |||
| 326 | ZD_ASSERT(in_interrupt()); | ||
| 327 | spin_lock(&intr->lock); | ||
| 328 | intr->read_regs_enabled = 0; | ||
| 329 | spin_unlock(&intr->lock); | ||
| 330 | } | ||
| 331 | |||
| 332 | #define urb_dev(urb) (&(urb)->dev->dev) | ||
| 333 | |||
| 334 | static inline void handle_regs_int(struct urb *urb) | ||
| 335 | { | ||
| 336 | struct zd_usb *usb = urb->context; | ||
| 337 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 338 | int len; | ||
| 339 | |||
| 340 | ZD_ASSERT(in_interrupt()); | ||
| 341 | spin_lock(&intr->lock); | ||
| 342 | |||
| 343 | if (intr->read_regs_enabled) { | ||
| 344 | intr->read_regs.length = len = urb->actual_length; | ||
| 345 | |||
| 346 | if (len > sizeof(intr->read_regs.buffer)) | ||
| 347 | len = sizeof(intr->read_regs.buffer); | ||
| 348 | memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); | ||
| 349 | intr->read_regs_enabled = 0; | ||
| 350 | complete(&intr->read_regs.completion); | ||
| 351 | goto out; | ||
| 352 | } | ||
| 353 | |||
| 354 | dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); | ||
| 355 | out: | ||
| 356 | spin_unlock(&intr->lock); | ||
| 357 | } | ||
| 358 | |||
| 359 | static inline void handle_retry_failed_int(struct urb *urb) | ||
| 360 | { | ||
| 361 | dev_dbg_f(urb_dev(urb), "retry failed interrupt\n"); | ||
| 362 | } | ||
| 363 | |||
| 364 | |||
| 365 | static void int_urb_complete(struct urb *urb, struct pt_regs *pt_regs) | ||
| 366 | { | ||
| 367 | int r; | ||
| 368 | struct usb_int_header *hdr; | ||
| 369 | |||
| 370 | switch (urb->status) { | ||
| 371 | case 0: | ||
| 372 | break; | ||
| 373 | case -ESHUTDOWN: | ||
| 374 | case -EINVAL: | ||
| 375 | case -ENODEV: | ||
| 376 | case -ENOENT: | ||
| 377 | case -ECONNRESET: | ||
| 378 | goto kfree; | ||
| 379 | case -EPIPE: | ||
| 380 | usb_clear_halt(urb->dev, EP_INT_IN); | ||
| 381 | /* FALL-THROUGH */ | ||
| 382 | default: | ||
| 383 | goto resubmit; | ||
| 384 | } | ||
| 385 | |||
| 386 | if (urb->actual_length < sizeof(hdr)) { | ||
| 387 | dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb); | ||
| 388 | goto resubmit; | ||
| 389 | } | ||
| 390 | |||
| 391 | hdr = urb->transfer_buffer; | ||
| 392 | if (hdr->type != USB_INT_TYPE) { | ||
| 393 | dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb); | ||
| 394 | goto resubmit; | ||
| 395 | } | ||
| 396 | |||
| 397 | switch (hdr->id) { | ||
| 398 | case USB_INT_ID_REGS: | ||
| 399 | handle_regs_int(urb); | ||
| 400 | break; | ||
| 401 | case USB_INT_ID_RETRY_FAILED: | ||
| 402 | handle_retry_failed_int(urb); | ||
| 403 | break; | ||
| 404 | default: | ||
| 405 | dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb, | ||
| 406 | (unsigned int)hdr->id); | ||
| 407 | goto resubmit; | ||
| 408 | } | ||
| 409 | |||
| 410 | resubmit: | ||
| 411 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 412 | if (r) { | ||
| 413 | dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb); | ||
| 414 | goto kfree; | ||
| 415 | } | ||
| 416 | return; | ||
| 417 | kfree: | ||
| 418 | kfree(urb->transfer_buffer); | ||
| 419 | } | ||
| 420 | |||
| 421 | static inline int int_urb_interval(struct usb_device *udev) | ||
| 422 | { | ||
| 423 | switch (udev->speed) { | ||
| 424 | case USB_SPEED_HIGH: | ||
| 425 | return 4; | ||
| 426 | case USB_SPEED_LOW: | ||
| 427 | return 10; | ||
| 428 | case USB_SPEED_FULL: | ||
| 429 | default: | ||
| 430 | return 1; | ||
| 431 | } | ||
| 432 | } | ||
| 433 | |||
| 434 | static inline int usb_int_enabled(struct zd_usb *usb) | ||
| 435 | { | ||
| 436 | unsigned long flags; | ||
| 437 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 438 | struct urb *urb; | ||
| 439 | |||
| 440 | spin_lock_irqsave(&intr->lock, flags); | ||
| 441 | urb = intr->urb; | ||
| 442 | spin_unlock_irqrestore(&intr->lock, flags); | ||
| 443 | return urb != NULL; | ||
| 444 | } | ||
| 445 | |||
| 446 | int zd_usb_enable_int(struct zd_usb *usb) | ||
| 447 | { | ||
| 448 | int r; | ||
| 449 | struct usb_device *udev; | ||
| 450 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 451 | void *transfer_buffer = NULL; | ||
| 452 | struct urb *urb; | ||
| 453 | |||
| 454 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
| 455 | |||
| 456 | urb = usb_alloc_urb(0, GFP_NOFS); | ||
| 457 | if (!urb) { | ||
| 458 | r = -ENOMEM; | ||
| 459 | goto out; | ||
| 460 | } | ||
| 461 | |||
| 462 | ZD_ASSERT(!irqs_disabled()); | ||
| 463 | spin_lock_irq(&intr->lock); | ||
| 464 | if (intr->urb) { | ||
| 465 | spin_unlock_irq(&intr->lock); | ||
| 466 | r = 0; | ||
| 467 | goto error_free_urb; | ||
| 468 | } | ||
| 469 | intr->urb = urb; | ||
| 470 | spin_unlock_irq(&intr->lock); | ||
| 471 | |||
| 472 | /* TODO: make it a DMA buffer */ | ||
| 473 | r = -ENOMEM; | ||
| 474 | transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_NOFS); | ||
| 475 | if (!transfer_buffer) { | ||
| 476 | dev_dbg_f(zd_usb_dev(usb), | ||
| 477 | "couldn't allocate transfer_buffer\n"); | ||
| 478 | goto error_set_urb_null; | ||
| 479 | } | ||
| 480 | |||
| 481 | udev = zd_usb_to_usbdev(usb); | ||
| 482 | usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), | ||
| 483 | transfer_buffer, USB_MAX_EP_INT_BUFFER, | ||
| 484 | int_urb_complete, usb, | ||
| 485 | intr->interval); | ||
| 486 | |||
| 487 | dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); | ||
| 488 | r = usb_submit_urb(urb, GFP_NOFS); | ||
| 489 | if (r) { | ||
| 490 | dev_dbg_f(zd_usb_dev(usb), | ||
| 491 | "Couldn't submit urb. Error number %d\n", r); | ||
| 492 | goto error; | ||
| 493 | } | ||
| 494 | |||
| 495 | return 0; | ||
| 496 | error: | ||
| 497 | kfree(transfer_buffer); | ||
| 498 | error_set_urb_null: | ||
| 499 | spin_lock_irq(&intr->lock); | ||
| 500 | intr->urb = NULL; | ||
| 501 | spin_unlock_irq(&intr->lock); | ||
| 502 | error_free_urb: | ||
| 503 | usb_free_urb(urb); | ||
| 504 | out: | ||
| 505 | return r; | ||
| 506 | } | ||
| 507 | |||
| 508 | void zd_usb_disable_int(struct zd_usb *usb) | ||
| 509 | { | ||
| 510 | unsigned long flags; | ||
| 511 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 512 | struct urb *urb; | ||
| 513 | |||
| 514 | spin_lock_irqsave(&intr->lock, flags); | ||
| 515 | urb = intr->urb; | ||
| 516 | if (!urb) { | ||
| 517 | spin_unlock_irqrestore(&intr->lock, flags); | ||
| 518 | return; | ||
| 519 | } | ||
| 520 | intr->urb = NULL; | ||
| 521 | spin_unlock_irqrestore(&intr->lock, flags); | ||
| 522 | |||
| 523 | usb_kill_urb(urb); | ||
| 524 | dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); | ||
| 525 | usb_free_urb(urb); | ||
| 526 | } | ||
| 527 | |||
| 528 | static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, | ||
| 529 | unsigned int length) | ||
| 530 | { | ||
| 531 | int i; | ||
| 532 | struct zd_mac *mac = zd_usb_to_mac(usb); | ||
| 533 | const struct rx_length_info *length_info; | ||
| 534 | |||
| 535 | if (length < sizeof(struct rx_length_info)) { | ||
| 536 | /* It's not a complete packet anyhow. */ | ||
| 537 | return; | ||
| 538 | } | ||
| 539 | length_info = (struct rx_length_info *) | ||
| 540 | (buffer + length - sizeof(struct rx_length_info)); | ||
| 541 | |||
| 542 | /* It might be that three frames are merged into a single URB | ||
| 543 | * transaction. We have to check for the length info tag. | ||
| 544 | * | ||
| 545 | * While testing we discovered that length_info might be unaligned, | ||
| 546 | * because if USB transactions are merged, the last packet will not | ||
| 547 | * be padded. Unaligned access might also happen if the length_info | ||
| 548 | * structure is not present. | ||
| 549 | */ | ||
| 550 | if (get_unaligned(&length_info->tag) == RX_LENGTH_INFO_TAG) { | ||
| 551 | unsigned int l, k, n; | ||
| 552 | for (i = 0, l = 0;; i++) { | ||
| 553 | k = le16_to_cpu(get_unaligned( | ||
| 554 | &length_info->length[i])); | ||
| 555 | n = l+k; | ||
| 556 | if (n > length) | ||
| 557 | return; | ||
| 558 | zd_mac_rx(mac, buffer+l, k); | ||
| 559 | if (i >= 2) | ||
| 560 | return; | ||
| 561 | l = (n+3) & ~3; | ||
| 562 | } | ||
| 563 | } else { | ||
| 564 | zd_mac_rx(mac, buffer, length); | ||
| 565 | } | ||
| 566 | } | ||
| 567 | |||
| 568 | static void rx_urb_complete(struct urb *urb, struct pt_regs *pt_regs) | ||
| 569 | { | ||
| 570 | struct zd_usb *usb; | ||
| 571 | struct zd_usb_rx *rx; | ||
| 572 | const u8 *buffer; | ||
| 573 | unsigned int length; | ||
| 574 | |||
| 575 | switch (urb->status) { | ||
| 576 | case 0: | ||
| 577 | break; | ||
| 578 | case -ESHUTDOWN: | ||
| 579 | case -EINVAL: | ||
| 580 | case -ENODEV: | ||
| 581 | case -ENOENT: | ||
| 582 | case -ECONNRESET: | ||
| 583 | return; | ||
| 584 | case -EPIPE: | ||
| 585 | usb_clear_halt(urb->dev, EP_DATA_IN); | ||
| 586 | /* FALL-THROUGH */ | ||
| 587 | default: | ||
| 588 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
| 589 | goto resubmit; | ||
| 590 | } | ||
| 591 | |||
| 592 | buffer = urb->transfer_buffer; | ||
| 593 | length = urb->actual_length; | ||
| 594 | usb = urb->context; | ||
| 595 | rx = &usb->rx; | ||
| 596 | |||
| 597 | if (length%rx->usb_packet_size > rx->usb_packet_size-4) { | ||
| 598 | /* If there is an old first fragment, we don't care. */ | ||
| 599 | dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); | ||
| 600 | ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment)); | ||
| 601 | spin_lock(&rx->lock); | ||
| 602 | memcpy(rx->fragment, buffer, length); | ||
| 603 | rx->fragment_length = length; | ||
| 604 | spin_unlock(&rx->lock); | ||
| 605 | goto resubmit; | ||
| 606 | } | ||
| 607 | |||
| 608 | spin_lock(&rx->lock); | ||
| 609 | if (rx->fragment_length > 0) { | ||
| 610 | /* We are on a second fragment, we believe */ | ||
| 611 | ZD_ASSERT(length + rx->fragment_length <= | ||
| 612 | ARRAY_SIZE(rx->fragment)); | ||
| 613 | dev_dbg_f(urb_dev(urb), "*** second fragment ***\n"); | ||
| 614 | memcpy(rx->fragment+rx->fragment_length, buffer, length); | ||
| 615 | handle_rx_packet(usb, rx->fragment, | ||
| 616 | rx->fragment_length + length); | ||
| 617 | rx->fragment_length = 0; | ||
| 618 | spin_unlock(&rx->lock); | ||
| 619 | } else { | ||
| 620 | spin_unlock(&rx->lock); | ||
| 621 | handle_rx_packet(usb, buffer, length); | ||
| 622 | } | ||
| 623 | |||
| 624 | resubmit: | ||
| 625 | usb_submit_urb(urb, GFP_ATOMIC); | ||
| 626 | } | ||
| 627 | |||
| 628 | struct urb *alloc_urb(struct zd_usb *usb) | ||
| 629 | { | ||
| 630 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
| 631 | struct urb *urb; | ||
| 632 | void *buffer; | ||
| 633 | |||
| 634 | urb = usb_alloc_urb(0, GFP_NOFS); | ||
| 635 | if (!urb) | ||
| 636 | return NULL; | ||
| 637 | buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_NOFS, | ||
| 638 | &urb->transfer_dma); | ||
| 639 | if (!buffer) { | ||
| 640 | usb_free_urb(urb); | ||
| 641 | return NULL; | ||
| 642 | } | ||
| 643 | |||
| 644 | usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN), | ||
| 645 | buffer, USB_MAX_RX_SIZE, | ||
| 646 | rx_urb_complete, usb); | ||
| 647 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 648 | |||
| 649 | return urb; | ||
| 650 | } | ||
| 651 | |||
| 652 | void free_urb(struct urb *urb) | ||
| 653 | { | ||
| 654 | if (!urb) | ||
| 655 | return; | ||
| 656 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
| 657 | urb->transfer_buffer, urb->transfer_dma); | ||
| 658 | usb_free_urb(urb); | ||
| 659 | } | ||
| 660 | |||
| 661 | int zd_usb_enable_rx(struct zd_usb *usb) | ||
| 662 | { | ||
| 663 | int i, r; | ||
| 664 | struct zd_usb_rx *rx = &usb->rx; | ||
| 665 | struct urb **urbs; | ||
| 666 | |||
| 667 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
| 668 | |||
| 669 | r = -ENOMEM; | ||
| 670 | urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_NOFS); | ||
| 671 | if (!urbs) | ||
| 672 | goto error; | ||
| 673 | for (i = 0; i < URBS_COUNT; i++) { | ||
| 674 | urbs[i] = alloc_urb(usb); | ||
| 675 | if (!urbs[i]) | ||
| 676 | goto error; | ||
| 677 | } | ||
| 678 | |||
| 679 | ZD_ASSERT(!irqs_disabled()); | ||
| 680 | spin_lock_irq(&rx->lock); | ||
| 681 | if (rx->urbs) { | ||
| 682 | spin_unlock_irq(&rx->lock); | ||
| 683 | r = 0; | ||
| 684 | goto error; | ||
| 685 | } | ||
| 686 | rx->urbs = urbs; | ||
| 687 | rx->urbs_count = URBS_COUNT; | ||
| 688 | spin_unlock_irq(&rx->lock); | ||
| 689 | |||
| 690 | for (i = 0; i < URBS_COUNT; i++) { | ||
| 691 | r = usb_submit_urb(urbs[i], GFP_NOFS); | ||
| 692 | if (r) | ||
| 693 | goto error_submit; | ||
| 694 | } | ||
| 695 | |||
| 696 | return 0; | ||
| 697 | error_submit: | ||
| 698 | for (i = 0; i < URBS_COUNT; i++) { | ||
| 699 | usb_kill_urb(urbs[i]); | ||
| 700 | } | ||
| 701 | spin_lock_irq(&rx->lock); | ||
| 702 | rx->urbs = NULL; | ||
| 703 | rx->urbs_count = 0; | ||
| 704 | spin_unlock_irq(&rx->lock); | ||
| 705 | error: | ||
| 706 | if (urbs) { | ||
| 707 | for (i = 0; i < URBS_COUNT; i++) | ||
| 708 | free_urb(urbs[i]); | ||
| 709 | } | ||
| 710 | return r; | ||
| 711 | } | ||
| 712 | |||
| 713 | void zd_usb_disable_rx(struct zd_usb *usb) | ||
| 714 | { | ||
| 715 | int i; | ||
| 716 | unsigned long flags; | ||
| 717 | struct urb **urbs; | ||
| 718 | unsigned int count; | ||
| 719 | struct zd_usb_rx *rx = &usb->rx; | ||
| 720 | |||
| 721 | spin_lock_irqsave(&rx->lock, flags); | ||
| 722 | urbs = rx->urbs; | ||
| 723 | count = rx->urbs_count; | ||
| 724 | spin_unlock_irqrestore(&rx->lock, flags); | ||
| 725 | if (!urbs) | ||
| 726 | return; | ||
| 727 | |||
| 728 | for (i = 0; i < count; i++) { | ||
| 729 | usb_kill_urb(urbs[i]); | ||
| 730 | free_urb(urbs[i]); | ||
| 731 | } | ||
| 732 | kfree(urbs); | ||
| 733 | |||
| 734 | spin_lock_irqsave(&rx->lock, flags); | ||
| 735 | rx->urbs = NULL; | ||
| 736 | rx->urbs_count = 0; | ||
| 737 | spin_unlock_irqrestore(&rx->lock, flags); | ||
| 738 | } | ||
| 739 | |||
| 740 | static void tx_urb_complete(struct urb *urb, struct pt_regs *pt_regs) | ||
| 741 | { | ||
| 742 | int r; | ||
| 743 | |||
| 744 | switch (urb->status) { | ||
| 745 | case 0: | ||
| 746 | break; | ||
| 747 | case -ESHUTDOWN: | ||
| 748 | case -EINVAL: | ||
| 749 | case -ENODEV: | ||
| 750 | case -ENOENT: | ||
| 751 | case -ECONNRESET: | ||
| 752 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
| 753 | break; | ||
| 754 | case -EPIPE: | ||
| 755 | usb_clear_halt(urb->dev, EP_DATA_OUT); | ||
| 756 | /* FALL-THROUGH */ | ||
| 757 | default: | ||
| 758 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
| 759 | goto resubmit; | ||
| 760 | } | ||
| 761 | free_urb: | ||
| 762 | usb_buffer_free(urb->dev, urb->transfer_buffer_length, | ||
| 763 | urb->transfer_buffer, urb->transfer_dma); | ||
| 764 | usb_free_urb(urb); | ||
| 765 | return; | ||
| 766 | resubmit: | ||
| 767 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 768 | if (r) { | ||
| 769 | dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); | ||
| 770 | goto free_urb; | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 774 | /* Puts the frame on the USB endpoint. It doesn't wait for | ||
| 775 | * completion. The frame must contain the control set. | ||
| 776 | */ | ||
| 777 | int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length) | ||
| 778 | { | ||
| 779 | int r; | ||
| 780 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
| 781 | struct urb *urb; | ||
| 782 | void *buffer; | ||
| 783 | |||
| 784 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 785 | if (!urb) { | ||
| 786 | r = -ENOMEM; | ||
| 787 | goto out; | ||
| 788 | } | ||
| 789 | |||
| 790 | buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC, | ||
| 791 | &urb->transfer_dma); | ||
| 792 | if (!buffer) { | ||
| 793 | r = -ENOMEM; | ||
| 794 | goto error_free_urb; | ||
| 795 | } | ||
| 796 | memcpy(buffer, frame, length); | ||
| 797 | |||
| 798 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), | ||
| 799 | buffer, length, tx_urb_complete, NULL); | ||
| 800 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 801 | |||
| 802 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 803 | if (r) | ||
| 804 | goto error; | ||
| 805 | return 0; | ||
| 806 | error: | ||
| 807 | usb_buffer_free(zd_usb_to_usbdev(usb), length, buffer, | ||
| 808 | urb->transfer_dma); | ||
| 809 | error_free_urb: | ||
| 810 | usb_free_urb(urb); | ||
| 811 | out: | ||
| 812 | return r; | ||
| 813 | } | ||
| 814 | |||
| 815 | static inline void init_usb_interrupt(struct zd_usb *usb) | ||
| 816 | { | ||
| 817 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 818 | |||
| 819 | spin_lock_init(&intr->lock); | ||
| 820 | intr->interval = int_urb_interval(zd_usb_to_usbdev(usb)); | ||
| 821 | init_completion(&intr->read_regs.completion); | ||
| 822 | intr->read_regs.cr_int_addr = cpu_to_le16(usb_addr(usb, CR_INTERRUPT)); | ||
| 823 | } | ||
| 824 | |||
| 825 | static inline void init_usb_rx(struct zd_usb *usb) | ||
| 826 | { | ||
| 827 | struct zd_usb_rx *rx = &usb->rx; | ||
| 828 | spin_lock_init(&rx->lock); | ||
| 829 | if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { | ||
| 830 | rx->usb_packet_size = 512; | ||
| 831 | } else { | ||
| 832 | rx->usb_packet_size = 64; | ||
| 833 | } | ||
| 834 | ZD_ASSERT(rx->fragment_length == 0); | ||
| 835 | } | ||
| 836 | |||
| 837 | static inline void init_usb_tx(struct zd_usb *usb) | ||
| 838 | { | ||
| 839 | /* FIXME: at this point we will allocate a fixed number of urb's for | ||
| 840 | * use in a cyclic scheme */ | ||
| 841 | } | ||
| 842 | |||
| 843 | void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, | ||
| 844 | struct usb_interface *intf) | ||
| 845 | { | ||
| 846 | memset(usb, 0, sizeof(*usb)); | ||
| 847 | usb->intf = usb_get_intf(intf); | ||
| 848 | usb_set_intfdata(usb->intf, netdev); | ||
| 849 | init_usb_interrupt(usb); | ||
| 850 | init_usb_tx(usb); | ||
| 851 | init_usb_rx(usb); | ||
| 852 | } | ||
| 853 | |||
| 854 | int zd_usb_init_hw(struct zd_usb *usb) | ||
| 855 | { | ||
| 856 | int r; | ||
| 857 | struct zd_chip *chip = zd_usb_to_chip(usb); | ||
| 858 | |||
| 859 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
| 860 | r = zd_ioread16_locked(chip, &usb->fw_base_offset, | ||
| 861 | USB_REG((u16)FW_BASE_ADDR_OFFSET)); | ||
| 862 | if (r) | ||
| 863 | return r; | ||
| 864 | dev_dbg_f(zd_usb_dev(usb), "fw_base_offset: %#06hx\n", | ||
| 865 | usb->fw_base_offset); | ||
| 866 | |||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | |||
| 870 | void zd_usb_clear(struct zd_usb *usb) | ||
| 871 | { | ||
| 872 | usb_set_intfdata(usb->intf, NULL); | ||
| 873 | usb_put_intf(usb->intf); | ||
| 874 | memset(usb, 0, sizeof(*usb)); | ||
| 875 | /* FIXME: usb_interrupt, usb_tx, usb_rx? */ | ||
| 876 | } | ||
| 877 | |||
| 878 | static const char *speed(enum usb_device_speed speed) | ||
| 879 | { | ||
| 880 | switch (speed) { | ||
| 881 | case USB_SPEED_LOW: | ||
| 882 | return "low"; | ||
| 883 | case USB_SPEED_FULL: | ||
| 884 | return "full"; | ||
| 885 | case USB_SPEED_HIGH: | ||
| 886 | return "high"; | ||
| 887 | default: | ||
| 888 | return "unknown speed"; | ||
| 889 | } | ||
| 890 | } | ||
| 891 | |||
| 892 | static int scnprint_id(struct usb_device *udev, char *buffer, size_t size) | ||
| 893 | { | ||
| 894 | return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s", | ||
| 895 | le16_to_cpu(udev->descriptor.idVendor), | ||
| 896 | le16_to_cpu(udev->descriptor.idProduct), | ||
| 897 | get_bcdDevice(udev), | ||
| 898 | speed(udev->speed)); | ||
| 899 | } | ||
| 900 | |||
| 901 | int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size) | ||
| 902 | { | ||
| 903 | struct usb_device *udev = interface_to_usbdev(usb->intf); | ||
| 904 | return scnprint_id(udev, buffer, size); | ||
| 905 | } | ||
| 906 | |||
| 907 | #ifdef DEBUG | ||
| 908 | static void print_id(struct usb_device *udev) | ||
| 909 | { | ||
| 910 | char buffer[40]; | ||
| 911 | |||
| 912 | scnprint_id(udev, buffer, sizeof(buffer)); | ||
| 913 | buffer[sizeof(buffer)-1] = 0; | ||
| 914 | dev_dbg_f(&udev->dev, "%s\n", buffer); | ||
| 915 | } | ||
| 916 | #else | ||
| 917 | #define print_id(udev) do { } while (0) | ||
| 918 | #endif | ||
| 919 | |||
| 920 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
| 921 | { | ||
| 922 | int r; | ||
| 923 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 924 | struct net_device *netdev = NULL; | ||
| 925 | |||
| 926 | print_id(udev); | ||
| 927 | |||
| 928 | switch (udev->speed) { | ||
| 929 | case USB_SPEED_LOW: | ||
| 930 | case USB_SPEED_FULL: | ||
| 931 | case USB_SPEED_HIGH: | ||
| 932 | break; | ||
| 933 | default: | ||
| 934 | dev_dbg_f(&intf->dev, "Unknown USB speed\n"); | ||
| 935 | r = -ENODEV; | ||
| 936 | goto error; | ||
| 937 | } | ||
| 938 | |||
| 939 | netdev = zd_netdev_alloc(intf); | ||
| 940 | if (netdev == NULL) { | ||
| 941 | r = -ENOMEM; | ||
| 942 | goto error; | ||
| 943 | } | ||
| 944 | |||
| 945 | r = upload_firmware(udev, id->driver_info); | ||
| 946 | if (r) { | ||
| 947 | dev_err(&intf->dev, | ||
| 948 | "couldn't load firmware. Error number %d\n", r); | ||
| 949 | goto error; | ||
| 950 | } | ||
| 951 | |||
| 952 | r = usb_reset_configuration(udev); | ||
| 953 | if (r) { | ||
| 954 | dev_dbg_f(&intf->dev, | ||
| 955 | "couldn't reset configuration. Error number %d\n", r); | ||
| 956 | goto error; | ||
| 957 | } | ||
| 958 | |||
| 959 | /* At this point the interrupt endpoint is not generally enabled. We | ||
| 960 | * save the USB bandwidth until the network device is opened. But | ||
| 961 | * notify that the initialization of the MAC will require the | ||
| 962 | * interrupts to be temporary enabled. | ||
| 963 | */ | ||
| 964 | r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info); | ||
| 965 | if (r) { | ||
| 966 | dev_dbg_f(&intf->dev, | ||
| 967 | "couldn't initialize mac. Error number %d\n", r); | ||
| 968 | goto error; | ||
| 969 | } | ||
| 970 | |||
| 971 | r = register_netdev(netdev); | ||
| 972 | if (r) { | ||
| 973 | dev_dbg_f(&intf->dev, | ||
| 974 | "couldn't register netdev. Error number %d\n", r); | ||
| 975 | goto error; | ||
| 976 | } | ||
| 977 | |||
| 978 | dev_dbg_f(&intf->dev, "successful\n"); | ||
| 979 | dev_info(&intf->dev,"%s\n", netdev->name); | ||
| 980 | return 0; | ||
| 981 | error: | ||
| 982 | usb_reset_device(interface_to_usbdev(intf)); | ||
| 983 | zd_netdev_free(netdev); | ||
| 984 | return r; | ||
| 985 | } | ||
| 986 | |||
| 987 | static void disconnect(struct usb_interface *intf) | ||
| 988 | { | ||
| 989 | struct net_device *netdev = zd_intf_to_netdev(intf); | ||
| 990 | struct zd_mac *mac = zd_netdev_mac(netdev); | ||
| 991 | struct zd_usb *usb = &mac->chip.usb; | ||
| 992 | |||
| 993 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
| 994 | |||
| 995 | zd_netdev_disconnect(netdev); | ||
| 996 | |||
| 997 | /* Just in case something has gone wrong! */ | ||
| 998 | zd_usb_disable_rx(usb); | ||
| 999 | zd_usb_disable_int(usb); | ||
| 1000 | |||
| 1001 | /* If the disconnect has been caused by a removal of the | ||
| 1002 | * driver module, the reset allows reloading of the driver. If the | ||
| 1003 | * reset will not be executed here, the upload of the firmware in the | ||
| 1004 | * probe function caused by the reloading of the driver will fail. | ||
| 1005 | */ | ||
| 1006 | usb_reset_device(interface_to_usbdev(intf)); | ||
| 1007 | |||
| 1008 | /* If somebody still waits on this lock now, this is an error. */ | ||
| 1009 | zd_netdev_free(netdev); | ||
| 1010 | dev_dbg(&intf->dev, "disconnected\n"); | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | static struct usb_driver driver = { | ||
| 1014 | .name = "zd1211rw", | ||
| 1015 | .id_table = usb_ids, | ||
| 1016 | .probe = probe, | ||
| 1017 | .disconnect = disconnect, | ||
| 1018 | }; | ||
| 1019 | |||
| 1020 | static int __init usb_init(void) | ||
| 1021 | { | ||
| 1022 | int r; | ||
| 1023 | |||
| 1024 | pr_debug("usb_init()\n"); | ||
| 1025 | |||
| 1026 | r = usb_register(&driver); | ||
| 1027 | if (r) { | ||
| 1028 | printk(KERN_ERR "usb_register() failed. Error number %d\n", r); | ||
| 1029 | return r; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | pr_debug("zd1211rw initialized\n"); | ||
| 1033 | return 0; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static void __exit usb_exit(void) | ||
| 1037 | { | ||
| 1038 | pr_debug("usb_exit()\n"); | ||
| 1039 | usb_deregister(&driver); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | module_init(usb_init); | ||
| 1043 | module_exit(usb_exit); | ||
| 1044 | |||
| 1045 | static int usb_int_regs_length(unsigned int count) | ||
| 1046 | { | ||
| 1047 | return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static void prepare_read_regs_int(struct zd_usb *usb) | ||
| 1051 | { | ||
| 1052 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 1053 | |||
| 1054 | spin_lock(&intr->lock); | ||
| 1055 | intr->read_regs_enabled = 1; | ||
| 1056 | INIT_COMPLETION(intr->read_regs.completion); | ||
| 1057 | spin_unlock(&intr->lock); | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | static int get_results(struct zd_usb *usb, u16 *values, | ||
| 1061 | struct usb_req_read_regs *req, unsigned int count) | ||
| 1062 | { | ||
| 1063 | int r; | ||
| 1064 | int i; | ||
| 1065 | struct zd_usb_interrupt *intr = &usb->intr; | ||
| 1066 | struct read_regs_int *rr = &intr->read_regs; | ||
| 1067 | struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; | ||
| 1068 | |||
| 1069 | spin_lock(&intr->lock); | ||
| 1070 | |||
| 1071 | r = -EIO; | ||
| 1072 | /* The created block size seems to be larger than expected. | ||
| 1073 | * However results appear to be correct. | ||
| 1074 | */ | ||
| 1075 | if (rr->length < usb_int_regs_length(count)) { | ||
| 1076 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1077 | "error: actual length %d less than expected %d\n", | ||
| 1078 | rr->length, usb_int_regs_length(count)); | ||
| 1079 | goto error_unlock; | ||
| 1080 | } | ||
| 1081 | if (rr->length > sizeof(rr->buffer)) { | ||
| 1082 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1083 | "error: actual length %d exceeds buffer size %zu\n", | ||
| 1084 | rr->length, sizeof(rr->buffer)); | ||
| 1085 | goto error_unlock; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | for (i = 0; i < count; i++) { | ||
| 1089 | struct reg_data *rd = ®s->regs[i]; | ||
| 1090 | if (rd->addr != req->addr[i]) { | ||
| 1091 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1092 | "rd[%d] addr %#06hx expected %#06hx\n", i, | ||
| 1093 | le16_to_cpu(rd->addr), | ||
| 1094 | le16_to_cpu(req->addr[i])); | ||
| 1095 | goto error_unlock; | ||
| 1096 | } | ||
| 1097 | values[i] = le16_to_cpu(rd->value); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | r = 0; | ||
| 1101 | error_unlock: | ||
| 1102 | spin_unlock(&intr->lock); | ||
| 1103 | return r; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | ||
| 1107 | const zd_addr_t *addresses, unsigned int count) | ||
| 1108 | { | ||
| 1109 | int r; | ||
| 1110 | int i, req_len, actual_req_len; | ||
| 1111 | struct usb_device *udev; | ||
| 1112 | struct usb_req_read_regs *req = NULL; | ||
| 1113 | unsigned long timeout; | ||
| 1114 | |||
| 1115 | if (count < 1) { | ||
| 1116 | dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); | ||
| 1117 | return -EINVAL; | ||
| 1118 | } | ||
| 1119 | if (count > USB_MAX_IOREAD16_COUNT) { | ||
| 1120 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1121 | "error: count %u exceeds possible max %u\n", | ||
| 1122 | count, USB_MAX_IOREAD16_COUNT); | ||
| 1123 | return -EINVAL; | ||
| 1124 | } | ||
| 1125 | if (in_atomic()) { | ||
| 1126 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1127 | "error: io in atomic context not supported\n"); | ||
| 1128 | return -EWOULDBLOCK; | ||
| 1129 | } | ||
| 1130 | if (!usb_int_enabled(usb)) { | ||
| 1131 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1132 | "error: usb interrupt not enabled\n"); | ||
| 1133 | return -EWOULDBLOCK; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); | ||
| 1137 | req = kmalloc(req_len, GFP_NOFS); | ||
| 1138 | if (!req) | ||
| 1139 | return -ENOMEM; | ||
| 1140 | req->id = cpu_to_le16(USB_REQ_READ_REGS); | ||
| 1141 | for (i = 0; i < count; i++) | ||
| 1142 | req->addr[i] = cpu_to_le16(usb_addr(usb, addresses[i])); | ||
| 1143 | |||
| 1144 | udev = zd_usb_to_usbdev(usb); | ||
| 1145 | prepare_read_regs_int(usb); | ||
| 1146 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
| 1147 | req, req_len, &actual_req_len, 1000 /* ms */); | ||
| 1148 | if (r) { | ||
| 1149 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1150 | "error in usb_bulk_msg(). Error number %d\n", r); | ||
| 1151 | goto error; | ||
| 1152 | } | ||
| 1153 | if (req_len != actual_req_len) { | ||
| 1154 | dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n" | ||
| 1155 | " req_len %d != actual_req_len %d\n", | ||
| 1156 | req_len, actual_req_len); | ||
| 1157 | r = -EIO; | ||
| 1158 | goto error; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, | ||
| 1162 | msecs_to_jiffies(1000)); | ||
| 1163 | if (!timeout) { | ||
| 1164 | disable_read_regs_int(usb); | ||
| 1165 | dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); | ||
| 1166 | r = -ETIMEDOUT; | ||
| 1167 | goto error; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | r = get_results(usb, values, req, count); | ||
| 1171 | error: | ||
| 1172 | kfree(req); | ||
| 1173 | return r; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | ||
| 1177 | unsigned int count) | ||
| 1178 | { | ||
| 1179 | int r; | ||
| 1180 | struct usb_device *udev; | ||
| 1181 | struct usb_req_write_regs *req = NULL; | ||
| 1182 | int i, req_len, actual_req_len; | ||
| 1183 | |||
| 1184 | if (count == 0) | ||
| 1185 | return 0; | ||
| 1186 | if (count > USB_MAX_IOWRITE16_COUNT) { | ||
| 1187 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1188 | "error: count %u exceeds possible max %u\n", | ||
| 1189 | count, USB_MAX_IOWRITE16_COUNT); | ||
| 1190 | return -EINVAL; | ||
| 1191 | } | ||
| 1192 | if (in_atomic()) { | ||
| 1193 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1194 | "error: io in atomic context not supported\n"); | ||
| 1195 | return -EWOULDBLOCK; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | req_len = sizeof(struct usb_req_write_regs) + | ||
| 1199 | count * sizeof(struct reg_data); | ||
| 1200 | req = kmalloc(req_len, GFP_NOFS); | ||
| 1201 | if (!req) | ||
| 1202 | return -ENOMEM; | ||
| 1203 | |||
| 1204 | req->id = cpu_to_le16(USB_REQ_WRITE_REGS); | ||
| 1205 | for (i = 0; i < count; i++) { | ||
| 1206 | struct reg_data *rw = &req->reg_writes[i]; | ||
| 1207 | rw->addr = cpu_to_le16(usb_addr(usb, ioreqs[i].addr)); | ||
| 1208 | rw->value = cpu_to_le16(ioreqs[i].value); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | udev = zd_usb_to_usbdev(usb); | ||
| 1212 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
| 1213 | req, req_len, &actual_req_len, 1000 /* ms */); | ||
| 1214 | if (r) { | ||
| 1215 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1216 | "error in usb_bulk_msg(). Error number %d\n", r); | ||
| 1217 | goto error; | ||
| 1218 | } | ||
| 1219 | if (req_len != actual_req_len) { | ||
| 1220 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1221 | "error in usb_bulk_msg()" | ||
| 1222 | " req_len %d != actual_req_len %d\n", | ||
| 1223 | req_len, actual_req_len); | ||
| 1224 | r = -EIO; | ||
| 1225 | goto error; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | /* FALL-THROUGH with r == 0 */ | ||
| 1229 | error: | ||
| 1230 | kfree(req); | ||
| 1231 | return r; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | ||
| 1235 | { | ||
| 1236 | int r; | ||
| 1237 | struct usb_device *udev; | ||
| 1238 | struct usb_req_rfwrite *req = NULL; | ||
| 1239 | int i, req_len, actual_req_len; | ||
| 1240 | u16 bit_value_template; | ||
| 1241 | |||
| 1242 | if (in_atomic()) { | ||
| 1243 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1244 | "error: io in atomic context not supported\n"); | ||
| 1245 | return -EWOULDBLOCK; | ||
| 1246 | } | ||
| 1247 | if (bits < USB_MIN_RFWRITE_BIT_COUNT) { | ||
| 1248 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1249 | "error: bits %d are smaller than" | ||
| 1250 | " USB_MIN_RFWRITE_BIT_COUNT %d\n", | ||
| 1251 | bits, USB_MIN_RFWRITE_BIT_COUNT); | ||
| 1252 | return -EINVAL; | ||
| 1253 | } | ||
| 1254 | if (bits > USB_MAX_RFWRITE_BIT_COUNT) { | ||
| 1255 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1256 | "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n", | ||
| 1257 | bits, USB_MAX_RFWRITE_BIT_COUNT); | ||
| 1258 | return -EINVAL; | ||
| 1259 | } | ||
| 1260 | #ifdef DEBUG | ||
| 1261 | if (value & (~0UL << bits)) { | ||
| 1262 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1263 | "error: value %#09x has bits >= %d set\n", | ||
| 1264 | value, bits); | ||
| 1265 | return -EINVAL; | ||
| 1266 | } | ||
| 1267 | #endif /* DEBUG */ | ||
| 1268 | |||
| 1269 | dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); | ||
| 1270 | |||
| 1271 | r = zd_usb_ioread16(usb, &bit_value_template, CR203); | ||
| 1272 | if (r) { | ||
| 1273 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1274 | "error %d: Couldn't read CR203\n", r); | ||
| 1275 | goto out; | ||
| 1276 | } | ||
| 1277 | bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); | ||
| 1278 | |||
| 1279 | req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); | ||
| 1280 | req = kmalloc(req_len, GFP_NOFS); | ||
| 1281 | if (!req) | ||
| 1282 | return -ENOMEM; | ||
| 1283 | |||
| 1284 | req->id = cpu_to_le16(USB_REQ_WRITE_RF); | ||
| 1285 | /* 1: 3683a, but not used in ZYDAS driver */ | ||
| 1286 | req->value = cpu_to_le16(2); | ||
| 1287 | req->bits = cpu_to_le16(bits); | ||
| 1288 | |||
| 1289 | for (i = 0; i < bits; i++) { | ||
| 1290 | u16 bv = bit_value_template; | ||
| 1291 | if (value & (1 << (bits-1-i))) | ||
| 1292 | bv |= RF_DATA; | ||
| 1293 | req->bit_values[i] = cpu_to_le16(bv); | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | udev = zd_usb_to_usbdev(usb); | ||
| 1297 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | ||
| 1298 | req, req_len, &actual_req_len, 1000 /* ms */); | ||
| 1299 | if (r) { | ||
| 1300 | dev_dbg_f(zd_usb_dev(usb), | ||
| 1301 | "error in usb_bulk_msg(). Error number %d\n", r); | ||
| 1302 | goto out; | ||
| 1303 | } | ||
| 1304 | if (req_len != actual_req_len) { | ||
| 1305 | dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" | ||
| 1306 | " req_len %d != actual_req_len %d\n", | ||
| 1307 | req_len, actual_req_len); | ||
| 1308 | r = -EIO; | ||
| 1309 | goto out; | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | /* FALL-THROUGH with r == 0 */ | ||
| 1313 | out: | ||
| 1314 | kfree(req); | ||
| 1315 | return r; | ||
| 1316 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h new file mode 100644 index 000000000000..d6420283bd5a --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_usb.h | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | /* zd_usb.h: Header for USB interface implemented by ZD1211 chip | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_USB_H | ||
| 19 | #define _ZD_USB_H | ||
| 20 | |||
| 21 | #include <linux/completion.h> | ||
| 22 | #include <linux/netdevice.h> | ||
| 23 | #include <linux/spinlock.h> | ||
| 24 | #include <linux/skbuff.h> | ||
| 25 | #include <linux/usb.h> | ||
| 26 | |||
| 27 | #include "zd_def.h" | ||
| 28 | #include "zd_types.h" | ||
| 29 | |||
| 30 | enum devicetype { | ||
| 31 | DEVICE_ZD1211 = 0, | ||
| 32 | DEVICE_ZD1211B = 1, | ||
| 33 | }; | ||
| 34 | |||
| 35 | enum endpoints { | ||
| 36 | EP_CTRL = 0, | ||
| 37 | EP_DATA_OUT = 1, | ||
| 38 | EP_DATA_IN = 2, | ||
| 39 | EP_INT_IN = 3, | ||
| 40 | EP_REGS_OUT = 4, | ||
| 41 | }; | ||
| 42 | |||
| 43 | enum { | ||
| 44 | USB_MAX_TRANSFER_SIZE = 4096, /* bytes */ | ||
| 45 | /* FIXME: The original driver uses this value. We have to check, | ||
| 46 | * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be | ||
| 47 | * used if one combined frame is split over two USB transactions. | ||
| 48 | */ | ||
| 49 | USB_MAX_RX_SIZE = 4800, /* bytes */ | ||
| 50 | USB_MAX_IOWRITE16_COUNT = 15, | ||
| 51 | USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2, | ||
| 52 | USB_MAX_IOREAD16_COUNT = 15, | ||
| 53 | USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2, | ||
| 54 | USB_MIN_RFWRITE_BIT_COUNT = 16, | ||
| 55 | USB_MAX_RFWRITE_BIT_COUNT = 28, | ||
| 56 | USB_MAX_EP_INT_BUFFER = 64, | ||
| 57 | USB_ZD1211B_BCD_DEVICE = 0x4810, | ||
| 58 | }; | ||
| 59 | |||
| 60 | enum control_requests { | ||
| 61 | USB_REQ_WRITE_REGS = 0x21, | ||
| 62 | USB_REQ_READ_REGS = 0x22, | ||
| 63 | USB_REQ_WRITE_RF = 0x23, | ||
| 64 | USB_REQ_PROG_FLASH = 0x24, | ||
| 65 | USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */ | ||
| 66 | USB_REQ_EEPROM_MID = 0x28, | ||
| 67 | USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */ | ||
| 68 | USB_REQ_FIRMWARE_DOWNLOAD = 0x30, | ||
| 69 | USB_REQ_FIRMWARE_CONFIRM = 0x31, | ||
| 70 | USB_REQ_FIRMWARE_READ_DATA = 0x32, | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct usb_req_read_regs { | ||
| 74 | __le16 id; | ||
| 75 | __le16 addr[0]; | ||
| 76 | } __attribute__((packed)); | ||
| 77 | |||
| 78 | struct reg_data { | ||
| 79 | __le16 addr; | ||
| 80 | __le16 value; | ||
| 81 | } __attribute__((packed)); | ||
| 82 | |||
| 83 | struct usb_req_write_regs { | ||
| 84 | __le16 id; | ||
| 85 | struct reg_data reg_writes[0]; | ||
| 86 | } __attribute__((packed)); | ||
| 87 | |||
| 88 | enum { | ||
| 89 | RF_IF_LE = 0x02, | ||
| 90 | RF_CLK = 0x04, | ||
| 91 | RF_DATA = 0x08, | ||
| 92 | }; | ||
| 93 | |||
| 94 | struct usb_req_rfwrite { | ||
| 95 | __le16 id; | ||
| 96 | __le16 value; | ||
| 97 | /* 1: 3683a */ | ||
| 98 | /* 2: other (default) */ | ||
| 99 | __le16 bits; | ||
| 100 | /* RF2595: 24 */ | ||
| 101 | __le16 bit_values[0]; | ||
| 102 | /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ | ||
| 103 | } __attribute__((packed)); | ||
| 104 | |||
| 105 | /* USB interrupt */ | ||
| 106 | |||
| 107 | enum usb_int_id { | ||
| 108 | USB_INT_TYPE = 0x01, | ||
| 109 | USB_INT_ID_REGS = 0x90, | ||
| 110 | USB_INT_ID_RETRY_FAILED = 0xa0, | ||
| 111 | }; | ||
| 112 | |||
| 113 | enum usb_int_flags { | ||
| 114 | USB_INT_READ_REGS_EN = 0x01, | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct usb_int_header { | ||
| 118 | u8 type; /* must always be 1 */ | ||
| 119 | u8 id; | ||
| 120 | } __attribute__((packed)); | ||
| 121 | |||
| 122 | struct usb_int_regs { | ||
| 123 | struct usb_int_header hdr; | ||
| 124 | struct reg_data regs[0]; | ||
| 125 | } __attribute__((packed)); | ||
| 126 | |||
| 127 | struct usb_int_retry_fail { | ||
| 128 | struct usb_int_header hdr; | ||
| 129 | u8 new_rate; | ||
| 130 | u8 _dummy; | ||
| 131 | u8 addr[ETH_ALEN]; | ||
| 132 | u8 ibss_wakeup_dest; | ||
| 133 | } __attribute__((packed)); | ||
| 134 | |||
| 135 | struct read_regs_int { | ||
| 136 | struct completion completion; | ||
| 137 | /* Stores the USB int structure and contains the USB address of the | ||
| 138 | * first requested register before request. | ||
| 139 | */ | ||
| 140 | u8 buffer[USB_MAX_EP_INT_BUFFER]; | ||
| 141 | int length; | ||
| 142 | __le16 cr_int_addr; | ||
| 143 | }; | ||
| 144 | |||
| 145 | struct zd_ioreq16 { | ||
| 146 | zd_addr_t addr; | ||
| 147 | u16 value; | ||
| 148 | }; | ||
| 149 | |||
| 150 | struct zd_ioreq32 { | ||
| 151 | zd_addr_t addr; | ||
| 152 | u32 value; | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct zd_usb_interrupt { | ||
| 156 | struct read_regs_int read_regs; | ||
| 157 | spinlock_t lock; | ||
| 158 | struct urb *urb; | ||
| 159 | int interval; | ||
| 160 | u8 read_regs_enabled:1; | ||
| 161 | }; | ||
| 162 | |||
| 163 | static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) | ||
| 164 | { | ||
| 165 | return (struct usb_int_regs *)intr->read_regs.buffer; | ||
| 166 | } | ||
| 167 | |||
| 168 | #define URBS_COUNT 5 | ||
| 169 | |||
| 170 | struct zd_usb_rx { | ||
| 171 | spinlock_t lock; | ||
| 172 | u8 fragment[2*USB_MAX_RX_SIZE]; | ||
| 173 | unsigned int fragment_length; | ||
| 174 | unsigned int usb_packet_size; | ||
| 175 | struct urb **urbs; | ||
| 176 | int urbs_count; | ||
| 177 | }; | ||
| 178 | |||
| 179 | struct zd_usb_tx { | ||
| 180 | spinlock_t lock; | ||
| 181 | }; | ||
| 182 | |||
| 183 | /* Contains the usb parts. The structure doesn't require a lock, because intf | ||
| 184 | * and fw_base_offset, will not be changed after initialization. | ||
| 185 | */ | ||
| 186 | struct zd_usb { | ||
| 187 | struct zd_usb_interrupt intr; | ||
| 188 | struct zd_usb_rx rx; | ||
| 189 | struct zd_usb_tx tx; | ||
| 190 | struct usb_interface *intf; | ||
| 191 | u16 fw_base_offset; | ||
| 192 | }; | ||
| 193 | |||
| 194 | #define zd_usb_dev(usb) (&usb->intf->dev) | ||
| 195 | |||
| 196 | static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb) | ||
| 197 | { | ||
| 198 | return interface_to_usbdev(usb->intf); | ||
| 199 | } | ||
| 200 | |||
| 201 | static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf) | ||
| 202 | { | ||
| 203 | return usb_get_intfdata(intf); | ||
| 204 | } | ||
| 205 | |||
| 206 | static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb) | ||
| 207 | { | ||
| 208 | return zd_intf_to_netdev(usb->intf); | ||
| 209 | } | ||
| 210 | |||
| 211 | void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, | ||
| 212 | struct usb_interface *intf); | ||
| 213 | int zd_usb_init_hw(struct zd_usb *usb); | ||
| 214 | void zd_usb_clear(struct zd_usb *usb); | ||
| 215 | |||
| 216 | int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); | ||
| 217 | |||
| 218 | int zd_usb_enable_int(struct zd_usb *usb); | ||
| 219 | void zd_usb_disable_int(struct zd_usb *usb); | ||
| 220 | |||
| 221 | int zd_usb_enable_rx(struct zd_usb *usb); | ||
| 222 | void zd_usb_disable_rx(struct zd_usb *usb); | ||
| 223 | |||
| 224 | int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length); | ||
| 225 | |||
| 226 | int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | ||
| 227 | const zd_addr_t *addresses, unsigned int count); | ||
| 228 | |||
| 229 | static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value, | ||
| 230 | const zd_addr_t addr) | ||
| 231 | { | ||
| 232 | return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1); | ||
| 233 | } | ||
| 234 | |||
| 235 | int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | ||
| 236 | unsigned int count); | ||
| 237 | |||
| 238 | int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); | ||
| 239 | |||
| 240 | #endif /* _ZD_USB_H */ | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_util.c b/drivers/net/wireless/zd1211rw/zd_util.c new file mode 100644 index 000000000000..d20036c15d11 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_util.c | |||
| @@ -0,0 +1,82 @@ | |||
| 1 | /* zd_util.c | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | * | ||
| 17 | * Utility program | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include "zd_def.h" | ||
| 21 | #include "zd_util.h" | ||
| 22 | |||
| 23 | #ifdef DEBUG | ||
| 24 | static char hex(u8 v) | ||
| 25 | { | ||
| 26 | v &= 0xf; | ||
| 27 | return (v < 10 ? '0' : 'a' - 10) + v; | ||
| 28 | } | ||
| 29 | |||
| 30 | static char hex_print(u8 c) | ||
| 31 | { | ||
| 32 | return (0x20 <= c && c < 0x7f) ? c : '.'; | ||
| 33 | } | ||
| 34 | |||
| 35 | static void dump_line(const u8 *bytes, size_t size) | ||
| 36 | { | ||
| 37 | char c; | ||
| 38 | size_t i; | ||
| 39 | |||
| 40 | size = size <= 8 ? size : 8; | ||
| 41 | printk(KERN_DEBUG "zd1211 %p ", bytes); | ||
| 42 | for (i = 0; i < 8; i++) { | ||
| 43 | switch (i) { | ||
| 44 | case 1: | ||
| 45 | case 5: | ||
| 46 | c = '.'; | ||
| 47 | break; | ||
| 48 | case 3: | ||
| 49 | c = ':'; | ||
| 50 | break; | ||
| 51 | default: | ||
| 52 | c = ' '; | ||
| 53 | } | ||
| 54 | if (i < size) { | ||
| 55 | printk("%c%c%c", hex(bytes[i] >> 4), hex(bytes[i]), c); | ||
| 56 | } else { | ||
| 57 | printk(" %c", c); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | for (i = 0; i < size; i++) | ||
| 62 | printk("%c", hex_print(bytes[i])); | ||
| 63 | printk("\n"); | ||
| 64 | } | ||
| 65 | |||
| 66 | void zd_hexdump(const void *bytes, size_t size) | ||
| 67 | { | ||
| 68 | size_t i = 0; | ||
| 69 | |||
| 70 | do { | ||
| 71 | dump_line((u8 *)bytes + i, size-i); | ||
| 72 | i += 8; | ||
| 73 | } while (i < size); | ||
| 74 | } | ||
| 75 | #endif /* DEBUG */ | ||
| 76 | |||
| 77 | void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size) | ||
| 78 | { | ||
| 79 | if (buffer_size < tail_size) | ||
| 80 | return NULL; | ||
| 81 | return (u8 *)buffer + (buffer_size - tail_size); | ||
| 82 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_util.h b/drivers/net/wireless/zd1211rw/zd_util.h new file mode 100644 index 000000000000..ce26f7adea92 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_util.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* zd_util.h | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation; either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program; if not, write to the Free Software | ||
| 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _ZD_UTIL_H | ||
| 19 | #define _ZD_UTIL_H | ||
| 20 | |||
| 21 | void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size); | ||
| 22 | |||
| 23 | #ifdef DEBUG | ||
| 24 | void zd_hexdump(const void *bytes, size_t size); | ||
| 25 | #else | ||
| 26 | #define zd_hexdump(bytes, size) | ||
| 27 | #endif /* DEBUG */ | ||
| 28 | |||
| 29 | #endif /* _ZD_UTIL_H */ | ||
