* improve similar pkg suggestions and share code in core-functions for all scripts...
[t2sde.git] / package / kernel / linux / 0010-wifi-orinoco.patch
blob0d775f303dcae1c2c6ed47d21f13fd4eea43ed49
1 # --- T2-COPYRIGHT-BEGIN ---
2 # t2/package/*/linux/0010-wifi-orinoco.patch
3 # Copyright (C) 2024 - 2025 The T2 SDE Project
4 # SPDX-License-Identifier: GPL-2.0 or patched project license
5 # --- T2-COPYRIGHT-END ---
7 From 1535d5962d79b8f4bddfd480399828b8db9d7a1c Mon Sep 17 00:00:00 2001
8 From: Arnd Bergmann <arnd@arndb.de>
9 Date: Mon, 23 Oct 2023 15:19:48 +0200
10 Subject: wifi: remove orphaned orinoco driver
12 Orinoco is a PIO-only ISA/PCMCIA 802.11b device with extra bus interface
13 connections for PCI/Cardbus/mini-PCI and a few pre-2002 Apple PowerMac
14 variants. It supports both wireless extensions and CFG80211, but I could
15 not tell if it requires using both.
17 This device used to be one of the most common ones 20 years ago, but
18 has been orphaned for most of the time since then, and the conversion
19 to cfg80211 has stalled in 2010.
21 --- b/MAINTAINERS
22 +++ a/MAINTAINERS
23 @@ -16068,6 +16068,13 @@
24 F: Documentation/filesystems/orangefs.rst
25 F: fs/orangefs/
27 +ORINOCO DRIVER
28 +L: linux-wireless@vger.kernel.org
29 +S: Orphan
30 +W: https://wireless.wiki.kernel.org/en/users/Drivers/orinoco
31 +W: http://www.nongnu.org/orinoco/
32 +F: drivers/net/wireless/intersil/orinoco/
34 OV2659 OMNIVISION SENSOR DRIVER
35 M: "Lad, Prabhakar" <prabhakar.csengg@gmail.com>
36 L: linux-media@vger.kernel.org
37 --- b/drivers/net/wireless/intersil/Kconfig
38 +++ a/drivers/net/wireless/intersil/Kconfig
39 @@ -12,6 +12,7 @@
41 if WLAN_VENDOR_INTERSIL
43 +source "drivers/net/wireless/intersil/orinoco/Kconfig"
44 source "drivers/net/wireless/intersil/p54/Kconfig"
46 endif # WLAN_VENDOR_INTERSIL
47 --- b/drivers/net/wireless/intersil/Makefile
48 +++ a/drivers/net/wireless/intersil/Makefile
49 @@ -1,2 +1,3 @@
50 # SPDX-License-Identifier: GPL-2.0-only
51 +obj-$(CONFIG_HERMES) += orinoco/
52 obj-$(CONFIG_P54_COMMON) += p54/
53 --- /dev/null
54 +++ a/drivers/net/wireless/intersil/orinoco/Kconfig
55 @@ -0,0 +1,143 @@
56 +# SPDX-License-Identifier: GPL-2.0-only
57 +config HERMES
58 + tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
59 + depends on (PPC_PMAC || PCI || PCMCIA)
60 + depends on CFG80211
61 + select CFG80211_WEXT_EXPORT
62 + select WIRELESS_EXT
63 + select WEXT_SPY
64 + select WEXT_PRIV
65 + select FW_LOADER
66 + select CRYPTO
67 + select CRYPTO_MICHAEL_MIC
68 + help
69 + A driver for 802.11b wireless cards based on the "Hermes" or
70 + Intersil HFA384x (Prism 2) MAC controller. This includes the vast
71 + majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
72 + - except for the Cisco/Aironet cards. Cards supported include the
73 + Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
74 + Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
75 + IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
76 + MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
77 + IPW2011, and Symbol Spectrum24 High Rate amongst others.
79 + This option includes the guts of the driver, but in order to
80 + actually use a card you will also need to enable support for PCMCIA
81 + Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
83 + You will also very likely also need the Wireless Tools in order to
84 + configure your card and that /etc/pcmcia/wireless.opts works :
85 + <https://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
87 +config HERMES_PRISM
88 + bool "Support Prism 2/2.5 chipset"
89 + depends on HERMES
90 + help
92 + Say Y to enable support for Prism 2 and 2.5 chipsets. These
93 + chipsets are better handled by the hostap driver. This driver
94 + would not support WPA or firmware download for Prism chipset.
96 + If you are not sure, say N.
98 +config HERMES_CACHE_FW_ON_INIT
99 + bool "Cache Hermes firmware on driver initialisation"
100 + depends on HERMES
101 + default y
102 + help
103 + Say Y to cache any firmware required by the Hermes drivers
104 + on startup. The firmware will remain cached until the
105 + driver is unloaded. The cache uses 64K of RAM.
107 + Otherwise load the firmware from userspace as required. In
108 + this case the driver should be unloaded and restarted
109 + whenever the firmware is changed.
111 + If you are not sure, say Y.
113 +config APPLE_AIRPORT
114 + tristate "Apple Airport support (built-in)"
115 + depends on PPC_PMAC && HERMES
116 + help
117 + Say Y here to support the Airport 802.11b wireless Ethernet hardware
118 + built into the Macintosh iBook and other recent PowerPC-based
119 + Macintosh machines. This is essentially a Lucent Orinoco card with
120 + a non-standard interface.
122 + This driver does not support the Airport Extreme (802.11b/g). Use
123 + the BCM43xx driver for Airport Extreme cards.
125 +config PLX_HERMES
126 + tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
127 + depends on PCI && HERMES
128 + help
129 + Enable support for PCMCIA cards supported by the "Hermes" (aka
130 + orinoco) driver when used in PLX9052 based PCI adaptors. These
131 + adaptors are not a full PCMCIA controller but act as a more limited
132 + PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
133 + 802.11b PCMCIA cards can be used in desktop machines. The Netgear
134 + MA301 is such an adaptor.
136 +config TMD_HERMES
137 + tristate "Hermes in TMD7160 based PCI adaptor support"
138 + depends on PCI && HERMES
139 + help
140 + Enable support for PCMCIA cards supported by the "Hermes" (aka
141 + orinoco) driver when used in TMD7160 based PCI adaptors. These
142 + adaptors are not a full PCMCIA controller but act as a more limited
143 + PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
144 + 802.11b PCMCIA cards can be used in desktop machines.
146 +config NORTEL_HERMES
147 + tristate "Nortel emobility PCI adaptor support"
148 + depends on PCI && HERMES
149 + help
150 + Enable support for PCMCIA cards supported by the "Hermes" (aka
151 + orinoco) driver when used in Nortel emobility PCI adaptors. These
152 + adaptors are not full PCMCIA controllers, but act as a more limited
153 + PCI <-> PCMCIA bridge.
155 +config PCI_HERMES
156 + tristate "Prism 2.5 PCI 802.11b adaptor support"
157 + depends on PCI && HERMES && HERMES_PRISM
158 + help
159 + Enable support for PCI and mini-PCI 802.11b wireless NICs based on
160 + the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
161 + PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
162 + common. Some of the built-in wireless adaptors in laptops are of
163 + this variety.
165 +config PCMCIA_HERMES
166 + tristate "Hermes PCMCIA card support"
167 + depends on PCMCIA && HERMES && HAS_IOPORT_MAP
168 + help
169 + A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
170 + as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
171 + EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
172 + others). It should also be usable on various Prism II based cards
173 + such as the Linksys, D-Link and Farallon Skyline. It should also
174 + work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
176 + You will very likely need the Wireless Tools in order to
177 + configure your card and that /etc/pcmcia/wireless.opts works:
178 + <https://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
180 +config PCMCIA_SPECTRUM
181 + tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
182 + depends on PCMCIA && HERMES && HAS_IOPORT_MAP
183 + help
185 + This is a driver for 802.11b cards using RAM-loadable Symbol
186 + firmware, such as Symbol Wireless Networker LA4100, CompactFlash
187 + cards by Socket Communications and Intel PRO/Wireless 2011B.
189 + This driver requires firmware download on startup. Utilities
190 + for downloading Symbol firmware are available at
191 + <http://sourceforge.net/projects/orinoco/>
193 +config ORINOCO_USB
194 + tristate "Agere Orinoco USB support"
195 + depends on USB && HERMES
196 + select FW_LOADER
197 + help
198 + This driver is for USB versions of the Agere Orinoco card.
199 --- /dev/null
200 +++ a/drivers/net/wireless/intersil/orinoco/Makefile
201 @@ -0,0 +1,15 @@
202 +# SPDX-License-Identifier: GPL-2.0
204 +# Makefile for the orinoco wireless device drivers.
206 +orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o hermes_dld.o hermes.o cfg.o
208 +obj-$(CONFIG_HERMES) += orinoco.o
209 +obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
210 +obj-$(CONFIG_APPLE_AIRPORT) += airport.o
211 +obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
212 +obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
213 +obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
214 +obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
215 +obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
216 +obj-$(CONFIG_ORINOCO_USB) += orinoco_usb.o
217 --- /dev/null
218 +++ a/drivers/net/wireless/intersil/orinoco/airport.c
219 @@ -0,0 +1,266 @@
220 +/* airport.c
222 + * A driver for "Hermes" chipset based Apple Airport wireless
223 + * card.
225 + * Copyright notice & release notes in file main.c
227 + * Note specific to airport stub:
229 + * 0.05 : first version of the new split driver
230 + * 0.06 : fix possible hang on powerup, add sleep support
231 + */
233 +#define DRIVER_NAME "airport"
234 +#define PFX DRIVER_NAME ": "
236 +#include <linux/module.h>
237 +#include <linux/kernel.h>
238 +#include <linux/init.h>
239 +#include <linux/delay.h>
240 +#include <linux/mod_devicetable.h>
241 +#include <asm/pmac_feature.h>
243 +#include "orinoco.h"
245 +#define AIRPORT_IO_LEN (0x1000) /* one page */
247 +struct airport {
248 + struct macio_dev *mdev;
249 + void __iomem *vaddr;
250 + unsigned int irq;
251 + int irq_requested;
252 + int ndev_registered;
255 +static int
256 +airport_suspend(struct macio_dev *mdev, pm_message_t state)
258 + struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
259 + struct net_device *dev = priv->ndev;
260 + struct airport *card = priv->card;
261 + unsigned long flags;
262 + int err;
264 + printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
266 + err = orinoco_lock(priv, &flags);
267 + if (err) {
268 + printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
269 + dev->name);
270 + return 0;
273 + orinoco_down(priv);
274 + orinoco_unlock(priv, &flags);
276 + disable_irq(card->irq);
277 + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
278 + macio_get_of_node(mdev), 0, 0);
280 + return 0;
283 +static int
284 +airport_resume(struct macio_dev *mdev)
286 + struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
287 + struct net_device *dev = priv->ndev;
288 + struct airport *card = priv->card;
289 + unsigned long flags;
290 + int err;
292 + printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
294 + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
295 + macio_get_of_node(mdev), 0, 1);
296 + msleep(200);
298 + enable_irq(card->irq);
300 + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
301 + err = orinoco_up(priv);
302 + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
304 + return err;
307 +static void
308 +airport_detach(struct macio_dev *mdev)
310 + struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
311 + struct airport *card = priv->card;
313 + if (card->ndev_registered)
314 + orinoco_if_del(priv);
315 + card->ndev_registered = 0;
317 + if (card->irq_requested)
318 + free_irq(card->irq, priv);
319 + card->irq_requested = 0;
321 + if (card->vaddr)
322 + iounmap(card->vaddr);
323 + card->vaddr = NULL;
325 + macio_release_resource(mdev, 0);
327 + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
328 + macio_get_of_node(mdev), 0, 0);
329 + ssleep(1);
331 + macio_set_drvdata(mdev, NULL);
332 + free_orinocodev(priv);
335 +static int airport_hard_reset(struct orinoco_private *priv)
337 + /* It would be nice to power cycle the Airport for a real hard
338 + * reset, but for some reason although it appears to
339 + * re-initialize properly, it falls in a screaming heap
340 + * shortly afterwards. */
341 +#if 0
342 + struct airport *card = priv->card;
344 + /* Vitally important. If we don't do this it seems we get an
345 + * interrupt somewhere during the power cycle, since
346 + * hw_unavailable is already set it doesn't get ACKed, we get
347 + * into an interrupt loop and the PMU decides to turn us
348 + * off. */
349 + disable_irq(card->irq);
351 + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
352 + macio_get_of_node(card->mdev), 0, 0);
353 + ssleep(1);
354 + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
355 + macio_get_of_node(card->mdev), 0, 1);
356 + ssleep(1);
358 + enable_irq(card->irq);
359 + ssleep(1);
360 +#endif
362 + return 0;
365 +static int
366 +airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
368 + struct orinoco_private *priv;
369 + struct airport *card;
370 + unsigned long phys_addr;
371 + struct hermes *hw;
373 + if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
374 + printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
375 + return -ENODEV;
378 + /* Allocate space for private device-specific data */
379 + priv = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
380 + airport_hard_reset, NULL);
381 + if (!priv) {
382 + printk(KERN_ERR PFX "Cannot allocate network device\n");
383 + return -ENODEV;
385 + card = priv->card;
387 + hw = &priv->hw;
388 + card->mdev = mdev;
390 + if (macio_request_resource(mdev, 0, DRIVER_NAME)) {
391 + printk(KERN_ERR PFX "can't request IO resource !\n");
392 + free_orinocodev(priv);
393 + return -EBUSY;
396 + macio_set_drvdata(mdev, priv);
398 + /* Setup interrupts & base address */
399 + card->irq = macio_irq(mdev, 0);
400 + phys_addr = macio_resource_start(mdev, 0); /* Physical address */
401 + printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
402 + card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
403 + if (!card->vaddr) {
404 + printk(KERN_ERR PFX "ioremap() failed\n");
405 + goto failed;
408 + hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
410 + /* Power up card */
411 + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
412 + macio_get_of_node(mdev), 0, 1);
413 + ssleep(1);
415 + /* Reset it before we get the interrupt */
416 + hw->ops->init(hw);
418 + if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
419 + printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
420 + goto failed;
422 + card->irq_requested = 1;
424 + /* Initialise the main driver */
425 + if (orinoco_init(priv) != 0) {
426 + printk(KERN_ERR PFX "orinoco_init() failed\n");
427 + goto failed;
430 + /* Register an interface with the stack */
431 + if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
432 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
433 + goto failed;
435 + card->ndev_registered = 1;
436 + return 0;
437 + failed:
438 + airport_detach(mdev);
439 + return -ENODEV;
440 +} /* airport_attach */
443 +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
444 + " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
445 +MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
446 +MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
447 +MODULE_LICENSE("Dual MPL/GPL");
449 +static const struct of_device_id airport_match[] = {
451 + .name = "radio",
452 + },
453 + {},
456 +MODULE_DEVICE_TABLE(of, airport_match);
458 +static struct macio_driver airport_driver = {
459 + .driver = {
460 + .name = DRIVER_NAME,
461 + .owner = THIS_MODULE,
462 + .of_match_table = airport_match,
463 + },
464 + .probe = airport_attach,
465 + .remove = airport_detach,
466 + .suspend = airport_suspend,
467 + .resume = airport_resume,
470 +static int __init
471 +init_airport(void)
473 + printk(KERN_DEBUG "%s\n", version);
475 + return macio_register_driver(&airport_driver);
478 +static void __exit
479 +exit_airport(void)
481 + macio_unregister_driver(&airport_driver);
484 +module_init(init_airport);
485 +module_exit(exit_airport);
486 --- /dev/null
487 +++ a/drivers/net/wireless/intersil/orinoco/cfg.c
488 @@ -0,0 +1,291 @@
489 +/* cfg80211 support
491 + * See copyright notice in main.c
492 + */
493 +#include <linux/ieee80211.h>
494 +#include <net/cfg80211.h>
495 +#include "hw.h"
496 +#include "main.h"
497 +#include "orinoco.h"
499 +#include "cfg.h"
501 +/* Supported bitrates. Must agree with hw.c */
502 +static struct ieee80211_rate orinoco_rates[] = {
503 + { .bitrate = 10 },
504 + { .bitrate = 20 },
505 + { .bitrate = 55 },
506 + { .bitrate = 110 },
509 +static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
511 +/* Called after orinoco_private is allocated. */
512 +void orinoco_wiphy_init(struct wiphy *wiphy)
514 + struct orinoco_private *priv = wiphy_priv(wiphy);
516 + wiphy->privid = orinoco_wiphy_privid;
518 + set_wiphy_dev(wiphy, priv->dev);
521 +/* Called after firmware is initialised */
522 +int orinoco_wiphy_register(struct wiphy *wiphy)
524 + struct orinoco_private *priv = wiphy_priv(wiphy);
525 + int i, channels = 0;
527 + if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
528 + wiphy->max_scan_ssids = 1;
529 + else
530 + wiphy->max_scan_ssids = 0;
532 + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
534 + /* TODO: should we set if we only have demo ad-hoc?
535 + * (priv->has_port3)
536 + */
537 + if (priv->has_ibss)
538 + wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
540 + if (!priv->broken_monitor || force_monitor)
541 + wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
543 + priv->band.bitrates = orinoco_rates;
544 + priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
546 + /* Only support channels allowed by the card EEPROM */
547 + for (i = 0; i < NUM_CHANNELS; i++) {
548 + if (priv->channel_mask & (1 << i)) {
549 + priv->channels[i].center_freq =
550 + ieee80211_channel_to_frequency(i + 1,
551 + NL80211_BAND_2GHZ);
552 + channels++;
555 + priv->band.channels = priv->channels;
556 + priv->band.n_channels = channels;
558 + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band;
559 + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
561 + i = 0;
562 + if (priv->has_wep) {
563 + priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
564 + i++;
566 + if (priv->has_big_wep) {
567 + priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
568 + i++;
571 + if (priv->has_wpa) {
572 + priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
573 + i++;
575 + wiphy->cipher_suites = priv->cipher_suites;
576 + wiphy->n_cipher_suites = i;
578 + wiphy->rts_threshold = priv->rts_thresh;
579 + if (!priv->has_mwo)
580 + wiphy->frag_threshold = priv->frag_thresh + 1;
581 + wiphy->retry_short = priv->short_retry_limit;
582 + wiphy->retry_long = priv->long_retry_limit;
584 + return wiphy_register(wiphy);
587 +static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
588 + enum nl80211_iftype type,
589 + struct vif_params *params)
591 + struct orinoco_private *priv = wiphy_priv(wiphy);
592 + int err = 0;
593 + unsigned long lock;
595 + if (orinoco_lock(priv, &lock) != 0)
596 + return -EBUSY;
598 + switch (type) {
599 + case NL80211_IFTYPE_ADHOC:
600 + if (!priv->has_ibss && !priv->has_port3)
601 + err = -EINVAL;
602 + break;
604 + case NL80211_IFTYPE_STATION:
605 + break;
607 + case NL80211_IFTYPE_MONITOR:
608 + if (priv->broken_monitor && !force_monitor) {
609 + wiphy_warn(wiphy,
610 + "Monitor mode support is buggy in this firmware, not enabling\n");
611 + err = -EINVAL;
613 + break;
615 + default:
616 + err = -EINVAL;
619 + if (!err) {
620 + priv->iw_mode = type;
621 + set_port_type(priv);
622 + err = orinoco_commit(priv);
625 + orinoco_unlock(priv, &lock);
627 + return err;
630 +static int orinoco_scan(struct wiphy *wiphy,
631 + struct cfg80211_scan_request *request)
633 + struct orinoco_private *priv = wiphy_priv(wiphy);
634 + int err;
636 + if (!request)
637 + return -EINVAL;
639 + if (priv->scan_request && priv->scan_request != request)
640 + return -EBUSY;
642 + priv->scan_request = request;
644 + err = orinoco_hw_trigger_scan(priv, request->ssids);
645 + /* On error the we aren't processing the request */
646 + if (err)
647 + priv->scan_request = NULL;
649 + return err;
652 +static int orinoco_set_monitor_channel(struct wiphy *wiphy, struct net_device *,
653 + struct cfg80211_chan_def *chandef)
655 + struct orinoco_private *priv = wiphy_priv(wiphy);
656 + int err = 0;
657 + unsigned long flags;
658 + int channel;
660 + if (!chandef->chan)
661 + return -EINVAL;
663 + if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
664 + return -EINVAL;
666 + if (chandef->chan->band != NL80211_BAND_2GHZ)
667 + return -EINVAL;
669 + channel = ieee80211_frequency_to_channel(chandef->chan->center_freq);
671 + if ((channel < 1) || (channel > NUM_CHANNELS) ||
672 + !(priv->channel_mask & (1 << (channel - 1))))
673 + return -EINVAL;
675 + if (orinoco_lock(priv, &flags) != 0)
676 + return -EBUSY;
678 + priv->channel = channel;
679 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
680 + /* Fast channel change - no commit if successful */
681 + struct hermes *hw = &priv->hw;
682 + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
683 + HERMES_TEST_SET_CHANNEL,
684 + channel, NULL);
686 + orinoco_unlock(priv, &flags);
688 + return err;
691 +static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
693 + struct orinoco_private *priv = wiphy_priv(wiphy);
694 + int frag_value = -1;
695 + int rts_value = -1;
696 + int err = 0;
698 + if (changed & WIPHY_PARAM_RETRY_SHORT) {
699 + /* Setting short retry not supported */
700 + err = -EINVAL;
703 + if (changed & WIPHY_PARAM_RETRY_LONG) {
704 + /* Setting long retry not supported */
705 + err = -EINVAL;
708 + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
709 + /* Set fragmentation */
710 + if (priv->has_mwo) {
711 + if (wiphy->frag_threshold == -1)
712 + frag_value = 0;
713 + else {
714 + printk(KERN_WARNING "%s: Fixed fragmentation "
715 + "is not supported on this firmware. "
716 + "Using MWO robust instead.\n",
717 + priv->ndev->name);
718 + frag_value = 1;
720 + } else {
721 + if (wiphy->frag_threshold == -1)
722 + frag_value = 2346;
723 + else if ((wiphy->frag_threshold < 257) ||
724 + (wiphy->frag_threshold > 2347))
725 + err = -EINVAL;
726 + else
727 + /* cfg80211 value is 257-2347 (odd only)
728 + * orinoco rid has range 256-2346 (even only) */
729 + frag_value = wiphy->frag_threshold & ~0x1;
733 + if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
734 + /* Set RTS.
736 + * Prism documentation suggests default of 2432,
737 + * and a range of 0-3000.
739 + * Current implementation uses 2347 as the default and
740 + * the upper limit.
741 + */
743 + if (wiphy->rts_threshold == -1)
744 + rts_value = 2347;
745 + else if (wiphy->rts_threshold > 2347)
746 + err = -EINVAL;
747 + else
748 + rts_value = wiphy->rts_threshold;
751 + if (!err) {
752 + unsigned long flags;
754 + if (orinoco_lock(priv, &flags) != 0)
755 + return -EBUSY;
757 + if (frag_value >= 0) {
758 + if (priv->has_mwo)
759 + priv->mwo_robust = frag_value;
760 + else
761 + priv->frag_thresh = frag_value;
763 + if (rts_value >= 0)
764 + priv->rts_thresh = rts_value;
766 + err = orinoco_commit(priv);
768 + orinoco_unlock(priv, &flags);
771 + return err;
774 +const struct cfg80211_ops orinoco_cfg_ops = {
775 + .change_virtual_intf = orinoco_change_vif,
776 + .set_monitor_channel = orinoco_set_monitor_channel,
777 + .scan = orinoco_scan,
778 + .set_wiphy_params = orinoco_set_wiphy_params,
780 --- /dev/null
781 +++ a/drivers/net/wireless/intersil/orinoco/cfg.h
782 @@ -0,0 +1,15 @@
783 +/* cfg80211 support.
785 + * See copyright notice in main.c
786 + */
787 +#ifndef ORINOCO_CFG_H
788 +#define ORINOCO_CFG_H
790 +#include <net/cfg80211.h>
792 +extern const struct cfg80211_ops orinoco_cfg_ops;
794 +void orinoco_wiphy_init(struct wiphy *wiphy);
795 +int orinoco_wiphy_register(struct wiphy *wiphy);
797 +#endif /* ORINOCO_CFG_H */
798 --- /dev/null
799 +++ a/drivers/net/wireless/intersil/orinoco/fw.c
800 @@ -0,0 +1,387 @@
801 +/* Firmware file reading and download helpers
803 + * See copyright notice in main.c
804 + */
805 +#include <linux/kernel.h>
806 +#include <linux/slab.h>
807 +#include <linux/firmware.h>
808 +#include <linux/device.h>
809 +#include <linux/module.h>
811 +#include "hermes.h"
812 +#include "hermes_dld.h"
813 +#include "orinoco.h"
815 +#include "fw.h"
817 +/* End markers (for Symbol firmware only) */
818 +#define TEXT_END 0x1A /* End of text header */
820 +struct fw_info {
821 + char *pri_fw;
822 + char *sta_fw;
823 + char *ap_fw;
824 + u32 pda_addr;
825 + u16 pda_size;
828 +static const struct fw_info orinoco_fw[] = {
829 + { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
830 + { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
831 + { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
833 +MODULE_FIRMWARE("agere_sta_fw.bin");
834 +MODULE_FIRMWARE("agere_ap_fw.bin");
835 +MODULE_FIRMWARE("prism_sta_fw.bin");
836 +MODULE_FIRMWARE("prism_ap_fw.bin");
837 +MODULE_FIRMWARE("symbol_sp24t_prim_fw");
838 +MODULE_FIRMWARE("symbol_sp24t_sec_fw");
840 +/* Structure used to access fields in FW
841 + * Make sure LE decoding macros are used
842 + */
843 +struct orinoco_fw_header {
844 + char hdr_vers[6]; /* ASCII string for header version */
845 + __le16 headersize; /* Total length of header */
846 + __le32 entry_point; /* NIC entry point */
847 + __le32 blocks; /* Number of blocks to program */
848 + __le32 block_offset; /* Offset of block data from eof header */
849 + __le32 pdr_offset; /* Offset to PDR data from eof header */
850 + __le32 pri_offset; /* Offset to primary plug data */
851 + __le32 compat_offset; /* Offset to compatibility data*/
852 + char signature[]; /* FW signature length headersize-20 */
853 +} __packed;
855 +/* Check the range of various header entries. Return a pointer to a
856 + * description of the problem, or NULL if everything checks out. */
857 +static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len)
859 + u16 hdrsize;
861 + if (len < sizeof(*hdr))
862 + return "image too small";
863 + if (memcmp(hdr->hdr_vers, "HFW", 3) != 0)
864 + return "format not recognised";
866 + hdrsize = le16_to_cpu(hdr->headersize);
867 + if (hdrsize > len)
868 + return "bad headersize";
869 + if ((hdrsize + le32_to_cpu(hdr->block_offset)) > len)
870 + return "bad block offset";
871 + if ((hdrsize + le32_to_cpu(hdr->pdr_offset)) > len)
872 + return "bad PDR offset";
873 + if ((hdrsize + le32_to_cpu(hdr->pri_offset)) > len)
874 + return "bad PRI offset";
875 + if ((hdrsize + le32_to_cpu(hdr->compat_offset)) > len)
876 + return "bad compat offset";
878 + /* TODO: consider adding a checksum or CRC to the firmware format */
879 + return NULL;
882 +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
883 +static inline const struct firmware *
884 +orinoco_cached_fw_get(struct orinoco_private *priv, bool primary)
886 + if (primary)
887 + return priv->cached_pri_fw;
888 + else
889 + return priv->cached_fw;
891 +#else
892 +#define orinoco_cached_fw_get(priv, primary) (NULL)
893 +#endif
895 +/* Download either STA or AP firmware into the card. */
896 +static int
897 +orinoco_dl_firmware(struct orinoco_private *priv,
898 + const struct fw_info *fw,
899 + int ap)
901 + /* Plug Data Area (PDA) */
902 + __le16 *pda;
904 + struct hermes *hw = &priv->hw;
905 + const struct firmware *fw_entry;
906 + const struct orinoco_fw_header *hdr;
907 + const unsigned char *first_block;
908 + const void *end;
909 + const char *firmware;
910 + const char *fw_err;
911 + struct device *dev = priv->dev;
912 + int err = 0;
914 + pda = kzalloc(fw->pda_size, GFP_KERNEL);
915 + if (!pda)
916 + return -ENOMEM;
918 + if (ap)
919 + firmware = fw->ap_fw;
920 + else
921 + firmware = fw->sta_fw;
923 + dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
925 + /* Read current plug data */
926 + err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
927 + dev_dbg(dev, "Read PDA returned %d\n", err);
928 + if (err)
929 + goto free;
931 + if (!orinoco_cached_fw_get(priv, false)) {
932 + err = request_firmware(&fw_entry, firmware, priv->dev);
934 + if (err) {
935 + dev_err(dev, "Cannot find firmware %s\n", firmware);
936 + err = -ENOENT;
937 + goto free;
939 + } else
940 + fw_entry = orinoco_cached_fw_get(priv, false);
942 + hdr = (const struct orinoco_fw_header *) fw_entry->data;
944 + fw_err = validate_fw(hdr, fw_entry->size);
945 + if (fw_err) {
946 + dev_warn(dev, "Invalid firmware image detected (%s). "
947 + "Aborting download\n", fw_err);
948 + err = -EINVAL;
949 + goto abort;
952 + /* Enable aux port to allow programming */
953 + err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));
954 + dev_dbg(dev, "Program init returned %d\n", err);
955 + if (err != 0)
956 + goto abort;
958 + /* Program data */
959 + first_block = (fw_entry->data +
960 + le16_to_cpu(hdr->headersize) +
961 + le32_to_cpu(hdr->block_offset));
962 + end = fw_entry->data + fw_entry->size;
964 + err = hermes_program(hw, first_block, end);
965 + dev_dbg(dev, "Program returned %d\n", err);
966 + if (err != 0)
967 + goto abort;
969 + /* Update production data */
970 + first_block = (fw_entry->data +
971 + le16_to_cpu(hdr->headersize) +
972 + le32_to_cpu(hdr->pdr_offset));
974 + err = hermes_apply_pda_with_defaults(hw, first_block, end, pda,
975 + &pda[fw->pda_size / sizeof(*pda)]);
976 + dev_dbg(dev, "Apply PDA returned %d\n", err);
977 + if (err)
978 + goto abort;
980 + /* Tell card we've finished */
981 + err = hw->ops->program_end(hw);
982 + dev_dbg(dev, "Program end returned %d\n", err);
983 + if (err != 0)
984 + goto abort;
986 + /* Check if we're running */
987 + dev_dbg(dev, "hermes_present returned %d\n", hermes_present(hw));
989 +abort:
990 + /* If we requested the firmware, release it. */
991 + if (!orinoco_cached_fw_get(priv, false))
992 + release_firmware(fw_entry);
994 +free:
995 + kfree(pda);
996 + return err;
1000 + * Process a firmware image - stop the card, load the firmware, reset
1001 + * the card and make sure it responds. For the secondary firmware take
1002 + * care of the PDA - read it and then write it on top of the firmware.
1003 + */
1004 +static int
1005 +symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
1006 + const unsigned char *image, const void *end,
1007 + int secondary)
1009 + struct hermes *hw = &priv->hw;
1010 + int ret = 0;
1011 + const unsigned char *ptr;
1012 + const unsigned char *first_block;
1014 + /* Plug Data Area (PDA) */
1015 + __le16 *pda = NULL;
1017 + /* Binary block begins after the 0x1A marker */
1018 + ptr = image;
1019 + while (*ptr++ != TEXT_END);
1020 + first_block = ptr;
1022 + /* Read the PDA from EEPROM */
1023 + if (secondary) {
1024 + pda = kzalloc(fw->pda_size, GFP_KERNEL);
1025 + if (!pda)
1026 + return -ENOMEM;
1028 + ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
1029 + if (ret)
1030 + goto free;
1033 + /* Stop the firmware, so that it can be safely rewritten */
1034 + if (priv->stop_fw) {
1035 + ret = priv->stop_fw(priv, 1);
1036 + if (ret)
1037 + goto free;
1040 + /* Program the adapter with new firmware */
1041 + ret = hermes_program(hw, first_block, end);
1042 + if (ret)
1043 + goto free;
1045 + /* Write the PDA to the adapter */
1046 + if (secondary) {
1047 + size_t len = hermes_blocks_length(first_block, end);
1048 + ptr = first_block + len;
1049 + ret = hermes_apply_pda(hw, ptr, end, pda,
1050 + &pda[fw->pda_size / sizeof(*pda)]);
1051 + kfree(pda);
1052 + if (ret)
1053 + return ret;
1056 + /* Run the firmware */
1057 + if (priv->stop_fw) {
1058 + ret = priv->stop_fw(priv, 0);
1059 + if (ret)
1060 + return ret;
1063 + /* Reset hermes chip and make sure it responds */
1064 + ret = hw->ops->init(hw);
1066 + /* hermes_reset() should return 0 with the secondary firmware */
1067 + if (secondary && ret != 0)
1068 + return -ENODEV;
1070 + /* And this should work with any firmware */
1071 + if (!hermes_present(hw))
1072 + return -ENODEV;
1074 + return 0;
1076 +free:
1077 + kfree(pda);
1078 + return ret;
1083 + * Download the firmware into the card, this also does a PCMCIA soft
1084 + * reset on the card, to make sure it's in a sane state.
1085 + */
1086 +static int
1087 +symbol_dl_firmware(struct orinoco_private *priv,
1088 + const struct fw_info *fw)
1090 + struct device *dev = priv->dev;
1091 + int ret;
1092 + const struct firmware *fw_entry;
1094 + if (!orinoco_cached_fw_get(priv, true)) {
1095 + if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) {
1096 + dev_err(dev, "Cannot find firmware: %s\n", fw->pri_fw);
1097 + return -ENOENT;
1099 + } else
1100 + fw_entry = orinoco_cached_fw_get(priv, true);
1102 + /* Load primary firmware */
1103 + ret = symbol_dl_image(priv, fw, fw_entry->data,
1104 + fw_entry->data + fw_entry->size, 0);
1106 + if (!orinoco_cached_fw_get(priv, true))
1107 + release_firmware(fw_entry);
1108 + if (ret) {
1109 + dev_err(dev, "Primary firmware download failed\n");
1110 + return ret;
1113 + if (!orinoco_cached_fw_get(priv, false)) {
1114 + if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) {
1115 + dev_err(dev, "Cannot find firmware: %s\n", fw->sta_fw);
1116 + return -ENOENT;
1118 + } else
1119 + fw_entry = orinoco_cached_fw_get(priv, false);
1121 + /* Load secondary firmware */
1122 + ret = symbol_dl_image(priv, fw, fw_entry->data,
1123 + fw_entry->data + fw_entry->size, 1);
1124 + if (!orinoco_cached_fw_get(priv, false))
1125 + release_firmware(fw_entry);
1126 + if (ret)
1127 + dev_err(dev, "Secondary firmware download failed\n");
1129 + return ret;
1132 +int orinoco_download(struct orinoco_private *priv)
1134 + int err = 0;
1135 + /* Reload firmware */
1136 + switch (priv->firmware_type) {
1137 + case FIRMWARE_TYPE_AGERE:
1138 + /* case FIRMWARE_TYPE_INTERSIL: */
1139 + err = orinoco_dl_firmware(priv,
1140 + &orinoco_fw[priv->firmware_type], 0);
1141 + break;
1143 + case FIRMWARE_TYPE_SYMBOL:
1144 + err = symbol_dl_firmware(priv,
1145 + &orinoco_fw[priv->firmware_type]);
1146 + break;
1147 + case FIRMWARE_TYPE_INTERSIL:
1148 + break;
1150 + /* TODO: if we fail we probably need to reinitialise
1151 + * the driver */
1153 + return err;
1156 +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
1157 +void orinoco_cache_fw(struct orinoco_private *priv, int ap)
1159 + const struct firmware *fw_entry = NULL;
1160 + const char *pri_fw;
1161 + const char *fw;
1163 + pri_fw = orinoco_fw[priv->firmware_type].pri_fw;
1164 + if (ap)
1165 + fw = orinoco_fw[priv->firmware_type].ap_fw;
1166 + else
1167 + fw = orinoco_fw[priv->firmware_type].sta_fw;
1169 + if (pri_fw) {
1170 + if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0)
1171 + priv->cached_pri_fw = fw_entry;
1174 + if (fw) {
1175 + if (request_firmware(&fw_entry, fw, priv->dev) == 0)
1176 + priv->cached_fw = fw_entry;
1180 +void orinoco_uncache_fw(struct orinoco_private *priv)
1182 + release_firmware(priv->cached_pri_fw);
1183 + release_firmware(priv->cached_fw);
1184 + priv->cached_pri_fw = NULL;
1185 + priv->cached_fw = NULL;
1187 +#endif
1188 --- /dev/null
1189 +++ a/drivers/net/wireless/intersil/orinoco/fw.h
1190 @@ -0,0 +1,21 @@
1191 +/* Firmware file reading and download helpers
1193 + * See copyright notice in main.c
1194 + */
1195 +#ifndef _ORINOCO_FW_H_
1196 +#define _ORINOCO_FW_H_
1198 +/* Forward declations */
1199 +struct orinoco_private;
1201 +int orinoco_download(struct orinoco_private *priv);
1203 +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
1204 +void orinoco_cache_fw(struct orinoco_private *priv, int ap);
1205 +void orinoco_uncache_fw(struct orinoco_private *priv);
1206 +#else
1207 +#define orinoco_cache_fw(priv, ap) do { } while (0)
1208 +#define orinoco_uncache_fw(priv) do { } while (0)
1209 +#endif
1211 +#endif /* _ORINOCO_FW_H_ */
1212 --- /dev/null
1213 +++ a/drivers/net/wireless/intersil/orinoco/hermes.c
1214 @@ -0,0 +1,778 @@
1215 +/* hermes.c
1217 + * Driver core for the "Hermes" wireless MAC controller, as used in
1218 + * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
1219 + * work on the hfa3841 and hfa3842 MAC controller chips used in the
1220 + * Prism II chipsets.
1222 + * This is not a complete driver, just low-level access routines for
1223 + * the MAC controller itself.
1225 + * Based on the prism2 driver from Absolute Value Systems' linux-wlan
1226 + * project, the Linux wvlan_cs driver, Lucent's HCF-Light
1227 + * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
1228 + * particular order).
1230 + * Copyright (C) 2000, David Gibson, Linuxcare Australia.
1231 + * (C) Copyright David Gibson, IBM Corp. 2001-2003.
1233 + * The contents of this file are subject to the Mozilla Public License
1234 + * Version 1.1 (the "License"); you may not use this file except in
1235 + * compliance with the License. You may obtain a copy of the License
1236 + * at http://www.mozilla.org/MPL/
1238 + * Software distributed under the License is distributed on an "AS IS"
1239 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
1240 + * the License for the specific language governing rights and
1241 + * limitations under the License.
1243 + * Alternatively, the contents of this file may be used under the
1244 + * terms of the GNU General Public License version 2 (the "GPL"), in
1245 + * which case the provisions of the GPL are applicable instead of the
1246 + * above. If you wish to allow the use of your version of this file
1247 + * only under the terms of the GPL and not to allow others to use your
1248 + * version of this file under the MPL, indicate your decision by
1249 + * deleting the provisions above and replace them with the notice and
1250 + * other provisions required by the GPL. If you do not delete the
1251 + * provisions above, a recipient may use your version of this file
1252 + * under either the MPL or the GPL.
1253 + */
1255 +#include <linux/net.h>
1256 +#include <linux/module.h>
1257 +#include <linux/kernel.h>
1258 +#include <linux/delay.h>
1260 +#include "hermes.h"
1262 +/* These are maximum timeouts. Most often, card wil react much faster */
1263 +#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
1264 +#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
1265 +#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
1266 +#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
1269 + * AUX port access. To unlock the AUX port write the access keys to the
1270 + * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
1271 + * register. Then read it and make sure it's HERMES_AUX_ENABLED.
1272 + */
1273 +#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
1274 +#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
1275 +#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
1276 +#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
1278 +#define HERMES_AUX_PW0 0xFE01
1279 +#define HERMES_AUX_PW1 0xDC23
1280 +#define HERMES_AUX_PW2 0xBA45
1282 +/* HERMES_CMD_DOWNLD */
1283 +#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
1284 +#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
1285 +#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
1286 +#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
1289 + * Debugging helpers
1290 + */
1292 +#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
1293 + printk(stuff); } while (0)
1295 +#undef HERMES_DEBUG
1296 +#ifdef HERMES_DEBUG
1298 +#define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff)
1300 +#else /* ! HERMES_DEBUG */
1302 +#define DEBUG(lvl, stuff...) do { } while (0)
1304 +#endif /* ! HERMES_DEBUG */
1306 +static const struct hermes_ops hermes_ops_local;
1309 + * Internal functions
1310 + */
1312 +/* Issue a command to the chip. Waiting for it to complete is the caller's
1313 + problem.
1315 + Returns -EBUSY if the command register is busy, 0 on success.
1317 + Callable from any context.
1319 +static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0,
1320 + u16 param1, u16 param2)
1322 + int k = CMD_BUSY_TIMEOUT;
1323 + u16 reg;
1325 + /* First wait for the command register to unbusy */
1326 + reg = hermes_read_regn(hw, CMD);
1327 + while ((reg & HERMES_CMD_BUSY) && k) {
1328 + k--;
1329 + udelay(1);
1330 + reg = hermes_read_regn(hw, CMD);
1332 + if (reg & HERMES_CMD_BUSY)
1333 + return -EBUSY;
1335 + hermes_write_regn(hw, PARAM2, param2);
1336 + hermes_write_regn(hw, PARAM1, param1);
1337 + hermes_write_regn(hw, PARAM0, param0);
1338 + hermes_write_regn(hw, CMD, cmd);
1340 + return 0;
1344 + * Function definitions
1345 + */
1347 +/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
1348 +static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
1349 + u16 parm0, u16 parm1, u16 parm2,
1350 + struct hermes_response *resp)
1352 + int err = 0;
1353 + int k;
1354 + u16 status, reg;
1356 + err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
1357 + if (err)
1358 + return err;
1360 + reg = hermes_read_regn(hw, EVSTAT);
1361 + k = CMD_INIT_TIMEOUT;
1362 + while ((!(reg & HERMES_EV_CMD)) && k) {
1363 + k--;
1364 + udelay(10);
1365 + reg = hermes_read_regn(hw, EVSTAT);
1368 + hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
1370 + if (!hermes_present(hw)) {
1371 + DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
1372 + hw->iobase);
1373 + err = -ENODEV;
1374 + goto out;
1377 + if (!(reg & HERMES_EV_CMD)) {
1378 + printk(KERN_ERR "hermes @ %p: "
1379 + "Timeout waiting for card to reset (reg=0x%04x)!\n",
1380 + hw->iobase, reg);
1381 + err = -ETIMEDOUT;
1382 + goto out;
1385 + status = hermes_read_regn(hw, STATUS);
1386 + if (resp) {
1387 + resp->status = status;
1388 + resp->resp0 = hermes_read_regn(hw, RESP0);
1389 + resp->resp1 = hermes_read_regn(hw, RESP1);
1390 + resp->resp2 = hermes_read_regn(hw, RESP2);
1393 + hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
1395 + if (status & HERMES_STATUS_RESULT)
1396 + err = -EIO;
1397 +out:
1398 + return err;
1401 +void hermes_struct_init(struct hermes *hw, void __iomem *address,
1402 + int reg_spacing)
1404 + hw->iobase = address;
1405 + hw->reg_spacing = reg_spacing;
1406 + hw->inten = 0x0;
1407 + hw->eeprom_pda = false;
1408 + hw->ops = &hermes_ops_local;
1410 +EXPORT_SYMBOL(hermes_struct_init);
1412 +static int hermes_init(struct hermes *hw)
1414 + u16 reg;
1415 + int err = 0;
1416 + int k;
1418 + /* We don't want to be interrupted while resetting the chipset */
1419 + hw->inten = 0x0;
1420 + hermes_write_regn(hw, INTEN, 0);
1421 + hermes_write_regn(hw, EVACK, 0xffff);
1423 + /* Normally it's a "can't happen" for the command register to
1424 + be busy when we go to issue a command because we are
1425 + serializing all commands. However we want to have some
1426 + chance of resetting the card even if it gets into a stupid
1427 + state, so we actually wait to see if the command register
1428 + will unbusy itself here. */
1429 + k = CMD_BUSY_TIMEOUT;
1430 + reg = hermes_read_regn(hw, CMD);
1431 + while (k && (reg & HERMES_CMD_BUSY)) {
1432 + if (reg == 0xffff) /* Special case - the card has probably been
1433 + removed, so don't wait for the timeout */
1434 + return -ENODEV;
1436 + k--;
1437 + udelay(1);
1438 + reg = hermes_read_regn(hw, CMD);
1441 + /* No need to explicitly handle the timeout - if we've timed
1442 + out hermes_issue_cmd() will probably return -EBUSY below */
1444 + /* According to the documentation, EVSTAT may contain
1445 + obsolete event occurrence information. We have to acknowledge
1446 + it by writing EVACK. */
1447 + reg = hermes_read_regn(hw, EVSTAT);
1448 + hermes_write_regn(hw, EVACK, reg);
1450 + /* We don't use hermes_docmd_wait here, because the reset wipes
1451 + the magic constant in SWSUPPORT0 away, and it gets confused */
1452 + err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL);
1454 + return err;
1457 +/* Issue a command to the chip, and (busy!) wait for it to
1458 + * complete.
1460 + * Returns:
1461 + * < 0 on internal error
1462 + * 0 on success
1463 + * > 0 on error returned by the firmware
1465 + * Callable from any context, but locking is your problem. */
1466 +static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
1467 + struct hermes_response *resp)
1469 + int err;
1470 + int k;
1471 + u16 reg;
1472 + u16 status;
1474 + err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
1475 + if (err) {
1476 + if (!hermes_present(hw)) {
1477 + if (net_ratelimit())
1478 + printk(KERN_WARNING "hermes @ %p: "
1479 + "Card removed while issuing command "
1480 + "0x%04x.\n", hw->iobase, cmd);
1481 + err = -ENODEV;
1482 + } else
1483 + if (net_ratelimit())
1484 + printk(KERN_ERR "hermes @ %p: "
1485 + "Error %d issuing command 0x%04x.\n",
1486 + hw->iobase, err, cmd);
1487 + goto out;
1490 + reg = hermes_read_regn(hw, EVSTAT);
1491 + k = CMD_COMPL_TIMEOUT;
1492 + while ((!(reg & HERMES_EV_CMD)) && k) {
1493 + k--;
1494 + udelay(10);
1495 + reg = hermes_read_regn(hw, EVSTAT);
1498 + if (!hermes_present(hw)) {
1499 + printk(KERN_WARNING "hermes @ %p: Card removed "
1500 + "while waiting for command 0x%04x completion.\n",
1501 + hw->iobase, cmd);
1502 + err = -ENODEV;
1503 + goto out;
1506 + if (!(reg & HERMES_EV_CMD)) {
1507 + printk(KERN_ERR "hermes @ %p: Timeout waiting for "
1508 + "command 0x%04x completion.\n", hw->iobase, cmd);
1509 + err = -ETIMEDOUT;
1510 + goto out;
1513 + status = hermes_read_regn(hw, STATUS);
1514 + if (resp) {
1515 + resp->status = status;
1516 + resp->resp0 = hermes_read_regn(hw, RESP0);
1517 + resp->resp1 = hermes_read_regn(hw, RESP1);
1518 + resp->resp2 = hermes_read_regn(hw, RESP2);
1521 + hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
1523 + if (status & HERMES_STATUS_RESULT)
1524 + err = -EIO;
1526 + out:
1527 + return err;
1530 +static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid)
1532 + int err = 0;
1533 + int k;
1534 + u16 reg;
1536 + if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX))
1537 + return -EINVAL;
1539 + err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL);
1540 + if (err)
1541 + return err;
1543 + reg = hermes_read_regn(hw, EVSTAT);
1544 + k = ALLOC_COMPL_TIMEOUT;
1545 + while ((!(reg & HERMES_EV_ALLOC)) && k) {
1546 + k--;
1547 + udelay(10);
1548 + reg = hermes_read_regn(hw, EVSTAT);
1551 + if (!hermes_present(hw)) {
1552 + printk(KERN_WARNING "hermes @ %p: "
1553 + "Card removed waiting for frame allocation.\n",
1554 + hw->iobase);
1555 + return -ENODEV;
1558 + if (!(reg & HERMES_EV_ALLOC)) {
1559 + printk(KERN_ERR "hermes @ %p: "
1560 + "Timeout waiting for frame allocation\n",
1561 + hw->iobase);
1562 + return -ETIMEDOUT;
1565 + *fid = hermes_read_regn(hw, ALLOCFID);
1566 + hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
1568 + return 0;
1571 +/* Set up a BAP to read a particular chunk of data from card's internal buffer.
1573 + * Returns:
1574 + * < 0 on internal failure (errno)
1575 + * 0 on success
1576 + * > 0 on error
1577 + * from firmware
1579 + * Callable from any context */
1580 +static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
1582 + int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
1583 + int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
1584 + int k;
1585 + u16 reg;
1587 + /* Paranoia.. */
1588 + if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2))
1589 + return -EINVAL;
1591 + k = HERMES_BAP_BUSY_TIMEOUT;
1592 + reg = hermes_read_reg(hw, oreg);
1593 + while ((reg & HERMES_OFFSET_BUSY) && k) {
1594 + k--;
1595 + udelay(1);
1596 + reg = hermes_read_reg(hw, oreg);
1599 + if (reg & HERMES_OFFSET_BUSY)
1600 + return -ETIMEDOUT;
1602 + /* Now we actually set up the transfer */
1603 + hermes_write_reg(hw, sreg, id);
1604 + hermes_write_reg(hw, oreg, offset);
1606 + /* Wait for the BAP to be ready */
1607 + k = HERMES_BAP_BUSY_TIMEOUT;
1608 + reg = hermes_read_reg(hw, oreg);
1609 + while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
1610 + k--;
1611 + udelay(1);
1612 + reg = hermes_read_reg(hw, oreg);
1615 + if (reg != offset) {
1616 + printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
1617 + "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
1618 + (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
1619 + reg, id, offset);
1621 + if (reg & HERMES_OFFSET_BUSY)
1622 + return -ETIMEDOUT;
1624 + return -EIO; /* error or wrong offset */
1627 + return 0;
1630 +/* Read a block of data from the chip's buffer, via the
1631 + * BAP. Synchronization/serialization is the caller's problem. len
1632 + * must be even.
1634 + * Returns:
1635 + * < 0 on internal failure (errno)
1636 + * 0 on success
1637 + * > 0 on error from firmware
1638 + */
1639 +static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len,
1640 + u16 id, u16 offset)
1642 + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
1643 + int err = 0;
1645 + if ((len < 0) || (len % 2))
1646 + return -EINVAL;
1648 + err = hermes_bap_seek(hw, bap, id, offset);
1649 + if (err)
1650 + goto out;
1652 + /* Actually do the transfer */
1653 + hermes_read_words(hw, dreg, buf, len / 2);
1655 + out:
1656 + return err;
1659 +/* Write a block of data to the chip's buffer, via the
1660 + * BAP. Synchronization/serialization is the caller's problem.
1662 + * Returns:
1663 + * < 0 on internal failure (errno)
1664 + * 0 on success
1665 + * > 0 on error from firmware
1666 + */
1667 +static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf,
1668 + int len, u16 id, u16 offset)
1670 + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
1671 + int err = 0;
1673 + if (len < 0)
1674 + return -EINVAL;
1676 + err = hermes_bap_seek(hw, bap, id, offset);
1677 + if (err)
1678 + goto out;
1680 + /* Actually do the transfer */
1681 + hermes_write_bytes(hw, dreg, buf, len);
1683 + out:
1684 + return err;
1687 +/* Read a Length-Type-Value record from the card.
1689 + * If length is NULL, we ignore the length read from the card, and
1690 + * read the entire buffer regardless. This is useful because some of
1691 + * the configuration records appear to have incorrect lengths in
1692 + * practice.
1694 + * Callable from user or bh context. */
1695 +static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid,
1696 + unsigned bufsize, u16 *length, void *buf)
1698 + int err = 0;
1699 + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
1700 + u16 rlength, rtype;
1701 + unsigned nwords;
1703 + if (bufsize % 2)
1704 + return -EINVAL;
1706 + err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
1707 + if (err)
1708 + return err;
1710 + err = hermes_bap_seek(hw, bap, rid, 0);
1711 + if (err)
1712 + return err;
1714 + rlength = hermes_read_reg(hw, dreg);
1716 + if (!rlength)
1717 + return -ENODATA;
1719 + rtype = hermes_read_reg(hw, dreg);
1721 + if (length)
1722 + *length = rlength;
1724 + if (rtype != rid)
1725 + printk(KERN_WARNING "hermes @ %p: %s(): "
1726 + "rid (0x%04x) does not match type (0x%04x)\n",
1727 + hw->iobase, __func__, rid, rtype);
1728 + if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
1729 + printk(KERN_WARNING "hermes @ %p: "
1730 + "Truncating LTV record from %d to %d bytes. "
1731 + "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
1732 + HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
1734 + nwords = min((unsigned)rlength - 1, bufsize / 2);
1735 + hermes_read_words(hw, dreg, buf, nwords);
1737 + return 0;
1740 +static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid,
1741 + u16 length, const void *value)
1743 + int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
1744 + int err = 0;
1745 + unsigned count;
1747 + if (length == 0)
1748 + return -EINVAL;
1750 + err = hermes_bap_seek(hw, bap, rid, 0);
1751 + if (err)
1752 + return err;
1754 + hermes_write_reg(hw, dreg, length);
1755 + hermes_write_reg(hw, dreg, rid);
1757 + count = length - 1;
1759 + hermes_write_bytes(hw, dreg, value, count << 1);
1761 + err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
1762 + rid, NULL);
1764 + return err;
1767 +/*** Hermes AUX control ***/
1769 +static inline void
1770 +hermes_aux_setaddr(struct hermes *hw, u32 addr)
1772 + hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
1773 + hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
1776 +static inline int
1777 +hermes_aux_control(struct hermes *hw, int enabled)
1779 + int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
1780 + int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
1781 + int i;
1783 + /* Already open? */
1784 + if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
1785 + return 0;
1787 + hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
1788 + hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
1789 + hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
1790 + hermes_write_reg(hw, HERMES_CONTROL, action);
1792 + for (i = 0; i < 20; i++) {
1793 + udelay(10);
1794 + if (hermes_read_reg(hw, HERMES_CONTROL) ==
1795 + desired_state)
1796 + return 0;
1799 + return -EBUSY;
1802 +/*** Hermes programming ***/
1804 +/* About to start programming data (Hermes I)
1805 + * offset is the entry point
1807 + * Spectrum_cs' Symbol fw does not require this
1808 + * wl_lkm Agere fw does
1809 + * Don't know about intersil
1810 + */
1811 +static int hermesi_program_init(struct hermes *hw, u32 offset)
1813 + int err;
1815 + /* Disable interrupts?*/
1816 + /*hw->inten = 0x0;*/
1817 + /*hermes_write_regn(hw, INTEN, 0);*/
1818 + /*hermes_set_irqmask(hw, 0);*/
1820 + /* Acknowledge any outstanding command */
1821 + hermes_write_regn(hw, EVACK, 0xFFFF);
1823 + /* Using init_cmd_wait rather than cmd_wait */
1824 + err = hw->ops->init_cmd_wait(hw,
1825 + 0x0100 | HERMES_CMD_INIT,
1826 + 0, 0, 0, NULL);
1827 + if (err)
1828 + return err;
1830 + err = hw->ops->init_cmd_wait(hw,
1831 + 0x0000 | HERMES_CMD_INIT,
1832 + 0, 0, 0, NULL);
1833 + if (err)
1834 + return err;
1836 + err = hermes_aux_control(hw, 1);
1837 + pr_debug("AUX enable returned %d\n", err);
1839 + if (err)
1840 + return err;
1842 + pr_debug("Enabling volatile, EP 0x%08x\n", offset);
1843 + err = hw->ops->init_cmd_wait(hw,
1844 + HERMES_PROGRAM_ENABLE_VOLATILE,
1845 + offset & 0xFFFFu,
1846 + offset >> 16,
1847 + 0,
1848 + NULL);
1849 + pr_debug("PROGRAM_ENABLE returned %d\n", err);
1851 + return err;
1854 +/* Done programming data (Hermes I)
1856 + * Spectrum_cs' Symbol fw does not require this
1857 + * wl_lkm Agere fw does
1858 + * Don't know about intersil
1859 + */
1860 +static int hermesi_program_end(struct hermes *hw)
1862 + struct hermes_response resp;
1863 + int rc = 0;
1864 + int err;
1866 + rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
1868 + pr_debug("PROGRAM_DISABLE returned %d, "
1869 + "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
1870 + rc, resp.resp0, resp.resp1, resp.resp2);
1872 + if ((rc == 0) &&
1873 + ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
1874 + rc = -EIO;
1876 + err = hermes_aux_control(hw, 0);
1877 + pr_debug("AUX disable returned %d\n", err);
1879 + /* Acknowledge any outstanding command */
1880 + hermes_write_regn(hw, EVACK, 0xFFFF);
1882 + /* Reinitialise, ignoring return */
1883 + (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
1884 + 0, 0, 0, NULL);
1886 + return rc ? rc : err;
1889 +static int hermes_program_bytes(struct hermes *hw, const char *data,
1890 + u32 addr, u32 len)
1892 + /* wl lkm splits the programming into chunks of 2000 bytes.
1893 + * This restriction appears to come from USB. The PCMCIA
1894 + * adapters can program the whole lot in one go */
1895 + hermes_aux_setaddr(hw, addr);
1896 + hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
1897 + return 0;
1900 +/* Read PDA from the adapter */
1901 +static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr,
1902 + u16 pda_len)
1904 + int ret;
1905 + u16 pda_size;
1906 + u16 data_len = pda_len;
1907 + __le16 *data = pda;
1909 + if (hw->eeprom_pda) {
1910 + /* PDA of spectrum symbol is in eeprom */
1912 + /* Issue command to read EEPROM */
1913 + ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
1914 + if (ret)
1915 + return ret;
1916 + } else {
1917 + /* wl_lkm does not include PDA size in the PDA area.
1918 + * We will pad the information into pda, so other routines
1919 + * don't have to be modified */
1920 + pda[0] = cpu_to_le16(pda_len - 2);
1921 + /* Includes CFG_PROD_DATA but not itself */
1922 + pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
1923 + data_len = pda_len - 4;
1924 + data = pda + 2;
1927 + /* Open auxiliary port */
1928 + ret = hermes_aux_control(hw, 1);
1929 + pr_debug("AUX enable returned %d\n", ret);
1930 + if (ret)
1931 + return ret;
1933 + /* Read PDA */
1934 + hermes_aux_setaddr(hw, pda_addr);
1935 + hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
1937 + /* Close aux port */
1938 + ret = hermes_aux_control(hw, 0);
1939 + pr_debug("AUX disable returned %d\n", ret);
1941 + /* Check PDA length */
1942 + pda_size = le16_to_cpu(pda[0]);
1943 + pr_debug("Actual PDA length %d, Max allowed %d\n",
1944 + pda_size, pda_len);
1945 + if (pda_size > pda_len)
1946 + return -EINVAL;
1948 + return 0;
1951 +static void hermes_lock_irqsave(spinlock_t *lock,
1952 + unsigned long *flags) __acquires(lock)
1954 + spin_lock_irqsave(lock, *flags);
1957 +static void hermes_unlock_irqrestore(spinlock_t *lock,
1958 + unsigned long *flags) __releases(lock)
1960 + spin_unlock_irqrestore(lock, *flags);
1963 +static void hermes_lock_irq(spinlock_t *lock) __acquires(lock)
1965 + spin_lock_irq(lock);
1968 +static void hermes_unlock_irq(spinlock_t *lock) __releases(lock)
1970 + spin_unlock_irq(lock);
1973 +/* Hermes operations for local buses */
1974 +static const struct hermes_ops hermes_ops_local = {
1975 + .init = hermes_init,
1976 + .cmd_wait = hermes_docmd_wait,
1977 + .init_cmd_wait = hermes_doicmd_wait,
1978 + .allocate = hermes_allocate,
1979 + .read_ltv = hermes_read_ltv,
1980 + .read_ltv_pr = hermes_read_ltv,
1981 + .write_ltv = hermes_write_ltv,
1982 + .bap_pread = hermes_bap_pread,
1983 + .bap_pwrite = hermes_bap_pwrite,
1984 + .read_pda = hermes_read_pda,
1985 + .program_init = hermesi_program_init,
1986 + .program_end = hermesi_program_end,
1987 + .program = hermes_program_bytes,
1988 + .lock_irqsave = hermes_lock_irqsave,
1989 + .unlock_irqrestore = hermes_unlock_irqrestore,
1990 + .lock_irq = hermes_lock_irq,
1991 + .unlock_irq = hermes_unlock_irq,
1993 --- /dev/null
1994 +++ a/drivers/net/wireless/intersil/orinoco/hermes.h
1995 @@ -0,0 +1,534 @@
1996 +/* SPDX-License-Identifier: GPL-2.0-only */
1997 +/* hermes.h
1999 + * Driver core for the "Hermes" wireless MAC controller, as used in
2000 + * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
2001 + * work on the hfa3841 and hfa3842 MAC controller chips used in the
2002 + * Prism I & II chipsets.
2004 + * This is not a complete driver, just low-level access routines for
2005 + * the MAC controller itself.
2007 + * Based on the prism2 driver from Absolute Value Systems' linux-wlan
2008 + * project, the Linux wvlan_cs driver, Lucent's HCF-Light
2009 + * (wvlan_hcf.c) library, and the NetBSD wireless driver.
2011 + * Copyright (C) 2000, David Gibson, Linuxcare Australia.
2012 + * (C) Copyright David Gibson, IBM Corp. 2001-2003.
2014 + * Portions taken from hfa384x.h.
2015 + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
2016 + */
2018 +#ifndef _HERMES_H
2019 +#define _HERMES_H
2021 +/* Notes on locking:
2023 + * As a module of low level hardware access routines, there is no
2024 + * locking. Users of this module should ensure that they serialize
2025 + * access to the hermes structure, and to the hardware
2028 +#include <linux/if_ether.h>
2029 +#include <linux/io.h>
2032 + * Limits and constants
2033 + */
2034 +#define HERMES_ALLOC_LEN_MIN (4)
2035 +#define HERMES_ALLOC_LEN_MAX (2400)
2036 +#define HERMES_LTV_LEN_MAX (34)
2037 +#define HERMES_BAP_DATALEN_MAX (4096)
2038 +#define HERMES_BAP_OFFSET_MAX (4096)
2039 +#define HERMES_PORTID_MAX (7)
2040 +#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX + 1)
2041 +#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */
2042 +#define HERMES_PDA_RECS_MAX (200) /* a guess */
2043 +#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */
2044 +#define HERMES_SCANRESULT_MAX (35)
2045 +#define HERMES_CHINFORESULT_MAX (8)
2046 +#define HERMES_MAX_MULTICAST (16)
2047 +#define HERMES_MAGIC (0x7d1f)
2050 + * Hermes register offsets
2051 + */
2052 +#define HERMES_CMD (0x00)
2053 +#define HERMES_PARAM0 (0x02)
2054 +#define HERMES_PARAM1 (0x04)
2055 +#define HERMES_PARAM2 (0x06)
2056 +#define HERMES_STATUS (0x08)
2057 +#define HERMES_RESP0 (0x0A)
2058 +#define HERMES_RESP1 (0x0C)
2059 +#define HERMES_RESP2 (0x0E)
2060 +#define HERMES_INFOFID (0x10)
2061 +#define HERMES_RXFID (0x20)
2062 +#define HERMES_ALLOCFID (0x22)
2063 +#define HERMES_TXCOMPLFID (0x24)
2064 +#define HERMES_SELECT0 (0x18)
2065 +#define HERMES_OFFSET0 (0x1C)
2066 +#define HERMES_DATA0 (0x36)
2067 +#define HERMES_SELECT1 (0x1A)
2068 +#define HERMES_OFFSET1 (0x1E)
2069 +#define HERMES_DATA1 (0x38)
2070 +#define HERMES_EVSTAT (0x30)
2071 +#define HERMES_INTEN (0x32)
2072 +#define HERMES_EVACK (0x34)
2073 +#define HERMES_CONTROL (0x14)
2074 +#define HERMES_SWSUPPORT0 (0x28)
2075 +#define HERMES_SWSUPPORT1 (0x2A)
2076 +#define HERMES_SWSUPPORT2 (0x2C)
2077 +#define HERMES_AUXPAGE (0x3A)
2078 +#define HERMES_AUXOFFSET (0x3C)
2079 +#define HERMES_AUXDATA (0x3E)
2082 + * CMD register bitmasks
2083 + */
2084 +#define HERMES_CMD_BUSY (0x8000)
2085 +#define HERMES_CMD_AINFO (0x7f00)
2086 +#define HERMES_CMD_MACPORT (0x0700)
2087 +#define HERMES_CMD_RECL (0x0100)
2088 +#define HERMES_CMD_WRITE (0x0100)
2089 +#define HERMES_CMD_PROGMODE (0x0300)
2090 +#define HERMES_CMD_CMDCODE (0x003f)
2093 + * STATUS register bitmasks
2094 + */
2095 +#define HERMES_STATUS_RESULT (0x7f00)
2096 +#define HERMES_STATUS_CMDCODE (0x003f)
2099 + * OFFSET register bitmasks
2100 + */
2101 +#define HERMES_OFFSET_BUSY (0x8000)
2102 +#define HERMES_OFFSET_ERR (0x4000)
2103 +#define HERMES_OFFSET_DATAOFF (0x0ffe)
2106 + * Event register bitmasks (INTEN, EVSTAT, EVACK)
2107 + */
2108 +#define HERMES_EV_TICK (0x8000)
2109 +#define HERMES_EV_WTERR (0x4000)
2110 +#define HERMES_EV_INFDROP (0x2000)
2111 +#define HERMES_EV_INFO (0x0080)
2112 +#define HERMES_EV_DTIM (0x0020)
2113 +#define HERMES_EV_CMD (0x0010)
2114 +#define HERMES_EV_ALLOC (0x0008)
2115 +#define HERMES_EV_TXEXC (0x0004)
2116 +#define HERMES_EV_TX (0x0002)
2117 +#define HERMES_EV_RX (0x0001)
2120 + * Command codes
2121 + */
2122 +/*--- Controller Commands ----------------------------*/
2123 +#define HERMES_CMD_INIT (0x0000)
2124 +#define HERMES_CMD_ENABLE (0x0001)
2125 +#define HERMES_CMD_DISABLE (0x0002)
2126 +#define HERMES_CMD_DIAG (0x0003)
2128 +/*--- Buffer Mgmt Commands ---------------------------*/
2129 +#define HERMES_CMD_ALLOC (0x000A)
2130 +#define HERMES_CMD_TX (0x000B)
2132 +/*--- Regulate Commands ------------------------------*/
2133 +#define HERMES_CMD_NOTIFY (0x0010)
2134 +#define HERMES_CMD_INQUIRE (0x0011)
2136 +/*--- Configure Commands -----------------------------*/
2137 +#define HERMES_CMD_ACCESS (0x0021)
2138 +#define HERMES_CMD_DOWNLD (0x0022)
2140 +/*--- Serial I/O Commands ----------------------------*/
2141 +#define HERMES_CMD_READMIF (0x0030)
2142 +#define HERMES_CMD_WRITEMIF (0x0031)
2144 +/*--- Debugging Commands -----------------------------*/
2145 +#define HERMES_CMD_TEST (0x0038)
2148 +/* Test command arguments */
2149 +#define HERMES_TEST_SET_CHANNEL 0x0800
2150 +#define HERMES_TEST_MONITOR 0x0b00
2151 +#define HERMES_TEST_STOP 0x0f00
2153 +/* Authentication algorithms */
2154 +#define HERMES_AUTH_OPEN 1
2155 +#define HERMES_AUTH_SHARED_KEY 2
2157 +/* WEP settings */
2158 +#define HERMES_WEP_PRIVACY_INVOKED 0x0001
2159 +#define HERMES_WEP_EXCL_UNENCRYPTED 0x0002
2160 +#define HERMES_WEP_HOST_ENCRYPT 0x0010
2161 +#define HERMES_WEP_HOST_DECRYPT 0x0080
2163 +/* Symbol hostscan options */
2164 +#define HERMES_HOSTSCAN_SYMBOL_5SEC 0x0001
2165 +#define HERMES_HOSTSCAN_SYMBOL_ONCE 0x0002
2166 +#define HERMES_HOSTSCAN_SYMBOL_PASSIVE 0x0040
2167 +#define HERMES_HOSTSCAN_SYMBOL_BCAST 0x0080
2170 + * Frame structures and constants
2171 + */
2173 +#define HERMES_DESCRIPTOR_OFFSET 0
2174 +#define HERMES_802_11_OFFSET (14)
2175 +#define HERMES_802_3_OFFSET (14 + 32)
2176 +#define HERMES_802_2_OFFSET (14 + 32 + 14)
2177 +#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
2179 +#define HERMES_RXSTAT_ERR (0x0003)
2180 +#define HERMES_RXSTAT_BADCRC (0x0001)
2181 +#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
2182 +#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */
2183 +#define HERMES_RXSTAT_MACPORT (0x0700)
2184 +#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */
2185 +#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */
2186 +#define HERMES_RXSTAT_MSGTYPE (0xE000)
2187 +#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */
2188 +#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */
2189 +#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
2191 +/* Shift amount for key ID in RXSTAT and TXCTRL */
2192 +#define HERMES_MIC_KEY_ID_SHIFT 11
2194 +struct hermes_tx_descriptor {
2195 + __le16 status;
2196 + __le16 reserved1;
2197 + __le16 reserved2;
2198 + __le32 sw_support;
2199 + u8 retry_count;
2200 + u8 tx_rate;
2201 + __le16 tx_control;
2202 +} __packed;
2204 +#define HERMES_TXSTAT_RETRYERR (0x0001)
2205 +#define HERMES_TXSTAT_AGEDERR (0x0002)
2206 +#define HERMES_TXSTAT_DISCON (0x0004)
2207 +#define HERMES_TXSTAT_FORMERR (0x0008)
2209 +#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */
2210 +#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */
2211 +#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */
2212 +#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */
2213 +#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */
2214 +#define HERMES_TXCTRL_ALT_RTRY (0x0020)
2216 +/* Inquiry constants and data types */
2218 +#define HERMES_INQ_TALLIES (0xF100)
2219 +#define HERMES_INQ_SCAN (0xF101)
2220 +#define HERMES_INQ_CHANNELINFO (0xF102)
2221 +#define HERMES_INQ_HOSTSCAN (0xF103)
2222 +#define HERMES_INQ_HOSTSCAN_SYMBOL (0xF104)
2223 +#define HERMES_INQ_LINKSTATUS (0xF200)
2224 +#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
2226 +struct hermes_tallies_frame {
2227 + __le16 TxUnicastFrames;
2228 + __le16 TxMulticastFrames;
2229 + __le16 TxFragments;
2230 + __le16 TxUnicastOctets;
2231 + __le16 TxMulticastOctets;
2232 + __le16 TxDeferredTransmissions;
2233 + __le16 TxSingleRetryFrames;
2234 + __le16 TxMultipleRetryFrames;
2235 + __le16 TxRetryLimitExceeded;
2236 + __le16 TxDiscards;
2237 + __le16 RxUnicastFrames;
2238 + __le16 RxMulticastFrames;
2239 + __le16 RxFragments;
2240 + __le16 RxUnicastOctets;
2241 + __le16 RxMulticastOctets;
2242 + __le16 RxFCSErrors;
2243 + __le16 RxDiscards_NoBuffer;
2244 + __le16 TxDiscardsWrongSA;
2245 + __le16 RxWEPUndecryptable;
2246 + __le16 RxMsgInMsgFragments;
2247 + __le16 RxMsgInBadMsgFragments;
2248 + /* Those last are probably not available in very old firmwares */
2249 + __le16 RxDiscards_WEPICVError;
2250 + __le16 RxDiscards_WEPExcluded;
2251 +} __packed;
2253 +/* Grabbed from wlan-ng - Thanks Mark... - Jean II
2254 + * This is the result of a scan inquiry command */
2255 +/* Structure describing info about an Access Point */
2256 +struct prism2_scan_apinfo {
2257 + __le16 channel; /* Channel where the AP sits */
2258 + __le16 noise; /* Noise level */
2259 + __le16 level; /* Signal level */
2260 + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
2261 + __le16 beacon_interv; /* Beacon interval */
2262 + __le16 capabilities; /* Capabilities */
2263 + __le16 essid_len; /* ESSID length */
2264 + u8 essid[32]; /* ESSID of the network */
2265 + u8 rates[10]; /* Bit rate supported */
2266 + __le16 proberesp_rate; /* Data rate of the response frame */
2267 + __le16 atim; /* ATIM window time, Kus (hostscan only) */
2268 +} __packed;
2270 +/* Same stuff for the Lucent/Agere card.
2271 + * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
2272 +struct agere_scan_apinfo {
2273 + __le16 channel; /* Channel where the AP sits */
2274 + __le16 noise; /* Noise level */
2275 + __le16 level; /* Signal level */
2276 + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
2277 + __le16 beacon_interv; /* Beacon interval */
2278 + __le16 capabilities; /* Capabilities */
2279 + /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
2280 + __le16 essid_len; /* ESSID length */
2281 + u8 essid[32]; /* ESSID of the network */
2282 +} __packed;
2284 +/* Moustafa: Scan structure for Symbol cards */
2285 +struct symbol_scan_apinfo {
2286 + u8 channel; /* Channel where the AP sits */
2287 + u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
2288 + __le16 noise; /* Noise level */
2289 + __le16 level; /* Signal level */
2290 + u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
2291 + __le16 beacon_interv; /* Beacon interval */
2292 + __le16 capabilities; /* Capabilities */
2293 + /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
2294 + __le16 essid_len; /* ESSID length */
2295 + u8 essid[32]; /* ESSID of the network */
2296 + __le16 rates[5]; /* Bit rate supported */
2297 + __le16 basic_rates; /* Basic rates bitmask */
2298 + u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
2299 + u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
2300 +} __packed;
2302 +union hermes_scan_info {
2303 + struct agere_scan_apinfo a;
2304 + struct prism2_scan_apinfo p;
2305 + struct symbol_scan_apinfo s;
2308 +/* Extended scan struct for HERMES_INQ_CHANNELINFO.
2309 + * wl_lkm calls this an ACS scan (Automatic Channel Select).
2310 + * Keep out of union hermes_scan_info because it is much bigger than
2311 + * the older scan structures. */
2312 +struct agere_ext_scan_info {
2313 + __le16 reserved0;
2315 + u8 noise;
2316 + u8 level;
2317 + u8 rx_flow;
2318 + u8 rate;
2319 + __le16 reserved1[2];
2321 + __le16 frame_control;
2322 + __le16 dur_id;
2323 + u8 addr1[ETH_ALEN];
2324 + u8 addr2[ETH_ALEN];
2325 + u8 bssid[ETH_ALEN];
2326 + __le16 sequence;
2327 + u8 addr4[ETH_ALEN];
2329 + __le16 data_length;
2331 + /* Next 3 fields do not get filled in. */
2332 + u8 daddr[ETH_ALEN];
2333 + u8 saddr[ETH_ALEN];
2334 + __le16 len_type;
2336 + __le64 timestamp;
2337 + __le16 beacon_interval;
2338 + __le16 capabilities;
2339 + u8 data[];
2340 +} __packed;
2342 +#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000)
2343 +#define HERMES_LINKSTATUS_CONNECTED (0x0001)
2344 +#define HERMES_LINKSTATUS_DISCONNECTED (0x0002)
2345 +#define HERMES_LINKSTATUS_AP_CHANGE (0x0003)
2346 +#define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004)
2347 +#define HERMES_LINKSTATUS_AP_IN_RANGE (0x0005)
2348 +#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
2350 +struct hermes_linkstatus {
2351 + __le16 linkstatus; /* Link status */
2352 +} __packed;
2354 +struct hermes_response {
2355 + u16 status, resp0, resp1, resp2;
2358 +/* "ID" structure - used for ESSID and station nickname */
2359 +struct hermes_idstring {
2360 + __le16 len;
2361 + __le16 val[16];
2362 +} __packed;
2364 +struct hermes_multicast {
2365 + u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
2366 +} __packed;
2368 +/* Timeouts */
2369 +#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
2371 +struct hermes;
2373 +/* Functions to access hardware */
2374 +struct hermes_ops {
2375 + int (*init)(struct hermes *hw);
2376 + int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0,
2377 + struct hermes_response *resp);
2378 + int (*init_cmd_wait)(struct hermes *hw, u16 cmd,
2379 + u16 parm0, u16 parm1, u16 parm2,
2380 + struct hermes_response *resp);
2381 + int (*allocate)(struct hermes *hw, u16 size, u16 *fid);
2382 + int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen,
2383 + u16 *length, void *buf);
2384 + int (*read_ltv_pr)(struct hermes *hw, int bap, u16 rid,
2385 + unsigned buflen, u16 *length, void *buf);
2386 + int (*write_ltv)(struct hermes *hw, int bap, u16 rid,
2387 + u16 length, const void *value);
2388 + int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len,
2389 + u16 id, u16 offset);
2390 + int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf,
2391 + int len, u16 id, u16 offset);
2392 + int (*read_pda)(struct hermes *hw, __le16 *pda,
2393 + u32 pda_addr, u16 pda_len);
2394 + int (*program_init)(struct hermes *hw, u32 entry_point);
2395 + int (*program_end)(struct hermes *hw);
2396 + int (*program)(struct hermes *hw, const char *buf,
2397 + u32 addr, u32 len);
2398 + void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags);
2399 + void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags);
2400 + void (*lock_irq)(spinlock_t *lock);
2401 + void (*unlock_irq)(spinlock_t *lock);
2404 +/* Basic control structure */
2405 +struct hermes {
2406 + void __iomem *iobase;
2407 + int reg_spacing;
2408 +#define HERMES_16BIT_REGSPACING 0
2409 +#define HERMES_32BIT_REGSPACING 1
2410 + u16 inten; /* Which interrupts should be enabled? */
2411 + bool eeprom_pda;
2412 + const struct hermes_ops *ops;
2413 + void *priv;
2416 +/* Register access convenience macros */
2417 +#define hermes_read_reg(hw, off) \
2418 + (ioread16((hw)->iobase + ((off) << (hw)->reg_spacing)))
2419 +#define hermes_write_reg(hw, off, val) \
2420 + (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing)))
2421 +#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name)
2422 +#define hermes_write_regn(hw, name, val) \
2423 + hermes_write_reg((hw), HERMES_##name, (val))
2425 +/* Function prototypes */
2426 +void hermes_struct_init(struct hermes *hw, void __iomem *address,
2427 + int reg_spacing);
2429 +/* Inline functions */
2431 +static inline int hermes_present(struct hermes *hw)
2433 + return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
2436 +static inline void hermes_set_irqmask(struct hermes *hw, u16 events)
2438 + hw->inten = events;
2439 + hermes_write_regn(hw, INTEN, events);
2442 +static inline int hermes_enable_port(struct hermes *hw, int port)
2444 + return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
2445 + 0, NULL);
2448 +static inline int hermes_disable_port(struct hermes *hw, int port)
2450 + return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
2451 + 0, NULL);
2454 +/* Initiate an INQUIRE command (tallies or scan). The result will come as an
2455 + * information frame in __orinoco_ev_info() */
2456 +static inline int hermes_inquire(struct hermes *hw, u16 rid)
2458 + return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
2461 +#define HERMES_BYTES_TO_RECLEN(n) ((((n) + 1) / 2) + 1)
2462 +#define HERMES_RECLEN_TO_BYTES(n) (((n) - 1) * 2)
2464 +/* Note that for the next two, the count is in 16-bit words, not bytes */
2465 +static inline void hermes_read_words(struct hermes *hw, int off,
2466 + void *buf, unsigned count)
2468 + off = off << hw->reg_spacing;
2469 + ioread16_rep(hw->iobase + off, buf, count);
2472 +static inline void hermes_write_bytes(struct hermes *hw, int off,
2473 + const char *buf, unsigned count)
2475 + off = off << hw->reg_spacing;
2476 + iowrite16_rep(hw->iobase + off, buf, count >> 1);
2477 + if (unlikely(count & 1))
2478 + iowrite8(buf[count - 1], hw->iobase + off);
2481 +static inline void hermes_clear_words(struct hermes *hw, int off,
2482 + unsigned count)
2484 + unsigned i;
2486 + off = off << hw->reg_spacing;
2488 + for (i = 0; i < count; i++)
2489 + iowrite16(0, hw->iobase + off);
2492 +#define HERMES_READ_RECORD(hw, bap, rid, buf) \
2493 + (hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
2494 +#define HERMES_READ_RECORD_PR(hw, bap, rid, buf) \
2495 + (hw->ops->read_ltv_pr((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
2496 +#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
2497 + (hw->ops->write_ltv((hw), (bap), (rid), \
2498 + HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
2500 +static inline int hermes_read_wordrec(struct hermes *hw, int bap, u16 rid,
2501 + u16 *word)
2503 + __le16 rec;
2504 + int err;
2506 + err = HERMES_READ_RECORD(hw, bap, rid, &rec);
2507 + *word = le16_to_cpu(rec);
2508 + return err;
2511 +static inline int hermes_read_wordrec_pr(struct hermes *hw, int bap, u16 rid,
2512 + u16 *word)
2514 + __le16 rec;
2515 + int err;
2517 + err = HERMES_READ_RECORD_PR(hw, bap, rid, &rec);
2518 + *word = le16_to_cpu(rec);
2519 + return err;
2522 +static inline int hermes_write_wordrec(struct hermes *hw, int bap, u16 rid,
2523 + u16 word)
2525 + __le16 rec = cpu_to_le16(word);
2526 + return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
2529 +#endif /* _HERMES_H */
2530 --- /dev/null
2531 +++ a/drivers/net/wireless/intersil/orinoco/hermes_dld.c
2532 @@ -0,0 +1,477 @@
2534 + * Hermes download helper.
2536 + * This helper:
2537 + * - is capable of writing to the volatile area of the hermes device
2538 + * - is currently not capable of writing to non-volatile areas
2539 + * - provide helpers to identify and update plugin data
2540 + * - is not capable of interpreting a fw image directly. That is up to
2541 + * the main card driver.
2542 + * - deals with Hermes I devices. It can probably be modified to deal
2543 + * with Hermes II devices
2545 + * Copyright (C) 2007, David Kilroy
2547 + * Plug data code slightly modified from spectrum_cs driver
2548 + * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
2549 + * Portions based on information in wl_lkm_718 Agere driver
2550 + * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved
2552 + * The contents of this file are subject to the Mozilla Public License
2553 + * Version 1.1 (the "License"); you may not use this file except in
2554 + * compliance with the License. You may obtain a copy of the License
2555 + * at http://www.mozilla.org/MPL/
2557 + * Software distributed under the License is distributed on an "AS IS"
2558 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
2559 + * the License for the specific language governing rights and
2560 + * limitations under the License.
2562 + * Alternatively, the contents of this file may be used under the
2563 + * terms of the GNU General Public License version 2 (the "GPL"), in
2564 + * which case the provisions of the GPL are applicable instead of the
2565 + * above. If you wish to allow the use of your version of this file
2566 + * only under the terms of the GPL and not to allow others to use your
2567 + * version of this file under the MPL, indicate your decision by
2568 + * deleting the provisions above and replace them with the notice and
2569 + * other provisions required by the GPL. If you do not delete the
2570 + * provisions above, a recipient may use your version of this file
2571 + * under either the MPL or the GPL.
2572 + */
2574 +#include <linux/module.h>
2575 +#include <linux/delay.h>
2576 +#include "hermes.h"
2577 +#include "hermes_dld.h"
2579 +#define PFX "hermes_dld: "
2581 +/* End markers used in dblocks */
2582 +#define PDI_END 0x00000000 /* End of PDA */
2583 +#define BLOCK_END 0xFFFFFFFF /* Last image block */
2584 +#define TEXT_END 0x1A /* End of text header */
2587 + * The following structures have little-endian fields denoted by
2588 + * the leading underscore. Don't access them directly - use inline
2589 + * functions defined below.
2590 + */
2593 + * The binary image to be downloaded consists of series of data blocks.
2594 + * Each block has the following structure.
2595 + */
2596 +struct dblock {
2597 + __le32 addr; /* adapter address where to write the block */
2598 + __le16 len; /* length of the data only, in bytes */
2599 + char data[]; /* data to be written */
2600 +} __packed;
2603 + * Plug Data References are located in the image after the last data
2604 + * block. They refer to areas in the adapter memory where the plug data
2605 + * items with matching ID should be written.
2606 + */
2607 +struct pdr {
2608 + __le32 id; /* record ID */
2609 + __le32 addr; /* adapter address where to write the data */
2610 + __le32 len; /* expected length of the data, in bytes */
2611 + char next[]; /* next PDR starts here */
2612 +} __packed;
2615 + * Plug Data Items are located in the EEPROM read from the adapter by
2616 + * primary firmware. They refer to the device-specific data that should
2617 + * be plugged into the secondary firmware.
2618 + */
2619 +struct pdi {
2620 + __le16 len; /* length of ID and data, in words */
2621 + __le16 id; /* record ID */
2622 + char data[]; /* plug data */
2623 +} __packed;
2625 +/*** FW data block access functions ***/
2627 +static inline u32
2628 +dblock_addr(const struct dblock *blk)
2630 + return le32_to_cpu(blk->addr);
2633 +static inline u32
2634 +dblock_len(const struct dblock *blk)
2636 + return le16_to_cpu(blk->len);
2639 +/*** PDR Access functions ***/
2641 +static inline u32
2642 +pdr_id(const struct pdr *pdr)
2644 + return le32_to_cpu(pdr->id);
2647 +static inline u32
2648 +pdr_addr(const struct pdr *pdr)
2650 + return le32_to_cpu(pdr->addr);
2653 +static inline u32
2654 +pdr_len(const struct pdr *pdr)
2656 + return le32_to_cpu(pdr->len);
2659 +/*** PDI Access functions ***/
2661 +static inline u32
2662 +pdi_id(const struct pdi *pdi)
2664 + return le16_to_cpu(pdi->id);
2667 +/* Return length of the data only, in bytes */
2668 +static inline u32
2669 +pdi_len(const struct pdi *pdi)
2671 + return 2 * (le16_to_cpu(pdi->len) - 1);
2674 +/*** Plug Data Functions ***/
2677 + * Scan PDR for the record with the specified RECORD_ID.
2678 + * If it's not found, return NULL.
2679 + */
2680 +static const struct pdr *
2681 +hermes_find_pdr(const struct pdr *first_pdr, u32 record_id, const void *end)
2683 + const struct pdr *pdr = first_pdr;
2685 + end -= sizeof(struct pdr);
2687 + while (((void *) pdr <= end) &&
2688 + (pdr_id(pdr) != PDI_END)) {
2689 + /*
2690 + * PDR area is currently not terminated by PDI_END.
2691 + * It's followed by CRC records, which have the type
2692 + * field where PDR has length. The type can be 0 or 1.
2693 + */
2694 + if (pdr_len(pdr) < 2)
2695 + return NULL;
2697 + /* If the record ID matches, we are done */
2698 + if (pdr_id(pdr) == record_id)
2699 + return pdr;
2701 + pdr = (struct pdr *) pdr->next;
2703 + return NULL;
2706 +/* Scan production data items for a particular entry */
2707 +static const struct pdi *
2708 +hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end)
2710 + const struct pdi *pdi = first_pdi;
2712 + end -= sizeof(struct pdi);
2714 + while (((void *) pdi <= end) &&
2715 + (pdi_id(pdi) != PDI_END)) {
2717 + /* If the record ID matches, we are done */
2718 + if (pdi_id(pdi) == record_id)
2719 + return pdi;
2721 + pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
2723 + return NULL;
2726 +/* Process one Plug Data Item - find corresponding PDR and plug it */
2727 +static int
2728 +hermes_plug_pdi(struct hermes *hw, const struct pdr *first_pdr,
2729 + const struct pdi *pdi, const void *pdr_end)
2731 + const struct pdr *pdr;
2733 + /* Find the PDR corresponding to this PDI */
2734 + pdr = hermes_find_pdr(first_pdr, pdi_id(pdi), pdr_end);
2736 + /* No match is found, safe to ignore */
2737 + if (!pdr)
2738 + return 0;
2740 + /* Lengths of the data in PDI and PDR must match */
2741 + if (pdi_len(pdi) != pdr_len(pdr))
2742 + return -EINVAL;
2744 + /* do the actual plugging */
2745 + hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));
2747 + return 0;
2750 +/* Parse PDA and write the records into the adapter
2752 + * Attempt to write every records that is in the specified pda
2753 + * which also has a valid production data record for the firmware.
2754 + */
2755 +int hermes_apply_pda(struct hermes *hw,
2756 + const char *first_pdr,
2757 + const void *pdr_end,
2758 + const __le16 *pda,
2759 + const void *pda_end)
2761 + int ret;
2762 + const struct pdi *pdi;
2763 + const struct pdr *pdr;
2765 + pdr = (const struct pdr *) first_pdr;
2766 + pda_end -= sizeof(struct pdi);
2768 + /* Go through every PDI and plug them into the adapter */
2769 + pdi = (const struct pdi *) (pda + 2);
2770 + while (((void *) pdi <= pda_end) &&
2771 + (pdi_id(pdi) != PDI_END)) {
2772 + ret = hermes_plug_pdi(hw, pdr, pdi, pdr_end);
2773 + if (ret)
2774 + return ret;
2776 + /* Increment to the next PDI */
2777 + pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)];
2779 + return 0;
2782 +/* Identify the total number of bytes in all blocks
2783 + * including the header data.
2784 + */
2785 +size_t
2786 +hermes_blocks_length(const char *first_block, const void *end)
2788 + const struct dblock *blk = (const struct dblock *) first_block;
2789 + int total_len = 0;
2790 + int len;
2792 + end -= sizeof(*blk);
2794 + /* Skip all blocks to locate Plug Data References
2795 + * (Spectrum CS) */
2796 + while (((void *) blk <= end) &&
2797 + (dblock_addr(blk) != BLOCK_END)) {
2798 + len = dblock_len(blk);
2799 + total_len += sizeof(*blk) + len;
2800 + blk = (struct dblock *) &blk->data[len];
2803 + return total_len;
2806 +/*** Hermes programming ***/
2808 +/* Program the data blocks */
2809 +int hermes_program(struct hermes *hw, const char *first_block, const void *end)
2811 + const struct dblock *blk;
2812 + u32 blkaddr;
2813 + u32 blklen;
2814 + int err = 0;
2816 + blk = (const struct dblock *) first_block;
2818 + if ((void *) blk > (end - sizeof(*blk)))
2819 + return -EIO;
2821 + blkaddr = dblock_addr(blk);
2822 + blklen = dblock_len(blk);
2824 + while ((blkaddr != BLOCK_END) &&
2825 + (((void *) blk + blklen) <= end)) {
2826 + pr_debug(PFX "Programming block of length %d "
2827 + "to address 0x%08x\n", blklen, blkaddr);
2829 + err = hw->ops->program(hw, blk->data, blkaddr, blklen);
2830 + if (err)
2831 + break;
2833 + blk = (const struct dblock *) &blk->data[blklen];
2835 + if ((void *) blk > (end - sizeof(*blk)))
2836 + return -EIO;
2838 + blkaddr = dblock_addr(blk);
2839 + blklen = dblock_len(blk);
2841 + return err;
2844 +/*** Default plugging data for Hermes I ***/
2845 +/* Values from wl_lkm_718/hcf/dhf.c */
2847 +#define DEFINE_DEFAULT_PDR(pid, length, data) \
2848 +static const struct { \
2849 + __le16 len; \
2850 + __le16 id; \
2851 + u8 val[length]; \
2852 +} __packed default_pdr_data_##pid = { \
2853 + cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
2854 + sizeof(__le16)) - 1), \
2855 + cpu_to_le16(pid), \
2856 + data \
2859 +#define DEFAULT_PDR(pid) default_pdr_data_##pid
2861 +/* HWIF Compatibility */
2862 +DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00");
2864 +/* PPPPSign */
2865 +DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00");
2867 +/* PPPPProf */
2868 +DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00");
2870 +/* Antenna diversity */
2871 +DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F");
2873 +/* Modem VCO band Set-up */
2874 +DEFINE_DEFAULT_PDR(0x0160, 28,
2875 + "\x00\x00\x00\x00\x00\x00\x00\x00"
2876 + "\x00\x00\x00\x00\x00\x00\x00\x00"
2877 + "\x00\x00\x00\x00\x00\x00\x00\x00"
2878 + "\x00\x00\x00\x00");
2880 +/* Modem Rx Gain Table Values */
2881 +DEFINE_DEFAULT_PDR(0x0161, 256,
2882 + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
2883 + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
2884 + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
2885 + "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
2886 + "\x3F\x01\x3E\01\x3E\x01\x3D\x01"
2887 + "\x3D\x01\x3C\01\x3C\x01\x3B\x01"
2888 + "\x3B\x01\x3A\01\x3A\x01\x39\x01"
2889 + "\x39\x01\x38\01\x38\x01\x37\x01"
2890 + "\x37\x01\x36\01\x36\x01\x35\x01"
2891 + "\x35\x01\x34\01\x34\x01\x33\x01"
2892 + "\x33\x01\x32\x01\x32\x01\x31\x01"
2893 + "\x31\x01\x30\x01\x30\x01\x7B\x01"
2894 + "\x7B\x01\x7A\x01\x7A\x01\x79\x01"
2895 + "\x79\x01\x78\x01\x78\x01\x77\x01"
2896 + "\x77\x01\x76\x01\x76\x01\x75\x01"
2897 + "\x75\x01\x74\x01\x74\x01\x73\x01"
2898 + "\x73\x01\x72\x01\x72\x01\x71\x01"
2899 + "\x71\x01\x70\x01\x70\x01\x68\x01"
2900 + "\x68\x01\x67\x01\x67\x01\x66\x01"
2901 + "\x66\x01\x65\x01\x65\x01\x57\x01"
2902 + "\x57\x01\x56\x01\x56\x01\x55\x01"
2903 + "\x55\x01\x54\x01\x54\x01\x53\x01"
2904 + "\x53\x01\x52\x01\x52\x01\x51\x01"
2905 + "\x51\x01\x50\x01\x50\x01\x48\x01"
2906 + "\x48\x01\x47\x01\x47\x01\x46\x01"
2907 + "\x46\x01\x45\x01\x45\x01\x44\x01"
2908 + "\x44\x01\x43\x01\x43\x01\x42\x01"
2909 + "\x42\x01\x41\x01\x41\x01\x40\x01"
2910 + "\x40\x01\x40\x01\x40\x01\x40\x01"
2911 + "\x40\x01\x40\x01\x40\x01\x40\x01"
2912 + "\x40\x01\x40\x01\x40\x01\x40\x01"
2913 + "\x40\x01\x40\x01\x40\x01\x40\x01");
2915 +/* Write PDA according to certain rules.
2917 + * For every production data record, look for a previous setting in
2918 + * the pda, and use that.
2920 + * For certain records, use defaults if they are not found in pda.
2921 + */
2922 +int hermes_apply_pda_with_defaults(struct hermes *hw,
2923 + const char *first_pdr,
2924 + const void *pdr_end,
2925 + const __le16 *pda,
2926 + const void *pda_end)
2928 + const struct pdr *pdr = (const struct pdr *) first_pdr;
2929 + const struct pdi *first_pdi = (const struct pdi *) &pda[2];
2930 + const struct pdi *pdi;
2931 + const struct pdi *default_pdi = NULL;
2932 + const struct pdi *outdoor_pdi;
2933 + int record_id;
2935 + pdr_end -= sizeof(struct pdr);
2937 + while (((void *) pdr <= pdr_end) &&
2938 + (pdr_id(pdr) != PDI_END)) {
2939 + /*
2940 + * For spectrum_cs firmwares,
2941 + * PDR area is currently not terminated by PDI_END.
2942 + * It's followed by CRC records, which have the type
2943 + * field where PDR has length. The type can be 0 or 1.
2944 + */
2945 + if (pdr_len(pdr) < 2)
2946 + break;
2947 + record_id = pdr_id(pdr);
2949 + pdi = hermes_find_pdi(first_pdi, record_id, pda_end);
2950 + if (pdi)
2951 + pr_debug(PFX "Found record 0x%04x at %p\n",
2952 + record_id, pdi);
2954 + switch (record_id) {
2955 + case 0x110: /* Modem REFDAC values */
2956 + case 0x120: /* Modem VGDAC values */
2957 + outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1,
2958 + pda_end);
2959 + default_pdi = NULL;
2960 + if (outdoor_pdi) {
2961 + pdi = outdoor_pdi;
2962 + pr_debug(PFX
2963 + "Using outdoor record 0x%04x at %p\n",
2964 + record_id + 1, pdi);
2966 + break;
2967 + case 0x5: /* HWIF Compatibility */
2968 + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005);
2969 + break;
2970 + case 0x108: /* PPPPSign */
2971 + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108);
2972 + break;
2973 + case 0x109: /* PPPPProf */
2974 + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109);
2975 + break;
2976 + case 0x150: /* Antenna diversity */
2977 + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150);
2978 + break;
2979 + case 0x160: /* Modem VCO band Set-up */
2980 + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160);
2981 + break;
2982 + case 0x161: /* Modem Rx Gain Table Values */
2983 + default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161);
2984 + break;
2985 + default:
2986 + default_pdi = NULL;
2987 + break;
2989 + if (!pdi && default_pdi) {
2990 + /* Use default */
2991 + pdi = default_pdi;
2992 + pr_debug(PFX "Using default record 0x%04x at %p\n",
2993 + record_id, pdi);
2996 + if (pdi) {
2997 + /* Lengths of the data in PDI and PDR must match */
2998 + if ((pdi_len(pdi) == pdr_len(pdr)) &&
2999 + ((void *) pdi->data + pdi_len(pdi) < pda_end)) {
3000 + /* do the actual plugging */
3001 + hw->ops->program(hw, pdi->data, pdr_addr(pdr),
3002 + pdi_len(pdi));
3006 + pdr++;
3008 + return 0;
3010 --- /dev/null
3011 +++ a/drivers/net/wireless/intersil/orinoco/hermes_dld.h
3012 @@ -0,0 +1,52 @@
3014 + * Copyright (C) 2007, David Kilroy
3016 + * The contents of this file are subject to the Mozilla Public License
3017 + * Version 1.1 (the "License"); you may not use this file except in
3018 + * compliance with the License. You may obtain a copy of the License
3019 + * at http://www.mozilla.org/MPL/
3021 + * Software distributed under the License is distributed on an "AS IS"
3022 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
3023 + * the License for the specific language governing rights and
3024 + * limitations under the License.
3026 + * Alternatively, the contents of this file may be used under the
3027 + * terms of the GNU General Public License version 2 (the "GPL"), in
3028 + * which case the provisions of the GPL are applicable instead of the
3029 + * above. If you wish to allow the use of your version of this file
3030 + * only under the terms of the GPL and not to allow others to use your
3031 + * version of this file under the MPL, indicate your decision by
3032 + * deleting the provisions above and replace them with the notice and
3033 + * other provisions required by the GPL. If you do not delete the
3034 + * provisions above, a recipient may use your version of this file
3035 + * under either the MPL or the GPL.
3036 + */
3037 +#ifndef _HERMES_DLD_H
3038 +#define _HERMES_DLD_H
3040 +#include "hermes.h"
3042 +int hermesi_program_init(struct hermes *hw, u32 offset);
3043 +int hermesi_program_end(struct hermes *hw);
3044 +int hermes_program(struct hermes *hw, const char *first_block, const void *end);
3046 +int hermes_read_pda(struct hermes *hw,
3047 + __le16 *pda,
3048 + u32 pda_addr,
3049 + u16 pda_len,
3050 + int use_eeprom);
3051 +int hermes_apply_pda(struct hermes *hw,
3052 + const char *first_pdr,
3053 + const void *pdr_end,
3054 + const __le16 *pda,
3055 + const void *pda_end);
3056 +int hermes_apply_pda_with_defaults(struct hermes *hw,
3057 + const char *first_pdr,
3058 + const void *pdr_end,
3059 + const __le16 *pda,
3060 + const void *pda_end);
3062 +size_t hermes_blocks_length(const char *first_block, const void *end);
3064 +#endif /* _HERMES_DLD_H */
3065 --- /dev/null
3066 +++ a/drivers/net/wireless/intersil/orinoco/hermes_rid.h
3067 @@ -0,0 +1,165 @@
3068 +#ifndef _HERMES_RID_H
3069 +#define _HERMES_RID_H
3072 + * Configuration RIDs
3073 + */
3074 +#define HERMES_RID_CNFPORTTYPE 0xFC00
3075 +#define HERMES_RID_CNFOWNMACADDR 0xFC01
3076 +#define HERMES_RID_CNFDESIREDSSID 0xFC02
3077 +#define HERMES_RID_CNFOWNCHANNEL 0xFC03
3078 +#define HERMES_RID_CNFOWNSSID 0xFC04
3079 +#define HERMES_RID_CNFOWNATIMWINDOW 0xFC05
3080 +#define HERMES_RID_CNFSYSTEMSCALE 0xFC06
3081 +#define HERMES_RID_CNFMAXDATALEN 0xFC07
3082 +#define HERMES_RID_CNFWDSADDRESS 0xFC08
3083 +#define HERMES_RID_CNFPMENABLED 0xFC09
3084 +#define HERMES_RID_CNFPMEPS 0xFC0A
3085 +#define HERMES_RID_CNFMULTICASTRECEIVE 0xFC0B
3086 +#define HERMES_RID_CNFMAXSLEEPDURATION 0xFC0C
3087 +#define HERMES_RID_CNFPMHOLDOVERDURATION 0xFC0D
3088 +#define HERMES_RID_CNFOWNNAME 0xFC0E
3089 +#define HERMES_RID_CNFOWNDTIMPERIOD 0xFC10
3090 +#define HERMES_RID_CNFWDSADDRESS1 0xFC11
3091 +#define HERMES_RID_CNFWDSADDRESS2 0xFC12
3092 +#define HERMES_RID_CNFWDSADDRESS3 0xFC13
3093 +#define HERMES_RID_CNFWDSADDRESS4 0xFC14
3094 +#define HERMES_RID_CNFWDSADDRESS5 0xFC15
3095 +#define HERMES_RID_CNFWDSADDRESS6 0xFC16
3096 +#define HERMES_RID_CNFMULTICASTPMBUFFERING 0xFC17
3097 +#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20
3098 +#define HERMES_RID_CNFAUTHENTICATION_AGERE 0xFC21
3099 +#define HERMES_RID_CNFMANDATORYBSSID_SYMBOL 0xFC21
3100 +#define HERMES_RID_CNFDROPUNENCRYPTED 0xFC22
3101 +#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23
3102 +#define HERMES_RID_CNFDEFAULTKEY0 0xFC24
3103 +#define HERMES_RID_CNFDEFAULTKEY1 0xFC25
3104 +#define HERMES_RID_CNFMWOROBUST_AGERE 0xFC25
3105 +#define HERMES_RID_CNFDEFAULTKEY2 0xFC26
3106 +#define HERMES_RID_CNFDEFAULTKEY3 0xFC27
3107 +#define HERMES_RID_CNFWEPFLAGS_INTERSIL 0xFC28
3108 +#define HERMES_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
3109 +#define HERMES_RID_CNFAUTHENTICATION 0xFC2A
3110 +#define HERMES_RID_CNFMAXASSOCSTA 0xFC2B
3111 +#define HERMES_RID_CNFKEYLENGTH_SYMBOL 0xFC2B
3112 +#define HERMES_RID_CNFTXCONTROL 0xFC2C
3113 +#define HERMES_RID_CNFROAMINGMODE 0xFC2D
3114 +#define HERMES_RID_CNFHOSTAUTHENTICATION 0xFC2E
3115 +#define HERMES_RID_CNFRCVCRCERROR 0xFC30
3116 +#define HERMES_RID_CNFMMLIFE 0xFC31
3117 +#define HERMES_RID_CNFALTRETRYCOUNT 0xFC32
3118 +#define HERMES_RID_CNFBEACONINT 0xFC33
3119 +#define HERMES_RID_CNFAPPCFINFO 0xFC34
3120 +#define HERMES_RID_CNFSTAPCFINFO 0xFC35
3121 +#define HERMES_RID_CNFPRIORITYQUSAGE 0xFC37
3122 +#define HERMES_RID_CNFTIMCTRL 0xFC40
3123 +#define HERMES_RID_CNFTHIRTY2TALLY 0xFC42
3124 +#define HERMES_RID_CNFENHSECURITY 0xFC43
3125 +#define HERMES_RID_CNFGROUPADDRESSES 0xFC80
3126 +#define HERMES_RID_CNFCREATEIBSS 0xFC81
3127 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD 0xFC82
3128 +#define HERMES_RID_CNFRTSTHRESHOLD 0xFC83
3129 +#define HERMES_RID_CNFTXRATECONTROL 0xFC84
3130 +#define HERMES_RID_CNFPROMISCUOUSMODE 0xFC85
3131 +#define HERMES_RID_CNFBASICRATES_SYMBOL 0xFC8A
3132 +#define HERMES_RID_CNFPREAMBLE_SYMBOL 0xFC8C
3133 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0 0xFC90
3134 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1 0xFC91
3135 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2 0xFC92
3136 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD3 0xFC93
3137 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD4 0xFC94
3138 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD5 0xFC95
3139 +#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD6 0xFC96
3140 +#define HERMES_RID_CNFRTSTHRESHOLD0 0xFC97
3141 +#define HERMES_RID_CNFRTSTHRESHOLD1 0xFC98
3142 +#define HERMES_RID_CNFRTSTHRESHOLD2 0xFC99
3143 +#define HERMES_RID_CNFRTSTHRESHOLD3 0xFC9A
3144 +#define HERMES_RID_CNFRTSTHRESHOLD4 0xFC9B
3145 +#define HERMES_RID_CNFRTSTHRESHOLD5 0xFC9C
3146 +#define HERMES_RID_CNFRTSTHRESHOLD6 0xFC9D
3147 +#define HERMES_RID_CNFHOSTSCAN_SYMBOL 0xFCAB
3148 +#define HERMES_RID_CNFSHORTPREAMBLE 0xFCB0
3149 +#define HERMES_RID_CNFWEPKEYS_AGERE 0xFCB0
3150 +#define HERMES_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
3151 +#define HERMES_RID_CNFTXKEY_AGERE 0xFCB1
3152 +#define HERMES_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
3153 +#define HERMES_RID_CNFSCANSSID_AGERE 0xFCB2
3154 +#define HERMES_RID_CNFBASICRATES 0xFCB3
3155 +#define HERMES_RID_CNFSUPPORTEDRATES 0xFCB4
3156 +#define HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE 0xFCB4
3157 +#define HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE 0xFCB5
3158 +#define HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE 0xFCB6
3159 +#define HERMES_RID_CNFADDMAPPEDTKIPKEY_AGERE 0xFCB7
3160 +#define HERMES_RID_CNFREMMAPPEDTKIPKEY_AGERE 0xFCB8
3161 +#define HERMES_RID_CNFSETWPACAPABILITIES_AGERE 0xFCB9
3162 +#define HERMES_RID_CNFCACHEDPMKADDRESS 0xFCBA
3163 +#define HERMES_RID_CNFREMOVEPMKADDRESS 0xFCBB
3164 +#define HERMES_RID_CNFSCANCHANNELS2GHZ 0xFCC2
3165 +#define HERMES_RID_CNFDISASSOCIATE 0xFCC8
3166 +#define HERMES_RID_CNFTICKTIME 0xFCE0
3167 +#define HERMES_RID_CNFSCANREQUEST 0xFCE1
3168 +#define HERMES_RID_CNFJOINREQUEST 0xFCE2
3169 +#define HERMES_RID_CNFAUTHENTICATESTATION 0xFCE3
3170 +#define HERMES_RID_CNFCHANNELINFOREQUEST 0xFCE4
3171 +#define HERMES_RID_CNFHOSTSCAN 0xFCE5
3174 + * Information RIDs
3175 + */
3176 +#define HERMES_RID_MAXLOADTIME 0xFD00
3177 +#define HERMES_RID_DOWNLOADBUFFER 0xFD01
3178 +#define HERMES_RID_PRIID 0xFD02
3179 +#define HERMES_RID_PRISUPRANGE 0xFD03
3180 +#define HERMES_RID_CFIACTRANGES 0xFD04
3181 +#define HERMES_RID_NICSERNUM 0xFD0A
3182 +#define HERMES_RID_NICID 0xFD0B
3183 +#define HERMES_RID_MFISUPRANGE 0xFD0C
3184 +#define HERMES_RID_CFISUPRANGE 0xFD0D
3185 +#define HERMES_RID_CHANNELLIST 0xFD10
3186 +#define HERMES_RID_REGULATORYDOMAINS 0xFD11
3187 +#define HERMES_RID_TEMPTYPE 0xFD12
3188 +#define HERMES_RID_CIS 0xFD13
3189 +#define HERMES_RID_STAID 0xFD20
3190 +#define HERMES_RID_STASUPRANGE 0xFD21
3191 +#define HERMES_RID_MFIACTRANGES 0xFD22
3192 +#define HERMES_RID_CFIACTRANGES2 0xFD23
3193 +#define HERMES_RID_SECONDARYVERSION_SYMBOL 0xFD24
3194 +#define HERMES_RID_PORTSTATUS 0xFD40
3195 +#define HERMES_RID_CURRENTSSID 0xFD41
3196 +#define HERMES_RID_CURRENTBSSID 0xFD42
3197 +#define HERMES_RID_COMMSQUALITY 0xFD43
3198 +#define HERMES_RID_CURRENTTXRATE 0xFD44
3199 +#define HERMES_RID_CURRENTBEACONINTERVAL 0xFD45
3200 +#define HERMES_RID_CURRENTSCALETHRESHOLDS 0xFD46
3201 +#define HERMES_RID_PROTOCOLRSPTIME 0xFD47
3202 +#define HERMES_RID_SHORTRETRYLIMIT 0xFD48
3203 +#define HERMES_RID_LONGRETRYLIMIT 0xFD49
3204 +#define HERMES_RID_MAXTRANSMITLIFETIME 0xFD4A
3205 +#define HERMES_RID_MAXRECEIVELIFETIME 0xFD4B
3206 +#define HERMES_RID_CFPOLLABLE 0xFD4C
3207 +#define HERMES_RID_AUTHENTICATIONALGORITHMS 0xFD4D
3208 +#define HERMES_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
3209 +#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL 0xFD51
3210 +#define HERMES_RID_CURRENTTXRATE1 0xFD80
3211 +#define HERMES_RID_CURRENTTXRATE2 0xFD81
3212 +#define HERMES_RID_CURRENTTXRATE3 0xFD82
3213 +#define HERMES_RID_CURRENTTXRATE4 0xFD83
3214 +#define HERMES_RID_CURRENTTXRATE5 0xFD84
3215 +#define HERMES_RID_CURRENTTXRATE6 0xFD85
3216 +#define HERMES_RID_OWNMACADDR 0xFD86
3217 +#define HERMES_RID_SCANRESULTSTABLE 0xFD88
3218 +#define HERMES_RID_CURRENT_COUNTRY_INFO 0xFD89
3219 +#define HERMES_RID_CURRENT_WPA_IE 0xFD8A
3220 +#define HERMES_RID_CURRENT_TKIP_IV 0xFD8B
3221 +#define HERMES_RID_CURRENT_ASSOC_REQ_INFO 0xFD8C
3222 +#define HERMES_RID_CURRENT_ASSOC_RESP_INFO 0xFD8D
3223 +#define HERMES_RID_TXQUEUEEMPTY 0xFD91
3224 +#define HERMES_RID_PHYTYPE 0xFDC0
3225 +#define HERMES_RID_CURRENTCHANNEL 0xFDC1
3226 +#define HERMES_RID_CURRENTPOWERSTATE 0xFDC2
3227 +#define HERMES_RID_CCAMODE 0xFDC3
3228 +#define HERMES_RID_SUPPORTEDDATARATES 0xFDC6
3229 +#define HERMES_RID_BUILDSEQ 0xFFFE
3230 +#define HERMES_RID_FWID 0xFFFF
3232 +#endif
3233 --- /dev/null
3234 +++ a/drivers/net/wireless/intersil/orinoco/hw.c
3235 @@ -0,0 +1,1362 @@
3236 +/* Encapsulate basic setting changes and retrieval on Hermes hardware
3238 + * See copyright notice in main.c
3239 + */
3240 +#include <linux/kernel.h>
3241 +#include <linux/device.h>
3242 +#include <linux/if_arp.h>
3243 +#include <linux/ieee80211.h>
3244 +#include <linux/wireless.h>
3245 +#include <net/cfg80211.h>
3246 +#include "hermes.h"
3247 +#include "hermes_rid.h"
3248 +#include "orinoco.h"
3250 +#include "hw.h"
3252 +#define SYMBOL_MAX_VER_LEN (14)
3254 +/* Symbol firmware has a bug allocating buffers larger than this */
3255 +#define TX_NICBUF_SIZE_BUG 1585
3257 +/********************************************************************/
3258 +/* Data tables */
3259 +/********************************************************************/
3261 +/* This tables gives the actual meanings of the bitrate IDs returned
3262 + * by the firmware. */
3263 +static const struct {
3264 + int bitrate; /* in 100s of kilobits */
3265 + int automatic;
3266 + u16 agere_txratectrl;
3267 + u16 intersil_txratectrl;
3268 +} bitrate_table[] = {
3269 + {110, 1, 3, 15}, /* Entry 0 is the default */
3270 + {10, 0, 1, 1},
3271 + {10, 1, 1, 1},
3272 + {20, 0, 2, 2},
3273 + {20, 1, 6, 3},
3274 + {55, 0, 4, 4},
3275 + {55, 1, 7, 7},
3276 + {110, 0, 5, 8},
3278 +#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
3280 +/* Firmware version encoding */
3281 +struct comp_id {
3282 + u16 id, variant, major, minor;
3283 +} __packed;
3285 +static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
3287 + if (nic_id->id < 0x8000)
3288 + return FIRMWARE_TYPE_AGERE;
3289 + else if (nic_id->id == 0x8000 && nic_id->major == 0)
3290 + return FIRMWARE_TYPE_SYMBOL;
3291 + else
3292 + return FIRMWARE_TYPE_INTERSIL;
3295 +/* Set priv->firmware type, determine firmware properties
3296 + * This function can be called before we have registerred with netdev,
3297 + * so all errors go out with dev_* rather than printk
3299 + * If non-NULL stores a firmware description in fw_name.
3300 + * If non-NULL stores a HW version in hw_ver
3302 + * These are output via generic cfg80211 ethtool support.
3303 + */
3304 +int determine_fw_capabilities(struct orinoco_private *priv,
3305 + char *fw_name, size_t fw_name_len,
3306 + u32 *hw_ver)
3308 + struct device *dev = priv->dev;
3309 + struct hermes *hw = &priv->hw;
3310 + int err;
3311 + struct comp_id nic_id, sta_id;
3312 + unsigned int firmver;
3313 + char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
3315 + /* Get the hardware version */
3316 + err = HERMES_READ_RECORD_PR(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
3317 + if (err) {
3318 + dev_err(dev, "Cannot read hardware identity: error %d\n",
3319 + err);
3320 + return err;
3323 + le16_to_cpus(&nic_id.id);
3324 + le16_to_cpus(&nic_id.variant);
3325 + le16_to_cpus(&nic_id.major);
3326 + le16_to_cpus(&nic_id.minor);
3327 + dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
3328 + nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
3330 + if (hw_ver)
3331 + *hw_ver = (((nic_id.id & 0xff) << 24) |
3332 + ((nic_id.variant & 0xff) << 16) |
3333 + ((nic_id.major & 0xff) << 8) |
3334 + (nic_id.minor & 0xff));
3336 + priv->firmware_type = determine_firmware_type(&nic_id);
3338 + /* Get the firmware version */
3339 + err = HERMES_READ_RECORD_PR(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
3340 + if (err) {
3341 + dev_err(dev, "Cannot read station identity: error %d\n",
3342 + err);
3343 + return err;
3346 + le16_to_cpus(&sta_id.id);
3347 + le16_to_cpus(&sta_id.variant);
3348 + le16_to_cpus(&sta_id.major);
3349 + le16_to_cpus(&sta_id.minor);
3350 + dev_info(dev, "Station identity %04x:%04x:%04x:%04x\n",
3351 + sta_id.id, sta_id.variant, sta_id.major, sta_id.minor);
3353 + switch (sta_id.id) {
3354 + case 0x15:
3355 + dev_err(dev, "Primary firmware is active\n");
3356 + return -ENODEV;
3357 + case 0x14b:
3358 + dev_err(dev, "Tertiary firmware is active\n");
3359 + return -ENODEV;
3360 + case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
3361 + case 0x21: /* Symbol Spectrum24 Trilogy */
3362 + break;
3363 + default:
3364 + dev_notice(dev, "Unknown station ID, please report\n");
3365 + break;
3368 + /* Default capabilities */
3369 + priv->has_sensitivity = 1;
3370 + priv->has_mwo = 0;
3371 + priv->has_preamble = 0;
3372 + priv->has_port3 = 1;
3373 + priv->has_ibss = 1;
3374 + priv->has_wep = 0;
3375 + priv->has_big_wep = 0;
3376 + priv->has_alt_txcntl = 0;
3377 + priv->has_ext_scan = 0;
3378 + priv->has_wpa = 0;
3379 + priv->do_fw_download = 0;
3381 + /* Determine capabilities from the firmware version */
3382 + switch (priv->firmware_type) {
3383 + case FIRMWARE_TYPE_AGERE:
3384 + /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
3385 + ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
3386 + if (fw_name)
3387 + snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d",
3388 + sta_id.major, sta_id.minor);
3390 + firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
3392 + priv->has_ibss = (firmver >= 0x60006);
3393 + priv->has_wep = (firmver >= 0x40020);
3394 + priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
3395 + Gold cards from the others? */
3396 + priv->has_mwo = (firmver >= 0x60000);
3397 + priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
3398 + priv->ibss_port = 1;
3399 + priv->has_hostscan = (firmver >= 0x8000a);
3400 + priv->do_fw_download = 1;
3401 + priv->broken_monitor = (firmver >= 0x80000);
3402 + priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
3403 + priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
3404 + priv->has_wpa = (firmver >= 0x9002a);
3405 + /* Tested with Agere firmware :
3406 + * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
3407 + * Tested CableTron firmware : 4.32 => Anton */
3408 + break;
3409 + case FIRMWARE_TYPE_SYMBOL:
3410 + /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
3411 + /* Intel MAC : 00:02:B3:* */
3412 + /* 3Com MAC : 00:50:DA:* */
3413 + memset(tmp, 0, sizeof(tmp));
3414 + /* Get the Symbol firmware version */
3415 + err = hw->ops->read_ltv_pr(hw, USER_BAP,
3416 + HERMES_RID_SECONDARYVERSION_SYMBOL,
3417 + SYMBOL_MAX_VER_LEN, NULL, &tmp);
3418 + if (err) {
3419 + dev_warn(dev, "Error %d reading Symbol firmware info. "
3420 + "Wildly guessing capabilities...\n", err);
3421 + firmver = 0;
3422 + tmp[0] = '\0';
3423 + } else {
3424 + /* The firmware revision is a string, the format is
3425 + * something like : "V2.20-01".
3426 + * Quick and dirty parsing... - Jean II
3427 + */
3428 + firmver = ((tmp[1] - '0') << 16)
3429 + | ((tmp[3] - '0') << 12)
3430 + | ((tmp[4] - '0') << 8)
3431 + | ((tmp[6] - '0') << 4)
3432 + | (tmp[7] - '0');
3434 + tmp[SYMBOL_MAX_VER_LEN] = '\0';
3437 + if (fw_name)
3438 + snprintf(fw_name, fw_name_len, "Symbol %s", tmp);
3440 + priv->has_ibss = (firmver >= 0x20000);
3441 + priv->has_wep = (firmver >= 0x15012);
3442 + priv->has_big_wep = (firmver >= 0x20000);
3443 + priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
3444 + (firmver >= 0x29000 && firmver < 0x30000) ||
3445 + firmver >= 0x31000;
3446 + priv->has_preamble = (firmver >= 0x20000);
3447 + priv->ibss_port = 4;
3449 + /* Symbol firmware is found on various cards, but
3450 + * there has been no attempt to check firmware
3451 + * download on non-spectrum_cs based cards.
3453 + * Given that the Agere firmware download works
3454 + * differently, we should avoid doing a firmware
3455 + * download with the Symbol algorithm on non-spectrum
3456 + * cards.
3458 + * For now we can identify a spectrum_cs based card
3459 + * because it has a firmware reset function.
3460 + */
3461 + priv->do_fw_download = (priv->stop_fw != NULL);
3463 + priv->broken_disableport = (firmver == 0x25013) ||
3464 + (firmver >= 0x30000 && firmver <= 0x31000);
3465 + priv->has_hostscan = (firmver >= 0x31001) ||
3466 + (firmver >= 0x29057 && firmver < 0x30000);
3467 + /* Tested with Intel firmware : 0x20015 => Jean II */
3468 + /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
3469 + break;
3470 + case FIRMWARE_TYPE_INTERSIL:
3471 + /* D-Link, Linksys, Adtron, ZoomAir, and many others...
3472 + * Samsung, Compaq 100/200 and Proxim are slightly
3473 + * different and less well tested */
3474 + /* D-Link MAC : 00:40:05:* */
3475 + /* Addtron MAC : 00:90:D1:* */
3476 + if (fw_name)
3477 + snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d",
3478 + sta_id.major, sta_id.minor, sta_id.variant);
3480 + firmver = ((unsigned long)sta_id.major << 16) |
3481 + ((unsigned long)sta_id.minor << 8) | sta_id.variant;
3483 + priv->has_ibss = (firmver >= 0x000700); /* FIXME */
3484 + priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
3485 + priv->has_pm = (firmver >= 0x000700);
3486 + priv->has_hostscan = (firmver >= 0x010301);
3488 + if (firmver >= 0x000800)
3489 + priv->ibss_port = 0;
3490 + else {
3491 + dev_notice(dev, "Intersil firmware earlier than v0.8.x"
3492 + " - several features not supported\n");
3493 + priv->ibss_port = 1;
3495 + break;
3497 + if (fw_name)
3498 + dev_info(dev, "Firmware determined as %s\n", fw_name);
3500 +#ifndef CONFIG_HERMES_PRISM
3501 + if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
3502 + dev_err(dev, "Support for Prism chipset is not enabled\n");
3503 + return -ENODEV;
3505 +#endif
3507 + return 0;
3510 +/* Read settings from EEPROM into our private structure.
3511 + * MAC address gets dropped into callers buffer
3512 + * Can be called before netdev registration.
3513 + */
3514 +int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
3516 + struct device *dev = priv->dev;
3517 + struct hermes_idstring nickbuf;
3518 + struct hermes *hw = &priv->hw;
3519 + int len;
3520 + int err;
3521 + u16 reclen;
3523 + /* Get the MAC address */
3524 + err = hw->ops->read_ltv_pr(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
3525 + ETH_ALEN, NULL, dev_addr);
3526 + if (err) {
3527 + dev_warn(dev, "Failed to read MAC address!\n");
3528 + goto out;
3531 + dev_dbg(dev, "MAC address %pM\n", dev_addr);
3533 + /* Get the station name */
3534 + err = hw->ops->read_ltv_pr(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
3535 + sizeof(nickbuf), &reclen, &nickbuf);
3536 + if (err) {
3537 + dev_err(dev, "failed to read station name\n");
3538 + goto out;
3540 + if (nickbuf.len)
3541 + len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
3542 + else
3543 + len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
3544 + memcpy(priv->nick, &nickbuf.val, len);
3545 + priv->nick[len] = '\0';
3547 + dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
3549 + /* Get allowed channels */
3550 + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CHANNELLIST,
3551 + &priv->channel_mask);
3552 + if (err) {
3553 + dev_err(dev, "Failed to read channel list!\n");
3554 + goto out;
3557 + /* Get initial AP density */
3558 + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
3559 + &priv->ap_density);
3560 + if (err || priv->ap_density < 1 || priv->ap_density > 3)
3561 + priv->has_sensitivity = 0;
3563 + /* Get initial RTS threshold */
3564 + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
3565 + &priv->rts_thresh);
3566 + if (err) {
3567 + dev_err(dev, "Failed to read RTS threshold!\n");
3568 + goto out;
3571 + /* Get initial fragmentation settings */
3572 + if (priv->has_mwo)
3573 + err = hermes_read_wordrec_pr(hw, USER_BAP,
3574 + HERMES_RID_CNFMWOROBUST_AGERE,
3575 + &priv->mwo_robust);
3576 + else
3577 + err = hermes_read_wordrec_pr(hw, USER_BAP,
3578 + HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
3579 + &priv->frag_thresh);
3580 + if (err) {
3581 + dev_err(dev, "Failed to read fragmentation settings!\n");
3582 + goto out;
3585 + /* Power management setup */
3586 + if (priv->has_pm) {
3587 + priv->pm_on = 0;
3588 + priv->pm_mcast = 1;
3589 + err = hermes_read_wordrec_pr(hw, USER_BAP,
3590 + HERMES_RID_CNFMAXSLEEPDURATION,
3591 + &priv->pm_period);
3592 + if (err) {
3593 + dev_err(dev, "Failed to read power management "
3594 + "period!\n");
3595 + goto out;
3597 + err = hermes_read_wordrec_pr(hw, USER_BAP,
3598 + HERMES_RID_CNFPMHOLDOVERDURATION,
3599 + &priv->pm_timeout);
3600 + if (err) {
3601 + dev_err(dev, "Failed to read power management "
3602 + "timeout!\n");
3603 + goto out;
3607 + /* Preamble setup */
3608 + if (priv->has_preamble) {
3609 + err = hermes_read_wordrec_pr(hw, USER_BAP,
3610 + HERMES_RID_CNFPREAMBLE_SYMBOL,
3611 + &priv->preamble);
3612 + if (err) {
3613 + dev_err(dev, "Failed to read preamble setup\n");
3614 + goto out;
3618 + /* Retry settings */
3619 + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
3620 + &priv->short_retry_limit);
3621 + if (err) {
3622 + dev_err(dev, "Failed to read short retry limit\n");
3623 + goto out;
3626 + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
3627 + &priv->long_retry_limit);
3628 + if (err) {
3629 + dev_err(dev, "Failed to read long retry limit\n");
3630 + goto out;
3633 + err = hermes_read_wordrec_pr(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
3634 + &priv->retry_lifetime);
3635 + if (err) {
3636 + dev_err(dev, "Failed to read max retry lifetime\n");
3637 + goto out;
3640 +out:
3641 + return err;
3644 +/* Can be called before netdev registration */
3645 +int orinoco_hw_allocate_fid(struct orinoco_private *priv)
3647 + struct device *dev = priv->dev;
3648 + struct hermes *hw = &priv->hw;
3649 + int err;
3651 + err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
3652 + if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
3653 + /* Try workaround for old Symbol firmware bug */
3654 + priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
3655 + err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
3657 + dev_warn(dev, "Firmware ALLOC bug detected "
3658 + "(old Symbol firmware?). Work around %s\n",
3659 + err ? "failed!" : "ok.");
3662 + return err;
3665 +int orinoco_get_bitratemode(int bitrate, int automatic)
3667 + int ratemode = -1;
3668 + int i;
3670 + if ((bitrate != 10) && (bitrate != 20) &&
3671 + (bitrate != 55) && (bitrate != 110))
3672 + return ratemode;
3674 + for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
3675 + if ((bitrate_table[i].bitrate == bitrate) &&
3676 + (bitrate_table[i].automatic == automatic)) {
3677 + ratemode = i;
3678 + break;
3681 + return ratemode;
3684 +void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
3686 + BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
3688 + *bitrate = bitrate_table[ratemode].bitrate * 100000;
3689 + *automatic = bitrate_table[ratemode].automatic;
3692 +int orinoco_hw_program_rids(struct orinoco_private *priv)
3694 + struct net_device *dev = priv->ndev;
3695 + struct wireless_dev *wdev = netdev_priv(dev);
3696 + struct hermes *hw = &priv->hw;
3697 + int err;
3698 + struct hermes_idstring idbuf;
3700 + /* Set the MAC address */
3701 + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
3702 + HERMES_BYTES_TO_RECLEN(ETH_ALEN),
3703 + dev->dev_addr);
3704 + if (err) {
3705 + printk(KERN_ERR "%s: Error %d setting MAC address\n",
3706 + dev->name, err);
3707 + return err;
3710 + /* Set up the link mode */
3711 + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
3712 + priv->port_type);
3713 + if (err) {
3714 + printk(KERN_ERR "%s: Error %d setting port type\n",
3715 + dev->name, err);
3716 + return err;
3718 + /* Set the channel/frequency */
3719 + if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) {
3720 + err = hermes_write_wordrec(hw, USER_BAP,
3721 + HERMES_RID_CNFOWNCHANNEL,
3722 + priv->channel);
3723 + if (err) {
3724 + printk(KERN_ERR "%s: Error %d setting channel %d\n",
3725 + dev->name, err, priv->channel);
3726 + return err;
3730 + if (priv->has_ibss) {
3731 + u16 createibss;
3733 + if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
3734 + printk(KERN_WARNING "%s: This firmware requires an "
3735 + "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
3736 + /* With wvlan_cs, in this case, we would crash.
3737 + * hopefully, this driver will behave better...
3738 + * Jean II */
3739 + createibss = 0;
3740 + } else {
3741 + createibss = priv->createibss;
3744 + err = hermes_write_wordrec(hw, USER_BAP,
3745 + HERMES_RID_CNFCREATEIBSS,
3746 + createibss);
3747 + if (err) {
3748 + printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
3749 + dev->name, err);
3750 + return err;
3754 + /* Set the desired BSSID */
3755 + err = __orinoco_hw_set_wap(priv);
3756 + if (err) {
3757 + printk(KERN_ERR "%s: Error %d setting AP address\n",
3758 + dev->name, err);
3759 + return err;
3762 + /* Set the desired ESSID */
3763 + idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
3764 + memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
3765 + /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
3766 + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
3767 + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
3768 + &idbuf);
3769 + if (err) {
3770 + printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
3771 + dev->name, err);
3772 + return err;
3774 + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
3775 + HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
3776 + &idbuf);
3777 + if (err) {
3778 + printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
3779 + dev->name, err);
3780 + return err;
3783 + /* Set the station name */
3784 + idbuf.len = cpu_to_le16(strlen(priv->nick));
3785 + memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
3786 + err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
3787 + HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
3788 + &idbuf);
3789 + if (err) {
3790 + printk(KERN_ERR "%s: Error %d setting nickname\n",
3791 + dev->name, err);
3792 + return err;
3795 + /* Set AP density */
3796 + if (priv->has_sensitivity) {
3797 + err = hermes_write_wordrec(hw, USER_BAP,
3798 + HERMES_RID_CNFSYSTEMSCALE,
3799 + priv->ap_density);
3800 + if (err) {
3801 + printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
3802 + "Disabling sensitivity control\n",
3803 + dev->name, err);
3805 + priv->has_sensitivity = 0;
3809 + /* Set RTS threshold */
3810 + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
3811 + priv->rts_thresh);
3812 + if (err) {
3813 + printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
3814 + dev->name, err);
3815 + return err;
3818 + /* Set fragmentation threshold or MWO robustness */
3819 + if (priv->has_mwo)
3820 + err = hermes_write_wordrec(hw, USER_BAP,
3821 + HERMES_RID_CNFMWOROBUST_AGERE,
3822 + priv->mwo_robust);
3823 + else
3824 + err = hermes_write_wordrec(hw, USER_BAP,
3825 + HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
3826 + priv->frag_thresh);
3827 + if (err) {
3828 + printk(KERN_ERR "%s: Error %d setting fragmentation\n",
3829 + dev->name, err);
3830 + return err;
3833 + /* Set bitrate */
3834 + err = __orinoco_hw_set_bitrate(priv);
3835 + if (err) {
3836 + printk(KERN_ERR "%s: Error %d setting bitrate\n",
3837 + dev->name, err);
3838 + return err;
3841 + /* Set power management */
3842 + if (priv->has_pm) {
3843 + err = hermes_write_wordrec(hw, USER_BAP,
3844 + HERMES_RID_CNFPMENABLED,
3845 + priv->pm_on);
3846 + if (err) {
3847 + printk(KERN_ERR "%s: Error %d setting up PM\n",
3848 + dev->name, err);
3849 + return err;
3852 + err = hermes_write_wordrec(hw, USER_BAP,
3853 + HERMES_RID_CNFMULTICASTRECEIVE,
3854 + priv->pm_mcast);
3855 + if (err) {
3856 + printk(KERN_ERR "%s: Error %d setting up PM\n",
3857 + dev->name, err);
3858 + return err;
3860 + err = hermes_write_wordrec(hw, USER_BAP,
3861 + HERMES_RID_CNFMAXSLEEPDURATION,
3862 + priv->pm_period);
3863 + if (err) {
3864 + printk(KERN_ERR "%s: Error %d setting up PM\n",
3865 + dev->name, err);
3866 + return err;
3868 + err = hermes_write_wordrec(hw, USER_BAP,
3869 + HERMES_RID_CNFPMHOLDOVERDURATION,
3870 + priv->pm_timeout);
3871 + if (err) {
3872 + printk(KERN_ERR "%s: Error %d setting up PM\n",
3873 + dev->name, err);
3874 + return err;
3878 + /* Set preamble - only for Symbol so far... */
3879 + if (priv->has_preamble) {
3880 + err = hermes_write_wordrec(hw, USER_BAP,
3881 + HERMES_RID_CNFPREAMBLE_SYMBOL,
3882 + priv->preamble);
3883 + if (err) {
3884 + printk(KERN_ERR "%s: Error %d setting preamble\n",
3885 + dev->name, err);
3886 + return err;
3890 + /* Set up encryption */
3891 + if (priv->has_wep || priv->has_wpa) {
3892 + err = __orinoco_hw_setup_enc(priv);
3893 + if (err) {
3894 + printk(KERN_ERR "%s: Error %d activating encryption\n",
3895 + dev->name, err);
3896 + return err;
3900 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
3901 + /* Enable monitor mode */
3902 + dev->type = ARPHRD_IEEE80211;
3903 + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
3904 + HERMES_TEST_MONITOR, 0, NULL);
3905 + } else {
3906 + /* Disable monitor mode */
3907 + dev->type = ARPHRD_ETHER;
3908 + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
3909 + HERMES_TEST_STOP, 0, NULL);
3911 + if (err)
3912 + return err;
3914 + /* Reset promiscuity / multicast*/
3915 + priv->promiscuous = 0;
3916 + priv->mc_count = 0;
3918 + /* Record mode change */
3919 + wdev->iftype = priv->iw_mode;
3921 + return 0;
3924 +/* Get tsc from the firmware */
3925 +int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
3927 + struct hermes *hw = &priv->hw;
3928 + int err = 0;
3929 + u8 tsc_arr[4][ORINOCO_SEQ_LEN];
3931 + if ((key < 0) || (key >= 4))
3932 + return -EINVAL;
3934 + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
3935 + sizeof(tsc_arr), NULL, &tsc_arr);
3936 + if (!err)
3937 + memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
3939 + return err;
3942 +int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
3944 + struct hermes *hw = &priv->hw;
3945 + int ratemode = priv->bitratemode;
3946 + int err = 0;
3948 + if (ratemode >= BITRATE_TABLE_SIZE) {
3949 + printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
3950 + priv->ndev->name, ratemode);
3951 + return -EINVAL;
3954 + switch (priv->firmware_type) {
3955 + case FIRMWARE_TYPE_AGERE:
3956 + err = hermes_write_wordrec(hw, USER_BAP,
3957 + HERMES_RID_CNFTXRATECONTROL,
3958 + bitrate_table[ratemode].agere_txratectrl);
3959 + break;
3960 + case FIRMWARE_TYPE_INTERSIL:
3961 + case FIRMWARE_TYPE_SYMBOL:
3962 + err = hermes_write_wordrec(hw, USER_BAP,
3963 + HERMES_RID_CNFTXRATECONTROL,
3964 + bitrate_table[ratemode].intersil_txratectrl);
3965 + break;
3966 + default:
3967 + BUG();
3970 + return err;
3973 +int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
3975 + struct hermes *hw = &priv->hw;
3976 + int i;
3977 + int err = 0;
3978 + u16 val;
3980 + err = hermes_read_wordrec(hw, USER_BAP,
3981 + HERMES_RID_CURRENTTXRATE, &val);
3982 + if (err)
3983 + return err;
3985 + switch (priv->firmware_type) {
3986 + case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
3987 + /* Note : in Lucent firmware, the return value of
3988 + * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
3989 + * and therefore is totally different from the
3990 + * encoding of HERMES_RID_CNFTXRATECONTROL.
3991 + * Don't forget that 6Mb/s is really 5.5Mb/s */
3992 + if (val == 6)
3993 + *bitrate = 5500000;
3994 + else
3995 + *bitrate = val * 1000000;
3996 + break;
3997 + case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
3998 + case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
3999 + for (i = 0; i < BITRATE_TABLE_SIZE; i++)
4000 + if (bitrate_table[i].intersil_txratectrl == val) {
4001 + *bitrate = bitrate_table[i].bitrate * 100000;
4002 + break;
4005 + if (i >= BITRATE_TABLE_SIZE) {
4006 + printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
4007 + priv->ndev->name, val);
4008 + err = -EIO;
4011 + break;
4012 + default:
4013 + BUG();
4016 + return err;
4019 +/* Set fixed AP address */
4020 +int __orinoco_hw_set_wap(struct orinoco_private *priv)
4022 + int roaming_flag;
4023 + int err = 0;
4024 + struct hermes *hw = &priv->hw;
4026 + switch (priv->firmware_type) {
4027 + case FIRMWARE_TYPE_AGERE:
4028 + /* not supported */
4029 + break;
4030 + case FIRMWARE_TYPE_INTERSIL:
4031 + if (priv->bssid_fixed)
4032 + roaming_flag = 2;
4033 + else
4034 + roaming_flag = 1;
4036 + err = hermes_write_wordrec(hw, USER_BAP,
4037 + HERMES_RID_CNFROAMINGMODE,
4038 + roaming_flag);
4039 + break;
4040 + case FIRMWARE_TYPE_SYMBOL:
4041 + err = HERMES_WRITE_RECORD(hw, USER_BAP,
4042 + HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
4043 + &priv->desired_bssid);
4044 + break;
4046 + return err;
4049 +/* Change the WEP keys and/or the current keys. Can be called
4050 + * either from __orinoco_hw_setup_enc() or directly from
4051 + * orinoco_ioctl_setiwencode(). In the later case the association
4052 + * with the AP is not broken (if the firmware can handle it),
4053 + * which is needed for 802.1x implementations. */
4054 +int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
4056 + struct hermes *hw = &priv->hw;
4057 + int err = 0;
4058 + int i;
4060 + switch (priv->firmware_type) {
4061 + case FIRMWARE_TYPE_AGERE:
4063 + struct orinoco_key keys[ORINOCO_MAX_KEYS];
4065 + memset(&keys, 0, sizeof(keys));
4066 + for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
4067 + int len = min(priv->keys[i].key_len,
4068 + ORINOCO_MAX_KEY_SIZE);
4069 + memcpy(&keys[i].data, priv->keys[i].key, len);
4070 + if (len > SMALL_KEY_SIZE)
4071 + keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
4072 + else if (len > 0)
4073 + keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
4074 + else
4075 + keys[i].len = cpu_to_le16(0);
4078 + err = HERMES_WRITE_RECORD(hw, USER_BAP,
4079 + HERMES_RID_CNFWEPKEYS_AGERE,
4080 + &keys);
4081 + if (err)
4082 + return err;
4083 + err = hermes_write_wordrec(hw, USER_BAP,
4084 + HERMES_RID_CNFTXKEY_AGERE,
4085 + priv->tx_key);
4086 + if (err)
4087 + return err;
4088 + break;
4090 + case FIRMWARE_TYPE_INTERSIL:
4091 + case FIRMWARE_TYPE_SYMBOL:
4093 + int keylen;
4095 + /* Force uniform key length to work around
4096 + * firmware bugs */
4097 + keylen = priv->keys[priv->tx_key].key_len;
4099 + if (keylen > LARGE_KEY_SIZE) {
4100 + printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
4101 + priv->ndev->name, priv->tx_key, keylen);
4102 + return -E2BIG;
4103 + } else if (keylen > SMALL_KEY_SIZE)
4104 + keylen = LARGE_KEY_SIZE;
4105 + else if (keylen > 0)
4106 + keylen = SMALL_KEY_SIZE;
4107 + else
4108 + keylen = 0;
4110 + /* Write all 4 keys */
4111 + for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
4112 + u8 key[LARGE_KEY_SIZE] = { 0 };
4114 + memcpy(key, priv->keys[i].key,
4115 + priv->keys[i].key_len);
4117 + err = hw->ops->write_ltv(hw, USER_BAP,
4118 + HERMES_RID_CNFDEFAULTKEY0 + i,
4119 + HERMES_BYTES_TO_RECLEN(keylen),
4120 + key);
4121 + if (err)
4122 + return err;
4125 + /* Write the index of the key used in transmission */
4126 + err = hermes_write_wordrec(hw, USER_BAP,
4127 + HERMES_RID_CNFWEPDEFAULTKEYID,
4128 + priv->tx_key);
4129 + if (err)
4130 + return err;
4132 + break;
4135 + return 0;
4138 +int __orinoco_hw_setup_enc(struct orinoco_private *priv)
4140 + struct hermes *hw = &priv->hw;
4141 + int err = 0;
4142 + int master_wep_flag;
4143 + int auth_flag;
4144 + int enc_flag;
4146 + /* Setup WEP keys */
4147 + if (priv->encode_alg == ORINOCO_ALG_WEP)
4148 + __orinoco_hw_setup_wepkeys(priv);
4150 + if (priv->wep_restrict)
4151 + auth_flag = HERMES_AUTH_SHARED_KEY;
4152 + else
4153 + auth_flag = HERMES_AUTH_OPEN;
4155 + if (priv->wpa_enabled)
4156 + enc_flag = 2;
4157 + else if (priv->encode_alg == ORINOCO_ALG_WEP)
4158 + enc_flag = 1;
4159 + else
4160 + enc_flag = 0;
4162 + switch (priv->firmware_type) {
4163 + case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
4164 + if (priv->encode_alg == ORINOCO_ALG_WEP) {
4165 + /* Enable the shared-key authentication. */
4166 + err = hermes_write_wordrec(hw, USER_BAP,
4167 + HERMES_RID_CNFAUTHENTICATION_AGERE,
4168 + auth_flag);
4169 + if (err)
4170 + return err;
4172 + err = hermes_write_wordrec(hw, USER_BAP,
4173 + HERMES_RID_CNFWEPENABLED_AGERE,
4174 + enc_flag);
4175 + if (err)
4176 + return err;
4178 + if (priv->has_wpa) {
4179 + /* Set WPA key management */
4180 + err = hermes_write_wordrec(hw, USER_BAP,
4181 + HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
4182 + priv->key_mgmt);
4183 + if (err)
4184 + return err;
4187 + break;
4189 + case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
4190 + case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
4191 + if (priv->encode_alg == ORINOCO_ALG_WEP) {
4192 + if (priv->wep_restrict ||
4193 + (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
4194 + master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
4195 + HERMES_WEP_EXCL_UNENCRYPTED;
4196 + else
4197 + master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
4199 + err = hermes_write_wordrec(hw, USER_BAP,
4200 + HERMES_RID_CNFAUTHENTICATION,
4201 + auth_flag);
4202 + if (err)
4203 + return err;
4204 + } else
4205 + master_wep_flag = 0;
4207 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
4208 + master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
4210 + /* Master WEP setting : on/off */
4211 + err = hermes_write_wordrec(hw, USER_BAP,
4212 + HERMES_RID_CNFWEPFLAGS_INTERSIL,
4213 + master_wep_flag);
4214 + if (err)
4215 + return err;
4217 + break;
4220 + return 0;
4223 +/* key must be 32 bytes, including the tx and rx MIC keys.
4224 + * rsc must be NULL or up to 8 bytes
4225 + * tsc must be NULL or up to 8 bytes
4226 + */
4227 +int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
4228 + int set_tx, const u8 *key, size_t key_len,
4229 + const u8 *rsc, size_t rsc_len,
4230 + const u8 *tsc, size_t tsc_len)
4232 + struct {
4233 + __le16 idx;
4234 + u8 rsc[ORINOCO_SEQ_LEN];
4235 + struct {
4236 + u8 key[TKIP_KEYLEN];
4237 + u8 tx_mic[MIC_KEYLEN];
4238 + u8 rx_mic[MIC_KEYLEN];
4239 + } tkip;
4240 + u8 tsc[ORINOCO_SEQ_LEN];
4241 + } __packed buf;
4242 + struct hermes *hw = &priv->hw;
4243 + int ret;
4244 + int err;
4245 + int k;
4246 + u16 xmitting;
4248 + key_idx &= 0x3;
4250 + if (set_tx)
4251 + key_idx |= 0x8000;
4253 + buf.idx = cpu_to_le16(key_idx);
4254 + if (key_len != sizeof(buf.tkip))
4255 + return -EINVAL;
4256 + memcpy(&buf.tkip, key, sizeof(buf.tkip));
4258 + if (rsc_len > sizeof(buf.rsc))
4259 + rsc_len = sizeof(buf.rsc);
4261 + if (tsc_len > sizeof(buf.tsc))
4262 + tsc_len = sizeof(buf.tsc);
4264 + memset(buf.rsc, 0, sizeof(buf.rsc));
4265 + memset(buf.tsc, 0, sizeof(buf.tsc));
4267 + if (rsc != NULL)
4268 + memcpy(buf.rsc, rsc, rsc_len);
4270 + if (tsc != NULL)
4271 + memcpy(buf.tsc, tsc, tsc_len);
4272 + else
4273 + buf.tsc[4] = 0x10;
4275 + /* Wait up to 100ms for tx queue to empty */
4276 + for (k = 100; k > 0; k--) {
4277 + udelay(1000);
4278 + ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
4279 + &xmitting);
4280 + if (ret || !xmitting)
4281 + break;
4284 + if (k == 0)
4285 + ret = -ETIMEDOUT;
4287 + err = HERMES_WRITE_RECORD(hw, USER_BAP,
4288 + HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
4289 + &buf);
4291 + return ret ? ret : err;
4294 +int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
4296 + struct hermes *hw = &priv->hw;
4297 + int err;
4299 + err = hermes_write_wordrec(hw, USER_BAP,
4300 + HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
4301 + key_idx);
4302 + if (err)
4303 + printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
4304 + priv->ndev->name, err, key_idx);
4305 + return err;
4308 +int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
4309 + struct net_device *dev,
4310 + int mc_count, int promisc)
4312 + struct hermes *hw = &priv->hw;
4313 + int err = 0;
4315 + if (promisc != priv->promiscuous) {
4316 + err = hermes_write_wordrec(hw, USER_BAP,
4317 + HERMES_RID_CNFPROMISCUOUSMODE,
4318 + promisc);
4319 + if (err) {
4320 + printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
4321 + priv->ndev->name, err);
4322 + } else
4323 + priv->promiscuous = promisc;
4326 + /* If we're not in promiscuous mode, then we need to set the
4327 + * group address if either we want to multicast, or if we were
4328 + * multicasting and want to stop */
4329 + if (!promisc && (mc_count || priv->mc_count)) {
4330 + struct netdev_hw_addr *ha;
4331 + struct hermes_multicast mclist;
4332 + int i = 0;
4334 + netdev_for_each_mc_addr(ha, dev) {
4335 + if (i == mc_count)
4336 + break;
4337 + memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
4340 + err = hw->ops->write_ltv(hw, USER_BAP,
4341 + HERMES_RID_CNFGROUPADDRESSES,
4342 + HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
4343 + &mclist);
4344 + if (err)
4345 + printk(KERN_ERR "%s: Error %d setting multicast list.\n",
4346 + priv->ndev->name, err);
4347 + else
4348 + priv->mc_count = mc_count;
4350 + return err;
4353 +/* Return : < 0 -> error code ; >= 0 -> length */
4354 +int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
4355 + char buf[IW_ESSID_MAX_SIZE + 1])
4357 + struct hermes *hw = &priv->hw;
4358 + int err = 0;
4359 + struct hermes_idstring essidbuf;
4360 + char *p = (char *)(&essidbuf.val);
4361 + int len;
4362 + unsigned long flags;
4364 + if (orinoco_lock(priv, &flags) != 0)
4365 + return -EBUSY;
4367 + if (strlen(priv->desired_essid) > 0) {
4368 + /* We read the desired SSID from the hardware rather
4369 + than from priv->desired_essid, just in case the
4370 + firmware is allowed to change it on us. I'm not
4371 + sure about this */
4372 + /* My guess is that the OWNSSID should always be whatever
4373 + * we set to the card, whereas CURRENT_SSID is the one that
4374 + * may change... - Jean II */
4375 + u16 rid;
4377 + *active = 1;
4379 + rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
4380 + HERMES_RID_CNFDESIREDSSID;
4382 + err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
4383 + NULL, &essidbuf);
4384 + if (err)
4385 + goto fail_unlock;
4386 + } else {
4387 + *active = 0;
4389 + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
4390 + sizeof(essidbuf), NULL, &essidbuf);
4391 + if (err)
4392 + goto fail_unlock;
4395 + len = le16_to_cpu(essidbuf.len);
4396 + BUG_ON(len > IW_ESSID_MAX_SIZE);
4398 + memset(buf, 0, IW_ESSID_MAX_SIZE);
4399 + memcpy(buf, p, len);
4400 + err = len;
4402 + fail_unlock:
4403 + orinoco_unlock(priv, &flags);
4405 + return err;
4408 +int orinoco_hw_get_freq(struct orinoco_private *priv)
4410 + struct hermes *hw = &priv->hw;
4411 + int err = 0;
4412 + u16 channel;
4413 + int freq = 0;
4414 + unsigned long flags;
4416 + if (orinoco_lock(priv, &flags) != 0)
4417 + return -EBUSY;
4419 + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
4420 + &channel);
4421 + if (err)
4422 + goto out;
4424 + /* Intersil firmware 1.3.5 returns 0 when the interface is down */
4425 + if (channel == 0) {
4426 + err = -EBUSY;
4427 + goto out;
4430 + if ((channel < 1) || (channel > NUM_CHANNELS)) {
4431 + printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
4432 + priv->ndev->name, channel);
4433 + err = -EBUSY;
4434 + goto out;
4437 + freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
4439 + out:
4440 + orinoco_unlock(priv, &flags);
4442 + if (err > 0)
4443 + err = -EBUSY;
4444 + return err ? err : freq;
4447 +int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
4448 + int *numrates, s32 *rates, int max)
4450 + struct hermes *hw = &priv->hw;
4451 + struct hermes_idstring list;
4452 + unsigned char *p = (unsigned char *)&list.val;
4453 + int err = 0;
4454 + int num;
4455 + int i;
4456 + unsigned long flags;
4458 + if (orinoco_lock(priv, &flags) != 0)
4459 + return -EBUSY;
4461 + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
4462 + sizeof(list), NULL, &list);
4463 + orinoco_unlock(priv, &flags);
4465 + if (err)
4466 + return err;
4468 + num = le16_to_cpu(list.len);
4469 + *numrates = num;
4470 + num = min(num, max);
4472 + for (i = 0; i < num; i++)
4473 + rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
4475 + return 0;
4478 +int orinoco_hw_trigger_scan(struct orinoco_private *priv,
4479 + const struct cfg80211_ssid *ssid)
4481 + struct net_device *dev = priv->ndev;
4482 + struct hermes *hw = &priv->hw;
4483 + unsigned long flags;
4484 + int err = 0;
4486 + if (orinoco_lock(priv, &flags) != 0)
4487 + return -EBUSY;
4489 + /* Scanning with port 0 disabled would fail */
4490 + if (!netif_running(dev)) {
4491 + err = -ENETDOWN;
4492 + goto out;
4495 + /* In monitor mode, the scan results are always empty.
4496 + * Probe responses are passed to the driver as received
4497 + * frames and could be processed in software. */
4498 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
4499 + err = -EOPNOTSUPP;
4500 + goto out;
4503 + if (priv->has_hostscan) {
4504 + switch (priv->firmware_type) {
4505 + case FIRMWARE_TYPE_SYMBOL:
4506 + err = hermes_write_wordrec(hw, USER_BAP,
4507 + HERMES_RID_CNFHOSTSCAN_SYMBOL,
4508 + HERMES_HOSTSCAN_SYMBOL_ONCE |
4509 + HERMES_HOSTSCAN_SYMBOL_BCAST);
4510 + break;
4511 + case FIRMWARE_TYPE_INTERSIL: {
4512 + __le16 req[3];
4514 + req[0] = cpu_to_le16(0x3fff); /* All channels */
4515 + req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
4516 + req[2] = 0; /* Any ESSID */
4517 + err = HERMES_WRITE_RECORD(hw, USER_BAP,
4518 + HERMES_RID_CNFHOSTSCAN, &req);
4519 + break;
4521 + case FIRMWARE_TYPE_AGERE:
4522 + if (ssid->ssid_len > 0) {
4523 + struct hermes_idstring idbuf;
4524 + size_t len = ssid->ssid_len;
4526 + idbuf.len = cpu_to_le16(len);
4527 + memcpy(idbuf.val, ssid->ssid, len);
4529 + err = hw->ops->write_ltv(hw, USER_BAP,
4530 + HERMES_RID_CNFSCANSSID_AGERE,
4531 + HERMES_BYTES_TO_RECLEN(len + 2),
4532 + &idbuf);
4533 + } else
4534 + err = hermes_write_wordrec(hw, USER_BAP,
4535 + HERMES_RID_CNFSCANSSID_AGERE,
4536 + 0); /* Any ESSID */
4537 + if (err)
4538 + break;
4540 + if (priv->has_ext_scan) {
4541 + err = hermes_write_wordrec(hw, USER_BAP,
4542 + HERMES_RID_CNFSCANCHANNELS2GHZ,
4543 + 0x7FFF);
4544 + if (err)
4545 + goto out;
4547 + err = hermes_inquire(hw,
4548 + HERMES_INQ_CHANNELINFO);
4549 + } else
4550 + err = hermes_inquire(hw, HERMES_INQ_SCAN);
4552 + break;
4554 + } else
4555 + err = hermes_inquire(hw, HERMES_INQ_SCAN);
4557 + out:
4558 + orinoco_unlock(priv, &flags);
4560 + return err;
4563 +/* Disassociate from node with BSSID addr */
4564 +int orinoco_hw_disassociate(struct orinoco_private *priv,
4565 + u8 *addr, u16 reason_code)
4567 + struct hermes *hw = &priv->hw;
4568 + int err;
4570 + struct {
4571 + u8 addr[ETH_ALEN];
4572 + __le16 reason_code;
4573 + } __packed buf;
4575 + /* Currently only supported by WPA enabled Agere fw */
4576 + if (!priv->has_wpa)
4577 + return -EOPNOTSUPP;
4579 + memcpy(buf.addr, addr, ETH_ALEN);
4580 + buf.reason_code = cpu_to_le16(reason_code);
4581 + err = HERMES_WRITE_RECORD(hw, USER_BAP,
4582 + HERMES_RID_CNFDISASSOCIATE,
4583 + &buf);
4584 + return err;
4587 +int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
4588 + u8 *addr)
4590 + struct hermes *hw = &priv->hw;
4591 + int err;
4593 + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
4594 + ETH_ALEN, NULL, addr);
4596 + return err;
4598 --- /dev/null
4599 +++ a/drivers/net/wireless/intersil/orinoco/hw.h
4600 @@ -0,0 +1,60 @@
4601 +/* Encapsulate basic setting changes on Hermes hardware
4603 + * See copyright notice in main.c
4604 + */
4605 +#ifndef _ORINOCO_HW_H_
4606 +#define _ORINOCO_HW_H_
4608 +#include <linux/types.h>
4609 +#include <linux/wireless.h>
4610 +#include <net/cfg80211.h>
4612 +/* Hardware BAPs */
4613 +#define USER_BAP 0
4614 +#define IRQ_BAP 1
4616 +/* WEP key sizes */
4617 +#define SMALL_KEY_SIZE 5
4618 +#define LARGE_KEY_SIZE 13
4620 +/* Number of supported channels */
4621 +#define NUM_CHANNELS 14
4623 +/* Forward declarations */
4624 +struct orinoco_private;
4626 +int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name,
4627 + size_t fw_name_len, u32 *hw_ver);
4628 +int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr);
4629 +int orinoco_hw_allocate_fid(struct orinoco_private *priv);
4630 +int orinoco_get_bitratemode(int bitrate, int automatic);
4631 +void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic);
4633 +int orinoco_hw_program_rids(struct orinoco_private *priv);
4634 +int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc);
4635 +int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
4636 +int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate);
4637 +int __orinoco_hw_set_wap(struct orinoco_private *priv);
4638 +int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
4639 +int __orinoco_hw_setup_enc(struct orinoco_private *priv);
4640 +int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
4641 + int set_tx, const u8 *key, size_t key_len,
4642 + const u8 *rsc, size_t rsc_len,
4643 + const u8 *tsc, size_t tsc_len);
4644 +int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
4645 +int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
4646 + struct net_device *dev,
4647 + int mc_count, int promisc);
4648 +int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
4649 + char buf[IW_ESSID_MAX_SIZE + 1]);
4650 +int orinoco_hw_get_freq(struct orinoco_private *priv);
4651 +int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
4652 + int *numrates, s32 *rates, int max);
4653 +int orinoco_hw_trigger_scan(struct orinoco_private *priv,
4654 + const struct cfg80211_ssid *ssid);
4655 +int orinoco_hw_disassociate(struct orinoco_private *priv,
4656 + u8 *addr, u16 reason_code);
4657 +int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
4658 + u8 *addr);
4660 +#endif /* _ORINOCO_HW_H_ */
4661 --- /dev/null
4662 +++ a/drivers/net/wireless/intersil/orinoco/main.c
4663 @@ -0,0 +1,2414 @@
4664 +/* main.c - (formerly known as dldwd_cs.c, orinoco_cs.c and orinoco.c)
4666 + * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
4667 + * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
4669 + * Current maintainers (as of 29 September 2003) are:
4670 + * Pavel Roskin <proski AT gnu.org>
4671 + * and David Gibson <hermes AT gibson.dropbear.id.au>
4673 + * (C) Copyright David Gibson, IBM Corporation 2001-2003.
4674 + * Copyright (C) 2000 David Gibson, Linuxcare Australia.
4675 + * With some help from :
4676 + * Copyright (C) 2001 Jean Tourrilhes, HP Labs
4677 + * Copyright (C) 2001 Benjamin Herrenschmidt
4679 + * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
4681 + * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
4682 + * AT fasta.fh-dortmund.de>
4683 + * http://www.stud.fh-dortmund.de/~andy/wvlan/
4685 + * The contents of this file are subject to the Mozilla Public License
4686 + * Version 1.1 (the "License"); you may not use this file except in
4687 + * compliance with the License. You may obtain a copy of the License
4688 + * at http://www.mozilla.org/MPL/
4690 + * Software distributed under the License is distributed on an "AS IS"
4691 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
4692 + * the License for the specific language governing rights and
4693 + * limitations under the License.
4695 + * The initial developer of the original code is David A. Hinds
4696 + * <dahinds AT users.sourceforge.net>. Portions created by David
4697 + * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
4698 + * Reserved.
4700 + * Alternatively, the contents of this file may be used under the
4701 + * terms of the GNU General Public License version 2 (the "GPL"), in
4702 + * which case the provisions of the GPL are applicable instead of the
4703 + * above. If you wish to allow the use of your version of this file
4704 + * only under the terms of the GPL and not to allow others to use your
4705 + * version of this file under the MPL, indicate your decision by
4706 + * deleting the provisions above and replace them with the notice and
4707 + * other provisions required by the GPL. If you do not delete the
4708 + * provisions above, a recipient may use your version of this file
4709 + * under either the MPL or the GPL. */
4712 + * TODO
4713 + * o Handle de-encapsulation within network layer, provide 802.11
4714 + * headers (patch from Thomas 'Dent' Mirlacher)
4715 + * o Fix possible races in SPY handling.
4716 + * o Disconnect wireless extensions from fundamental configuration.
4717 + * o (maybe) Software WEP support (patch from Stano Meduna).
4718 + * o (maybe) Use multiple Tx buffers - driver handling queue
4719 + * rather than firmware.
4720 + */
4722 +/* Locking and synchronization:
4724 + * The basic principle is that everything is serialized through a
4725 + * single spinlock, priv->lock. The lock is used in user, bh and irq
4726 + * context, so when taken outside hardirq context it should always be
4727 + * taken with interrupts disabled. The lock protects both the
4728 + * hardware and the struct orinoco_private.
4730 + * Another flag, priv->hw_unavailable indicates that the hardware is
4731 + * unavailable for an extended period of time (e.g. suspended, or in
4732 + * the middle of a hard reset). This flag is protected by the
4733 + * spinlock. All code which touches the hardware should check the
4734 + * flag after taking the lock, and if it is set, give up on whatever
4735 + * they are doing and drop the lock again. The orinoco_lock()
4736 + * function handles this (it unlocks and returns -EBUSY if
4737 + * hw_unavailable is non-zero).
4738 + */
4740 +#define DRIVER_NAME "orinoco"
4742 +#include <linux/module.h>
4743 +#include <linux/kernel.h>
4744 +#include <linux/slab.h>
4745 +#include <linux/init.h>
4746 +#include <linux/delay.h>
4747 +#include <linux/device.h>
4748 +#include <linux/netdevice.h>
4749 +#include <linux/etherdevice.h>
4750 +#include <linux/suspend.h>
4751 +#include <linux/if_arp.h>
4752 +#include <linux/wireless.h>
4753 +#include <linux/ieee80211.h>
4754 +#include <net/iw_handler.h>
4755 +#include <net/cfg80211.h>
4757 +#include "hermes_rid.h"
4758 +#include "hermes_dld.h"
4759 +#include "hw.h"
4760 +#include "scan.h"
4761 +#include "mic.h"
4762 +#include "fw.h"
4763 +#include "wext.h"
4764 +#include "cfg.h"
4765 +#include "main.h"
4767 +#include "orinoco.h"
4769 +/********************************************************************/
4770 +/* Module information */
4771 +/********************************************************************/
4773 +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & "
4774 + "David Gibson <hermes@gibson.dropbear.id.au>");
4775 +MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based "
4776 + "and similar wireless cards");
4777 +MODULE_LICENSE("Dual MPL/GPL");
4779 +/* Level of debugging. Used in the macros in orinoco.h */
4780 +#ifdef ORINOCO_DEBUG
4781 +int orinoco_debug = ORINOCO_DEBUG;
4782 +EXPORT_SYMBOL(orinoco_debug);
4783 +module_param(orinoco_debug, int, 0644);
4784 +MODULE_PARM_DESC(orinoco_debug, "Debug level");
4785 +#endif
4787 +static bool suppress_linkstatus; /* = 0 */
4788 +module_param(suppress_linkstatus, bool, 0644);
4789 +MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
4791 +static int ignore_disconnect; /* = 0 */
4792 +module_param(ignore_disconnect, int, 0644);
4793 +MODULE_PARM_DESC(ignore_disconnect,
4794 + "Don't report lost link to the network layer");
4796 +int force_monitor; /* = 0 */
4797 +module_param(force_monitor, int, 0644);
4798 +MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
4800 +/********************************************************************/
4801 +/* Internal constants */
4802 +/********************************************************************/
4804 +/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
4805 +static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
4806 +#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
4808 +#define ORINOCO_MIN_MTU 256
4809 +#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
4811 +#define MAX_IRQLOOPS_PER_IRQ 10
4812 +#define MAX_IRQLOOPS_PER_JIFFY (20000 / HZ) /* Based on a guestimate of
4813 + * how many events the
4814 + * device could
4815 + * legitimately generate */
4817 +#define DUMMY_FID 0xFFFF
4819 +/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
4820 + HERMES_MAX_MULTICAST : 0)*/
4821 +#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
4823 +#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
4824 + | HERMES_EV_TX | HERMES_EV_TXEXC \
4825 + | HERMES_EV_WTERR | HERMES_EV_INFO \
4826 + | HERMES_EV_INFDROP)
4828 +/********************************************************************/
4829 +/* Data types */
4830 +/********************************************************************/
4832 +/* Beginning of the Tx descriptor, used in TxExc handling */
4833 +struct hermes_txexc_data {
4834 + struct hermes_tx_descriptor desc;
4835 + __le16 frame_ctl;
4836 + __le16 duration_id;
4837 + u8 addr1[ETH_ALEN];
4838 +} __packed;
4840 +/* Rx frame header except compatibility 802.3 header */
4841 +struct hermes_rx_descriptor {
4842 + /* Control */
4843 + __le16 status;
4844 + __le32 time;
4845 + u8 silence;
4846 + u8 signal;
4847 + u8 rate;
4848 + u8 rxflow;
4849 + __le32 reserved;
4851 + /* 802.11 header */
4852 + __le16 frame_ctl;
4853 + __le16 duration_id;
4854 + u8 addr1[ETH_ALEN];
4855 + u8 addr2[ETH_ALEN];
4856 + u8 addr3[ETH_ALEN];
4857 + __le16 seq_ctl;
4858 + u8 addr4[ETH_ALEN];
4860 + /* Data length */
4861 + __le16 data_len;
4862 +} __packed;
4864 +struct orinoco_rx_data {
4865 + struct hermes_rx_descriptor *desc;
4866 + struct sk_buff *skb;
4867 + struct list_head list;
4870 +struct orinoco_scan_data {
4871 + void *buf;
4872 + size_t len;
4873 + int type;
4874 + struct list_head list;
4877 +/********************************************************************/
4878 +/* Function prototypes */
4879 +/********************************************************************/
4881 +static int __orinoco_set_multicast_list(struct net_device *dev);
4882 +static int __orinoco_up(struct orinoco_private *priv);
4883 +static int __orinoco_down(struct orinoco_private *priv);
4884 +static int __orinoco_commit(struct orinoco_private *priv);
4886 +/********************************************************************/
4887 +/* Internal helper functions */
4888 +/********************************************************************/
4890 +void set_port_type(struct orinoco_private *priv)
4892 + switch (priv->iw_mode) {
4893 + case NL80211_IFTYPE_STATION:
4894 + priv->port_type = 1;
4895 + priv->createibss = 0;
4896 + break;
4897 + case NL80211_IFTYPE_ADHOC:
4898 + if (priv->prefer_port3) {
4899 + priv->port_type = 3;
4900 + priv->createibss = 0;
4901 + } else {
4902 + priv->port_type = priv->ibss_port;
4903 + priv->createibss = 1;
4905 + break;
4906 + case NL80211_IFTYPE_MONITOR:
4907 + priv->port_type = 3;
4908 + priv->createibss = 0;
4909 + break;
4910 + default:
4911 + printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
4912 + priv->ndev->name);
4916 +/********************************************************************/
4917 +/* Device methods */
4918 +/********************************************************************/
4920 +int orinoco_open(struct net_device *dev)
4922 + struct orinoco_private *priv = ndev_priv(dev);
4923 + unsigned long flags;
4924 + int err;
4926 + if (orinoco_lock(priv, &flags) != 0)
4927 + return -EBUSY;
4929 + err = __orinoco_up(priv);
4931 + if (!err)
4932 + priv->open = 1;
4934 + orinoco_unlock(priv, &flags);
4936 + return err;
4938 +EXPORT_SYMBOL(orinoco_open);
4940 +int orinoco_stop(struct net_device *dev)
4942 + struct orinoco_private *priv = ndev_priv(dev);
4943 + int err = 0;
4945 + /* We mustn't use orinoco_lock() here, because we need to be
4946 + able to close the interface even if hw_unavailable is set
4947 + (e.g. as we're released after a PC Card removal) */
4948 + orinoco_lock_irq(priv);
4950 + priv->open = 0;
4952 + err = __orinoco_down(priv);
4954 + orinoco_unlock_irq(priv);
4956 + return err;
4958 +EXPORT_SYMBOL(orinoco_stop);
4960 +void orinoco_set_multicast_list(struct net_device *dev)
4962 + struct orinoco_private *priv = ndev_priv(dev);
4963 + unsigned long flags;
4965 + if (orinoco_lock(priv, &flags) != 0) {
4966 + printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
4967 + "called when hw_unavailable\n", dev->name);
4968 + return;
4971 + __orinoco_set_multicast_list(dev);
4972 + orinoco_unlock(priv, &flags);
4974 +EXPORT_SYMBOL(orinoco_set_multicast_list);
4976 +int orinoco_change_mtu(struct net_device *dev, int new_mtu)
4978 + struct orinoco_private *priv = ndev_priv(dev);
4980 + /* MTU + encapsulation + header length */
4981 + if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
4982 + (priv->nicbuf_size - ETH_HLEN))
4983 + return -EINVAL;
4985 + dev->mtu = new_mtu;
4987 + return 0;
4989 +EXPORT_SYMBOL(orinoco_change_mtu);
4991 +/********************************************************************/
4992 +/* Tx path */
4993 +/********************************************************************/
4995 +/* Add encapsulation and MIC to the existing SKB.
4996 + * The main xmit routine will then send the whole lot to the card.
4997 + * Need 8 bytes headroom
4998 + * Need 8 bytes tailroom
5000 + * With encapsulated ethernet II frame
5001 + * --------
5002 + * 803.3 header (14 bytes)
5003 + * dst[6]
5004 + * -------- src[6]
5005 + * 803.3 header (14 bytes) len[2]
5006 + * dst[6] 803.2 header (8 bytes)
5007 + * src[6] encaps[6]
5008 + * len[2] <- leave alone -> len[2]
5009 + * -------- -------- <-- 0
5010 + * Payload Payload
5011 + * ... ...
5013 + * -------- --------
5014 + * MIC (8 bytes)
5015 + * --------
5017 + * returns 0 on success, -ENOMEM on error.
5018 + */
5019 +int orinoco_process_xmit_skb(struct sk_buff *skb,
5020 + struct net_device *dev,
5021 + struct orinoco_private *priv,
5022 + int *tx_control,
5023 + u8 *mic_buf)
5025 + struct orinoco_tkip_key *key;
5026 + struct ethhdr *eh;
5027 + int do_mic;
5029 + key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
5031 + do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
5032 + (key != NULL));
5034 + if (do_mic)
5035 + *tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
5036 + HERMES_TXCTRL_MIC;
5038 + eh = (struct ethhdr *)skb->data;
5040 + /* Encapsulate Ethernet-II frames */
5041 + if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
5042 + struct header_struct {
5043 + struct ethhdr eth; /* 802.3 header */
5044 + u8 encap[6]; /* 802.2 header */
5045 + } __packed hdr;
5046 + int len = skb->len + sizeof(encaps_hdr) - (2 * ETH_ALEN);
5048 + if (skb_headroom(skb) < ENCAPS_OVERHEAD) {
5049 + if (net_ratelimit())
5050 + printk(KERN_ERR
5051 + "%s: Not enough headroom for 802.2 headers %d\n",
5052 + dev->name, skb_headroom(skb));
5053 + return -ENOMEM;
5056 + /* Fill in new header */
5057 + memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
5058 + hdr.eth.h_proto = htons(len);
5059 + memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
5061 + /* Make room for the new header, and copy it in */
5062 + eh = skb_push(skb, ENCAPS_OVERHEAD);
5063 + memcpy(eh, &hdr, sizeof(hdr));
5066 + /* Calculate Michael MIC */
5067 + if (do_mic) {
5068 + size_t len = skb->len - ETH_HLEN;
5069 + u8 *mic = &mic_buf[0];
5071 + /* Have to write to an even address, so copy the spare
5072 + * byte across */
5073 + if (skb->len % 2) {
5074 + *mic = skb->data[skb->len - 1];
5075 + mic++;
5078 + orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
5079 + eh->h_dest, eh->h_source, 0 /* priority */,
5080 + skb->data + ETH_HLEN,
5081 + len, mic);
5084 + return 0;
5086 +EXPORT_SYMBOL(orinoco_process_xmit_skb);
5088 +static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
5090 + struct orinoco_private *priv = ndev_priv(dev);
5091 + struct net_device_stats *stats = &dev->stats;
5092 + struct hermes *hw = &priv->hw;
5093 + int err = 0;
5094 + u16 txfid = priv->txfid;
5095 + int tx_control;
5096 + unsigned long flags;
5097 + u8 mic_buf[MICHAEL_MIC_LEN + 1];
5099 + if (!netif_running(dev)) {
5100 + printk(KERN_ERR "%s: Tx on stopped device!\n",
5101 + dev->name);
5102 + return NETDEV_TX_BUSY;
5105 + if (netif_queue_stopped(dev)) {
5106 + printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
5107 + dev->name);
5108 + return NETDEV_TX_BUSY;
5111 + if (orinoco_lock(priv, &flags) != 0) {
5112 + printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
5113 + dev->name);
5114 + return NETDEV_TX_BUSY;
5117 + if (!netif_carrier_ok(dev) ||
5118 + (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
5119 + /* Oops, the firmware hasn't established a connection,
5120 + silently drop the packet (this seems to be the
5121 + safest approach). */
5122 + goto drop;
5125 + /* Check packet length */
5126 + if (skb->len < ETH_HLEN)
5127 + goto drop;
5129 + tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
5131 + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
5132 + &mic_buf[0]);
5133 + if (err)
5134 + goto drop;
5136 + if (priv->has_alt_txcntl) {
5137 + /* WPA enabled firmwares have tx_cntl at the end of
5138 + * the 802.11 header. So write zeroed descriptor and
5139 + * 802.11 header at the same time
5140 + */
5141 + char desc[HERMES_802_3_OFFSET];
5142 + __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET];
5144 + memset(&desc, 0, sizeof(desc));
5146 + *txcntl = cpu_to_le16(tx_control);
5147 + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
5148 + txfid, 0);
5149 + if (err) {
5150 + if (net_ratelimit())
5151 + printk(KERN_ERR "%s: Error %d writing Tx "
5152 + "descriptor to BAP\n", dev->name, err);
5153 + goto busy;
5155 + } else {
5156 + struct hermes_tx_descriptor desc;
5158 + memset(&desc, 0, sizeof(desc));
5160 + desc.tx_control = cpu_to_le16(tx_control);
5161 + err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
5162 + txfid, 0);
5163 + if (err) {
5164 + if (net_ratelimit())
5165 + printk(KERN_ERR "%s: Error %d writing Tx "
5166 + "descriptor to BAP\n", dev->name, err);
5167 + goto busy;
5170 + /* Clear the 802.11 header and data length fields - some
5171 + * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
5172 + * if this isn't done. */
5173 + hermes_clear_words(hw, HERMES_DATA0,
5174 + HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
5177 + err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len,
5178 + txfid, HERMES_802_3_OFFSET);
5179 + if (err) {
5180 + printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
5181 + dev->name, err);
5182 + goto busy;
5185 + if (tx_control & HERMES_TXCTRL_MIC) {
5186 + size_t offset = HERMES_802_3_OFFSET + skb->len;
5187 + size_t len = MICHAEL_MIC_LEN;
5189 + if (offset % 2) {
5190 + offset--;
5191 + len++;
5193 + err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
5194 + txfid, offset);
5195 + if (err) {
5196 + printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
5197 + dev->name, err);
5198 + goto busy;
5202 + /* Finally, we actually initiate the send */
5203 + netif_stop_queue(dev);
5205 + err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
5206 + txfid, NULL);
5207 + if (err) {
5208 + netif_start_queue(dev);
5209 + if (net_ratelimit())
5210 + printk(KERN_ERR "%s: Error %d transmitting packet\n",
5211 + dev->name, err);
5212 + goto busy;
5215 + stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
5216 + goto ok;
5218 + drop:
5219 + stats->tx_errors++;
5220 + stats->tx_dropped++;
5222 + ok:
5223 + orinoco_unlock(priv, &flags);
5224 + dev_kfree_skb(skb);
5225 + return NETDEV_TX_OK;
5227 + busy:
5228 + if (err == -EIO)
5229 + schedule_work(&priv->reset_work);
5230 + orinoco_unlock(priv, &flags);
5231 + return NETDEV_TX_BUSY;
5234 +static void __orinoco_ev_alloc(struct net_device *dev, struct hermes *hw)
5236 + struct orinoco_private *priv = ndev_priv(dev);
5237 + u16 fid = hermes_read_regn(hw, ALLOCFID);
5239 + if (fid != priv->txfid) {
5240 + if (fid != DUMMY_FID)
5241 + printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
5242 + dev->name, fid);
5243 + return;
5246 + hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
5249 +static void __orinoco_ev_tx(struct net_device *dev, struct hermes *hw)
5251 + dev->stats.tx_packets++;
5253 + netif_wake_queue(dev);
5255 + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
5258 +static void __orinoco_ev_txexc(struct net_device *dev, struct hermes *hw)
5260 + struct net_device_stats *stats = &dev->stats;
5261 + u16 fid = hermes_read_regn(hw, TXCOMPLFID);
5262 + u16 status;
5263 + struct hermes_txexc_data hdr;
5264 + int err = 0;
5266 + if (fid == DUMMY_FID)
5267 + return; /* Nothing's really happened */
5269 + /* Read part of the frame header - we need status and addr1 */
5270 + err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr,
5271 + sizeof(struct hermes_txexc_data),
5272 + fid, 0);
5274 + hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
5275 + stats->tx_errors++;
5277 + if (err) {
5278 + printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
5279 + "(FID=%04X error %d)\n",
5280 + dev->name, fid, err);
5281 + return;
5284 + DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
5285 + err, fid);
5287 + /* We produce a TXDROP event only for retry or lifetime
5288 + * exceeded, because that's the only status that really mean
5289 + * that this particular node went away.
5290 + * Other errors means that *we* screwed up. - Jean II */
5291 + status = le16_to_cpu(hdr.desc.status);
5292 + if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
5293 + union iwreq_data wrqu;
5295 + /* Copy 802.11 dest address.
5296 + * We use the 802.11 header because the frame may
5297 + * not be 802.3 or may be mangled...
5298 + * In Ad-Hoc mode, it will be the node address.
5299 + * In managed mode, it will be most likely the AP addr
5300 + * User space will figure out how to convert it to
5301 + * whatever it needs (IP address or else).
5302 + * - Jean II */
5303 + memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
5304 + wrqu.addr.sa_family = ARPHRD_ETHER;
5306 + /* Send event to user space */
5307 + wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
5310 + netif_wake_queue(dev);
5313 +void orinoco_tx_timeout(struct net_device *dev, unsigned int txqueue)
5315 + struct orinoco_private *priv = ndev_priv(dev);
5316 + struct net_device_stats *stats = &dev->stats;
5317 + struct hermes *hw = &priv->hw;
5319 + printk(KERN_WARNING "%s: Tx timeout! "
5320 + "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
5321 + dev->name, hermes_read_regn(hw, ALLOCFID),
5322 + hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
5324 + stats->tx_errors++;
5326 + schedule_work(&priv->reset_work);
5328 +EXPORT_SYMBOL(orinoco_tx_timeout);
5330 +/********************************************************************/
5331 +/* Rx path (data frames) */
5332 +/********************************************************************/
5334 +/* Does the frame have a SNAP header indicating it should be
5335 + * de-encapsulated to Ethernet-II? */
5336 +static inline int is_ethersnap(void *_hdr)
5338 + u8 *hdr = _hdr;
5340 + /* We de-encapsulate all packets which, a) have SNAP headers
5341 + * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
5342 + * and where b) the OUI of the SNAP header is 00:00:00 or
5343 + * 00:00:f8 - we need both because different APs appear to use
5344 + * different OUIs for some reason */
5345 + return (memcmp(hdr, &encaps_hdr, 5) == 0)
5346 + && ((hdr[5] == 0x00) || (hdr[5] == 0xf8));
5349 +static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
5350 + int level, int noise)
5352 + struct iw_quality wstats;
5353 + wstats.level = level - 0x95;
5354 + wstats.noise = noise - 0x95;
5355 + wstats.qual = (level > noise) ? (level - noise) : 0;
5356 + wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
5357 + /* Update spy records */
5358 + wireless_spy_update(dev, mac, &wstats);
5361 +static void orinoco_stat_gather(struct net_device *dev,
5362 + struct sk_buff *skb,
5363 + struct hermes_rx_descriptor *desc)
5365 + struct orinoco_private *priv = ndev_priv(dev);
5367 + /* Using spy support with lots of Rx packets, like in an
5368 + * infrastructure (AP), will really slow down everything, because
5369 + * the MAC address must be compared to each entry of the spy list.
5370 + * If the user really asks for it (set some address in the
5371 + * spy list), we do it, but he will pay the price.
5372 + * Note that to get here, you need both WIRELESS_SPY
5373 + * compiled in AND some addresses in the list !!!
5374 + */
5375 + /* Note : gcc will optimise the whole section away if
5376 + * WIRELESS_SPY is not defined... - Jean II */
5377 + if (SPY_NUMBER(priv)) {
5378 + orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN,
5379 + desc->signal, desc->silence);
5384 + * orinoco_rx_monitor - handle received monitor frames.
5386 + * Arguments:
5387 + * dev network device
5388 + * rxfid received FID
5389 + * desc rx descriptor of the frame
5391 + * Call context: interrupt
5392 + */
5393 +static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
5394 + struct hermes_rx_descriptor *desc)
5396 + u32 hdrlen = 30; /* return full header by default */
5397 + u32 datalen = 0;
5398 + u16 fc;
5399 + int err;
5400 + int len;
5401 + struct sk_buff *skb;
5402 + struct orinoco_private *priv = ndev_priv(dev);
5403 + struct net_device_stats *stats = &dev->stats;
5404 + struct hermes *hw = &priv->hw;
5406 + len = le16_to_cpu(desc->data_len);
5408 + /* Determine the size of the header and the data */
5409 + fc = le16_to_cpu(desc->frame_ctl);
5410 + switch (fc & IEEE80211_FCTL_FTYPE) {
5411 + case IEEE80211_FTYPE_DATA:
5412 + if ((fc & IEEE80211_FCTL_TODS)
5413 + && (fc & IEEE80211_FCTL_FROMDS))
5414 + hdrlen = 30;
5415 + else
5416 + hdrlen = 24;
5417 + datalen = len;
5418 + break;
5419 + case IEEE80211_FTYPE_MGMT:
5420 + hdrlen = 24;
5421 + datalen = len;
5422 + break;
5423 + case IEEE80211_FTYPE_CTL:
5424 + switch (fc & IEEE80211_FCTL_STYPE) {
5425 + case IEEE80211_STYPE_PSPOLL:
5426 + case IEEE80211_STYPE_RTS:
5427 + case IEEE80211_STYPE_CFEND:
5428 + case IEEE80211_STYPE_CFENDACK:
5429 + hdrlen = 16;
5430 + break;
5431 + case IEEE80211_STYPE_CTS:
5432 + case IEEE80211_STYPE_ACK:
5433 + hdrlen = 10;
5434 + break;
5436 + break;
5437 + default:
5438 + /* Unknown frame type */
5439 + break;
5442 + /* sanity check the length */
5443 + if (datalen > IEEE80211_MAX_DATA_LEN + 12) {
5444 + printk(KERN_DEBUG "%s: oversized monitor frame, "
5445 + "data length = %d\n", dev->name, datalen);
5446 + stats->rx_length_errors++;
5447 + goto update_stats;
5450 + skb = dev_alloc_skb(hdrlen + datalen);
5451 + if (!skb) {
5452 + printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
5453 + dev->name);
5454 + goto update_stats;
5457 + /* Copy the 802.11 header to the skb */
5458 + skb_put_data(skb, &(desc->frame_ctl), hdrlen);
5459 + skb_reset_mac_header(skb);
5461 + /* If any, copy the data from the card to the skb */
5462 + if (datalen > 0) {
5463 + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
5464 + ALIGN(datalen, 2), rxfid,
5465 + HERMES_802_2_OFFSET);
5466 + if (err) {
5467 + printk(KERN_ERR "%s: error %d reading monitor frame\n",
5468 + dev->name, err);
5469 + goto drop;
5473 + skb->dev = dev;
5474 + skb->ip_summed = CHECKSUM_NONE;
5475 + skb->pkt_type = PACKET_OTHERHOST;
5476 + skb->protocol = cpu_to_be16(ETH_P_802_2);
5478 + stats->rx_packets++;
5479 + stats->rx_bytes += skb->len;
5481 + netif_rx(skb);
5482 + return;
5484 + drop:
5485 + dev_kfree_skb_irq(skb);
5486 + update_stats:
5487 + stats->rx_errors++;
5488 + stats->rx_dropped++;
5491 +void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw)
5493 + struct orinoco_private *priv = ndev_priv(dev);
5494 + struct net_device_stats *stats = &dev->stats;
5495 + struct iw_statistics *wstats = &priv->wstats;
5496 + struct sk_buff *skb = NULL;
5497 + u16 rxfid, status;
5498 + int length;
5499 + struct hermes_rx_descriptor *desc;
5500 + struct orinoco_rx_data *rx_data;
5501 + int err;
5503 + desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
5504 + if (!desc)
5505 + goto update_stats;
5507 + rxfid = hermes_read_regn(hw, RXFID);
5509 + err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
5510 + rxfid, 0);
5511 + if (err) {
5512 + printk(KERN_ERR "%s: error %d reading Rx descriptor. "
5513 + "Frame dropped.\n", dev->name, err);
5514 + goto update_stats;
5517 + status = le16_to_cpu(desc->status);
5519 + if (status & HERMES_RXSTAT_BADCRC) {
5520 + DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
5521 + dev->name);
5522 + stats->rx_crc_errors++;
5523 + goto update_stats;
5526 + /* Handle frames in monitor mode */
5527 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
5528 + orinoco_rx_monitor(dev, rxfid, desc);
5529 + goto out;
5532 + if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
5533 + DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
5534 + dev->name);
5535 + wstats->discard.code++;
5536 + goto update_stats;
5539 + length = le16_to_cpu(desc->data_len);
5541 + /* Sanity checks */
5542 + if (length < 3) { /* No for even an 802.2 LLC header */
5543 + /* At least on Symbol firmware with PCF we get quite a
5544 + lot of these legitimately - Poll frames with no
5545 + data. */
5546 + goto out;
5548 + if (length > IEEE80211_MAX_DATA_LEN) {
5549 + printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
5550 + dev->name, length);
5551 + stats->rx_length_errors++;
5552 + goto update_stats;
5555 + /* Payload size does not include Michael MIC. Increase payload
5556 + * size to read it together with the data. */
5557 + if (status & HERMES_RXSTAT_MIC)
5558 + length += MICHAEL_MIC_LEN;
5560 + /* We need space for the packet data itself, plus an ethernet
5561 + header, plus 2 bytes so we can align the IP header on a
5562 + 32bit boundary, plus 1 byte so we can read in odd length
5563 + packets from the card, which has an IO granularity of 16
5564 + bits */
5565 + skb = dev_alloc_skb(length + ETH_HLEN + 2 + 1);
5566 + if (!skb) {
5567 + printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
5568 + dev->name);
5569 + goto update_stats;
5572 + /* We'll prepend the header, so reserve space for it. The worst
5573 + case is no decapsulation, when 802.3 header is prepended and
5574 + nothing is removed. 2 is for aligning the IP header. */
5575 + skb_reserve(skb, ETH_HLEN + 2);
5577 + err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length),
5578 + ALIGN(length, 2), rxfid,
5579 + HERMES_802_2_OFFSET);
5580 + if (err) {
5581 + printk(KERN_ERR "%s: error %d reading frame. "
5582 + "Frame dropped.\n", dev->name, err);
5583 + goto drop;
5586 + /* Add desc and skb to rx queue */
5587 + rx_data = kzalloc(sizeof(*rx_data), GFP_ATOMIC);
5588 + if (!rx_data)
5589 + goto drop;
5591 + rx_data->desc = desc;
5592 + rx_data->skb = skb;
5593 + list_add_tail(&rx_data->list, &priv->rx_list);
5594 + tasklet_schedule(&priv->rx_tasklet);
5596 + return;
5598 +drop:
5599 + dev_kfree_skb_irq(skb);
5600 +update_stats:
5601 + stats->rx_errors++;
5602 + stats->rx_dropped++;
5603 +out:
5604 + kfree(desc);
5606 +EXPORT_SYMBOL(__orinoco_ev_rx);
5608 +static void orinoco_rx(struct net_device *dev,
5609 + struct hermes_rx_descriptor *desc,
5610 + struct sk_buff *skb)
5612 + struct orinoco_private *priv = ndev_priv(dev);
5613 + struct net_device_stats *stats = &dev->stats;
5614 + u16 status, fc;
5615 + int length;
5616 + struct ethhdr *hdr;
5618 + status = le16_to_cpu(desc->status);
5619 + length = le16_to_cpu(desc->data_len);
5620 + fc = le16_to_cpu(desc->frame_ctl);
5622 + /* Calculate and check MIC */
5623 + if (status & HERMES_RXSTAT_MIC) {
5624 + struct orinoco_tkip_key *key;
5625 + int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
5626 + HERMES_MIC_KEY_ID_SHIFT);
5627 + u8 mic[MICHAEL_MIC_LEN];
5628 + u8 *rxmic;
5629 + u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
5630 + desc->addr3 : desc->addr2;
5632 + /* Extract Michael MIC from payload */
5633 + rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
5635 + skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
5636 + length -= MICHAEL_MIC_LEN;
5638 + key = (struct orinoco_tkip_key *) priv->keys[key_id].key;
5640 + if (!key) {
5641 + printk(KERN_WARNING "%s: Received encrypted frame from "
5642 + "%pM using key %i, but key is not installed\n",
5643 + dev->name, src, key_id);
5644 + goto drop;
5647 + orinoco_mic(priv->rx_tfm_mic, key->rx_mic, desc->addr1, src,
5648 + 0, /* priority or QoS? */
5649 + skb->data, skb->len, &mic[0]);
5651 + if (memcmp(mic, rxmic,
5652 + MICHAEL_MIC_LEN)) {
5653 + union iwreq_data wrqu;
5654 + struct iw_michaelmicfailure wxmic;
5656 + printk(KERN_WARNING "%s: "
5657 + "Invalid Michael MIC in data frame from %pM, "
5658 + "using key %i\n",
5659 + dev->name, src, key_id);
5661 + /* TODO: update stats */
5663 + /* Notify userspace */
5664 + memset(&wxmic, 0, sizeof(wxmic));
5665 + wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
5666 + wxmic.flags |= (desc->addr1[0] & 1) ?
5667 + IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
5668 + wxmic.src_addr.sa_family = ARPHRD_ETHER;
5669 + memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
5671 + (void) orinoco_hw_get_tkip_iv(priv, key_id,
5672 + &wxmic.tsc[0]);
5674 + memset(&wrqu, 0, sizeof(wrqu));
5675 + wrqu.data.length = sizeof(wxmic);
5676 + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
5677 + (char *) &wxmic);
5679 + goto drop;
5683 + /* Handle decapsulation
5684 + * In most cases, the firmware tell us about SNAP frames.
5685 + * For some reason, the SNAP frames sent by LinkSys APs
5686 + * are not properly recognised by most firmwares.
5687 + * So, check ourselves */
5688 + if (length >= ENCAPS_OVERHEAD &&
5689 + (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
5690 + ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
5691 + is_ethersnap(skb->data))) {
5692 + /* These indicate a SNAP within 802.2 LLC within
5693 + 802.11 frame which we'll need to de-encapsulate to
5694 + the original EthernetII frame. */
5695 + hdr = skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
5696 + } else {
5697 + /* 802.3 frame - prepend 802.3 header as is */
5698 + hdr = skb_push(skb, ETH_HLEN);
5699 + hdr->h_proto = htons(length);
5701 + memcpy(hdr->h_dest, desc->addr1, ETH_ALEN);
5702 + if (fc & IEEE80211_FCTL_FROMDS)
5703 + memcpy(hdr->h_source, desc->addr3, ETH_ALEN);
5704 + else
5705 + memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
5707 + skb->protocol = eth_type_trans(skb, dev);
5708 + skb->ip_summed = CHECKSUM_NONE;
5709 + if (fc & IEEE80211_FCTL_TODS)
5710 + skb->pkt_type = PACKET_OTHERHOST;
5712 + /* Process the wireless stats if needed */
5713 + orinoco_stat_gather(dev, skb, desc);
5715 + /* Pass the packet to the networking stack */
5716 + netif_rx(skb);
5717 + stats->rx_packets++;
5718 + stats->rx_bytes += length;
5720 + return;
5722 + drop:
5723 + dev_kfree_skb(skb);
5724 + stats->rx_errors++;
5725 + stats->rx_dropped++;
5728 +static void orinoco_rx_isr_tasklet(struct tasklet_struct *t)
5730 + struct orinoco_private *priv = from_tasklet(priv, t, rx_tasklet);
5731 + struct net_device *dev = priv->ndev;
5732 + struct orinoco_rx_data *rx_data, *temp;
5733 + struct hermes_rx_descriptor *desc;
5734 + struct sk_buff *skb;
5735 + unsigned long flags;
5737 + /* orinoco_rx requires the driver lock, and we also need to
5738 + * protect priv->rx_list, so just hold the lock over the
5739 + * lot.
5741 + * If orinoco_lock fails, we've unplugged the card. In this
5742 + * case just abort. */
5743 + if (orinoco_lock(priv, &flags) != 0)
5744 + return;
5746 + /* extract desc and skb from queue */
5747 + list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
5748 + desc = rx_data->desc;
5749 + skb = rx_data->skb;
5750 + list_del(&rx_data->list);
5751 + kfree(rx_data);
5753 + orinoco_rx(dev, desc, skb);
5755 + kfree(desc);
5758 + orinoco_unlock(priv, &flags);
5761 +/********************************************************************/
5762 +/* Rx path (info frames) */
5763 +/********************************************************************/
5765 +static void print_linkstatus(struct net_device *dev, u16 status)
5767 + char *s;
5769 + if (suppress_linkstatus)
5770 + return;
5772 + switch (status) {
5773 + case HERMES_LINKSTATUS_NOT_CONNECTED:
5774 + s = "Not Connected";
5775 + break;
5776 + case HERMES_LINKSTATUS_CONNECTED:
5777 + s = "Connected";
5778 + break;
5779 + case HERMES_LINKSTATUS_DISCONNECTED:
5780 + s = "Disconnected";
5781 + break;
5782 + case HERMES_LINKSTATUS_AP_CHANGE:
5783 + s = "AP Changed";
5784 + break;
5785 + case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
5786 + s = "AP Out of Range";
5787 + break;
5788 + case HERMES_LINKSTATUS_AP_IN_RANGE:
5789 + s = "AP In Range";
5790 + break;
5791 + case HERMES_LINKSTATUS_ASSOC_FAILED:
5792 + s = "Association Failed";
5793 + break;
5794 + default:
5795 + s = "UNKNOWN";
5798 + printk(KERN_DEBUG "%s: New link status: %s (%04x)\n",
5799 + dev->name, s, status);
5802 +/* Search scan results for requested BSSID, join it if found */
5803 +static void orinoco_join_ap(struct work_struct *work)
5805 + struct orinoco_private *priv =
5806 + container_of(work, struct orinoco_private, join_work);
5807 + struct net_device *dev = priv->ndev;
5808 + struct hermes *hw = &priv->hw;
5809 + int err;
5810 + unsigned long flags;
5811 + struct join_req {
5812 + u8 bssid[ETH_ALEN];
5813 + __le16 channel;
5814 + } __packed req;
5815 + const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
5816 + struct prism2_scan_apinfo *atom = NULL;
5817 + int offset = 4;
5818 + int found = 0;
5819 + u8 *buf;
5820 + u16 len;
5822 + /* Allocate buffer for scan results */
5823 + buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
5824 + if (!buf)
5825 + return;
5827 + if (orinoco_lock(priv, &flags) != 0)
5828 + goto fail_lock;
5830 + /* Sanity checks in case user changed something in the meantime */
5831 + if (!priv->bssid_fixed)
5832 + goto out;
5834 + if (strlen(priv->desired_essid) == 0)
5835 + goto out;
5837 + /* Read scan results from the firmware */
5838 + err = hw->ops->read_ltv(hw, USER_BAP,
5839 + HERMES_RID_SCANRESULTSTABLE,
5840 + MAX_SCAN_LEN, &len, buf);
5841 + if (err) {
5842 + printk(KERN_ERR "%s: Cannot read scan results\n",
5843 + dev->name);
5844 + goto out;
5847 + len = HERMES_RECLEN_TO_BYTES(len);
5849 + /* Go through the scan results looking for the channel of the AP
5850 + * we were requested to join */
5851 + for (; offset + atom_len <= len; offset += atom_len) {
5852 + atom = (struct prism2_scan_apinfo *) (buf + offset);
5853 + if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
5854 + found = 1;
5855 + break;
5859 + if (!found) {
5860 + DEBUG(1, "%s: Requested AP not found in scan results\n",
5861 + dev->name);
5862 + goto out;
5865 + memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
5866 + req.channel = atom->channel; /* both are little-endian */
5867 + err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
5868 + &req);
5869 + if (err)
5870 + printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
5872 + out:
5873 + orinoco_unlock(priv, &flags);
5875 + fail_lock:
5876 + kfree(buf);
5879 +/* Send new BSSID to userspace */
5880 +static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
5882 + struct net_device *dev = priv->ndev;
5883 + struct hermes *hw = &priv->hw;
5884 + union iwreq_data wrqu;
5885 + int err;
5887 + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
5888 + ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
5889 + if (err != 0)
5890 + return;
5892 + wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5894 + /* Send event to user space */
5895 + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
5898 +static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
5900 + struct net_device *dev = priv->ndev;
5901 + struct hermes *hw = &priv->hw;
5902 + union iwreq_data wrqu;
5903 + int err;
5904 + u8 buf[88];
5905 + u8 *ie;
5907 + if (!priv->has_wpa)
5908 + return;
5910 + err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
5911 + sizeof(buf), NULL, &buf);
5912 + if (err != 0)
5913 + return;
5915 + ie = orinoco_get_wpa_ie(buf, sizeof(buf));
5916 + if (ie) {
5917 + int rem = sizeof(buf) - (ie - &buf[0]);
5918 + wrqu.data.length = ie[1] + 2;
5919 + if (wrqu.data.length > rem)
5920 + wrqu.data.length = rem;
5922 + if (wrqu.data.length)
5923 + /* Send event to user space */
5924 + wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie);
5928 +static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
5930 + struct net_device *dev = priv->ndev;
5931 + struct hermes *hw = &priv->hw;
5932 + union iwreq_data wrqu;
5933 + int err;
5934 + u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */
5935 + u8 *ie;
5937 + if (!priv->has_wpa)
5938 + return;
5940 + err = hw->ops->read_ltv(hw, USER_BAP,
5941 + HERMES_RID_CURRENT_ASSOC_RESP_INFO,
5942 + sizeof(buf), NULL, &buf);
5943 + if (err != 0)
5944 + return;
5946 + ie = orinoco_get_wpa_ie(buf, sizeof(buf));
5947 + if (ie) {
5948 + int rem = sizeof(buf) - (ie - &buf[0]);
5949 + wrqu.data.length = ie[1] + 2;
5950 + if (wrqu.data.length > rem)
5951 + wrqu.data.length = rem;
5953 + if (wrqu.data.length)
5954 + /* Send event to user space */
5955 + wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie);
5959 +static void orinoco_send_wevents(struct work_struct *work)
5961 + struct orinoco_private *priv =
5962 + container_of(work, struct orinoco_private, wevent_work);
5963 + unsigned long flags;
5965 + if (orinoco_lock(priv, &flags) != 0)
5966 + return;
5968 + orinoco_send_assocreqie_wevent(priv);
5969 + orinoco_send_assocrespie_wevent(priv);
5970 + orinoco_send_bssid_wevent(priv);
5972 + orinoco_unlock(priv, &flags);
5975 +static void qbuf_scan(struct orinoco_private *priv, void *buf,
5976 + int len, int type)
5978 + struct orinoco_scan_data *sd;
5979 + unsigned long flags;
5981 + sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
5982 + if (!sd)
5983 + return;
5985 + sd->buf = buf;
5986 + sd->len = len;
5987 + sd->type = type;
5989 + spin_lock_irqsave(&priv->scan_lock, flags);
5990 + list_add_tail(&sd->list, &priv->scan_list);
5991 + spin_unlock_irqrestore(&priv->scan_lock, flags);
5993 + schedule_work(&priv->process_scan);
5996 +static void qabort_scan(struct orinoco_private *priv)
5998 + struct orinoco_scan_data *sd;
5999 + unsigned long flags;
6001 + sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
6002 + if (!sd)
6003 + return;
6005 + sd->len = -1; /* Abort */
6007 + spin_lock_irqsave(&priv->scan_lock, flags);
6008 + list_add_tail(&sd->list, &priv->scan_list);
6009 + spin_unlock_irqrestore(&priv->scan_lock, flags);
6011 + schedule_work(&priv->process_scan);
6014 +static void orinoco_process_scan_results(struct work_struct *work)
6016 + struct orinoco_private *priv =
6017 + container_of(work, struct orinoco_private, process_scan);
6018 + struct orinoco_scan_data *sd, *temp;
6019 + unsigned long flags;
6020 + void *buf;
6021 + int len;
6022 + int type;
6024 + spin_lock_irqsave(&priv->scan_lock, flags);
6025 + list_for_each_entry_safe(sd, temp, &priv->scan_list, list) {
6027 + buf = sd->buf;
6028 + len = sd->len;
6029 + type = sd->type;
6031 + list_del(&sd->list);
6032 + spin_unlock_irqrestore(&priv->scan_lock, flags);
6033 + kfree(sd);
6035 + if (len > 0) {
6036 + if (type == HERMES_INQ_CHANNELINFO)
6037 + orinoco_add_extscan_result(priv, buf, len);
6038 + else
6039 + orinoco_add_hostscan_results(priv, buf, len);
6041 + kfree(buf);
6042 + } else {
6043 + /* Either abort or complete the scan */
6044 + orinoco_scan_done(priv, (len < 0));
6047 + spin_lock_irqsave(&priv->scan_lock, flags);
6049 + spin_unlock_irqrestore(&priv->scan_lock, flags);
6052 +void __orinoco_ev_info(struct net_device *dev, struct hermes *hw)
6054 + struct orinoco_private *priv = ndev_priv(dev);
6055 + u16 infofid;
6056 + struct {
6057 + __le16 len;
6058 + __le16 type;
6059 + } __packed info;
6060 + int len, type;
6061 + int err;
6063 + /* This is an answer to an INQUIRE command that we did earlier,
6064 + * or an information "event" generated by the card
6065 + * The controller return to us a pseudo frame containing
6066 + * the information in question - Jean II */
6067 + infofid = hermes_read_regn(hw, INFOFID);
6069 + /* Read the info frame header - don't try too hard */
6070 + err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info),
6071 + infofid, 0);
6072 + if (err) {
6073 + printk(KERN_ERR "%s: error %d reading info frame. "
6074 + "Frame dropped.\n", dev->name, err);
6075 + return;
6078 + len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
6079 + type = le16_to_cpu(info.type);
6081 + switch (type) {
6082 + case HERMES_INQ_TALLIES: {
6083 + struct hermes_tallies_frame tallies;
6084 + struct iw_statistics *wstats = &priv->wstats;
6086 + if (len > sizeof(tallies)) {
6087 + printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
6088 + dev->name, len);
6089 + len = sizeof(tallies);
6092 + err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len,
6093 + infofid, sizeof(info));
6094 + if (err)
6095 + break;
6097 + /* Increment our various counters */
6098 + /* wstats->discard.nwid - no wrong BSSID stuff */
6099 + wstats->discard.code +=
6100 + le16_to_cpu(tallies.RxWEPUndecryptable);
6101 + if (len == sizeof(tallies))
6102 + wstats->discard.code +=
6103 + le16_to_cpu(tallies.RxDiscards_WEPICVError) +
6104 + le16_to_cpu(tallies.RxDiscards_WEPExcluded);
6105 + wstats->discard.misc +=
6106 + le16_to_cpu(tallies.TxDiscardsWrongSA);
6107 + wstats->discard.fragment +=
6108 + le16_to_cpu(tallies.RxMsgInBadMsgFragments);
6109 + wstats->discard.retries +=
6110 + le16_to_cpu(tallies.TxRetryLimitExceeded);
6111 + /* wstats->miss.beacon - no match */
6113 + break;
6114 + case HERMES_INQ_LINKSTATUS: {
6115 + struct hermes_linkstatus linkstatus;
6116 + u16 newstatus;
6117 + int connected;
6119 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
6120 + break;
6122 + if (len != sizeof(linkstatus)) {
6123 + printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
6124 + dev->name, len);
6125 + break;
6128 + err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len,
6129 + infofid, sizeof(info));
6130 + if (err)
6131 + break;
6132 + newstatus = le16_to_cpu(linkstatus.linkstatus);
6134 + /* Symbol firmware uses "out of range" to signal that
6135 + * the hostscan frame can be requested. */
6136 + if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
6137 + priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
6138 + priv->has_hostscan && priv->scan_request) {
6139 + hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
6140 + break;
6143 + connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
6144 + || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
6145 + || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
6147 + if (connected)
6148 + netif_carrier_on(dev);
6149 + else if (!ignore_disconnect)
6150 + netif_carrier_off(dev);
6152 + if (newstatus != priv->last_linkstatus) {
6153 + priv->last_linkstatus = newstatus;
6154 + print_linkstatus(dev, newstatus);
6155 + /* The info frame contains only one word which is the
6156 + * status (see hermes.h). The status is pretty boring
6157 + * in itself, that's why we export the new BSSID...
6158 + * Jean II */
6159 + schedule_work(&priv->wevent_work);
6162 + break;
6163 + case HERMES_INQ_SCAN:
6164 + if (!priv->scan_request && priv->bssid_fixed &&
6165 + priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
6166 + schedule_work(&priv->join_work);
6167 + break;
6169 + fallthrough;
6170 + case HERMES_INQ_HOSTSCAN:
6171 + case HERMES_INQ_HOSTSCAN_SYMBOL: {
6172 + /* Result of a scanning. Contains information about
6173 + * cells in the vicinity - Jean II */
6174 + unsigned char *buf;
6176 + /* Sanity check */
6177 + if (len > 4096) {
6178 + printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
6179 + dev->name, len);
6180 + qabort_scan(priv);
6181 + break;
6184 + /* Allocate buffer for results */
6185 + buf = kmalloc(len, GFP_ATOMIC);
6186 + if (buf == NULL) {
6187 + /* No memory, so can't printk()... */
6188 + qabort_scan(priv);
6189 + break;
6192 + /* Read scan data */
6193 + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len,
6194 + infofid, sizeof(info));
6195 + if (err) {
6196 + kfree(buf);
6197 + qabort_scan(priv);
6198 + break;
6201 +#ifdef ORINOCO_DEBUG
6203 + int i;
6204 + printk(KERN_DEBUG "Scan result [%02X", buf[0]);
6205 + for (i = 1; i < (len * 2); i++)
6206 + printk(":%02X", buf[i]);
6207 + printk("]\n");
6209 +#endif /* ORINOCO_DEBUG */
6211 + qbuf_scan(priv, buf, len, type);
6213 + break;
6214 + case HERMES_INQ_CHANNELINFO:
6216 + struct agere_ext_scan_info *bss;
6218 + if (!priv->scan_request) {
6219 + printk(KERN_DEBUG "%s: Got chaninfo without scan, "
6220 + "len=%d\n", dev->name, len);
6221 + break;
6224 + /* An empty result indicates that the scan is complete */
6225 + if (len == 0) {
6226 + qbuf_scan(priv, NULL, len, type);
6227 + break;
6230 + /* Sanity check */
6231 + else if (len < (offsetof(struct agere_ext_scan_info,
6232 + data) + 2)) {
6233 + /* Drop this result now so we don't have to
6234 + * keep checking later */
6235 + printk(KERN_WARNING
6236 + "%s: Ext scan results too short (%d bytes)\n",
6237 + dev->name, len);
6238 + break;
6241 + bss = kmalloc(len, GFP_ATOMIC);
6242 + if (bss == NULL)
6243 + break;
6245 + /* Read scan data */
6246 + err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len,
6247 + infofid, sizeof(info));
6248 + if (err)
6249 + kfree(bss);
6250 + else
6251 + qbuf_scan(priv, bss, len, type);
6253 + break;
6255 + case HERMES_INQ_SEC_STAT_AGERE:
6256 + /* Security status (Agere specific) */
6257 + /* Ignore this frame for now */
6258 + if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
6259 + break;
6260 + fallthrough;
6261 + default:
6262 + printk(KERN_DEBUG "%s: Unknown information frame received: "
6263 + "type 0x%04x, length %d\n", dev->name, type, len);
6264 + /* We don't actually do anything about it */
6265 + break;
6268 +EXPORT_SYMBOL(__orinoco_ev_info);
6270 +static void __orinoco_ev_infdrop(struct net_device *dev, struct hermes *hw)
6272 + if (net_ratelimit())
6273 + printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
6276 +/********************************************************************/
6277 +/* Internal hardware control routines */
6278 +/********************************************************************/
6280 +static int __orinoco_up(struct orinoco_private *priv)
6282 + struct net_device *dev = priv->ndev;
6283 + struct hermes *hw = &priv->hw;
6284 + int err;
6286 + netif_carrier_off(dev); /* just to make sure */
6288 + err = __orinoco_commit(priv);
6289 + if (err) {
6290 + printk(KERN_ERR "%s: Error %d configuring card\n",
6291 + dev->name, err);
6292 + return err;
6295 + /* Fire things up again */
6296 + hermes_set_irqmask(hw, ORINOCO_INTEN);
6297 + err = hermes_enable_port(hw, 0);
6298 + if (err) {
6299 + printk(KERN_ERR "%s: Error %d enabling MAC port\n",
6300 + dev->name, err);
6301 + return err;
6304 + netif_start_queue(dev);
6306 + return 0;
6309 +static int __orinoco_down(struct orinoco_private *priv)
6311 + struct net_device *dev = priv->ndev;
6312 + struct hermes *hw = &priv->hw;
6313 + int err;
6315 + netif_stop_queue(dev);
6317 + if (!priv->hw_unavailable) {
6318 + if (!priv->broken_disableport) {
6319 + err = hermes_disable_port(hw, 0);
6320 + if (err) {
6321 + /* Some firmwares (e.g. Intersil 1.3.x) seem
6322 + * to have problems disabling the port, oh
6323 + * well, too bad. */
6324 + printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
6325 + dev->name, err);
6326 + priv->broken_disableport = 1;
6329 + hermes_set_irqmask(hw, 0);
6330 + hermes_write_regn(hw, EVACK, 0xffff);
6333 + orinoco_scan_done(priv, true);
6335 + /* firmware will have to reassociate */
6336 + netif_carrier_off(dev);
6337 + priv->last_linkstatus = 0xffff;
6339 + return 0;
6342 +static int orinoco_reinit_firmware(struct orinoco_private *priv)
6344 + struct hermes *hw = &priv->hw;
6345 + int err;
6347 + err = hw->ops->init(hw);
6348 + if (priv->do_fw_download && !err) {
6349 + err = orinoco_download(priv);
6350 + if (err)
6351 + priv->do_fw_download = 0;
6353 + if (!err)
6354 + err = orinoco_hw_allocate_fid(priv);
6356 + return err;
6359 +static int
6360 +__orinoco_set_multicast_list(struct net_device *dev)
6362 + struct orinoco_private *priv = ndev_priv(dev);
6363 + int err = 0;
6364 + int promisc, mc_count;
6366 + /* The Hermes doesn't seem to have an allmulti mode, so we go
6367 + * into promiscuous mode and let the upper levels deal. */
6368 + if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
6369 + (netdev_mc_count(dev) > MAX_MULTICAST(priv))) {
6370 + promisc = 1;
6371 + mc_count = 0;
6372 + } else {
6373 + promisc = 0;
6374 + mc_count = netdev_mc_count(dev);
6377 + err = __orinoco_hw_set_multicast_list(priv, dev, mc_count, promisc);
6379 + return err;
6382 +/* This must be called from user context, without locks held - use
6383 + * schedule_work() */
6384 +void orinoco_reset(struct work_struct *work)
6386 + struct orinoco_private *priv =
6387 + container_of(work, struct orinoco_private, reset_work);
6388 + struct net_device *dev = priv->ndev;
6389 + struct hermes *hw = &priv->hw;
6390 + int err;
6391 + unsigned long flags;
6393 + if (orinoco_lock(priv, &flags) != 0)
6394 + /* When the hardware becomes available again, whatever
6395 + * detects that is responsible for re-initializing
6396 + * it. So no need for anything further */
6397 + return;
6399 + netif_stop_queue(dev);
6401 + /* Shut off interrupts. Depending on what state the hardware
6402 + * is in, this might not work, but we'll try anyway */
6403 + hermes_set_irqmask(hw, 0);
6404 + hermes_write_regn(hw, EVACK, 0xffff);
6406 + priv->hw_unavailable++;
6407 + priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
6408 + netif_carrier_off(dev);
6410 + orinoco_unlock(priv, &flags);
6412 + /* Scanning support: Notify scan cancellation */
6413 + orinoco_scan_done(priv, true);
6415 + if (priv->hard_reset) {
6416 + err = (*priv->hard_reset)(priv);
6417 + if (err) {
6418 + printk(KERN_ERR "%s: orinoco_reset: Error %d "
6419 + "performing hard reset\n", dev->name, err);
6420 + goto disable;
6424 + err = orinoco_reinit_firmware(priv);
6425 + if (err) {
6426 + printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
6427 + dev->name, err);
6428 + goto disable;
6431 + /* This has to be called from user context */
6432 + orinoco_lock_irq(priv);
6434 + priv->hw_unavailable--;
6436 + /* priv->open or priv->hw_unavailable might have changed while
6437 + * we dropped the lock */
6438 + if (priv->open && (!priv->hw_unavailable)) {
6439 + err = __orinoco_up(priv);
6440 + if (err) {
6441 + printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
6442 + dev->name, err);
6443 + } else
6444 + netif_trans_update(dev);
6447 + orinoco_unlock_irq(priv);
6449 + return;
6450 + disable:
6451 + hermes_set_irqmask(hw, 0);
6452 + netif_device_detach(dev);
6453 + printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
6456 +static int __orinoco_commit(struct orinoco_private *priv)
6458 + struct net_device *dev = priv->ndev;
6459 + int err = 0;
6461 + /* If we've called commit, we are reconfiguring or bringing the
6462 + * interface up. Maintaining countermeasures across this would
6463 + * be confusing, so note that we've disabled them. The port will
6464 + * be enabled later in orinoco_commit or __orinoco_up. */
6465 + priv->tkip_cm_active = 0;
6467 + err = orinoco_hw_program_rids(priv);
6469 + /* FIXME: what about netif_tx_lock */
6470 + (void) __orinoco_set_multicast_list(dev);
6472 + return err;
6475 +/* Ensures configuration changes are applied. May result in a reset.
6476 + * The caller should hold priv->lock
6477 + */
6478 +int orinoco_commit(struct orinoco_private *priv)
6480 + struct net_device *dev = priv->ndev;
6481 + struct hermes *hw = &priv->hw;
6482 + int err;
6484 + if (priv->broken_disableport) {
6485 + schedule_work(&priv->reset_work);
6486 + return 0;
6489 + err = hermes_disable_port(hw, 0);
6490 + if (err) {
6491 + printk(KERN_WARNING "%s: Unable to disable port "
6492 + "while reconfiguring card\n", dev->name);
6493 + priv->broken_disableport = 1;
6494 + goto out;
6497 + err = __orinoco_commit(priv);
6498 + if (err) {
6499 + printk(KERN_WARNING "%s: Unable to reconfigure card\n",
6500 + dev->name);
6501 + goto out;
6504 + err = hermes_enable_port(hw, 0);
6505 + if (err) {
6506 + printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
6507 + dev->name);
6508 + goto out;
6511 + out:
6512 + if (err) {
6513 + printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
6514 + schedule_work(&priv->reset_work);
6515 + err = 0;
6517 + return err;
6520 +/********************************************************************/
6521 +/* Interrupt handler */
6522 +/********************************************************************/
6524 +static void __orinoco_ev_tick(struct net_device *dev, struct hermes *hw)
6526 + printk(KERN_DEBUG "%s: TICK\n", dev->name);
6529 +static void __orinoco_ev_wterr(struct net_device *dev, struct hermes *hw)
6531 + /* This seems to happen a fair bit under load, but ignoring it
6532 + seems to work fine...*/
6533 + printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
6534 + dev->name);
6537 +irqreturn_t orinoco_interrupt(int irq, void *dev_id)
6539 + struct orinoco_private *priv = dev_id;
6540 + struct net_device *dev = priv->ndev;
6541 + struct hermes *hw = &priv->hw;
6542 + int count = MAX_IRQLOOPS_PER_IRQ;
6543 + u16 evstat, events;
6544 + /* These are used to detect a runaway interrupt situation.
6546 + * If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
6547 + * we panic and shut down the hardware
6548 + */
6549 + /* jiffies value the last time we were called */
6550 + static int last_irq_jiffy; /* = 0 */
6551 + static int loops_this_jiffy; /* = 0 */
6552 + unsigned long flags;
6554 + if (orinoco_lock(priv, &flags) != 0) {
6555 + /* If hw is unavailable - we don't know if the irq was
6556 + * for us or not */
6557 + return IRQ_HANDLED;
6560 + evstat = hermes_read_regn(hw, EVSTAT);
6561 + events = evstat & hw->inten;
6562 + if (!events) {
6563 + orinoco_unlock(priv, &flags);
6564 + return IRQ_NONE;
6567 + if (jiffies != last_irq_jiffy)
6568 + loops_this_jiffy = 0;
6569 + last_irq_jiffy = jiffies;
6571 + while (events && count--) {
6572 + if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
6573 + printk(KERN_WARNING "%s: IRQ handler is looping too "
6574 + "much! Resetting.\n", dev->name);
6575 + /* Disable interrupts for now */
6576 + hermes_set_irqmask(hw, 0);
6577 + schedule_work(&priv->reset_work);
6578 + break;
6581 + /* Check the card hasn't been removed */
6582 + if (!hermes_present(hw)) {
6583 + DEBUG(0, "orinoco_interrupt(): card removed\n");
6584 + break;
6587 + if (events & HERMES_EV_TICK)
6588 + __orinoco_ev_tick(dev, hw);
6589 + if (events & HERMES_EV_WTERR)
6590 + __orinoco_ev_wterr(dev, hw);
6591 + if (events & HERMES_EV_INFDROP)
6592 + __orinoco_ev_infdrop(dev, hw);
6593 + if (events & HERMES_EV_INFO)
6594 + __orinoco_ev_info(dev, hw);
6595 + if (events & HERMES_EV_RX)
6596 + __orinoco_ev_rx(dev, hw);
6597 + if (events & HERMES_EV_TXEXC)
6598 + __orinoco_ev_txexc(dev, hw);
6599 + if (events & HERMES_EV_TX)
6600 + __orinoco_ev_tx(dev, hw);
6601 + if (events & HERMES_EV_ALLOC)
6602 + __orinoco_ev_alloc(dev, hw);
6604 + hermes_write_regn(hw, EVACK, evstat);
6606 + evstat = hermes_read_regn(hw, EVSTAT);
6607 + events = evstat & hw->inten;
6610 + orinoco_unlock(priv, &flags);
6611 + return IRQ_HANDLED;
6613 +EXPORT_SYMBOL(orinoco_interrupt);
6615 +/********************************************************************/
6616 +/* Power management */
6617 +/********************************************************************/
6618 +#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
6619 +static int orinoco_pm_notifier(struct notifier_block *notifier,
6620 + unsigned long pm_event,
6621 + void *unused)
6623 + struct orinoco_private *priv = container_of(notifier,
6624 + struct orinoco_private,
6625 + pm_notifier);
6627 + /* All we need to do is cache the firmware before suspend, and
6628 + * release it when we come out.
6630 + * Only need to do this if we're downloading firmware. */
6631 + if (!priv->do_fw_download)
6632 + return NOTIFY_DONE;
6634 + switch (pm_event) {
6635 + case PM_HIBERNATION_PREPARE:
6636 + case PM_SUSPEND_PREPARE:
6637 + orinoco_cache_fw(priv, 0);
6638 + break;
6640 + case PM_POST_RESTORE:
6641 + /* Restore from hibernation failed. We need to clean
6642 + * up in exactly the same way, so fall through. */
6643 + case PM_POST_HIBERNATION:
6644 + case PM_POST_SUSPEND:
6645 + orinoco_uncache_fw(priv);
6646 + break;
6648 + case PM_RESTORE_PREPARE:
6649 + default:
6650 + break;
6653 + return NOTIFY_DONE;
6656 +static void orinoco_register_pm_notifier(struct orinoco_private *priv)
6658 + priv->pm_notifier.notifier_call = orinoco_pm_notifier;
6659 + register_pm_notifier(&priv->pm_notifier);
6662 +static void orinoco_unregister_pm_notifier(struct orinoco_private *priv)
6664 + unregister_pm_notifier(&priv->pm_notifier);
6666 +#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
6667 +#define orinoco_register_pm_notifier(priv) do { } while (0)
6668 +#define orinoco_unregister_pm_notifier(priv) do { } while (0)
6669 +#endif
6671 +/********************************************************************/
6672 +/* Initialization */
6673 +/********************************************************************/
6675 +int orinoco_init(struct orinoco_private *priv)
6677 + struct device *dev = priv->dev;
6678 + struct wiphy *wiphy = priv_to_wiphy(priv);
6679 + struct hermes *hw = &priv->hw;
6680 + int err = 0;
6682 + /* No need to lock, the hw_unavailable flag is already set in
6683 + * alloc_orinocodev() */
6684 + priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
6686 + /* Initialize the firmware */
6687 + err = hw->ops->init(hw);
6688 + if (err != 0) {
6689 + dev_err(dev, "Failed to initialize firmware (err = %d)\n",
6690 + err);
6691 + goto out;
6694 + err = determine_fw_capabilities(priv, wiphy->fw_version,
6695 + sizeof(wiphy->fw_version),
6696 + &wiphy->hw_version);
6697 + if (err != 0) {
6698 + dev_err(dev, "Incompatible firmware, aborting\n");
6699 + goto out;
6702 + if (priv->do_fw_download) {
6703 +#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
6704 + orinoco_cache_fw(priv, 0);
6705 +#endif
6707 + err = orinoco_download(priv);
6708 + if (err)
6709 + priv->do_fw_download = 0;
6711 + /* Check firmware version again */
6712 + err = determine_fw_capabilities(priv, wiphy->fw_version,
6713 + sizeof(wiphy->fw_version),
6714 + &wiphy->hw_version);
6715 + if (err != 0) {
6716 + dev_err(dev, "Incompatible firmware, aborting\n");
6717 + goto out;
6721 + if (priv->has_port3)
6722 + dev_info(dev, "Ad-hoc demo mode supported\n");
6723 + if (priv->has_ibss)
6724 + dev_info(dev, "IEEE standard IBSS ad-hoc mode supported\n");
6725 + if (priv->has_wep)
6726 + dev_info(dev, "WEP supported, %s-bit key\n",
6727 + priv->has_big_wep ? "104" : "40");
6728 + if (priv->has_wpa) {
6729 + dev_info(dev, "WPA-PSK supported\n");
6730 + if (orinoco_mic_init(priv)) {
6731 + dev_err(dev, "Failed to setup MIC crypto algorithm. "
6732 + "Disabling WPA support\n");
6733 + priv->has_wpa = 0;
6737 + err = orinoco_hw_read_card_settings(priv, wiphy->perm_addr);
6738 + if (err)
6739 + goto out;
6741 + err = orinoco_hw_allocate_fid(priv);
6742 + if (err) {
6743 + dev_err(dev, "Failed to allocate NIC buffer!\n");
6744 + goto out;
6747 + /* Set up the default configuration */
6748 + priv->iw_mode = NL80211_IFTYPE_STATION;
6749 + /* By default use IEEE/IBSS ad-hoc mode if we have it */
6750 + priv->prefer_port3 = priv->has_port3 && (!priv->has_ibss);
6751 + set_port_type(priv);
6752 + priv->channel = 0; /* use firmware default */
6754 + priv->promiscuous = 0;
6755 + priv->encode_alg = ORINOCO_ALG_NONE;
6756 + priv->tx_key = 0;
6757 + priv->wpa_enabled = 0;
6758 + priv->tkip_cm_active = 0;
6759 + priv->key_mgmt = 0;
6760 + priv->wpa_ie_len = 0;
6761 + priv->wpa_ie = NULL;
6763 + if (orinoco_wiphy_register(wiphy)) {
6764 + err = -ENODEV;
6765 + goto out;
6768 + /* Make the hardware available, as long as it hasn't been
6769 + * removed elsewhere (e.g. by PCMCIA hot unplug) */
6770 + orinoco_lock_irq(priv);
6771 + priv->hw_unavailable--;
6772 + orinoco_unlock_irq(priv);
6774 + dev_dbg(dev, "Ready\n");
6776 + out:
6777 + return err;
6779 +EXPORT_SYMBOL(orinoco_init);
6781 +static const struct net_device_ops orinoco_netdev_ops = {
6782 + .ndo_open = orinoco_open,
6783 + .ndo_stop = orinoco_stop,
6784 + .ndo_start_xmit = orinoco_xmit,
6785 + .ndo_set_rx_mode = orinoco_set_multicast_list,
6786 + .ndo_change_mtu = orinoco_change_mtu,
6787 + .ndo_set_mac_address = eth_mac_addr,
6788 + .ndo_validate_addr = eth_validate_addr,
6789 + .ndo_tx_timeout = orinoco_tx_timeout,
6792 +/* Allocate private data.
6794 + * This driver has a number of structures associated with it
6795 + * netdev - Net device structure for each network interface
6796 + * wiphy - structure associated with wireless phy
6797 + * wireless_dev (wdev) - structure for each wireless interface
6798 + * hw - structure for hermes chip info
6799 + * card - card specific structure for use by the card driver
6800 + * (airport, orinoco_cs)
6801 + * priv - orinoco private data
6802 + * device - generic linux device structure
6804 + * +---------+ +---------+
6805 + * | wiphy | | netdev |
6806 + * | +-------+ | +-------+
6807 + * | | priv | | | wdev |
6808 + * | | +-----+ +-+-------+
6809 + * | | | hw |
6810 + * | +-+-----+
6811 + * | | card |
6812 + * +-+-------+
6814 + * priv has a link to netdev and device
6815 + * wdev has a link to wiphy
6816 + */
6817 +struct orinoco_private
6818 +*alloc_orinocodev(int sizeof_card,
6819 + struct device *device,
6820 + int (*hard_reset)(struct orinoco_private *),
6821 + int (*stop_fw)(struct orinoco_private *, int))
6823 + struct orinoco_private *priv;
6824 + struct wiphy *wiphy;
6826 + /* allocate wiphy
6827 + * NOTE: We only support a single virtual interface
6828 + * but this may change when monitor mode is added
6829 + */
6830 + wiphy = wiphy_new(&orinoco_cfg_ops,
6831 + sizeof(struct orinoco_private) + sizeof_card);
6832 + if (!wiphy)
6833 + return NULL;
6835 + priv = wiphy_priv(wiphy);
6836 + priv->dev = device;
6838 + if (sizeof_card)
6839 + priv->card = (void *)((unsigned long)priv
6840 + + sizeof(struct orinoco_private));
6841 + else
6842 + priv->card = NULL;
6844 + orinoco_wiphy_init(wiphy);
6846 +#ifdef WIRELESS_SPY
6847 + priv->wireless_data.spy_data = &priv->spy_data;
6848 +#endif
6850 + /* Set up default callbacks */
6851 + priv->hard_reset = hard_reset;
6852 + priv->stop_fw = stop_fw;
6854 + spin_lock_init(&priv->lock);
6855 + priv->open = 0;
6856 + priv->hw_unavailable = 1; /* orinoco_init() must clear this
6857 + * before anything else touches the
6858 + * hardware */
6859 + INIT_WORK(&priv->reset_work, orinoco_reset);
6860 + INIT_WORK(&priv->join_work, orinoco_join_ap);
6861 + INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
6863 + INIT_LIST_HEAD(&priv->rx_list);
6864 + tasklet_setup(&priv->rx_tasklet, orinoco_rx_isr_tasklet);
6866 + spin_lock_init(&priv->scan_lock);
6867 + INIT_LIST_HEAD(&priv->scan_list);
6868 + INIT_WORK(&priv->process_scan, orinoco_process_scan_results);
6870 + priv->last_linkstatus = 0xffff;
6872 +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
6873 + priv->cached_pri_fw = NULL;
6874 + priv->cached_fw = NULL;
6875 +#endif
6877 + /* Register PM notifiers */
6878 + orinoco_register_pm_notifier(priv);
6880 + return priv;
6882 +EXPORT_SYMBOL(alloc_orinocodev);
6884 +/* We can only support a single interface. We provide a separate
6885 + * function to set it up to distinguish between hardware
6886 + * initialisation and interface setup.
6888 + * The base_addr and irq parameters are passed on to netdev for use
6889 + * with SIOCGIFMAP.
6890 + */
6891 +int orinoco_if_add(struct orinoco_private *priv,
6892 + unsigned long base_addr,
6893 + unsigned int irq,
6894 + const struct net_device_ops *ops)
6896 + struct wiphy *wiphy = priv_to_wiphy(priv);
6897 + struct wireless_dev *wdev;
6898 + struct net_device *dev;
6899 + int ret;
6901 + dev = alloc_etherdev(sizeof(struct wireless_dev));
6903 + if (!dev)
6904 + return -ENOMEM;
6906 + /* Initialise wireless_dev */
6907 + wdev = netdev_priv(dev);
6908 + wdev->wiphy = wiphy;
6909 + wdev->iftype = NL80211_IFTYPE_STATION;
6911 + /* Setup / override net_device fields */
6912 + dev->ieee80211_ptr = wdev;
6913 + dev->watchdog_timeo = HZ; /* 1 second timeout */
6914 + dev->wireless_handlers = &orinoco_handler_def;
6915 +#ifdef WIRELESS_SPY
6916 + dev->wireless_data = &priv->wireless_data;
6917 +#endif
6918 + /* Default to standard ops if not set */
6919 + if (ops)
6920 + dev->netdev_ops = ops;
6921 + else
6922 + dev->netdev_ops = &orinoco_netdev_ops;
6924 + /* we use the default eth_mac_addr for setting the MAC addr */
6926 + /* Reserve space in skb for the SNAP header */
6927 + dev->needed_headroom = ENCAPS_OVERHEAD;
6929 + netif_carrier_off(dev);
6931 + eth_hw_addr_set(dev, wiphy->perm_addr);
6933 + dev->base_addr = base_addr;
6934 + dev->irq = irq;
6936 + dev->min_mtu = ORINOCO_MIN_MTU;
6937 + dev->max_mtu = ORINOCO_MAX_MTU;
6939 + SET_NETDEV_DEV(dev, priv->dev);
6940 + ret = register_netdev(dev);
6941 + if (ret)
6942 + goto fail;
6944 + priv->ndev = dev;
6946 + /* Report what we've done */
6947 + dev_dbg(priv->dev, "Registered interface %s.\n", dev->name);
6949 + return 0;
6951 + fail:
6952 + free_netdev(dev);
6953 + return ret;
6955 +EXPORT_SYMBOL(orinoco_if_add);
6957 +void orinoco_if_del(struct orinoco_private *priv)
6959 + struct net_device *dev = priv->ndev;
6961 + unregister_netdev(dev);
6962 + free_netdev(dev);
6964 +EXPORT_SYMBOL(orinoco_if_del);
6966 +void free_orinocodev(struct orinoco_private *priv)
6968 + struct wiphy *wiphy = priv_to_wiphy(priv);
6969 + struct orinoco_rx_data *rx_data, *temp;
6970 + struct orinoco_scan_data *sd, *sdtemp;
6972 + /* If the tasklet is scheduled when we call tasklet_kill it
6973 + * will run one final time. However the tasklet will only
6974 + * drain priv->rx_list if the hw is still available. */
6975 + tasklet_kill(&priv->rx_tasklet);
6977 + /* Explicitly drain priv->rx_list */
6978 + list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
6979 + list_del(&rx_data->list);
6981 + dev_kfree_skb(rx_data->skb);
6982 + kfree(rx_data->desc);
6983 + kfree(rx_data);
6986 + cancel_work_sync(&priv->process_scan);
6987 + /* Explicitly drain priv->scan_list */
6988 + list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) {
6989 + list_del(&sd->list);
6991 + if (sd->len > 0)
6992 + kfree(sd->buf);
6993 + kfree(sd);
6996 + orinoco_unregister_pm_notifier(priv);
6997 + orinoco_uncache_fw(priv);
6999 + priv->wpa_ie_len = 0;
7000 + kfree(priv->wpa_ie);
7001 + orinoco_mic_free(priv);
7002 + wiphy_free(wiphy);
7004 +EXPORT_SYMBOL(free_orinocodev);
7006 +int orinoco_up(struct orinoco_private *priv)
7008 + struct net_device *dev = priv->ndev;
7009 + unsigned long flags;
7010 + int err;
7012 + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
7014 + err = orinoco_reinit_firmware(priv);
7015 + if (err) {
7016 + printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
7017 + dev->name, err);
7018 + goto exit;
7021 + netif_device_attach(dev);
7022 + priv->hw_unavailable--;
7024 + if (priv->open && !priv->hw_unavailable) {
7025 + err = __orinoco_up(priv);
7026 + if (err)
7027 + printk(KERN_ERR "%s: Error %d restarting card\n",
7028 + dev->name, err);
7031 +exit:
7032 + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
7034 + return 0;
7036 +EXPORT_SYMBOL(orinoco_up);
7038 +void orinoco_down(struct orinoco_private *priv)
7040 + struct net_device *dev = priv->ndev;
7041 + unsigned long flags;
7042 + int err;
7044 + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
7045 + err = __orinoco_down(priv);
7046 + if (err)
7047 + printk(KERN_WARNING "%s: Error %d downing interface\n",
7048 + dev->name, err);
7050 + netif_device_detach(dev);
7051 + priv->hw_unavailable++;
7052 + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
7054 +EXPORT_SYMBOL(orinoco_down);
7056 +/********************************************************************/
7057 +/* Module initialization */
7058 +/********************************************************************/
7060 +/* Can't be declared "const" or the whole __initdata section will
7061 + * become const */
7062 +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
7063 + " (David Gibson <hermes@gibson.dropbear.id.au>, "
7064 + "Pavel Roskin <proski@gnu.org>, et al)";
7066 +static int __init init_orinoco(void)
7068 + printk(KERN_DEBUG "%s\n", version);
7069 + return 0;
7072 +static void __exit exit_orinoco(void)
7076 +module_init(init_orinoco);
7077 +module_exit(exit_orinoco);
7078 --- /dev/null
7079 +++ a/drivers/net/wireless/intersil/orinoco/main.h
7080 @@ -0,0 +1,50 @@
7081 +/* Exports from main to helper modules
7083 + * See copyright notice in main.c
7084 + */
7085 +#ifndef _ORINOCO_MAIN_H_
7086 +#define _ORINOCO_MAIN_H_
7088 +#include <linux/ieee80211.h>
7089 +#include "orinoco.h"
7091 +/********************************************************************/
7092 +/* Compile time configuration and compatibility stuff */
7093 +/********************************************************************/
7095 +/* We do this this way to avoid ifdefs in the actual code */
7096 +#ifdef WIRELESS_SPY
7097 +#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
7098 +#else
7099 +#define SPY_NUMBER(priv) 0
7100 +#endif /* WIRELESS_SPY */
7102 +/********************************************************************/
7104 +/* Export module parameter */
7105 +extern int force_monitor;
7107 +/* Forward declarations */
7108 +struct net_device;
7109 +struct work_struct;
7111 +void set_port_type(struct orinoco_private *priv);
7112 +int orinoco_commit(struct orinoco_private *priv);
7113 +void orinoco_reset(struct work_struct *work);
7115 +/* Information element helpers - find a home for these... */
7116 +#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
7117 +#define WPA_SELECTOR_LEN 4
7118 +static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
7120 + u8 *p = data;
7121 + while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
7122 + if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) &&
7123 + (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
7124 + return p;
7125 + p += p[1] + 2;
7127 + return NULL;
7130 +#endif /* _ORINOCO_MAIN_H_ */
7131 --- /dev/null
7132 +++ a/drivers/net/wireless/intersil/orinoco/mic.c
7133 @@ -0,0 +1,89 @@
7134 +/* Orinoco MIC helpers
7136 + * See copyright notice in main.c
7137 + */
7138 +#include <linux/kernel.h>
7139 +#include <linux/string.h>
7140 +#include <linux/if_ether.h>
7141 +#include <linux/scatterlist.h>
7142 +#include <crypto/hash.h>
7144 +#include "orinoco.h"
7145 +#include "mic.h"
7147 +/********************************************************************/
7148 +/* Michael MIC crypto setup */
7149 +/********************************************************************/
7150 +int orinoco_mic_init(struct orinoco_private *priv)
7152 + priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
7153 + if (IS_ERR(priv->tx_tfm_mic)) {
7154 + printk(KERN_DEBUG "%s: could not allocate "
7155 + "crypto API michael_mic\n", __func__);
7156 + priv->tx_tfm_mic = NULL;
7157 + return -ENOMEM;
7160 + priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
7161 + if (IS_ERR(priv->rx_tfm_mic)) {
7162 + printk(KERN_DEBUG "%s: could not allocate "
7163 + "crypto API michael_mic\n", __func__);
7164 + priv->rx_tfm_mic = NULL;
7165 + return -ENOMEM;
7168 + return 0;
7171 +void orinoco_mic_free(struct orinoco_private *priv)
7173 + if (priv->tx_tfm_mic)
7174 + crypto_free_shash(priv->tx_tfm_mic);
7175 + if (priv->rx_tfm_mic)
7176 + crypto_free_shash(priv->rx_tfm_mic);
7179 +int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
7180 + u8 *da, u8 *sa, u8 priority,
7181 + u8 *data, size_t data_len, u8 *mic)
7183 + SHASH_DESC_ON_STACK(desc, tfm_michael);
7184 + u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
7185 + int err;
7187 + if (tfm_michael == NULL) {
7188 + printk(KERN_WARNING "%s: tfm_michael == NULL\n", __func__);
7189 + return -1;
7192 + /* Copy header into buffer. We need the padding on the end zeroed */
7193 + memcpy(&hdr[0], da, ETH_ALEN);
7194 + memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
7195 + hdr[ETH_ALEN * 2] = priority;
7196 + hdr[ETH_ALEN * 2 + 1] = 0;
7197 + hdr[ETH_ALEN * 2 + 2] = 0;
7198 + hdr[ETH_ALEN * 2 + 3] = 0;
7200 + desc->tfm = tfm_michael;
7202 + err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
7203 + if (err)
7204 + return err;
7206 + err = crypto_shash_init(desc);
7207 + if (err)
7208 + return err;
7210 + err = crypto_shash_update(desc, hdr, sizeof(hdr));
7211 + if (err)
7212 + return err;
7214 + err = crypto_shash_update(desc, data, data_len);
7215 + if (err)
7216 + return err;
7218 + err = crypto_shash_final(desc, mic);
7219 + shash_desc_zero(desc);
7221 + return err;
7223 --- /dev/null
7224 +++ a/drivers/net/wireless/intersil/orinoco/mic.h
7225 @@ -0,0 +1,23 @@
7226 +/* Orinoco MIC helpers
7228 + * See copyright notice in main.c
7229 + */
7230 +#ifndef _ORINOCO_MIC_H_
7231 +#define _ORINOCO_MIC_H_
7233 +#include <linux/types.h>
7234 +#include <crypto/hash.h>
7236 +#define MICHAEL_MIC_LEN 8
7238 +/* Forward declarations */
7239 +struct orinoco_private;
7240 +struct crypto_ahash;
7242 +int orinoco_mic_init(struct orinoco_private *priv);
7243 +void orinoco_mic_free(struct orinoco_private *priv);
7244 +int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
7245 + u8 *da, u8 *sa, u8 priority,
7246 + u8 *data, size_t data_len, u8 *mic);
7248 +#endif /* ORINOCO_MIC_H */
7249 --- /dev/null
7250 +++ a/drivers/net/wireless/intersil/orinoco/orinoco.h
7251 @@ -0,0 +1,251 @@
7252 +/* orinoco.h
7254 + * Common definitions to all pieces of the various orinoco
7255 + * drivers
7256 + */
7258 +#ifndef _ORINOCO_H
7259 +#define _ORINOCO_H
7261 +#define DRIVER_VERSION "0.15"
7263 +#include <linux/interrupt.h>
7264 +#include <linux/suspend.h>
7265 +#include <linux/netdevice.h>
7266 +#include <linux/wireless.h>
7267 +#include <net/iw_handler.h>
7268 +#include <net/cfg80211.h>
7270 +#include "hermes.h"
7272 +/* To enable debug messages */
7273 +/*#define ORINOCO_DEBUG 3*/
7275 +#define WIRELESS_SPY /* enable iwspy support */
7277 +#define MAX_SCAN_LEN 4096
7279 +#define ORINOCO_SEQ_LEN 8
7280 +#define ORINOCO_MAX_KEY_SIZE 14
7281 +#define ORINOCO_MAX_KEYS 4
7283 +struct orinoco_key {
7284 + __le16 len; /* always stored as little-endian */
7285 + char data[ORINOCO_MAX_KEY_SIZE];
7286 +} __packed;
7288 +#define TKIP_KEYLEN 16
7289 +#define MIC_KEYLEN 8
7291 +struct orinoco_tkip_key {
7292 + u8 tkip[TKIP_KEYLEN];
7293 + u8 tx_mic[MIC_KEYLEN];
7294 + u8 rx_mic[MIC_KEYLEN];
7297 +enum orinoco_alg {
7298 + ORINOCO_ALG_NONE,
7299 + ORINOCO_ALG_WEP,
7300 + ORINOCO_ALG_TKIP
7303 +enum fwtype {
7304 + FIRMWARE_TYPE_AGERE,
7305 + FIRMWARE_TYPE_INTERSIL,
7306 + FIRMWARE_TYPE_SYMBOL
7309 +struct firmware;
7311 +struct orinoco_private {
7312 + void *card; /* Pointer to card dependent structure */
7313 + struct device *dev;
7314 + int (*hard_reset)(struct orinoco_private *);
7315 + int (*stop_fw)(struct orinoco_private *, int);
7317 + struct ieee80211_supported_band band;
7318 + struct ieee80211_channel channels[14];
7319 + u32 cipher_suites[3];
7321 + /* Synchronisation stuff */
7322 + spinlock_t lock;
7323 + int hw_unavailable;
7324 + struct work_struct reset_work;
7326 + /* Interrupt tasklets */
7327 + struct tasklet_struct rx_tasklet;
7328 + struct list_head rx_list;
7330 + /* driver state */
7331 + int open;
7332 + u16 last_linkstatus;
7333 + struct work_struct join_work;
7334 + struct work_struct wevent_work;
7336 + /* Net device stuff */
7337 + struct net_device *ndev;
7338 + struct iw_statistics wstats;
7340 + /* Hardware control variables */
7341 + struct hermes hw;
7342 + u16 txfid;
7344 + /* Capabilities of the hardware/firmware */
7345 + enum fwtype firmware_type;
7346 + int ibss_port;
7347 + int nicbuf_size;
7348 + u16 channel_mask;
7350 + /* Boolean capabilities */
7351 + unsigned int has_ibss:1;
7352 + unsigned int has_port3:1;
7353 + unsigned int has_wep:1;
7354 + unsigned int has_big_wep:1;
7355 + unsigned int has_mwo:1;
7356 + unsigned int has_pm:1;
7357 + unsigned int has_preamble:1;
7358 + unsigned int has_sensitivity:1;
7359 + unsigned int has_hostscan:1;
7360 + unsigned int has_alt_txcntl:1;
7361 + unsigned int has_ext_scan:1;
7362 + unsigned int has_wpa:1;
7363 + unsigned int do_fw_download:1;
7364 + unsigned int broken_disableport:1;
7365 + unsigned int broken_monitor:1;
7366 + unsigned int prefer_port3:1;
7368 + /* Configuration paramaters */
7369 + enum nl80211_iftype iw_mode;
7370 + enum orinoco_alg encode_alg;
7371 + u16 wep_restrict, tx_key;
7372 + struct key_params keys[ORINOCO_MAX_KEYS];
7374 + int bitratemode;
7375 + char nick[IW_ESSID_MAX_SIZE + 1];
7376 + char desired_essid[IW_ESSID_MAX_SIZE + 1];
7377 + char desired_bssid[ETH_ALEN];
7378 + int bssid_fixed;
7379 + u16 frag_thresh, mwo_robust;
7380 + u16 channel;
7381 + u16 ap_density, rts_thresh;
7382 + u16 pm_on, pm_mcast, pm_period, pm_timeout;
7383 + u16 preamble;
7384 + u16 short_retry_limit, long_retry_limit;
7385 + u16 retry_lifetime;
7386 +#ifdef WIRELESS_SPY
7387 + struct iw_spy_data spy_data; /* iwspy support */
7388 + struct iw_public_data wireless_data;
7389 +#endif
7391 + /* Configuration dependent variables */
7392 + int port_type, createibss;
7393 + int promiscuous, mc_count;
7395 + /* Scanning support */
7396 + struct cfg80211_scan_request *scan_request;
7397 + struct work_struct process_scan;
7398 + struct list_head scan_list;
7399 + spinlock_t scan_lock; /* protects the scan list */
7401 + /* WPA support */
7402 + u8 *wpa_ie;
7403 + int wpa_ie_len;
7405 + struct crypto_shash *rx_tfm_mic;
7406 + struct crypto_shash *tx_tfm_mic;
7408 + unsigned int wpa_enabled:1;
7409 + unsigned int tkip_cm_active:1;
7410 + unsigned int key_mgmt:3;
7412 +#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
7413 + /* Cached in memory firmware to use during ->resume. */
7414 + const struct firmware *cached_pri_fw;
7415 + const struct firmware *cached_fw;
7416 +#endif
7418 + struct notifier_block pm_notifier;
7421 +#ifdef ORINOCO_DEBUG
7422 +extern int orinoco_debug;
7423 +#define DEBUG(n, args...) do { \
7424 + if (orinoco_debug > (n)) \
7425 + printk(KERN_DEBUG args); \
7426 +} while (0)
7427 +#else
7428 +#define DEBUG(n, args...) do { } while (0)
7429 +#endif /* ORINOCO_DEBUG */
7431 +/********************************************************************/
7432 +/* Exported prototypes */
7433 +/********************************************************************/
7435 +struct orinoco_private *alloc_orinocodev(int sizeof_card, struct device *device,
7436 + int (*hard_reset)(struct orinoco_private *),
7437 + int (*stop_fw)(struct orinoco_private *, int));
7438 +void free_orinocodev(struct orinoco_private *priv);
7439 +int orinoco_init(struct orinoco_private *priv);
7440 +int orinoco_if_add(struct orinoco_private *priv, unsigned long base_addr,
7441 + unsigned int irq, const struct net_device_ops *ops);
7442 +void orinoco_if_del(struct orinoco_private *priv);
7443 +int orinoco_up(struct orinoco_private *priv);
7444 +void orinoco_down(struct orinoco_private *priv);
7445 +irqreturn_t orinoco_interrupt(int irq, void *dev_id);
7447 +void __orinoco_ev_info(struct net_device *dev, struct hermes *hw);
7448 +void __orinoco_ev_rx(struct net_device *dev, struct hermes *hw);
7450 +int orinoco_process_xmit_skb(struct sk_buff *skb,
7451 + struct net_device *dev,
7452 + struct orinoco_private *priv,
7453 + int *tx_control,
7454 + u8 *mic);
7456 +/* Common ndo functions exported for reuse by orinoco_usb */
7457 +int orinoco_open(struct net_device *dev);
7458 +int orinoco_stop(struct net_device *dev);
7459 +void orinoco_set_multicast_list(struct net_device *dev);
7460 +int orinoco_change_mtu(struct net_device *dev, int new_mtu);
7461 +void orinoco_tx_timeout(struct net_device *dev, unsigned int txqueue);
7463 +/********************************************************************/
7464 +/* Locking and synchronization functions */
7465 +/********************************************************************/
7467 +static inline int orinoco_lock(struct orinoco_private *priv,
7468 + unsigned long *flags)
7470 + priv->hw.ops->lock_irqsave(&priv->lock, flags);
7471 + if (priv->hw_unavailable) {
7472 + DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
7473 + priv->ndev);
7474 + priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
7475 + return -EBUSY;
7477 + return 0;
7480 +static inline void orinoco_unlock(struct orinoco_private *priv,
7481 + unsigned long *flags)
7483 + priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
7486 +static inline void orinoco_lock_irq(struct orinoco_private *priv)
7488 + priv->hw.ops->lock_irq(&priv->lock);
7491 +static inline void orinoco_unlock_irq(struct orinoco_private *priv)
7493 + priv->hw.ops->unlock_irq(&priv->lock);
7496 +/*** Navigate from net_device to orinoco_private ***/
7497 +static inline struct orinoco_private *ndev_priv(struct net_device *dev)
7499 + struct wireless_dev *wdev = netdev_priv(dev);
7500 + return wdev_priv(wdev);
7502 +#endif /* _ORINOCO_H */
7503 --- /dev/null
7504 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
7505 @@ -0,0 +1,350 @@
7506 +/* orinoco_cs.c (formerly known as dldwd_cs.c)
7508 + * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
7509 + * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
7510 + * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
7511 + * It should also be usable on various Prism II based cards such as the
7512 + * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
7513 + * cards such as the 3Com AirConnect and Ericsson WLAN.
7515 + * Copyright notice & release notes in file main.c
7516 + */
7518 +#define DRIVER_NAME "orinoco_cs"
7519 +#define PFX DRIVER_NAME ": "
7521 +#include <linux/module.h>
7522 +#include <linux/kernel.h>
7523 +#include <linux/delay.h>
7524 +#include <pcmcia/cistpl.h>
7525 +#include <pcmcia/cisreg.h>
7526 +#include <pcmcia/ds.h>
7528 +#include "orinoco.h"
7530 +/********************************************************************/
7531 +/* Module stuff */
7532 +/********************************************************************/
7534 +MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
7535 +MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco,"
7536 + " Prism II based and similar wireless cards");
7537 +MODULE_LICENSE("Dual MPL/GPL");
7539 +/* Module parameters */
7541 +/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
7542 + * don't have any CIS entry for it. This workaround it... */
7543 +static int ignore_cis_vcc; /* = 0 */
7544 +module_param(ignore_cis_vcc, int, 0);
7545 +MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
7547 +/********************************************************************/
7548 +/* Data structures */
7549 +/********************************************************************/
7551 +/* PCMCIA specific device information (goes in the card field of
7552 + * struct orinoco_private */
7553 +struct orinoco_pccard {
7554 + struct pcmcia_device *p_dev;
7556 + /* Used to handle hard reset */
7557 + /* yuck, we need this hack to work around the insanity of the
7558 + * PCMCIA layer */
7559 + unsigned long hard_reset_in_progress;
7563 +/********************************************************************/
7564 +/* Function prototypes */
7565 +/********************************************************************/
7567 +static int orinoco_cs_config(struct pcmcia_device *link);
7568 +static void orinoco_cs_release(struct pcmcia_device *link);
7569 +static void orinoco_cs_detach(struct pcmcia_device *p_dev);
7571 +/********************************************************************/
7572 +/* Device methods */
7573 +/********************************************************************/
7575 +static int
7576 +orinoco_cs_hard_reset(struct orinoco_private *priv)
7578 + struct orinoco_pccard *card = priv->card;
7579 + struct pcmcia_device *link = card->p_dev;
7580 + int err;
7582 + /* We need atomic ops here, because we're not holding the lock */
7583 + set_bit(0, &card->hard_reset_in_progress);
7585 + err = pcmcia_reset_card(link->socket);
7586 + if (err)
7587 + return err;
7589 + msleep(100);
7590 + clear_bit(0, &card->hard_reset_in_progress);
7592 + return 0;
7595 +/********************************************************************/
7596 +/* PCMCIA stuff */
7597 +/********************************************************************/
7599 +static int
7600 +orinoco_cs_probe(struct pcmcia_device *link)
7602 + struct orinoco_private *priv;
7603 + struct orinoco_pccard *card;
7604 + int ret;
7606 + priv = alloc_orinocodev(sizeof(*card), &link->dev,
7607 + orinoco_cs_hard_reset, NULL);
7608 + if (!priv)
7609 + return -ENOMEM;
7610 + card = priv->card;
7612 + /* Link both structures together */
7613 + card->p_dev = link;
7614 + link->priv = priv;
7616 + ret = orinoco_cs_config(link);
7617 + if (ret)
7618 + goto err_free_orinocodev;
7620 + return 0;
7622 +err_free_orinocodev:
7623 + free_orinocodev(priv);
7624 + return ret;
7627 +static void orinoco_cs_detach(struct pcmcia_device *link)
7629 + struct orinoco_private *priv = link->priv;
7631 + orinoco_if_del(priv);
7633 + orinoco_cs_release(link);
7635 + wiphy_unregister(priv_to_wiphy(priv));
7636 + free_orinocodev(priv);
7637 +} /* orinoco_cs_detach */
7639 +static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
7641 + if (p_dev->config_index == 0)
7642 + return -EINVAL;
7644 + return pcmcia_request_io(p_dev);
7647 +static int
7648 +orinoco_cs_config(struct pcmcia_device *link)
7650 + struct orinoco_private *priv = link->priv;
7651 + struct hermes *hw = &priv->hw;
7652 + int ret;
7653 + void __iomem *mem;
7655 + link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
7656 + CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
7657 + if (ignore_cis_vcc)
7658 + link->config_flags &= ~CONF_AUTO_CHECK_VCC;
7659 + ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
7660 + if (ret) {
7661 + if (!ignore_cis_vcc)
7662 + printk(KERN_ERR PFX "GetNextTuple(): No matching "
7663 + "CIS configuration. Maybe you need the "
7664 + "ignore_cis_vcc=1 parameter.\n");
7665 + goto failed;
7668 + mem = ioport_map(link->resource[0]->start,
7669 + resource_size(link->resource[0]));
7670 + if (!mem)
7671 + goto failed;
7673 + /* We initialize the hermes structure before completing PCMCIA
7674 + * configuration just in case the interrupt handler gets
7675 + * called. */
7676 + hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
7678 + ret = pcmcia_request_irq(link, orinoco_interrupt);
7679 + if (ret)
7680 + goto failed;
7682 + ret = pcmcia_enable_device(link);
7683 + if (ret)
7684 + goto failed;
7686 + /* Initialise the main driver */
7687 + if (orinoco_init(priv) != 0) {
7688 + printk(KERN_ERR PFX "orinoco_init() failed\n");
7689 + goto failed;
7692 + /* Register an interface with the stack */
7693 + if (orinoco_if_add(priv, link->resource[0]->start,
7694 + link->irq, NULL) != 0) {
7695 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
7696 + goto failed;
7699 + return 0;
7701 + failed:
7702 + orinoco_cs_release(link);
7703 + return -ENODEV;
7704 +} /* orinoco_cs_config */
7706 +static void
7707 +orinoco_cs_release(struct pcmcia_device *link)
7709 + struct orinoco_private *priv = link->priv;
7710 + unsigned long flags;
7712 + /* We're committed to taking the device away now, so mark the
7713 + * hardware as unavailable */
7714 + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
7715 + priv->hw_unavailable++;
7716 + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
7718 + pcmcia_disable_device(link);
7719 + if (priv->hw.iobase)
7720 + ioport_unmap(priv->hw.iobase);
7721 +} /* orinoco_cs_release */
7723 +static int orinoco_cs_suspend(struct pcmcia_device *link)
7725 + struct orinoco_private *priv = link->priv;
7726 + struct orinoco_pccard *card = priv->card;
7728 + /* This is probably racy, but I can't think of
7729 + a better way, short of rewriting the PCMCIA
7730 + layer to not suck :-( */
7731 + if (!test_bit(0, &card->hard_reset_in_progress))
7732 + orinoco_down(priv);
7734 + return 0;
7737 +static int orinoco_cs_resume(struct pcmcia_device *link)
7739 + struct orinoco_private *priv = link->priv;
7740 + struct orinoco_pccard *card = priv->card;
7741 + int err = 0;
7743 + if (!test_bit(0, &card->hard_reset_in_progress))
7744 + err = orinoco_up(priv);
7746 + return err;
7750 +/********************************************************************/
7751 +/* Module initialization */
7752 +/********************************************************************/
7754 +static const struct pcmcia_device_id orinoco_cs_ids[] = {
7755 + PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
7756 + PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
7757 + PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
7758 + PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
7759 + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
7760 + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
7761 + PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
7762 + PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
7763 + PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
7764 + PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
7765 + PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
7766 + PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
7767 + PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
7768 + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
7769 + PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
7770 + PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
7771 + PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
7772 + PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
7773 + PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
7774 + PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
7775 + PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
7776 + PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
7777 + PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
7778 + PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
7779 + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
7780 + PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
7781 + PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
7782 + PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
7783 + PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
7784 + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
7785 + PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
7786 + PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
7787 + PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
7788 + PCMCIA_DEVICE_MANF_CARD_PROD_ID3(0x0156, 0x0002, "Version 01.01", 0xd27deb1a), /* Lucent Orinoco */
7789 +#ifdef CONFIG_HERMES_PRISM
7790 + /* Only entries that certainly identify Prism chipset */
7791 + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
7792 + PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
7793 + PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
7794 + PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
7795 + PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
7796 + PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
7797 + PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
7798 + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
7799 + PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
7800 + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
7801 + PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
7802 + PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
7803 + PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
7804 + PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
7805 + PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
7806 + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
7807 + PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
7808 + PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
7809 + PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
7810 + PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
7811 + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
7812 + PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
7813 + PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
7814 + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
7815 + PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
7816 + PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
7817 + PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
7818 + PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
7819 + PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
7820 + PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
7821 + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
7822 + PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
7823 + PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
7824 + PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
7825 + PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
7826 + PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
7827 + PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
7828 + PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
7829 + PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
7830 + PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
7831 + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
7832 + PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
7833 + PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
7834 + PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
7835 + PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
7836 + PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
7837 + PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
7839 + /* This may be Agere or Intersil Firmware */
7840 + PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002),
7841 +#endif
7842 + PCMCIA_DEVICE_NULL,
7844 +MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
7846 +static struct pcmcia_driver orinoco_driver = {
7847 + .owner = THIS_MODULE,
7848 + .name = DRIVER_NAME,
7849 + .probe = orinoco_cs_probe,
7850 + .remove = orinoco_cs_detach,
7851 + .id_table = orinoco_cs_ids,
7852 + .suspend = orinoco_cs_suspend,
7853 + .resume = orinoco_cs_resume,
7855 +module_pcmcia_driver(orinoco_driver);
7856 --- /dev/null
7857 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_nortel.c
7858 @@ -0,0 +1,314 @@
7859 +/* orinoco_nortel.c
7861 + * Driver for Prism II devices which would usually be driven by orinoco_cs,
7862 + * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in
7863 + * Nortel emobility, Symbol LA-4113 and Symbol LA-4123.
7865 + * Copyright (C) 2002 Tobias Hoffmann
7866 + * (C) 2003 Christoph Jungegger <disdos@traum404.de>
7868 + * Some of this code is borrowed from orinoco_plx.c
7869 + * Copyright (C) 2001 Daniel Barlow
7870 + * Some of this code is borrowed from orinoco_pci.c
7871 + * Copyright (C) 2001 Jean Tourrilhes
7872 + * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
7873 + * has been copied from it. linux-wlan-ng-0.1.10 is originally :
7874 + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
7876 + * The contents of this file are subject to the Mozilla Public License
7877 + * Version 1.1 (the "License"); you may not use this file except in
7878 + * compliance with the License. You may obtain a copy of the License
7879 + * at http://www.mozilla.org/MPL/
7881 + * Software distributed under the License is distributed on an "AS IS"
7882 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
7883 + * the License for the specific language governing rights and
7884 + * limitations under the License.
7886 + * Alternatively, the contents of this file may be used under the
7887 + * terms of the GNU General Public License version 2 (the "GPL"), in
7888 + * which case the provisions of the GPL are applicable instead of the
7889 + * above. If you wish to allow the use of your version of this file
7890 + * only under the terms of the GPL and not to allow others to use your
7891 + * version of this file under the MPL, indicate your decision by
7892 + * deleting the provisions above and replace them with the notice and
7893 + * other provisions required by the GPL. If you do not delete the
7894 + * provisions above, a recipient may use your version of this file
7895 + * under either the MPL or the GPL.
7896 + */
7898 +#define DRIVER_NAME "orinoco_nortel"
7899 +#define PFX DRIVER_NAME ": "
7901 +#include <linux/module.h>
7902 +#include <linux/kernel.h>
7903 +#include <linux/init.h>
7904 +#include <linux/delay.h>
7905 +#include <linux/pci.h>
7906 +#include <pcmcia/cisreg.h>
7908 +#include "orinoco.h"
7909 +#include "orinoco_pci.h"
7911 +#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
7912 +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
7916 + * Do a soft reset of the card using the Configuration Option Register
7917 + * We need this to get going...
7918 + * This is the part of the code that is strongly inspired from wlan-ng
7920 + * Note bis : Don't try to access HERMES_CMD during the reset phase.
7921 + * It just won't work !
7922 + */
7923 +static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
7925 + struct orinoco_pci_card *card = priv->card;
7927 + /* Assert the reset until the card notices */
7928 + iowrite16(8, card->bridge_io + 2);
7929 + ioread16(card->attr_io + COR_OFFSET);
7930 + iowrite16(0x80, card->attr_io + COR_OFFSET);
7931 + mdelay(1);
7933 + /* Give time for the card to recover from this hard effort */
7934 + iowrite16(0, card->attr_io + COR_OFFSET);
7935 + iowrite16(0, card->attr_io + COR_OFFSET);
7936 + mdelay(1);
7938 + /* Set COR as usual */
7939 + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
7940 + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
7941 + mdelay(1);
7943 + iowrite16(0x228, card->bridge_io + 2);
7945 + return 0;
7948 +static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
7950 + int i;
7951 + u32 reg;
7953 + /* Setup bridge */
7954 + if (ioread16(card->bridge_io) & 1) {
7955 + printk(KERN_ERR PFX "brg1 answer1 wrong\n");
7956 + return -EBUSY;
7958 + iowrite16(0x118, card->bridge_io + 2);
7959 + iowrite16(0x108, card->bridge_io + 2);
7960 + mdelay(30);
7961 + iowrite16(0x8, card->bridge_io + 2);
7962 + for (i = 0; i < 30; i++) {
7963 + mdelay(30);
7964 + if (ioread16(card->bridge_io) & 0x10)
7965 + break;
7967 + if (i == 30) {
7968 + printk(KERN_ERR PFX "brg1 timed out\n");
7969 + return -EBUSY;
7971 + if (ioread16(card->attr_io + COR_OFFSET) & 1) {
7972 + printk(KERN_ERR PFX "brg2 answer1 wrong\n");
7973 + return -EBUSY;
7975 + if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
7976 + printk(KERN_ERR PFX "brg2 answer2 wrong\n");
7977 + return -EBUSY;
7979 + if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
7980 + printk(KERN_ERR PFX "brg2 answer3 wrong\n");
7981 + return -EBUSY;
7984 + /* Set the PCMCIA COR register */
7985 + iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
7986 + mdelay(1);
7987 + reg = ioread16(card->attr_io + COR_OFFSET);
7988 + if (reg != COR_VALUE) {
7989 + printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
7990 + reg);
7991 + return -EBUSY;
7994 + /* Set LEDs */
7995 + iowrite16(1, card->bridge_io + 10);
7996 + return 0;
7999 +static int orinoco_nortel_init_one(struct pci_dev *pdev,
8000 + const struct pci_device_id *ent)
8002 + int err;
8003 + struct orinoco_private *priv;
8004 + struct orinoco_pci_card *card;
8005 + void __iomem *hermes_io, *bridge_io, *attr_io;
8007 + err = pci_enable_device(pdev);
8008 + if (err) {
8009 + printk(KERN_ERR PFX "Cannot enable PCI device\n");
8010 + return err;
8013 + err = pci_request_regions(pdev, DRIVER_NAME);
8014 + if (err) {
8015 + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
8016 + goto fail_resources;
8019 + bridge_io = pci_iomap(pdev, 0, 0);
8020 + if (!bridge_io) {
8021 + printk(KERN_ERR PFX "Cannot map bridge registers\n");
8022 + err = -EIO;
8023 + goto fail_map_bridge;
8026 + attr_io = pci_iomap(pdev, 1, 0);
8027 + if (!attr_io) {
8028 + printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
8029 + err = -EIO;
8030 + goto fail_map_attr;
8033 + hermes_io = pci_iomap(pdev, 2, 0);
8034 + if (!hermes_io) {
8035 + printk(KERN_ERR PFX "Cannot map chipset registers\n");
8036 + err = -EIO;
8037 + goto fail_map_hermes;
8040 + /* Allocate network device */
8041 + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
8042 + orinoco_nortel_cor_reset, NULL);
8043 + if (!priv) {
8044 + printk(KERN_ERR PFX "Cannot allocate network device\n");
8045 + err = -ENOMEM;
8046 + goto fail_alloc;
8049 + card = priv->card;
8050 + card->bridge_io = bridge_io;
8051 + card->attr_io = attr_io;
8053 + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
8055 + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
8056 + DRIVER_NAME, priv);
8057 + if (err) {
8058 + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
8059 + err = -EBUSY;
8060 + goto fail_irq;
8063 + err = orinoco_nortel_hw_init(card);
8064 + if (err) {
8065 + printk(KERN_ERR PFX "Hardware initialization failed\n");
8066 + goto fail;
8069 + err = orinoco_nortel_cor_reset(priv);
8070 + if (err) {
8071 + printk(KERN_ERR PFX "Initial reset failed\n");
8072 + goto fail;
8075 + err = orinoco_init(priv);
8076 + if (err) {
8077 + printk(KERN_ERR PFX "orinoco_init() failed\n");
8078 + goto fail;
8081 + err = orinoco_if_add(priv, 0, 0, NULL);
8082 + if (err) {
8083 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
8084 + goto fail_wiphy;
8087 + pci_set_drvdata(pdev, priv);
8089 + return 0;
8091 + fail_wiphy:
8092 + wiphy_unregister(priv_to_wiphy(priv));
8093 + fail:
8094 + free_irq(pdev->irq, priv);
8096 + fail_irq:
8097 + free_orinocodev(priv);
8099 + fail_alloc:
8100 + pci_iounmap(pdev, hermes_io);
8102 + fail_map_hermes:
8103 + pci_iounmap(pdev, attr_io);
8105 + fail_map_attr:
8106 + pci_iounmap(pdev, bridge_io);
8108 + fail_map_bridge:
8109 + pci_release_regions(pdev);
8111 + fail_resources:
8112 + pci_disable_device(pdev);
8114 + return err;
8117 +static void orinoco_nortel_remove_one(struct pci_dev *pdev)
8119 + struct orinoco_private *priv = pci_get_drvdata(pdev);
8120 + struct orinoco_pci_card *card = priv->card;
8122 + /* Clear LEDs */
8123 + iowrite16(0, card->bridge_io + 10);
8125 + orinoco_if_del(priv);
8126 + wiphy_unregister(priv_to_wiphy(priv));
8127 + free_irq(pdev->irq, priv);
8128 + free_orinocodev(priv);
8129 + pci_iounmap(pdev, priv->hw.iobase);
8130 + pci_iounmap(pdev, card->attr_io);
8131 + pci_iounmap(pdev, card->bridge_io);
8132 + pci_release_regions(pdev);
8133 + pci_disable_device(pdev);
8136 +static const struct pci_device_id orinoco_nortel_id_table[] = {
8137 + /* Nortel emobility PCI */
8138 + {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
8139 + /* Symbol LA-4123 PCI */
8140 + {0x1562, 0x0001, PCI_ANY_ID, PCI_ANY_ID,},
8141 + {0,},
8144 +MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);
8146 +static struct pci_driver orinoco_nortel_driver = {
8147 + .name = DRIVER_NAME,
8148 + .id_table = orinoco_nortel_id_table,
8149 + .probe = orinoco_nortel_init_one,
8150 + .remove = orinoco_nortel_remove_one,
8151 + .driver.pm = &orinoco_pci_pm_ops,
8154 +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
8155 + " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
8156 +MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
8157 +MODULE_DESCRIPTION("Driver for wireless LAN cards using the Nortel PCI bridge");
8158 +MODULE_LICENSE("Dual MPL/GPL");
8160 +static int __init orinoco_nortel_init(void)
8162 + printk(KERN_DEBUG "%s\n", version);
8163 + return pci_register_driver(&orinoco_nortel_driver);
8166 +static void __exit orinoco_nortel_exit(void)
8168 + pci_unregister_driver(&orinoco_nortel_driver);
8171 +module_init(orinoco_nortel_init);
8172 +module_exit(orinoco_nortel_exit);
8173 --- /dev/null
8174 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_pci.c
8175 @@ -0,0 +1,257 @@
8176 +/* orinoco_pci.c
8178 + * Driver for Prism 2.5/3 devices that have a direct PCI interface
8179 + * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge).
8180 + * The card contains only one PCI region, which contains all the usual
8181 + * hermes registers, as well as the COR register.
8183 + * Current maintainers are:
8184 + * Pavel Roskin <proski AT gnu.org>
8185 + * and David Gibson <hermes AT gibson.dropbear.id.au>
8187 + * Some of this code is borrowed from orinoco_plx.c
8188 + * Copyright (C) 2001 Daniel Barlow <dan AT telent.net>
8189 + * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
8190 + * has been copied from it. linux-wlan-ng-0.1.10 is originally :
8191 + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
8192 + * This file originally written by:
8193 + * Copyright (C) 2001 Jean Tourrilhes <jt AT hpl.hp.com>
8194 + * And is now maintained by:
8195 + * (C) Copyright David Gibson, IBM Corp. 2002-2003.
8197 + * The contents of this file are subject to the Mozilla Public License
8198 + * Version 1.1 (the "License"); you may not use this file except in
8199 + * compliance with the License. You may obtain a copy of the License
8200 + * at http://www.mozilla.org/MPL/
8202 + * Software distributed under the License is distributed on an "AS IS"
8203 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
8204 + * the License for the specific language governing rights and
8205 + * limitations under the License.
8207 + * Alternatively, the contents of this file may be used under the
8208 + * terms of the GNU General Public License version 2 (the "GPL"), in
8209 + * which case the provisions of the GPL are applicable instead of the
8210 + * above. If you wish to allow the use of your version of this file
8211 + * only under the terms of the GPL and not to allow others to use your
8212 + * version of this file under the MPL, indicate your decision by
8213 + * deleting the provisions above and replace them with the notice and
8214 + * other provisions required by the GPL. If you do not delete the
8215 + * provisions above, a recipient may use your version of this file
8216 + * under either the MPL or the GPL.
8217 + */
8219 +#define DRIVER_NAME "orinoco_pci"
8220 +#define PFX DRIVER_NAME ": "
8222 +#include <linux/module.h>
8223 +#include <linux/kernel.h>
8224 +#include <linux/init.h>
8225 +#include <linux/delay.h>
8226 +#include <linux/pci.h>
8228 +#include "orinoco.h"
8229 +#include "orinoco_pci.h"
8231 +/* Offset of the COR register of the PCI card */
8232 +#define HERMES_PCI_COR (0x26)
8234 +/* Bitmask to reset the card */
8235 +#define HERMES_PCI_COR_MASK (0x0080)
8237 +/* Magic timeouts for doing the reset.
8238 + * Those times are straight from wlan-ng, and it is claimed that they
8239 + * are necessary. Alan will kill me. Take your time and grab a coffee. */
8240 +#define HERMES_PCI_COR_ONT (250) /* ms */
8241 +#define HERMES_PCI_COR_OFFT (500) /* ms */
8242 +#define HERMES_PCI_COR_BUSYT (500) /* ms */
8245 + * Do a soft reset of the card using the Configuration Option Register
8246 + * We need this to get going...
8247 + * This is the part of the code that is strongly inspired from wlan-ng
8249 + * Note : This code is done with irq enabled. This mean that many
8250 + * interrupts will occur while we are there. This is why we use the
8251 + * jiffies to regulate time instead of a straight mdelay(). Usually we
8252 + * need only around 245 iteration of the loop to do 250 ms delay.
8254 + * Note bis : Don't try to access HERMES_CMD during the reset phase.
8255 + * It just won't work !
8256 + */
8257 +static int orinoco_pci_cor_reset(struct orinoco_private *priv)
8259 + struct hermes *hw = &priv->hw;
8260 + unsigned long timeout;
8261 + u16 reg;
8263 + /* Assert the reset until the card notices */
8264 + hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
8265 + mdelay(HERMES_PCI_COR_ONT);
8267 + /* Give time for the card to recover from this hard effort */
8268 + hermes_write_regn(hw, PCI_COR, 0x0000);
8269 + mdelay(HERMES_PCI_COR_OFFT);
8271 + /* The card is ready when it's no longer busy */
8272 + timeout = jiffies + msecs_to_jiffies(HERMES_PCI_COR_BUSYT);
8273 + reg = hermes_read_regn(hw, CMD);
8274 + while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
8275 + mdelay(1);
8276 + reg = hermes_read_regn(hw, CMD);
8279 + /* Still busy? */
8280 + if (reg & HERMES_CMD_BUSY) {
8281 + printk(KERN_ERR PFX "Busy timeout\n");
8282 + return -ETIMEDOUT;
8285 + return 0;
8288 +static int orinoco_pci_init_one(struct pci_dev *pdev,
8289 + const struct pci_device_id *ent)
8291 + int err;
8292 + struct orinoco_private *priv;
8293 + struct orinoco_pci_card *card;
8294 + void __iomem *hermes_io;
8296 + err = pci_enable_device(pdev);
8297 + if (err) {
8298 + printk(KERN_ERR PFX "Cannot enable PCI device\n");
8299 + return err;
8302 + err = pci_request_regions(pdev, DRIVER_NAME);
8303 + if (err) {
8304 + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
8305 + goto fail_resources;
8308 + hermes_io = pci_iomap(pdev, 0, 0);
8309 + if (!hermes_io) {
8310 + printk(KERN_ERR PFX "Cannot remap chipset registers\n");
8311 + err = -EIO;
8312 + goto fail_map_hermes;
8315 + /* Allocate network device */
8316 + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
8317 + orinoco_pci_cor_reset, NULL);
8318 + if (!priv) {
8319 + printk(KERN_ERR PFX "Cannot allocate network device\n");
8320 + err = -ENOMEM;
8321 + goto fail_alloc;
8324 + card = priv->card;
8326 + hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
8328 + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
8329 + DRIVER_NAME, priv);
8330 + if (err) {
8331 + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
8332 + err = -EBUSY;
8333 + goto fail_irq;
8336 + err = orinoco_pci_cor_reset(priv);
8337 + if (err) {
8338 + printk(KERN_ERR PFX "Initial reset failed\n");
8339 + goto fail;
8342 + err = orinoco_init(priv);
8343 + if (err) {
8344 + printk(KERN_ERR PFX "orinoco_init() failed\n");
8345 + goto fail;
8348 + err = orinoco_if_add(priv, 0, 0, NULL);
8349 + if (err) {
8350 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
8351 + goto fail_wiphy;
8354 + pci_set_drvdata(pdev, priv);
8356 + return 0;
8358 + fail_wiphy:
8359 + wiphy_unregister(priv_to_wiphy(priv));
8360 + fail:
8361 + free_irq(pdev->irq, priv);
8363 + fail_irq:
8364 + free_orinocodev(priv);
8366 + fail_alloc:
8367 + pci_iounmap(pdev, hermes_io);
8369 + fail_map_hermes:
8370 + pci_release_regions(pdev);
8372 + fail_resources:
8373 + pci_disable_device(pdev);
8375 + return err;
8378 +static void orinoco_pci_remove_one(struct pci_dev *pdev)
8380 + struct orinoco_private *priv = pci_get_drvdata(pdev);
8382 + orinoco_if_del(priv);
8383 + wiphy_unregister(priv_to_wiphy(priv));
8384 + free_irq(pdev->irq, priv);
8385 + free_orinocodev(priv);
8386 + pci_iounmap(pdev, priv->hw.iobase);
8387 + pci_release_regions(pdev);
8388 + pci_disable_device(pdev);
8391 +static const struct pci_device_id orinoco_pci_id_table[] = {
8392 + /* Intersil Prism 3 */
8393 + {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
8394 + /* Intersil Prism 2.5 */
8395 + {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
8396 + /* Samsung MagicLAN SWL-2210P */
8397 + {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,},
8398 + {0,},
8401 +MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
8403 +static struct pci_driver orinoco_pci_driver = {
8404 + .name = DRIVER_NAME,
8405 + .id_table = orinoco_pci_id_table,
8406 + .probe = orinoco_pci_init_one,
8407 + .remove = orinoco_pci_remove_one,
8408 + .driver.pm = &orinoco_pci_pm_ops,
8411 +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
8412 + " (Pavel Roskin <proski@gnu.org>,"
8413 + " David Gibson <hermes@gibson.dropbear.id.au> &"
8414 + " Jean Tourrilhes <jt@hpl.hp.com>)";
8415 +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> &"
8416 + " David Gibson <hermes@gibson.dropbear.id.au>");
8417 +MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface");
8418 +MODULE_LICENSE("Dual MPL/GPL");
8420 +static int __init orinoco_pci_init(void)
8422 + printk(KERN_DEBUG "%s\n", version);
8423 + return pci_register_driver(&orinoco_pci_driver);
8426 +static void __exit orinoco_pci_exit(void)
8428 + pci_unregister_driver(&orinoco_pci_driver);
8431 +module_init(orinoco_pci_init);
8432 +module_exit(orinoco_pci_exit);
8433 --- /dev/null
8434 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_pci.h
8435 @@ -0,0 +1,54 @@
8436 +/* orinoco_pci.h
8438 + * Common code for all Orinoco drivers for PCI devices, including
8439 + * both native PCI and PCMCIA-to-PCI bridges.
8441 + * Copyright (C) 2005, Pavel Roskin.
8442 + * See main.c for license.
8443 + */
8445 +#ifndef _ORINOCO_PCI_H
8446 +#define _ORINOCO_PCI_H
8448 +#include <linux/netdevice.h>
8450 +/* Driver specific data */
8451 +struct orinoco_pci_card {
8452 + void __iomem *bridge_io;
8453 + void __iomem *attr_io;
8456 +static int __maybe_unused orinoco_pci_suspend(struct device *dev_d)
8458 + struct pci_dev *pdev = to_pci_dev(dev_d);
8459 + struct orinoco_private *priv = pci_get_drvdata(pdev);
8461 + orinoco_down(priv);
8462 + free_irq(pdev->irq, priv);
8464 + return 0;
8467 +static int __maybe_unused orinoco_pci_resume(struct device *dev_d)
8469 + struct pci_dev *pdev = to_pci_dev(dev_d);
8470 + struct orinoco_private *priv = pci_get_drvdata(pdev);
8471 + struct net_device *dev = priv->ndev;
8472 + int err;
8474 + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
8475 + dev->name, priv);
8476 + if (err) {
8477 + printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
8478 + dev->name);
8479 + return -EBUSY;
8482 + return orinoco_up(priv);
8485 +static SIMPLE_DEV_PM_OPS(orinoco_pci_pm_ops,
8486 + orinoco_pci_suspend,
8487 + orinoco_pci_resume);
8489 +#endif /* _ORINOCO_PCI_H */
8490 --- /dev/null
8491 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_plx.c
8492 @@ -0,0 +1,362 @@
8493 +/* orinoco_plx.c
8495 + * Driver for Prism II devices which would usually be driven by orinoco_cs,
8496 + * but are connected to the PCI bus by a PLX9052.
8498 + * Current maintainers are:
8499 + * Pavel Roskin <proski AT gnu.org>
8500 + * and David Gibson <hermes AT gibson.dropbear.id.au>
8502 + * (C) Copyright David Gibson, IBM Corp. 2001-2003.
8503 + * Copyright (C) 2001 Daniel Barlow
8505 + * The contents of this file are subject to the Mozilla Public License
8506 + * Version 1.1 (the "License"); you may not use this file except in
8507 + * compliance with the License. You may obtain a copy of the License
8508 + * at http://www.mozilla.org/MPL/
8510 + * Software distributed under the License is distributed on an "AS IS"
8511 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
8512 + * the License for the specific language governing rights and
8513 + * limitations under the License.
8515 + * Alternatively, the contents of this file may be used under the
8516 + * terms of the GNU General Public License version 2 (the "GPL"), in
8517 + * which case the provisions of the GPL are applicable instead of the
8518 + * above. If you wish to allow the use of your version of this file
8519 + * only under the terms of the GPL and not to allow others to use your
8520 + * version of this file under the MPL, indicate your decision by
8521 + * deleting the provisions above and replace them with the notice and
8522 + * other provisions required by the GPL. If you do not delete the
8523 + * provisions above, a recipient may use your version of this file
8524 + * under either the MPL or the GPL.
8526 + * Here's the general details on how the PLX9052 adapter works:
8528 + * - Two PCI I/O address spaces, one 0x80 long which contains the
8529 + * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
8530 + * slot I/O address space.
8532 + * - One PCI memory address space, mapped to the PCMCIA attribute space
8533 + * (containing the CIS).
8535 + * Using the later, you can read through the CIS data to make sure the
8536 + * card is compatible with the driver. Keep in mind that the PCMCIA
8537 + * spec specifies the CIS as the lower 8 bits of each word read from
8538 + * the CIS, so to read the bytes of the CIS, read every other byte
8539 + * (0,2,4,...). Passing that test, you need to enable the I/O address
8540 + * space on the PCMCIA card via the PCMCIA COR register. This is the
8541 + * first byte following the CIS. In my case (which may not have any
8542 + * relation to what's on the PRISM2 cards), COR was at offset 0x800
8543 + * within the PCI memory space. Write 0x41 to the COR register to
8544 + * enable I/O mode and to select level triggered interrupts. To
8545 + * confirm you actually succeeded, read the COR register back and make
8546 + * sure it actually got set to 0x41, in case you have an unexpected
8547 + * card inserted.
8549 + * Following that, you can treat the second PCI I/O address space (the
8550 + * one that's not 0x80 in length) as the PCMCIA I/O space.
8552 + * Note that in the Eumitcom's source for their drivers, they register
8553 + * the interrupt as edge triggered when registering it with the
8554 + * Windows kernel. I don't recall how to register edge triggered on
8555 + * Linux (if it can be done at all). But in some experimentation, I
8556 + * don't see much operational difference between using either
8557 + * interrupt mode. Don't mess with the interrupt mode in the COR
8558 + * register though, as the PLX9052 wants level triggers with the way
8559 + * the serial EEPROM configures it on the WL11000.
8561 + * There's some other little quirks related to timing that I bumped
8562 + * into, but I don't recall right now. Also, there's two variants of
8563 + * the WL11000 I've seen, revision A1 and T2. These seem to differ
8564 + * slightly in the timings configured in the wait-state generator in
8565 + * the PLX9052. There have also been some comments from Eumitcom that
8566 + * cards shouldn't be hot swapped, apparently due to risk of cooking
8567 + * the PLX9052. I'm unsure why they believe this, as I can't see
8568 + * anything in the design that would really cause a problem, except
8569 + * for crashing drivers not written to expect it. And having developed
8570 + * drivers for the WL11000, I'd say it's quite tricky to write code
8571 + * that will successfully deal with a hot unplug. Very odd things
8572 + * happen on the I/O side of things. But anyway, be warned. Despite
8573 + * that, I've hot-swapped a number of times during debugging and
8574 + * driver development for various reasons (stuck WAIT# line after the
8575 + * radio card's firmware locks up).
8576 + */
8578 +#define DRIVER_NAME "orinoco_plx"
8579 +#define PFX DRIVER_NAME ": "
8581 +#include <linux/module.h>
8582 +#include <linux/kernel.h>
8583 +#include <linux/init.h>
8584 +#include <linux/delay.h>
8585 +#include <linux/pci.h>
8586 +#include <pcmcia/cisreg.h>
8588 +#include "orinoco.h"
8589 +#include "orinoco_pci.h"
8591 +#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
8592 +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
8593 +#define COR_RESET (0x80) /* reset bit in the COR register */
8594 +#define PLX_RESET_TIME (500) /* milliseconds */
8596 +#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
8597 +#define PLX_INTCSR_INTEN (1 << 6) /* Interrupt Enable bit */
8600 + * Do a soft reset of the card using the Configuration Option Register
8601 + */
8602 +static int orinoco_plx_cor_reset(struct orinoco_private *priv)
8604 + struct hermes *hw = &priv->hw;
8605 + struct orinoco_pci_card *card = priv->card;
8606 + unsigned long timeout;
8607 + u16 reg;
8609 + iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
8610 + mdelay(1);
8612 + iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
8613 + mdelay(1);
8615 + /* Just in case, wait more until the card is no longer busy */
8616 + timeout = jiffies + msecs_to_jiffies(PLX_RESET_TIME);
8617 + reg = hermes_read_regn(hw, CMD);
8618 + while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
8619 + mdelay(1);
8620 + reg = hermes_read_regn(hw, CMD);
8623 + /* Still busy? */
8624 + if (reg & HERMES_CMD_BUSY) {
8625 + printk(KERN_ERR PFX "Busy timeout\n");
8626 + return -ETIMEDOUT;
8629 + return 0;
8632 +static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
8634 + int i;
8635 + u32 csr_reg;
8636 + static const u8 cis_magic[] = {
8637 + 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
8638 + };
8640 + printk(KERN_DEBUG PFX "CIS: ");
8641 + for (i = 0; i < 16; i++)
8642 + printk("%02X:", ioread8(card->attr_io + (i << 1)));
8643 + printk("\n");
8645 + /* Verify whether a supported PC card is present */
8646 + /* FIXME: we probably need to be smarted about this */
8647 + for (i = 0; i < sizeof(cis_magic); i++) {
8648 + if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
8649 + printk(KERN_ERR PFX "The CIS value of Prism2 PC "
8650 + "card is unexpected\n");
8651 + return -ENODEV;
8655 + /* bjoern: We need to tell the card to enable interrupts, in
8656 + case the serial eprom didn't do this already. See the
8657 + PLX9052 data book, p8-1 and 8-24 for reference. */
8658 + csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
8659 + if (!(csr_reg & PLX_INTCSR_INTEN)) {
8660 + csr_reg |= PLX_INTCSR_INTEN;
8661 + iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
8662 + csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
8663 + if (!(csr_reg & PLX_INTCSR_INTEN)) {
8664 + printk(KERN_ERR PFX "Cannot enable interrupts\n");
8665 + return -EIO;
8669 + return 0;
8672 +static int orinoco_plx_init_one(struct pci_dev *pdev,
8673 + const struct pci_device_id *ent)
8675 + int err;
8676 + struct orinoco_private *priv;
8677 + struct orinoco_pci_card *card;
8678 + void __iomem *hermes_io, *attr_io, *bridge_io;
8680 + err = pci_enable_device(pdev);
8681 + if (err) {
8682 + printk(KERN_ERR PFX "Cannot enable PCI device\n");
8683 + return err;
8686 + err = pci_request_regions(pdev, DRIVER_NAME);
8687 + if (err) {
8688 + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
8689 + goto fail_resources;
8692 + bridge_io = pci_iomap(pdev, 1, 0);
8693 + if (!bridge_io) {
8694 + printk(KERN_ERR PFX "Cannot map bridge registers\n");
8695 + err = -EIO;
8696 + goto fail_map_bridge;
8699 + attr_io = pci_iomap(pdev, 2, 0);
8700 + if (!attr_io) {
8701 + printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
8702 + err = -EIO;
8703 + goto fail_map_attr;
8706 + hermes_io = pci_iomap(pdev, 3, 0);
8707 + if (!hermes_io) {
8708 + printk(KERN_ERR PFX "Cannot map chipset registers\n");
8709 + err = -EIO;
8710 + goto fail_map_hermes;
8713 + /* Allocate network device */
8714 + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
8715 + orinoco_plx_cor_reset, NULL);
8716 + if (!priv) {
8717 + printk(KERN_ERR PFX "Cannot allocate network device\n");
8718 + err = -ENOMEM;
8719 + goto fail_alloc;
8722 + card = priv->card;
8723 + card->bridge_io = bridge_io;
8724 + card->attr_io = attr_io;
8726 + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
8728 + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
8729 + DRIVER_NAME, priv);
8730 + if (err) {
8731 + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
8732 + err = -EBUSY;
8733 + goto fail_irq;
8736 + err = orinoco_plx_hw_init(card);
8737 + if (err) {
8738 + printk(KERN_ERR PFX "Hardware initialization failed\n");
8739 + goto fail;
8742 + err = orinoco_plx_cor_reset(priv);
8743 + if (err) {
8744 + printk(KERN_ERR PFX "Initial reset failed\n");
8745 + goto fail;
8748 + err = orinoco_init(priv);
8749 + if (err) {
8750 + printk(KERN_ERR PFX "orinoco_init() failed\n");
8751 + goto fail;
8754 + err = orinoco_if_add(priv, 0, 0, NULL);
8755 + if (err) {
8756 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
8757 + goto fail_wiphy;
8760 + pci_set_drvdata(pdev, priv);
8762 + return 0;
8764 + fail_wiphy:
8765 + wiphy_unregister(priv_to_wiphy(priv));
8766 + fail:
8767 + free_irq(pdev->irq, priv);
8769 + fail_irq:
8770 + free_orinocodev(priv);
8772 + fail_alloc:
8773 + pci_iounmap(pdev, hermes_io);
8775 + fail_map_hermes:
8776 + pci_iounmap(pdev, attr_io);
8778 + fail_map_attr:
8779 + pci_iounmap(pdev, bridge_io);
8781 + fail_map_bridge:
8782 + pci_release_regions(pdev);
8784 + fail_resources:
8785 + pci_disable_device(pdev);
8787 + return err;
8790 +static void orinoco_plx_remove_one(struct pci_dev *pdev)
8792 + struct orinoco_private *priv = pci_get_drvdata(pdev);
8793 + struct orinoco_pci_card *card = priv->card;
8795 + orinoco_if_del(priv);
8796 + wiphy_unregister(priv_to_wiphy(priv));
8797 + free_irq(pdev->irq, priv);
8798 + free_orinocodev(priv);
8799 + pci_iounmap(pdev, priv->hw.iobase);
8800 + pci_iounmap(pdev, card->attr_io);
8801 + pci_iounmap(pdev, card->bridge_io);
8802 + pci_release_regions(pdev);
8803 + pci_disable_device(pdev);
8806 +static const struct pci_device_id orinoco_plx_id_table[] = {
8807 + {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */
8808 + {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
8809 + {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */
8810 + {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W,
8811 + Eumitcom PCI WL11000,
8812 + Addtron AWA-100 */
8813 + {0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* Global Sun Tech GL24110P */
8814 + {0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,}, /* Reported working, but unknown */
8815 + {0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,}, /* Linksys WDT11 */
8816 + {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */
8817 + {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by
8818 + Brendan W. McAdams <rit AT jacked-in.org> */
8819 + {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3Com AirConnect PCI tested by
8820 + Damien Persohn <damien AT persohn.net> */
8821 + {0,},
8824 +MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
8826 +static struct pci_driver orinoco_plx_driver = {
8827 + .name = DRIVER_NAME,
8828 + .id_table = orinoco_plx_id_table,
8829 + .probe = orinoco_plx_init_one,
8830 + .remove = orinoco_plx_remove_one,
8831 + .driver.pm = &orinoco_pci_pm_ops,
8834 +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
8835 + " (Pavel Roskin <proski@gnu.org>,"
8836 + " David Gibson <hermes@gibson.dropbear.id.au>,"
8837 + " Daniel Barlow <dan@telent.net>)";
8838 +MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
8839 +MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
8840 +MODULE_LICENSE("Dual MPL/GPL");
8842 +static int __init orinoco_plx_init(void)
8844 + printk(KERN_DEBUG "%s\n", version);
8845 + return pci_register_driver(&orinoco_plx_driver);
8848 +static void __exit orinoco_plx_exit(void)
8850 + pci_unregister_driver(&orinoco_plx_driver);
8853 +module_init(orinoco_plx_init);
8854 +module_exit(orinoco_plx_exit);
8855 --- /dev/null
8856 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_tmd.c
8857 @@ -0,0 +1,237 @@
8858 +/* orinoco_tmd.c
8860 + * Driver for Prism II devices which would usually be driven by orinoco_cs,
8861 + * but are connected to the PCI bus by a TMD7160.
8863 + * Copyright (C) 2003 Joerg Dorchain <joerg AT dorchain.net>
8864 + * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow
8866 + * The contents of this file are subject to the Mozilla Public License
8867 + * Version 1.1 (the "License"); you may not use this file except in
8868 + * compliance with the License. You may obtain a copy of the License
8869 + * at http://www.mozilla.org/MPL/
8871 + * Software distributed under the License is distributed on an "AS IS"
8872 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
8873 + * the License for the specific language governing rights and
8874 + * limitations under the License.
8876 + * Alternatively, the contents of this file may be used under the
8877 + * terms of the GNU General Public License version 2 (the "GPL"), in
8878 + * which case the provisions of the GPL are applicable instead of the
8879 + * above. If you wish to allow the use of your version of this file
8880 + * only under the terms of the GPL and not to allow others to use your
8881 + * version of this file under the MPL, indicate your decision by
8882 + * deleting the provisions above and replace them with the notice and
8883 + * other provisions required by the GPL. If you do not delete the
8884 + * provisions above, a recipient may use your version of this file
8885 + * under either the MPL or the GPL.
8887 + * The actual driving is done by main.c, this is just resource
8888 + * allocation stuff.
8890 + * This driver is modeled after the orinoco_plx driver. The main
8891 + * difference is that the TMD chip has only IO port ranges and doesn't
8892 + * provide access to the PCMCIA attribute space.
8894 + * Pheecom sells cards with the TMD chip as "ASIC version"
8895 + */
8897 +#define DRIVER_NAME "orinoco_tmd"
8898 +#define PFX DRIVER_NAME ": "
8900 +#include <linux/module.h>
8901 +#include <linux/kernel.h>
8902 +#include <linux/init.h>
8903 +#include <linux/delay.h>
8904 +#include <linux/pci.h>
8905 +#include <pcmcia/cisreg.h>
8907 +#include "orinoco.h"
8908 +#include "orinoco_pci.h"
8910 +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
8911 +#define COR_RESET (0x80) /* reset bit in the COR register */
8912 +#define TMD_RESET_TIME (500) /* milliseconds */
8915 + * Do a soft reset of the card using the Configuration Option Register
8916 + */
8917 +static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
8919 + struct hermes *hw = &priv->hw;
8920 + struct orinoco_pci_card *card = priv->card;
8921 + unsigned long timeout;
8922 + u16 reg;
8924 + iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
8925 + mdelay(1);
8927 + iowrite8(COR_VALUE, card->bridge_io);
8928 + mdelay(1);
8930 + /* Just in case, wait more until the card is no longer busy */
8931 + timeout = jiffies + msecs_to_jiffies(TMD_RESET_TIME);
8932 + reg = hermes_read_regn(hw, CMD);
8933 + while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
8934 + mdelay(1);
8935 + reg = hermes_read_regn(hw, CMD);
8938 + /* Still busy? */
8939 + if (reg & HERMES_CMD_BUSY) {
8940 + printk(KERN_ERR PFX "Busy timeout\n");
8941 + return -ETIMEDOUT;
8944 + return 0;
8948 +static int orinoco_tmd_init_one(struct pci_dev *pdev,
8949 + const struct pci_device_id *ent)
8951 + int err;
8952 + struct orinoco_private *priv;
8953 + struct orinoco_pci_card *card;
8954 + void __iomem *hermes_io, *bridge_io;
8956 + err = pci_enable_device(pdev);
8957 + if (err) {
8958 + printk(KERN_ERR PFX "Cannot enable PCI device\n");
8959 + return err;
8962 + err = pci_request_regions(pdev, DRIVER_NAME);
8963 + if (err) {
8964 + printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
8965 + goto fail_resources;
8968 + bridge_io = pci_iomap(pdev, 1, 0);
8969 + if (!bridge_io) {
8970 + printk(KERN_ERR PFX "Cannot map bridge registers\n");
8971 + err = -EIO;
8972 + goto fail_map_bridge;
8975 + hermes_io = pci_iomap(pdev, 2, 0);
8976 + if (!hermes_io) {
8977 + printk(KERN_ERR PFX "Cannot map chipset registers\n");
8978 + err = -EIO;
8979 + goto fail_map_hermes;
8982 + /* Allocate network device */
8983 + priv = alloc_orinocodev(sizeof(*card), &pdev->dev,
8984 + orinoco_tmd_cor_reset, NULL);
8985 + if (!priv) {
8986 + printk(KERN_ERR PFX "Cannot allocate network device\n");
8987 + err = -ENOMEM;
8988 + goto fail_alloc;
8991 + card = priv->card;
8992 + card->bridge_io = bridge_io;
8994 + hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
8996 + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
8997 + DRIVER_NAME, priv);
8998 + if (err) {
8999 + printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
9000 + err = -EBUSY;
9001 + goto fail_irq;
9004 + err = orinoco_tmd_cor_reset(priv);
9005 + if (err) {
9006 + printk(KERN_ERR PFX "Initial reset failed\n");
9007 + goto fail;
9010 + err = orinoco_init(priv);
9011 + if (err) {
9012 + printk(KERN_ERR PFX "orinoco_init() failed\n");
9013 + goto fail;
9016 + err = orinoco_if_add(priv, 0, 0, NULL);
9017 + if (err) {
9018 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
9019 + goto fail;
9022 + pci_set_drvdata(pdev, priv);
9024 + return 0;
9026 + fail:
9027 + free_irq(pdev->irq, priv);
9029 + fail_irq:
9030 + free_orinocodev(priv);
9032 + fail_alloc:
9033 + pci_iounmap(pdev, hermes_io);
9035 + fail_map_hermes:
9036 + pci_iounmap(pdev, bridge_io);
9038 + fail_map_bridge:
9039 + pci_release_regions(pdev);
9041 + fail_resources:
9042 + pci_disable_device(pdev);
9044 + return err;
9047 +static void orinoco_tmd_remove_one(struct pci_dev *pdev)
9049 + struct orinoco_private *priv = pci_get_drvdata(pdev);
9050 + struct orinoco_pci_card *card = priv->card;
9052 + orinoco_if_del(priv);
9053 + free_irq(pdev->irq, priv);
9054 + free_orinocodev(priv);
9055 + pci_iounmap(pdev, priv->hw.iobase);
9056 + pci_iounmap(pdev, card->bridge_io);
9057 + pci_release_regions(pdev);
9058 + pci_disable_device(pdev);
9061 +static const struct pci_device_id orinoco_tmd_id_table[] = {
9062 + {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */
9063 + {0,},
9066 +MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
9068 +static struct pci_driver orinoco_tmd_driver = {
9069 + .name = DRIVER_NAME,
9070 + .id_table = orinoco_tmd_id_table,
9071 + .probe = orinoco_tmd_init_one,
9072 + .remove = orinoco_tmd_remove_one,
9073 + .driver.pm = &orinoco_pci_pm_ops,
9076 +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
9077 + " (Joerg Dorchain <joerg@dorchain.net>)";
9078 +MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
9079 +MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge");
9080 +MODULE_LICENSE("Dual MPL/GPL");
9082 +static int __init orinoco_tmd_init(void)
9084 + printk(KERN_DEBUG "%s\n", version);
9085 + return pci_register_driver(&orinoco_tmd_driver);
9088 +static void __exit orinoco_tmd_exit(void)
9090 + pci_unregister_driver(&orinoco_tmd_driver);
9093 +module_init(orinoco_tmd_init);
9094 +module_exit(orinoco_tmd_exit);
9095 --- /dev/null
9096 +++ a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
9097 @@ -0,0 +1,1787 @@
9099 + * USB Orinoco driver
9101 + * Copyright (c) 2003 Manuel Estrada Sainz
9103 + * The contents of this file are subject to the Mozilla Public License
9104 + * Version 1.1 (the "License"); you may not use this file except in
9105 + * compliance with the License. You may obtain a copy of the License
9106 + * at http://www.mozilla.org/MPL/
9108 + * Software distributed under the License is distributed on an "AS IS"
9109 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9110 + * the License for the specific language governing rights and
9111 + * limitations under the License.
9113 + * Alternatively, the contents of this file may be used under the
9114 + * terms of the GNU General Public License version 2 (the "GPL"), in
9115 + * which case the provisions of the GPL are applicable instead of the
9116 + * above. If you wish to allow the use of your version of this file
9117 + * only under the terms of the GPL and not to allow others to use your
9118 + * version of this file under the MPL, indicate your decision by
9119 + * deleting the provisions above and replace them with the notice and
9120 + * other provisions required by the GPL. If you do not delete the
9121 + * provisions above, a recipient may use your version of this file
9122 + * under either the MPL or the GPL.
9124 + * Queueing code based on linux-wlan-ng 0.2.1-pre5
9126 + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
9128 + * The license is the same as above.
9130 + * Initialy based on USB Skeleton driver - 0.7
9132 + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
9134 + * This program is free software; you can redistribute it and/or
9135 + * modify it under the terms of the GNU General Public License as
9136 + * published by the Free Software Foundation; either version 2 of
9137 + * the License, or (at your option) any later version.
9139 + * NOTE: The original USB Skeleton driver is GPL, but all that code is
9140 + * gone so MPL/GPL applies.
9141 + */
9143 +#define DRIVER_NAME "orinoco_usb"
9144 +#define PFX DRIVER_NAME ": "
9146 +#include <linux/module.h>
9147 +#include <linux/kernel.h>
9148 +#include <linux/sched.h>
9149 +#include <linux/signal.h>
9150 +#include <linux/errno.h>
9151 +#include <linux/poll.h>
9152 +#include <linux/slab.h>
9153 +#include <linux/fcntl.h>
9154 +#include <linux/spinlock.h>
9155 +#include <linux/list.h>
9156 +#include <linux/usb.h>
9157 +#include <linux/timer.h>
9159 +#include <linux/netdevice.h>
9160 +#include <linux/if_arp.h>
9161 +#include <linux/etherdevice.h>
9162 +#include <linux/wireless.h>
9163 +#include <linux/firmware.h>
9164 +#include <linux/refcount.h>
9166 +#include "mic.h"
9167 +#include "orinoco.h"
9169 +#ifndef URB_ASYNC_UNLINK
9170 +#define URB_ASYNC_UNLINK 0
9171 +#endif
9173 +struct header_struct {
9174 + /* 802.3 */
9175 + u8 dest[ETH_ALEN];
9176 + u8 src[ETH_ALEN];
9177 + __be16 len;
9178 + /* 802.2 */
9179 + u8 dsap;
9180 + u8 ssap;
9181 + u8 ctrl;
9182 + /* SNAP */
9183 + u8 oui[3];
9184 + __be16 ethertype;
9185 +} __packed;
9187 +struct ez_usb_fw {
9188 + u16 size;
9189 + const u8 *code;
9192 +static struct ez_usb_fw firmware = {
9193 + .size = 0,
9194 + .code = NULL,
9197 +/* Debugging macros */
9198 +#undef err
9199 +#define err(format, arg...) \
9200 + do { printk(KERN_ERR PFX format "\n", ## arg); } while (0)
9202 +MODULE_FIRMWARE("orinoco_ezusb_fw");
9205 + * Under some conditions, the card gets stuck and stops paying attention
9206 + * to the world (i.e. data communication stalls) until we do something to
9207 + * it. Sending an INQ_TALLIES command seems to be enough and should be
9208 + * harmless otherwise. This behaviour has been observed when using the
9209 + * driver on a systemimager client during installation. In the past a
9210 + * timer was used to send INQ_TALLIES commands when there was no other
9211 + * activity, but it was troublesome and was removed.
9212 + */
9214 +#define USB_COMPAQ_VENDOR_ID 0x049f /* Compaq Computer Corp. */
9215 +#define USB_COMPAQ_WL215_ID 0x001f /* Compaq WL215 USB Adapter */
9216 +#define USB_COMPAQ_W200_ID 0x0076 /* Compaq W200 USB Adapter */
9217 +#define USB_HP_WL215_ID 0x0082 /* Compaq WL215 USB Adapter */
9219 +#define USB_MELCO_VENDOR_ID 0x0411
9220 +#define USB_BUFFALO_L11_ID 0x0006 /* BUFFALO WLI-USB-L11 */
9221 +#define USB_BUFFALO_L11G_WR_ID 0x000B /* BUFFALO WLI-USB-L11G-WR */
9222 +#define USB_BUFFALO_L11G_ID 0x000D /* BUFFALO WLI-USB-L11G */
9224 +#define USB_LUCENT_VENDOR_ID 0x047E /* Lucent Technologies */
9225 +#define USB_LUCENT_ORINOCO_ID 0x0300 /* Lucent/Agere Orinoco USB Client */
9227 +#define USB_AVAYA8_VENDOR_ID 0x0D98
9228 +#define USB_AVAYAE_VENDOR_ID 0x0D9E
9229 +#define USB_AVAYA_WIRELESS_ID 0x0300 /* Avaya USB Wireless Card */
9231 +#define USB_AGERE_VENDOR_ID 0x0D4E /* Agere Systems */
9232 +#define USB_AGERE_MODEL0801_ID 0x1000 /* USB Wireless Card Model 0801 */
9233 +#define USB_AGERE_MODEL0802_ID 0x1001 /* USB Wireless Card Model 0802 */
9234 +#define USB_AGERE_REBRANDED_ID 0x047A /* USB WLAN Card */
9236 +#define USB_ELSA_VENDOR_ID 0x05CC
9237 +#define USB_ELSA_AIRLANCER_ID 0x3100 /* ELSA AirLancer USB-11 */
9239 +#define USB_LEGEND_VENDOR_ID 0x0E7C
9240 +#define USB_LEGEND_JOYNET_ID 0x0300 /* Joynet USB WLAN Card */
9242 +#define USB_SAMSUNG_VENDOR_ID 0x04E8
9243 +#define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */
9244 +#define USB_SAMSUNG_SEW2001U2_ID 0x5B11 /* Samsung SEW-2001u Card */
9245 +#define USB_SAMSUNG_SEW2003U_ID 0x7011 /* Samsung SEW-2003U Card */
9247 +#define USB_IGATE_VENDOR_ID 0x0681
9248 +#define USB_IGATE_IGATE_11M_ID 0x0012 /* I-GATE 11M USB Card */
9250 +#define USB_FUJITSU_VENDOR_ID 0x0BF8
9251 +#define USB_FUJITSU_E1100_ID 0x1002 /* connect2AIR WLAN E-1100 USB */
9253 +#define USB_2WIRE_VENDOR_ID 0x1630
9254 +#define USB_2WIRE_WIRELESS_ID 0xff81 /* 2Wire USB Wireless adapter */
9257 +#define EZUSB_REQUEST_FW_TRANS 0xA0
9258 +#define EZUSB_REQUEST_TRIGGER 0xAA
9259 +#define EZUSB_REQUEST_TRIG_AC 0xAC
9260 +#define EZUSB_CPUCS_REG 0x7F92
9262 +#define EZUSB_RID_TX 0x0700
9263 +#define EZUSB_RID_RX 0x0701
9264 +#define EZUSB_RID_INIT1 0x0702
9265 +#define EZUSB_RID_ACK 0x0710
9266 +#define EZUSB_RID_READ_PDA 0x0800
9267 +#define EZUSB_RID_PROG_INIT 0x0852
9268 +#define EZUSB_RID_PROG_SET_ADDR 0x0853
9269 +#define EZUSB_RID_PROG_BYTES 0x0854
9270 +#define EZUSB_RID_PROG_END 0x0855
9271 +#define EZUSB_RID_DOCMD 0x0860
9273 +/* Recognize info frames */
9274 +#define EZUSB_IS_INFO(id) ((id >= 0xF000) && (id <= 0xF2FF))
9276 +#define EZUSB_MAGIC 0x0210
9278 +#define EZUSB_FRAME_DATA 1
9279 +#define EZUSB_FRAME_CONTROL 2
9281 +#define DEF_TIMEOUT (3 * HZ)
9283 +#define BULK_BUF_SIZE 2048
9285 +#define MAX_DL_SIZE (BULK_BUF_SIZE - sizeof(struct ezusb_packet))
9287 +#define FW_BUF_SIZE 64
9288 +#define FW_VAR_OFFSET_PTR 0x359
9289 +#define FW_VAR_VALUE 0
9290 +#define FW_HOLE_START 0x100
9291 +#define FW_HOLE_END 0x300
9293 +struct ezusb_packet {
9294 + __le16 magic; /* 0x0210 */
9295 + u8 req_reply_count;
9296 + u8 ans_reply_count;
9297 + __le16 frame_type; /* 0x01 for data frames, 0x02 otherwise */
9298 + __le16 size; /* transport size */
9299 + __le16 crc; /* CRC up to here */
9300 + __le16 hermes_len;
9301 + __le16 hermes_rid;
9302 + u8 data[];
9303 +} __packed;
9305 +/* Table of devices that work or may work with this driver */
9306 +static const struct usb_device_id ezusb_table[] = {
9307 + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_WL215_ID)},
9308 + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_HP_WL215_ID)},
9309 + {USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_W200_ID)},
9310 + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11_ID)},
9311 + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_WR_ID)},
9312 + {USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_ID)},
9313 + {USB_DEVICE(USB_LUCENT_VENDOR_ID, USB_LUCENT_ORINOCO_ID)},
9314 + {USB_DEVICE(USB_AVAYA8_VENDOR_ID, USB_AVAYA_WIRELESS_ID)},
9315 + {USB_DEVICE(USB_AVAYAE_VENDOR_ID, USB_AVAYA_WIRELESS_ID)},
9316 + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0801_ID)},
9317 + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0802_ID)},
9318 + {USB_DEVICE(USB_ELSA_VENDOR_ID, USB_ELSA_AIRLANCER_ID)},
9319 + {USB_DEVICE(USB_LEGEND_VENDOR_ID, USB_LEGEND_JOYNET_ID)},
9320 + {USB_DEVICE_VER(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U1_ID,
9321 + 0, 0)},
9322 + {USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U2_ID)},
9323 + {USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2003U_ID)},
9324 + {USB_DEVICE(USB_IGATE_VENDOR_ID, USB_IGATE_IGATE_11M_ID)},
9325 + {USB_DEVICE(USB_FUJITSU_VENDOR_ID, USB_FUJITSU_E1100_ID)},
9326 + {USB_DEVICE(USB_2WIRE_VENDOR_ID, USB_2WIRE_WIRELESS_ID)},
9327 + {USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_REBRANDED_ID)},
9328 + {} /* Terminating entry */
9331 +MODULE_DEVICE_TABLE(usb, ezusb_table);
9333 +/* Structure to hold all of our device specific stuff */
9334 +struct ezusb_priv {
9335 + struct usb_device *udev;
9336 + struct net_device *dev;
9337 + struct mutex mtx;
9338 + spinlock_t req_lock;
9339 + struct list_head req_pending;
9340 + struct list_head req_active;
9341 + spinlock_t reply_count_lock;
9342 + u16 hermes_reg_fake[0x40];
9343 + u8 *bap_buf;
9344 + struct urb *read_urb;
9345 + int read_pipe;
9346 + int write_pipe;
9347 + u8 reply_count;
9350 +enum ezusb_state {
9351 + EZUSB_CTX_START,
9352 + EZUSB_CTX_QUEUED,
9353 + EZUSB_CTX_REQ_SUBMITTED,
9354 + EZUSB_CTX_REQ_COMPLETE,
9355 + EZUSB_CTX_RESP_RECEIVED,
9356 + EZUSB_CTX_REQ_TIMEOUT,
9357 + EZUSB_CTX_REQ_FAILED,
9358 + EZUSB_CTX_RESP_TIMEOUT,
9359 + EZUSB_CTX_REQSUBMIT_FAIL,
9360 + EZUSB_CTX_COMPLETE,
9363 +struct request_context {
9364 + struct list_head list;
9365 + refcount_t refcount;
9366 + struct completion done; /* Signals that CTX is dead */
9367 + int killed;
9368 + struct urb *outurb; /* OUT for req pkt */
9369 + struct ezusb_priv *upriv;
9370 + struct ezusb_packet *buf;
9371 + int buf_length;
9372 + struct timer_list timer; /* Timeout handling */
9373 + enum ezusb_state state; /* Current state */
9374 + /* the RID that we will wait for */
9375 + u16 out_rid;
9376 + u16 in_rid;
9380 +/* Forward declarations */
9381 +static void ezusb_ctx_complete(struct request_context *ctx);
9382 +static void ezusb_req_queue_run(struct ezusb_priv *upriv);
9383 +static void ezusb_bulk_in_callback(struct urb *urb);
9385 +static inline u8 ezusb_reply_inc(u8 count)
9387 + if (count < 0x7F)
9388 + return count + 1;
9389 + else
9390 + return 1;
9393 +static void ezusb_request_context_put(struct request_context *ctx)
9395 + if (!refcount_dec_and_test(&ctx->refcount))
9396 + return;
9398 + WARN_ON(!ctx->done.done);
9399 + BUG_ON(ctx->outurb->status == -EINPROGRESS);
9400 + BUG_ON(timer_pending(&ctx->timer));
9401 + usb_free_urb(ctx->outurb);
9402 + kfree(ctx->buf);
9403 + kfree(ctx);
9406 +static inline void ezusb_mod_timer(struct ezusb_priv *upriv,
9407 + struct timer_list *timer,
9408 + unsigned long expire)
9410 + if (!upriv->udev)
9411 + return;
9412 + mod_timer(timer, expire);
9415 +static void ezusb_request_timerfn(struct timer_list *t)
9417 + struct request_context *ctx = from_timer(ctx, t, timer);
9419 + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
9420 + if (usb_unlink_urb(ctx->outurb) == -EINPROGRESS) {
9421 + ctx->state = EZUSB_CTX_REQ_TIMEOUT;
9422 + } else {
9423 + ctx->state = EZUSB_CTX_RESP_TIMEOUT;
9424 + dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
9425 + refcount_inc(&ctx->refcount);
9426 + ctx->killed = 1;
9427 + ezusb_ctx_complete(ctx);
9428 + ezusb_request_context_put(ctx);
9432 +static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
9433 + u16 out_rid, u16 in_rid)
9435 + struct request_context *ctx;
9437 + ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
9438 + if (!ctx)
9439 + return NULL;
9441 + ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC);
9442 + if (!ctx->buf) {
9443 + kfree(ctx);
9444 + return NULL;
9446 + ctx->outurb = usb_alloc_urb(0, GFP_ATOMIC);
9447 + if (!ctx->outurb) {
9448 + kfree(ctx->buf);
9449 + kfree(ctx);
9450 + return NULL;
9453 + ctx->upriv = upriv;
9454 + ctx->state = EZUSB_CTX_START;
9455 + ctx->out_rid = out_rid;
9456 + ctx->in_rid = in_rid;
9458 + refcount_set(&ctx->refcount, 1);
9459 + init_completion(&ctx->done);
9461 + timer_setup(&ctx->timer, ezusb_request_timerfn, 0);
9462 + return ctx;
9465 +static void ezusb_ctx_complete(struct request_context *ctx)
9467 + struct ezusb_priv *upriv = ctx->upriv;
9468 + unsigned long flags;
9470 + spin_lock_irqsave(&upriv->req_lock, flags);
9472 + list_del_init(&ctx->list);
9473 + if (upriv->udev) {
9474 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9475 + ezusb_req_queue_run(upriv);
9476 + spin_lock_irqsave(&upriv->req_lock, flags);
9479 + switch (ctx->state) {
9480 + case EZUSB_CTX_COMPLETE:
9481 + case EZUSB_CTX_REQSUBMIT_FAIL:
9482 + case EZUSB_CTX_REQ_FAILED:
9483 + case EZUSB_CTX_REQ_TIMEOUT:
9484 + case EZUSB_CTX_RESP_TIMEOUT:
9485 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9487 + if ((ctx->out_rid == EZUSB_RID_TX) && upriv->dev) {
9488 + struct net_device *dev = upriv->dev;
9489 + struct net_device_stats *stats = &dev->stats;
9491 + if (ctx->state != EZUSB_CTX_COMPLETE)
9492 + stats->tx_errors++;
9493 + else
9494 + stats->tx_packets++;
9496 + netif_wake_queue(dev);
9498 + complete_all(&ctx->done);
9499 + ezusb_request_context_put(ctx);
9500 + break;
9502 + default:
9503 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9504 + if (!upriv->udev) {
9505 + /* This is normal, as all request contexts get flushed
9506 + * when the device is disconnected */
9507 + err("Called, CTX not terminating, but device gone");
9508 + complete_all(&ctx->done);
9509 + ezusb_request_context_put(ctx);
9510 + break;
9513 + err("Called, CTX not in terminating state.");
9514 + /* Things are really bad if this happens. Just leak
9515 + * the CTX because it may still be linked to the
9516 + * queue or the OUT urb may still be active.
9517 + * Just leaking at least prevents an Oops or Panic.
9518 + */
9519 + break;
9524 + * ezusb_req_queue_run:
9525 + * Description:
9526 + * Note: Only one active CTX at any one time, because there's no
9527 + * other (reliable) way to match the response URB to the correct
9528 + * CTX.
9529 + */
9530 +static void ezusb_req_queue_run(struct ezusb_priv *upriv)
9532 + unsigned long flags;
9533 + struct request_context *ctx;
9534 + int result;
9536 + spin_lock_irqsave(&upriv->req_lock, flags);
9538 + if (!list_empty(&upriv->req_active))
9539 + goto unlock;
9541 + if (list_empty(&upriv->req_pending))
9542 + goto unlock;
9544 + ctx =
9545 + list_entry(upriv->req_pending.next, struct request_context,
9546 + list);
9548 + if (!ctx->upriv->udev)
9549 + goto unlock;
9551 + /* We need to split this off to avoid a race condition */
9552 + list_move_tail(&ctx->list, &upriv->req_active);
9554 + if (ctx->state == EZUSB_CTX_QUEUED) {
9555 + refcount_inc(&ctx->refcount);
9556 + result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
9557 + if (result) {
9558 + ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
9560 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9562 + err("Fatal, failed to submit command urb."
9563 + " error=%d\n", result);
9565 + ezusb_ctx_complete(ctx);
9566 + ezusb_request_context_put(ctx);
9567 + goto done;
9570 + ctx->state = EZUSB_CTX_REQ_SUBMITTED;
9571 + ezusb_mod_timer(ctx->upriv, &ctx->timer,
9572 + jiffies + DEF_TIMEOUT);
9575 + unlock:
9576 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9578 + done:
9579 + return;
9582 +static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
9583 + struct request_context *ctx)
9585 + unsigned long flags;
9587 + spin_lock_irqsave(&upriv->req_lock, flags);
9589 + if (!ctx->upriv->udev) {
9590 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9591 + goto done;
9593 + refcount_inc(&ctx->refcount);
9594 + list_add_tail(&ctx->list, &upriv->req_pending);
9595 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9597 + ctx->state = EZUSB_CTX_QUEUED;
9598 + ezusb_req_queue_run(upriv);
9600 + done:
9601 + return;
9604 +static void ezusb_request_out_callback(struct urb *urb)
9606 + unsigned long flags;
9607 + enum ezusb_state state;
9608 + struct request_context *ctx = urb->context;
9609 + struct ezusb_priv *upriv = ctx->upriv;
9611 + spin_lock_irqsave(&upriv->req_lock, flags);
9613 + del_timer(&ctx->timer);
9615 + if (ctx->killed) {
9616 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9617 + pr_warn("interrupt called with dead ctx\n");
9618 + goto out;
9621 + state = ctx->state;
9623 + if (urb->status == 0) {
9624 + switch (state) {
9625 + case EZUSB_CTX_REQ_SUBMITTED:
9626 + if (ctx->in_rid) {
9627 + ctx->state = EZUSB_CTX_REQ_COMPLETE;
9628 + /* reply URB still pending */
9629 + ezusb_mod_timer(upriv, &ctx->timer,
9630 + jiffies + DEF_TIMEOUT);
9631 + spin_unlock_irqrestore(&upriv->req_lock,
9632 + flags);
9633 + break;
9635 + fallthrough;
9636 + case EZUSB_CTX_RESP_RECEIVED:
9637 + /* IN already received before this OUT-ACK */
9638 + ctx->state = EZUSB_CTX_COMPLETE;
9639 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9640 + ezusb_ctx_complete(ctx);
9641 + break;
9643 + default:
9644 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9645 + err("Unexpected state(0x%x, %d) in OUT URB",
9646 + state, urb->status);
9647 + break;
9649 + } else {
9650 + /* If someone cancels the OUT URB then its status
9651 + * should be either -ECONNRESET or -ENOENT.
9652 + */
9653 + switch (state) {
9654 + case EZUSB_CTX_REQ_SUBMITTED:
9655 + case EZUSB_CTX_RESP_RECEIVED:
9656 + ctx->state = EZUSB_CTX_REQ_FAILED;
9657 + fallthrough;
9659 + case EZUSB_CTX_REQ_FAILED:
9660 + case EZUSB_CTX_REQ_TIMEOUT:
9661 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9663 + ezusb_ctx_complete(ctx);
9664 + break;
9666 + default:
9667 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9669 + err("Unexpected state(0x%x, %d) in OUT URB",
9670 + state, urb->status);
9671 + break;
9674 + out:
9675 + ezusb_request_context_put(ctx);
9678 +static void ezusb_request_in_callback(struct ezusb_priv *upriv,
9679 + struct urb *urb)
9681 + struct ezusb_packet *ans = urb->transfer_buffer;
9682 + struct request_context *ctx = NULL;
9683 + enum ezusb_state state;
9684 + unsigned long flags;
9686 + /* Find the CTX on the active queue that requested this URB */
9687 + spin_lock_irqsave(&upriv->req_lock, flags);
9688 + if (upriv->udev) {
9689 + struct list_head *item;
9691 + list_for_each(item, &upriv->req_active) {
9692 + struct request_context *c;
9693 + int reply_count;
9695 + c = list_entry(item, struct request_context, list);
9696 + reply_count =
9697 + ezusb_reply_inc(c->buf->req_reply_count);
9698 + if ((ans->ans_reply_count == reply_count)
9699 + && (le16_to_cpu(ans->hermes_rid) == c->in_rid)) {
9700 + ctx = c;
9701 + break;
9703 + netdev_dbg(upriv->dev, "Skipped (0x%x/0x%x) (%d/%d)\n",
9704 + le16_to_cpu(ans->hermes_rid), c->in_rid,
9705 + ans->ans_reply_count, reply_count);
9709 + if (ctx == NULL) {
9710 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9711 + err("%s: got unexpected RID: 0x%04X", __func__,
9712 + le16_to_cpu(ans->hermes_rid));
9713 + ezusb_req_queue_run(upriv);
9714 + return;
9717 + /* The data we want is in the in buffer, exchange */
9718 + urb->transfer_buffer = ctx->buf;
9719 + ctx->buf = (void *) ans;
9720 + ctx->buf_length = urb->actual_length;
9722 + state = ctx->state;
9723 + switch (state) {
9724 + case EZUSB_CTX_REQ_SUBMITTED:
9725 + /* We have received our response URB before
9726 + * our request has been acknowledged. Do NOT
9727 + * destroy our CTX yet, because our OUT URB
9728 + * is still alive ...
9729 + */
9730 + ctx->state = EZUSB_CTX_RESP_RECEIVED;
9731 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9733 + /* Let the machine continue running. */
9734 + break;
9736 + case EZUSB_CTX_REQ_COMPLETE:
9737 + /* This is the usual path: our request
9738 + * has already been acknowledged, and
9739 + * we have now received the reply.
9740 + */
9741 + ctx->state = EZUSB_CTX_COMPLETE;
9743 + /* Stop the intimer */
9744 + del_timer(&ctx->timer);
9745 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9747 + /* Call the completion handler */
9748 + ezusb_ctx_complete(ctx);
9749 + break;
9751 + default:
9752 + spin_unlock_irqrestore(&upriv->req_lock, flags);
9754 + pr_warn("Matched IN URB, unexpected context state(0x%x)\n",
9755 + state);
9756 + /* Throw this CTX away and try submitting another */
9757 + del_timer(&ctx->timer);
9758 + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
9759 + usb_unlink_urb(ctx->outurb);
9760 + ezusb_req_queue_run(upriv);
9761 + break;
9762 + } /* switch */
9765 +typedef void (*ezusb_ctx_wait)(struct ezusb_priv *, struct request_context *);
9767 +static void ezusb_req_ctx_wait_compl(struct ezusb_priv *upriv,
9768 + struct request_context *ctx)
9770 + switch (ctx->state) {
9771 + case EZUSB_CTX_QUEUED:
9772 + case EZUSB_CTX_REQ_SUBMITTED:
9773 + case EZUSB_CTX_REQ_COMPLETE:
9774 + case EZUSB_CTX_RESP_RECEIVED:
9775 + wait_for_completion(&ctx->done);
9776 + break;
9777 + default:
9778 + /* Done or failed - nothing to wait for */
9779 + break;
9783 +static void ezusb_req_ctx_wait_poll(struct ezusb_priv *upriv,
9784 + struct request_context *ctx)
9786 + int msecs;
9788 + switch (ctx->state) {
9789 + case EZUSB_CTX_QUEUED:
9790 + case EZUSB_CTX_REQ_SUBMITTED:
9791 + case EZUSB_CTX_REQ_COMPLETE:
9792 + case EZUSB_CTX_RESP_RECEIVED:
9793 + /* If we get called from a timer or with our lock acquired, then
9794 + * we can't wait for the completion and have to poll. This won't
9795 + * happen if the USB controller completes the URB requests in
9796 + * BH.
9797 + */
9798 + msecs = DEF_TIMEOUT * (1000 / HZ);
9800 + while (!try_wait_for_completion(&ctx->done) && msecs--)
9801 + udelay(1000);
9802 + break;
9803 + default:
9804 + /* Done or failed - nothing to wait for */
9805 + break;
9809 +static void ezusb_req_ctx_wait_skip(struct ezusb_priv *upriv,
9810 + struct request_context *ctx)
9812 + WARN(1, "Shouldn't be invoked for in_rid\n");
9815 +static inline u16 build_crc(struct ezusb_packet *data)
9817 + u16 crc = 0;
9818 + u8 *bytes = (u8 *)data;
9819 + int i;
9821 + for (i = 0; i < 8; i++)
9822 + crc = (crc << 1) + bytes[i];
9824 + return crc;
9828 + * ezusb_fill_req:
9830 + * if data == NULL and length > 0 the data is assumed to be already in
9831 + * the target buffer and only the header is filled.
9833 + */
9834 +static int ezusb_fill_req(struct ezusb_packet *req, u16 length, u16 rid,
9835 + const void *data, u16 frame_type, u8 reply_count)
9837 + int total_size = sizeof(*req) + length;
9839 + BUG_ON(total_size > BULK_BUF_SIZE);
9841 + req->magic = cpu_to_le16(EZUSB_MAGIC);
9842 + req->req_reply_count = reply_count;
9843 + req->ans_reply_count = 0;
9844 + req->frame_type = cpu_to_le16(frame_type);
9845 + req->size = cpu_to_le16(length + 4);
9846 + req->crc = cpu_to_le16(build_crc(req));
9847 + req->hermes_len = cpu_to_le16(HERMES_BYTES_TO_RECLEN(length));
9848 + req->hermes_rid = cpu_to_le16(rid);
9849 + if (data)
9850 + memcpy(req->data, data, length);
9851 + return total_size;
9854 +static int ezusb_submit_in_urb(struct ezusb_priv *upriv)
9856 + int retval = 0;
9857 + void *cur_buf = upriv->read_urb->transfer_buffer;
9859 + if (upriv->read_urb->status == -EINPROGRESS) {
9860 + netdev_dbg(upriv->dev, "urb busy, not resubmiting\n");
9861 + retval = -EBUSY;
9862 + goto exit;
9864 + usb_fill_bulk_urb(upriv->read_urb, upriv->udev, upriv->read_pipe,
9865 + cur_buf, BULK_BUF_SIZE,
9866 + ezusb_bulk_in_callback, upriv);
9867 + upriv->read_urb->transfer_flags = 0;
9868 + retval = usb_submit_urb(upriv->read_urb, GFP_ATOMIC);
9869 + if (retval)
9870 + err("%s submit failed %d", __func__, retval);
9872 + exit:
9873 + return retval;
9876 +static inline int ezusb_8051_cpucs(struct ezusb_priv *upriv, int reset)
9878 + int ret;
9879 + u8 *res_val = NULL;
9881 + if (!upriv->udev) {
9882 + err("%s: !upriv->udev", __func__);
9883 + return -EFAULT;
9886 + res_val = kmalloc(sizeof(*res_val), GFP_KERNEL);
9888 + if (!res_val)
9889 + return -ENOMEM;
9891 + *res_val = reset; /* avoid argument promotion */
9893 + ret = usb_control_msg(upriv->udev,
9894 + usb_sndctrlpipe(upriv->udev, 0),
9895 + EZUSB_REQUEST_FW_TRANS,
9896 + USB_TYPE_VENDOR | USB_RECIP_DEVICE |
9897 + USB_DIR_OUT, EZUSB_CPUCS_REG, 0, res_val,
9898 + sizeof(*res_val), DEF_TIMEOUT);
9900 + kfree(res_val);
9902 + return ret;
9905 +static int ezusb_firmware_download(struct ezusb_priv *upriv,
9906 + struct ez_usb_fw *fw)
9908 + u8 *fw_buffer;
9909 + int retval, addr;
9910 + int variant_offset;
9912 + fw_buffer = kmalloc(FW_BUF_SIZE, GFP_KERNEL);
9913 + if (!fw_buffer) {
9914 + printk(KERN_ERR PFX "Out of memory for firmware buffer.\n");
9915 + return -ENOMEM;
9917 + /*
9918 + * This byte is 1 and should be replaced with 0. The offset is
9919 + * 0x10AD in version 0.0.6. The byte in question should follow
9920 + * the end of the code pointed to by the jump in the beginning
9921 + * of the firmware. Also, it is read by code located at 0x358.
9922 + */
9923 + variant_offset = be16_to_cpup((__be16 *) &fw->code[FW_VAR_OFFSET_PTR]);
9924 + if (variant_offset >= fw->size) {
9925 + printk(KERN_ERR PFX "Invalid firmware variant offset: "
9926 + "0x%04x\n", variant_offset);
9927 + retval = -EINVAL;
9928 + goto fail;
9931 + retval = ezusb_8051_cpucs(upriv, 1);
9932 + if (retval < 0)
9933 + goto fail;
9934 + for (addr = 0; addr < fw->size; addr += FW_BUF_SIZE) {
9935 + /* 0x100-0x300 should be left alone, it contains card
9936 + * specific data, like USB enumeration information */
9937 + if ((addr >= FW_HOLE_START) && (addr < FW_HOLE_END))
9938 + continue;
9940 + memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE);
9941 + if (variant_offset >= addr &&
9942 + variant_offset < addr + FW_BUF_SIZE) {
9943 + netdev_dbg(upriv->dev,
9944 + "Patching card_variant byte at 0x%04X\n",
9945 + variant_offset);
9946 + fw_buffer[variant_offset - addr] = FW_VAR_VALUE;
9948 + retval = usb_control_msg(upriv->udev,
9949 + usb_sndctrlpipe(upriv->udev, 0),
9950 + EZUSB_REQUEST_FW_TRANS,
9951 + USB_TYPE_VENDOR | USB_RECIP_DEVICE
9952 + | USB_DIR_OUT,
9953 + addr, 0x0,
9954 + fw_buffer, FW_BUF_SIZE,
9955 + DEF_TIMEOUT);
9957 + if (retval < 0)
9958 + goto fail;
9960 + retval = ezusb_8051_cpucs(upriv, 0);
9961 + if (retval < 0)
9962 + goto fail;
9964 + goto exit;
9965 + fail:
9966 + printk(KERN_ERR PFX "Firmware download failed, error %d\n",
9967 + retval);
9968 + exit:
9969 + kfree(fw_buffer);
9970 + return retval;
9973 +static int ezusb_access_ltv(struct ezusb_priv *upriv,
9974 + struct request_context *ctx,
9975 + u16 length, const void *data, u16 frame_type,
9976 + void *ans_buff, unsigned ans_size, u16 *ans_length,
9977 + ezusb_ctx_wait ezusb_ctx_wait_func)
9979 + int req_size;
9980 + int retval = 0;
9981 + enum ezusb_state state;
9983 + if (!upriv->udev) {
9984 + retval = -ENODEV;
9985 + goto exit;
9988 + if (upriv->read_urb->status != -EINPROGRESS)
9989 + err("%s: in urb not pending", __func__);
9991 + /* protect upriv->reply_count, guarantee sequential numbers */
9992 + spin_lock_bh(&upriv->reply_count_lock);
9993 + req_size = ezusb_fill_req(ctx->buf, length, ctx->out_rid, data,
9994 + frame_type, upriv->reply_count);
9995 + usb_fill_bulk_urb(ctx->outurb, upriv->udev, upriv->write_pipe,
9996 + ctx->buf, req_size,
9997 + ezusb_request_out_callback, ctx);
9999 + if (ctx->in_rid)
10000 + upriv->reply_count = ezusb_reply_inc(upriv->reply_count);
10002 + ezusb_req_enqueue_run(upriv, ctx);
10004 + spin_unlock_bh(&upriv->reply_count_lock);
10006 + if (ctx->in_rid)
10007 + ezusb_ctx_wait_func(upriv, ctx);
10009 + state = ctx->state;
10010 + switch (state) {
10011 + case EZUSB_CTX_COMPLETE:
10012 + retval = ctx->outurb->status;
10013 + break;
10015 + case EZUSB_CTX_QUEUED:
10016 + case EZUSB_CTX_REQ_SUBMITTED:
10017 + if (!ctx->in_rid)
10018 + break;
10019 + fallthrough;
10020 + default:
10021 + err("%s: Unexpected context state %d", __func__,
10022 + state);
10023 + fallthrough;
10024 + case EZUSB_CTX_REQ_TIMEOUT:
10025 + case EZUSB_CTX_REQ_FAILED:
10026 + case EZUSB_CTX_RESP_TIMEOUT:
10027 + case EZUSB_CTX_REQSUBMIT_FAIL:
10028 + printk(KERN_ERR PFX "Access failed, resetting (state %d,"
10029 + " reply_count %d)\n", state, upriv->reply_count);
10030 + upriv->reply_count = 0;
10031 + if (state == EZUSB_CTX_REQ_TIMEOUT
10032 + || state == EZUSB_CTX_RESP_TIMEOUT) {
10033 + printk(KERN_ERR PFX "ctx timed out\n");
10034 + retval = -ETIMEDOUT;
10035 + } else {
10036 + printk(KERN_ERR PFX "ctx failed\n");
10037 + retval = -EFAULT;
10039 + goto exit;
10041 + if (ctx->in_rid) {
10042 + struct ezusb_packet *ans = ctx->buf;
10043 + unsigned exp_len;
10045 + if (ans->hermes_len != 0)
10046 + exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
10047 + else
10048 + exp_len = 14;
10050 + if (exp_len != ctx->buf_length) {
10051 + err("%s: length mismatch for RID 0x%04x: "
10052 + "expected %d, got %d", __func__,
10053 + ctx->in_rid, exp_len, ctx->buf_length);
10054 + retval = -EIO;
10055 + goto exit;
10058 + if (ans_buff)
10059 + memcpy(ans_buff, ans->data, min(exp_len, ans_size));
10060 + if (ans_length)
10061 + *ans_length = le16_to_cpu(ans->hermes_len);
10063 + exit:
10064 + ezusb_request_context_put(ctx);
10065 + return retval;
10068 +static int __ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
10069 + u16 length, const void *data,
10070 + ezusb_ctx_wait ezusb_ctx_wait_func)
10072 + struct ezusb_priv *upriv = hw->priv;
10073 + u16 frame_type;
10074 + struct request_context *ctx;
10076 + if (length == 0)
10077 + return -EINVAL;
10079 + length = HERMES_RECLEN_TO_BYTES(length);
10081 + /* On memory mapped devices HERMES_RID_CNFGROUPADDRESSES can be
10082 + * set to be empty, but the USB bridge doesn't like it */
10083 + if (length == 0)
10084 + return 0;
10086 + ctx = ezusb_alloc_ctx(upriv, rid, EZUSB_RID_ACK);
10087 + if (!ctx)
10088 + return -ENOMEM;
10090 + if (rid == EZUSB_RID_TX)
10091 + frame_type = EZUSB_FRAME_DATA;
10092 + else
10093 + frame_type = EZUSB_FRAME_CONTROL;
10095 + return ezusb_access_ltv(upriv, ctx, length, data, frame_type,
10096 + NULL, 0, NULL, ezusb_ctx_wait_func);
10099 +static int ezusb_write_ltv(struct hermes *hw, int bap, u16 rid,
10100 + u16 length, const void *data)
10102 + return __ezusb_write_ltv(hw, bap, rid, length, data,
10103 + ezusb_req_ctx_wait_poll);
10106 +static int __ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
10107 + unsigned bufsize, u16 *length, void *buf,
10108 + ezusb_ctx_wait ezusb_ctx_wait_func)
10111 + struct ezusb_priv *upriv = hw->priv;
10112 + struct request_context *ctx;
10114 + if (bufsize % 2)
10115 + return -EINVAL;
10117 + ctx = ezusb_alloc_ctx(upriv, rid, rid);
10118 + if (!ctx)
10119 + return -ENOMEM;
10121 + return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL,
10122 + buf, bufsize, length, ezusb_req_ctx_wait_poll);
10125 +static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
10126 + unsigned bufsize, u16 *length, void *buf)
10128 + return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf,
10129 + ezusb_req_ctx_wait_poll);
10132 +static int ezusb_read_ltv_preempt(struct hermes *hw, int bap, u16 rid,
10133 + unsigned bufsize, u16 *length, void *buf)
10135 + return __ezusb_read_ltv(hw, bap, rid, bufsize, length, buf,
10136 + ezusb_req_ctx_wait_compl);
10139 +static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
10140 + u16 parm2, struct hermes_response *resp)
10142 + WARN_ON_ONCE(1);
10143 + return -EINVAL;
10146 +static int __ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
10147 + struct hermes_response *resp,
10148 + ezusb_ctx_wait ezusb_ctx_wait_func)
10150 + struct ezusb_priv *upriv = hw->priv;
10151 + struct request_context *ctx;
10153 + __le16 data[4] = {
10154 + cpu_to_le16(cmd),
10155 + cpu_to_le16(parm0),
10156 + 0,
10157 + 0,
10158 + };
10159 + netdev_dbg(upriv->dev, "0x%04X, parm0 0x%04X\n", cmd, parm0);
10160 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
10161 + if (!ctx)
10162 + return -ENOMEM;
10164 + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
10165 + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
10166 + ezusb_ctx_wait_func);
10169 +static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
10170 + struct hermes_response *resp)
10172 + return __ezusb_docmd_wait(hw, cmd, parm0, resp, ezusb_req_ctx_wait_poll);
10175 +static int ezusb_bap_pread(struct hermes *hw, int bap,
10176 + void *buf, int len, u16 id, u16 offset)
10178 + struct ezusb_priv *upriv = hw->priv;
10179 + struct ezusb_packet *ans = (void *) upriv->read_urb->transfer_buffer;
10180 + int actual_length = upriv->read_urb->actual_length;
10182 + if (id == EZUSB_RID_RX) {
10183 + if ((sizeof(*ans) + offset + len) > actual_length) {
10184 + printk(KERN_ERR PFX "BAP read beyond buffer end "
10185 + "in rx frame\n");
10186 + return -EINVAL;
10188 + memcpy(buf, ans->data + offset, len);
10189 + return 0;
10192 + if (EZUSB_IS_INFO(id)) {
10193 + /* Include 4 bytes for length/type */
10194 + if ((sizeof(*ans) + offset + len - 4) > actual_length) {
10195 + printk(KERN_ERR PFX "BAP read beyond buffer end "
10196 + "in info frame\n");
10197 + return -EFAULT;
10199 + memcpy(buf, ans->data + offset - 4, len);
10200 + } else {
10201 + printk(KERN_ERR PFX "Unexpected fid 0x%04x\n", id);
10202 + return -EINVAL;
10205 + return 0;
10208 +static int ezusb_read_pda(struct hermes *hw, __le16 *pda,
10209 + u32 pda_addr, u16 pda_len)
10211 + struct ezusb_priv *upriv = hw->priv;
10212 + struct request_context *ctx;
10213 + __le16 data[] = {
10214 + cpu_to_le16(pda_addr & 0xffff),
10215 + cpu_to_le16(pda_len - 4)
10216 + };
10217 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_READ_PDA, EZUSB_RID_READ_PDA);
10218 + if (!ctx)
10219 + return -ENOMEM;
10221 + /* wl_lkm does not include PDA size in the PDA area.
10222 + * We will pad the information into pda, so other routines
10223 + * don't have to be modified */
10224 + pda[0] = cpu_to_le16(pda_len - 2);
10225 + /* Includes CFG_PROD_DATA but not itself */
10226 + pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
10228 + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
10229 + EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4,
10230 + NULL, ezusb_req_ctx_wait_compl);
10233 +static int ezusb_program_init(struct hermes *hw, u32 entry_point)
10235 + struct ezusb_priv *upriv = hw->priv;
10236 + struct request_context *ctx;
10237 + __le32 data = cpu_to_le32(entry_point);
10239 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_INIT, EZUSB_RID_ACK);
10240 + if (!ctx)
10241 + return -ENOMEM;
10243 + return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
10244 + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
10245 + ezusb_req_ctx_wait_compl);
10248 +static int ezusb_program_end(struct hermes *hw)
10250 + struct ezusb_priv *upriv = hw->priv;
10251 + struct request_context *ctx;
10253 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_END, EZUSB_RID_ACK);
10254 + if (!ctx)
10255 + return -ENOMEM;
10257 + return ezusb_access_ltv(upriv, ctx, 0, NULL,
10258 + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
10259 + ezusb_req_ctx_wait_compl);
10262 +static int ezusb_program_bytes(struct hermes *hw, const char *buf,
10263 + u32 addr, u32 len)
10265 + struct ezusb_priv *upriv = hw->priv;
10266 + struct request_context *ctx;
10267 + __le32 data = cpu_to_le32(addr);
10268 + int err;
10270 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_SET_ADDR, EZUSB_RID_ACK);
10271 + if (!ctx)
10272 + return -ENOMEM;
10274 + err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
10275 + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
10276 + ezusb_req_ctx_wait_compl);
10277 + if (err)
10278 + return err;
10280 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_BYTES, EZUSB_RID_ACK);
10281 + if (!ctx)
10282 + return -ENOMEM;
10284 + return ezusb_access_ltv(upriv, ctx, len, buf,
10285 + EZUSB_FRAME_CONTROL, NULL, 0, NULL,
10286 + ezusb_req_ctx_wait_compl);
10289 +static int ezusb_program(struct hermes *hw, const char *buf,
10290 + u32 addr, u32 len)
10292 + u32 ch_addr;
10293 + u32 ch_len;
10294 + int err = 0;
10296 + /* We can only send 2048 bytes out of the bulk xmit at a time,
10297 + * so we have to split any programming into chunks of <2048
10298 + * bytes. */
10300 + ch_len = (len < MAX_DL_SIZE) ? len : MAX_DL_SIZE;
10301 + ch_addr = addr;
10303 + while (ch_addr < (addr + len)) {
10304 + pr_debug("Programming subblock of length %d "
10305 + "to address 0x%08x. Data @ %p\n",
10306 + ch_len, ch_addr, &buf[ch_addr - addr]);
10308 + err = ezusb_program_bytes(hw, &buf[ch_addr - addr],
10309 + ch_addr, ch_len);
10310 + if (err)
10311 + break;
10313 + ch_addr += ch_len;
10314 + ch_len = ((addr + len - ch_addr) < MAX_DL_SIZE) ?
10315 + (addr + len - ch_addr) : MAX_DL_SIZE;
10318 + return err;
10321 +static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
10323 + struct orinoco_private *priv = ndev_priv(dev);
10324 + struct net_device_stats *stats = &dev->stats;
10325 + struct ezusb_priv *upriv = priv->card;
10326 + u8 mic[MICHAEL_MIC_LEN + 1];
10327 + int err = 0;
10328 + int tx_control;
10329 + unsigned long flags;
10330 + struct request_context *ctx;
10331 + u8 *buf;
10332 + int tx_size;
10334 + if (!netif_running(dev)) {
10335 + printk(KERN_ERR "%s: Tx on stopped device!\n",
10336 + dev->name);
10337 + return NETDEV_TX_BUSY;
10340 + if (netif_queue_stopped(dev)) {
10341 + printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
10342 + dev->name);
10343 + return NETDEV_TX_BUSY;
10346 + if (orinoco_lock(priv, &flags) != 0) {
10347 + printk(KERN_ERR
10348 + "%s: ezusb_xmit() called while hw_unavailable\n",
10349 + dev->name);
10350 + return NETDEV_TX_BUSY;
10353 + if (!netif_carrier_ok(dev) ||
10354 + (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
10355 + /* Oops, the firmware hasn't established a connection,
10356 + silently drop the packet (this seems to be the
10357 + safest approach). */
10358 + goto drop;
10361 + /* Check packet length */
10362 + if (skb->len < ETH_HLEN)
10363 + goto drop;
10365 + tx_control = 0;
10367 + err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
10368 + &mic[0]);
10369 + if (err)
10370 + goto drop;
10372 + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
10373 + if (!ctx)
10374 + goto drop;
10376 + memset(ctx->buf, 0, BULK_BUF_SIZE);
10377 + buf = ctx->buf->data;
10380 + __le16 *tx_cntl = (__le16 *)buf;
10381 + *tx_cntl = cpu_to_le16(tx_control);
10382 + buf += sizeof(*tx_cntl);
10385 + memcpy(buf, skb->data, skb->len);
10386 + buf += skb->len;
10388 + if (tx_control & HERMES_TXCTRL_MIC) {
10389 + u8 *m = mic;
10390 + /* Mic has been offset so it can be copied to an even
10391 + * address. We're copying eveything anyway, so we
10392 + * don't need to copy that first byte. */
10393 + if (skb->len % 2)
10394 + m++;
10395 + memcpy(buf, m, MICHAEL_MIC_LEN);
10396 + buf += MICHAEL_MIC_LEN;
10399 + /* Finally, we actually initiate the send */
10400 + netif_stop_queue(dev);
10402 + /* The card may behave better if we send evenly sized usb transfers */
10403 + tx_size = ALIGN(buf - ctx->buf->data, 2);
10405 + err = ezusb_access_ltv(upriv, ctx, tx_size, NULL,
10406 + EZUSB_FRAME_DATA, NULL, 0, NULL,
10407 + ezusb_req_ctx_wait_skip);
10409 + if (err) {
10410 + netif_start_queue(dev);
10411 + if (net_ratelimit())
10412 + printk(KERN_ERR "%s: Error %d transmitting packet\n",
10413 + dev->name, err);
10414 + goto busy;
10417 + netif_trans_update(dev);
10418 + stats->tx_bytes += skb->len;
10419 + goto ok;
10421 + drop:
10422 + stats->tx_errors++;
10423 + stats->tx_dropped++;
10425 + ok:
10426 + orinoco_unlock(priv, &flags);
10427 + dev_kfree_skb(skb);
10428 + return NETDEV_TX_OK;
10430 + busy:
10431 + orinoco_unlock(priv, &flags);
10432 + return NETDEV_TX_BUSY;
10435 +static int ezusb_allocate(struct hermes *hw, u16 size, u16 *fid)
10437 + *fid = EZUSB_RID_TX;
10438 + return 0;
10442 +static int ezusb_hard_reset(struct orinoco_private *priv)
10444 + struct ezusb_priv *upriv = priv->card;
10445 + int retval = ezusb_8051_cpucs(upriv, 1);
10447 + if (retval < 0) {
10448 + err("Failed to reset");
10449 + return retval;
10452 + retval = ezusb_8051_cpucs(upriv, 0);
10453 + if (retval < 0) {
10454 + err("Failed to unreset");
10455 + return retval;
10458 + netdev_dbg(upriv->dev, "sending control message\n");
10459 + retval = usb_control_msg(upriv->udev,
10460 + usb_sndctrlpipe(upriv->udev, 0),
10461 + EZUSB_REQUEST_TRIGGER,
10462 + USB_TYPE_VENDOR | USB_RECIP_DEVICE |
10463 + USB_DIR_OUT, 0x0, 0x0, NULL, 0,
10464 + DEF_TIMEOUT);
10465 + if (retval < 0) {
10466 + err("EZUSB_REQUEST_TRIGGER failed retval %d", retval);
10467 + return retval;
10469 +#if 0
10470 + dbg("Sending EZUSB_REQUEST_TRIG_AC");
10471 + retval = usb_control_msg(upriv->udev,
10472 + usb_sndctrlpipe(upriv->udev, 0),
10473 + EZUSB_REQUEST_TRIG_AC,
10474 + USB_TYPE_VENDOR | USB_RECIP_DEVICE |
10475 + USB_DIR_OUT, 0x00FA, 0x0, NULL, 0,
10476 + DEF_TIMEOUT);
10477 + if (retval < 0) {
10478 + err("EZUSB_REQUEST_TRIG_AC failed retval %d", retval);
10479 + return retval;
10481 +#endif
10483 + return 0;
10487 +static int ezusb_init(struct hermes *hw)
10489 + struct ezusb_priv *upriv = hw->priv;
10490 + int retval;
10492 + if (!upriv)
10493 + return -EINVAL;
10495 + upriv->reply_count = 0;
10496 + /* Write the MAGIC number on the simulated registers to keep
10497 + * orinoco.c happy */
10498 + hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
10499 + hermes_write_regn(hw, RXFID, EZUSB_RID_RX);
10501 + usb_kill_urb(upriv->read_urb);
10502 + ezusb_submit_in_urb(upriv);
10504 + retval = __ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1,
10505 + HERMES_BYTES_TO_RECLEN(2), "\x10\x00",
10506 + ezusb_req_ctx_wait_compl);
10507 + if (retval < 0) {
10508 + printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval);
10509 + return retval;
10512 + retval = __ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL,
10513 + ezusb_req_ctx_wait_compl);
10514 + if (retval < 0) {
10515 + printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval);
10516 + return retval;
10519 + return 0;
10522 +static void ezusb_bulk_in_callback(struct urb *urb)
10524 + struct ezusb_priv *upriv = (struct ezusb_priv *) urb->context;
10525 + struct ezusb_packet *ans = urb->transfer_buffer;
10526 + u16 crc;
10527 + u16 hermes_rid;
10529 + if (upriv->udev == NULL)
10530 + return;
10532 + if (urb->status == -ETIMEDOUT) {
10533 + /* When a device gets unplugged we get this every time
10534 + * we resubmit, flooding the logs. Since we don't use
10535 + * USB timeouts, it shouldn't happen any other time*/
10536 + pr_warn("%s: urb timed out, not resubmitting\n", __func__);
10537 + return;
10539 + if (urb->status == -ECONNABORTED) {
10540 + pr_warn("%s: connection abort, resubmitting urb\n",
10541 + __func__);
10542 + goto resubmit;
10544 + if ((urb->status == -EILSEQ)
10545 + || (urb->status == -ENOENT)
10546 + || (urb->status == -ECONNRESET)) {
10547 + netdev_dbg(upriv->dev, "status %d, not resubmiting\n",
10548 + urb->status);
10549 + return;
10551 + if (urb->status)
10552 + netdev_dbg(upriv->dev, "status: %d length: %d\n",
10553 + urb->status, urb->actual_length);
10554 + if (urb->actual_length < sizeof(*ans)) {
10555 + err("%s: short read, ignoring", __func__);
10556 + goto resubmit;
10558 + crc = build_crc(ans);
10559 + if (le16_to_cpu(ans->crc) != crc) {
10560 + err("CRC error, ignoring packet");
10561 + goto resubmit;
10564 + hermes_rid = le16_to_cpu(ans->hermes_rid);
10565 + if ((hermes_rid != EZUSB_RID_RX) && !EZUSB_IS_INFO(hermes_rid)) {
10566 + ezusb_request_in_callback(upriv, urb);
10567 + } else if (upriv->dev) {
10568 + struct net_device *dev = upriv->dev;
10569 + struct orinoco_private *priv = ndev_priv(dev);
10570 + struct hermes *hw = &priv->hw;
10572 + if (hermes_rid == EZUSB_RID_RX) {
10573 + __orinoco_ev_rx(dev, hw);
10574 + } else {
10575 + hermes_write_regn(hw, INFOFID,
10576 + le16_to_cpu(ans->hermes_rid));
10577 + __orinoco_ev_info(dev, hw);
10581 + resubmit:
10582 + if (upriv->udev)
10583 + ezusb_submit_in_urb(upriv);
10586 +static inline void ezusb_delete(struct ezusb_priv *upriv)
10588 + struct list_head *item;
10589 + struct list_head *tmp_item;
10590 + unsigned long flags;
10592 + BUG_ON(!upriv);
10594 + mutex_lock(&upriv->mtx);
10596 + upriv->udev = NULL; /* No timer will be rearmed from here */
10598 + usb_kill_urb(upriv->read_urb);
10600 + spin_lock_irqsave(&upriv->req_lock, flags);
10601 + list_for_each_safe(item, tmp_item, &upriv->req_active) {
10602 + struct request_context *ctx;
10603 + int err;
10605 + ctx = list_entry(item, struct request_context, list);
10606 + refcount_inc(&ctx->refcount);
10608 + ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
10609 + err = usb_unlink_urb(ctx->outurb);
10611 + spin_unlock_irqrestore(&upriv->req_lock, flags);
10612 + if (err == -EINPROGRESS)
10613 + wait_for_completion(&ctx->done);
10615 + del_timer_sync(&ctx->timer);
10616 + /* FIXME: there is an slight chance for the irq handler to
10617 + * be running */
10618 + if (!list_empty(&ctx->list))
10619 + ezusb_ctx_complete(ctx);
10621 + ezusb_request_context_put(ctx);
10622 + spin_lock_irqsave(&upriv->req_lock, flags);
10624 + spin_unlock_irqrestore(&upriv->req_lock, flags);
10626 + list_for_each_safe(item, tmp_item, &upriv->req_pending)
10627 + ezusb_ctx_complete(list_entry(item,
10628 + struct request_context, list));
10630 + if (upriv->read_urb && upriv->read_urb->status == -EINPROGRESS)
10631 + printk(KERN_ERR PFX "Some URB in progress\n");
10633 + mutex_unlock(&upriv->mtx);
10635 + if (upriv->read_urb) {
10636 + kfree(upriv->read_urb->transfer_buffer);
10637 + usb_free_urb(upriv->read_urb);
10639 + kfree(upriv->bap_buf);
10640 + if (upriv->dev) {
10641 + struct orinoco_private *priv = ndev_priv(upriv->dev);
10642 + orinoco_if_del(priv);
10643 + wiphy_unregister(priv_to_wiphy(upriv));
10644 + free_orinocodev(priv);
10648 +static void ezusb_lock_irqsave(spinlock_t *lock,
10649 + unsigned long *flags) __acquires(lock)
10651 + spin_lock_bh(lock);
10654 +static void ezusb_unlock_irqrestore(spinlock_t *lock,
10655 + unsigned long *flags) __releases(lock)
10657 + spin_unlock_bh(lock);
10660 +static void ezusb_lock_irq(spinlock_t *lock) __acquires(lock)
10662 + spin_lock_bh(lock);
10665 +static void ezusb_unlock_irq(spinlock_t *lock) __releases(lock)
10667 + spin_unlock_bh(lock);
10670 +static const struct hermes_ops ezusb_ops = {
10671 + .init = ezusb_init,
10672 + .cmd_wait = ezusb_docmd_wait,
10673 + .init_cmd_wait = ezusb_doicmd_wait,
10674 + .allocate = ezusb_allocate,
10675 + .read_ltv = ezusb_read_ltv,
10676 + .read_ltv_pr = ezusb_read_ltv_preempt,
10677 + .write_ltv = ezusb_write_ltv,
10678 + .bap_pread = ezusb_bap_pread,
10679 + .read_pda = ezusb_read_pda,
10680 + .program_init = ezusb_program_init,
10681 + .program_end = ezusb_program_end,
10682 + .program = ezusb_program,
10683 + .lock_irqsave = ezusb_lock_irqsave,
10684 + .unlock_irqrestore = ezusb_unlock_irqrestore,
10685 + .lock_irq = ezusb_lock_irq,
10686 + .unlock_irq = ezusb_unlock_irq,
10689 +static const struct net_device_ops ezusb_netdev_ops = {
10690 + .ndo_open = orinoco_open,
10691 + .ndo_stop = orinoco_stop,
10692 + .ndo_start_xmit = ezusb_xmit,
10693 + .ndo_set_rx_mode = orinoco_set_multicast_list,
10694 + .ndo_change_mtu = orinoco_change_mtu,
10695 + .ndo_set_mac_address = eth_mac_addr,
10696 + .ndo_validate_addr = eth_validate_addr,
10697 + .ndo_tx_timeout = orinoco_tx_timeout,
10700 +static int ezusb_probe(struct usb_interface *interface,
10701 + const struct usb_device_id *id)
10703 + struct usb_device *udev = interface_to_usbdev(interface);
10704 + struct orinoco_private *priv;
10705 + struct hermes *hw;
10706 + struct ezusb_priv *upriv = NULL;
10707 + struct usb_interface_descriptor *iface_desc;
10708 + struct usb_endpoint_descriptor *ep;
10709 + const struct firmware *fw_entry = NULL;
10710 + int retval = 0;
10711 + int i;
10713 + priv = alloc_orinocodev(sizeof(*upriv), &udev->dev,
10714 + ezusb_hard_reset, NULL);
10715 + if (!priv) {
10716 + err("Couldn't allocate orinocodev");
10717 + retval = -ENOMEM;
10718 + goto exit;
10721 + hw = &priv->hw;
10723 + upriv = priv->card;
10725 + mutex_init(&upriv->mtx);
10726 + spin_lock_init(&upriv->reply_count_lock);
10728 + spin_lock_init(&upriv->req_lock);
10729 + INIT_LIST_HEAD(&upriv->req_pending);
10730 + INIT_LIST_HEAD(&upriv->req_active);
10732 + upriv->udev = udev;
10734 + hw->iobase = (void __force __iomem *) &upriv->hermes_reg_fake;
10735 + hw->reg_spacing = HERMES_16BIT_REGSPACING;
10736 + hw->priv = upriv;
10737 + hw->ops = &ezusb_ops;
10739 + /* set up the endpoint information */
10740 + /* check out the endpoints */
10742 + iface_desc = &interface->cur_altsetting->desc;
10743 + for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
10744 + ep = &interface->cur_altsetting->endpoint[i].desc;
10746 + if (usb_endpoint_is_bulk_in(ep)) {
10747 + /* we found a bulk in endpoint */
10748 + if (upriv->read_urb != NULL) {
10749 + pr_warn("Found a second bulk in ep, ignored\n");
10750 + continue;
10753 + upriv->read_urb = usb_alloc_urb(0, GFP_KERNEL);
10754 + if (!upriv->read_urb)
10755 + goto error;
10756 + if (le16_to_cpu(ep->wMaxPacketSize) != 64)
10757 + pr_warn("bulk in: wMaxPacketSize!= 64\n");
10758 + if (ep->bEndpointAddress != (2 | USB_DIR_IN))
10759 + pr_warn("bulk in: bEndpointAddress: %d\n",
10760 + ep->bEndpointAddress);
10761 + upriv->read_pipe = usb_rcvbulkpipe(udev,
10762 + ep->
10763 + bEndpointAddress);
10764 + upriv->read_urb->transfer_buffer =
10765 + kmalloc(BULK_BUF_SIZE, GFP_KERNEL);
10766 + if (!upriv->read_urb->transfer_buffer) {
10767 + err("Couldn't allocate IN buffer");
10768 + goto error;
10772 + if (usb_endpoint_is_bulk_out(ep)) {
10773 + /* we found a bulk out endpoint */
10774 + if (upriv->bap_buf != NULL) {
10775 + pr_warn("Found a second bulk out ep, ignored\n");
10776 + continue;
10779 + if (le16_to_cpu(ep->wMaxPacketSize) != 64)
10780 + pr_warn("bulk out: wMaxPacketSize != 64\n");
10781 + if (ep->bEndpointAddress != 2)
10782 + pr_warn("bulk out: bEndpointAddress: %d\n",
10783 + ep->bEndpointAddress);
10784 + upriv->write_pipe = usb_sndbulkpipe(udev,
10785 + ep->
10786 + bEndpointAddress);
10787 + upriv->bap_buf = kmalloc(BULK_BUF_SIZE, GFP_KERNEL);
10788 + if (!upriv->bap_buf) {
10789 + err("Couldn't allocate bulk_out_buffer");
10790 + goto error;
10794 + if (!upriv->bap_buf || !upriv->read_urb) {
10795 + err("Didn't find the required bulk endpoints");
10796 + goto error;
10799 + if (request_firmware(&fw_entry, "orinoco_ezusb_fw",
10800 + &interface->dev) == 0) {
10801 + firmware.size = fw_entry->size;
10802 + firmware.code = fw_entry->data;
10804 + if (firmware.size && firmware.code) {
10805 + if (ezusb_firmware_download(upriv, &firmware) < 0)
10806 + goto error;
10807 + } else {
10808 + err("No firmware to download");
10809 + goto error;
10812 + if (ezusb_hard_reset(priv) < 0) {
10813 + err("Cannot reset the device");
10814 + goto error;
10817 + /* If the firmware is already downloaded orinoco.c will call
10818 + * ezusb_init but if the firmware is not already there, that will make
10819 + * the kernel very unstable, so we try initializing here and quit in
10820 + * case of error */
10821 + if (ezusb_init(hw) < 0) {
10822 + err("Couldn't initialize the device");
10823 + err("Firmware may not be downloaded or may be wrong.");
10824 + goto error;
10827 + /* Initialise the main driver */
10828 + if (orinoco_init(priv) != 0) {
10829 + err("orinoco_init() failed\n");
10830 + goto error;
10833 + if (orinoco_if_add(priv, 0, 0, &ezusb_netdev_ops) != 0) {
10834 + upriv->dev = NULL;
10835 + err("%s: orinoco_if_add() failed", __func__);
10836 + wiphy_unregister(priv_to_wiphy(priv));
10837 + goto error;
10839 + upriv->dev = priv->ndev;
10841 + goto exit;
10843 + error:
10844 + ezusb_delete(upriv);
10845 + if (upriv->dev) {
10846 + /* upriv->dev was 0, so ezusb_delete() didn't free it */
10847 + free_orinocodev(priv);
10849 + upriv = NULL;
10850 + retval = -EFAULT;
10851 + exit:
10852 + if (fw_entry) {
10853 + firmware.code = NULL;
10854 + firmware.size = 0;
10855 + release_firmware(fw_entry);
10857 + usb_set_intfdata(interface, upriv);
10858 + return retval;
10862 +static void ezusb_disconnect(struct usb_interface *intf)
10864 + struct ezusb_priv *upriv = usb_get_intfdata(intf);
10865 + usb_set_intfdata(intf, NULL);
10866 + ezusb_delete(upriv);
10867 + printk(KERN_INFO PFX "Disconnected\n");
10871 +/* usb specific object needed to register this driver with the usb subsystem */
10872 +static struct usb_driver orinoco_driver = {
10873 + .name = DRIVER_NAME,
10874 + .probe = ezusb_probe,
10875 + .disconnect = ezusb_disconnect,
10876 + .id_table = ezusb_table,
10877 + .disable_hub_initiated_lpm = 1,
10880 +module_usb_driver(orinoco_driver);
10882 +MODULE_AUTHOR("Manuel Estrada Sainz");
10883 +MODULE_DESCRIPTION("Driver for Orinoco wireless LAN cards using EZUSB bridge");
10884 +MODULE_LICENSE("Dual MPL/GPL");
10885 --- /dev/null
10886 +++ a/drivers/net/wireless/intersil/orinoco/scan.c
10887 @@ -0,0 +1,259 @@
10888 +/* Helpers for managing scan queues
10890 + * See copyright notice in main.c
10891 + */
10893 +#include <linux/gfp.h>
10894 +#include <linux/kernel.h>
10895 +#include <linux/string.h>
10896 +#include <linux/ieee80211.h>
10897 +#include <net/cfg80211.h>
10899 +#include "hermes.h"
10900 +#include "orinoco.h"
10901 +#include "main.h"
10903 +#include "scan.h"
10905 +#define ZERO_DBM_OFFSET 0x95
10906 +#define MAX_SIGNAL_LEVEL 0x8A
10907 +#define MIN_SIGNAL_LEVEL 0x2F
10909 +#define SIGNAL_TO_DBM(x) \
10910 + (clamp_t(s32, (x), MIN_SIGNAL_LEVEL, MAX_SIGNAL_LEVEL) \
10911 + - ZERO_DBM_OFFSET)
10912 +#define SIGNAL_TO_MBM(x) (SIGNAL_TO_DBM(x) * 100)
10914 +static int symbol_build_supp_rates(u8 *buf, const __le16 *rates)
10916 + int i;
10917 + u8 rate;
10919 + buf[0] = WLAN_EID_SUPP_RATES;
10920 + for (i = 0; i < 5; i++) {
10921 + rate = le16_to_cpu(rates[i]);
10922 + /* NULL terminated */
10923 + if (rate == 0x0)
10924 + break;
10925 + buf[i + 2] = rate;
10927 + buf[1] = i;
10929 + return i + 2;
10932 +static int prism_build_supp_rates(u8 *buf, const u8 *rates)
10934 + int i;
10936 + buf[0] = WLAN_EID_SUPP_RATES;
10937 + for (i = 0; i < 8; i++) {
10938 + /* NULL terminated */
10939 + if (rates[i] == 0x0)
10940 + break;
10941 + buf[i + 2] = rates[i];
10943 + buf[1] = i;
10945 + /* We might still have another 2 rates, which need to go in
10946 + * extended supported rates */
10947 + if (i == 8 && rates[i] > 0) {
10948 + buf[10] = WLAN_EID_EXT_SUPP_RATES;
10949 + for (; i < 10; i++) {
10950 + /* NULL terminated */
10951 + if (rates[i] == 0x0)
10952 + break;
10953 + buf[i + 2] = rates[i];
10955 + buf[11] = i - 8;
10958 + return (i < 8) ? i + 2 : i + 4;
10961 +static void orinoco_add_hostscan_result(struct orinoco_private *priv,
10962 + const union hermes_scan_info *bss)
10964 + struct wiphy *wiphy = priv_to_wiphy(priv);
10965 + struct ieee80211_channel *channel;
10966 + struct cfg80211_bss *cbss;
10967 + u8 *ie;
10968 + u8 ie_buf[46];
10969 + u64 timestamp;
10970 + s32 signal;
10971 + u16 capability;
10972 + u16 beacon_interval;
10973 + int ie_len;
10974 + int freq;
10975 + int len;
10977 + len = le16_to_cpu(bss->a.essid_len);
10979 + /* Reconstruct SSID and bitrate IEs to pass up */
10980 + ie_buf[0] = WLAN_EID_SSID;
10981 + ie_buf[1] = len;
10982 + memcpy(&ie_buf[2], bss->a.essid, len);
10984 + ie = ie_buf + len + 2;
10985 + ie_len = ie_buf[1] + 2;
10986 + switch (priv->firmware_type) {
10987 + case FIRMWARE_TYPE_SYMBOL:
10988 + ie_len += symbol_build_supp_rates(ie, bss->s.rates);
10989 + break;
10991 + case FIRMWARE_TYPE_INTERSIL:
10992 + ie_len += prism_build_supp_rates(ie, bss->p.rates);
10993 + break;
10995 + case FIRMWARE_TYPE_AGERE:
10996 + default:
10997 + break;
11000 + freq = ieee80211_channel_to_frequency(
11001 + le16_to_cpu(bss->a.channel), NL80211_BAND_2GHZ);
11002 + channel = ieee80211_get_channel(wiphy, freq);
11003 + if (!channel) {
11004 + printk(KERN_DEBUG "Invalid channel designation %04X(%04X)",
11005 + bss->a.channel, freq);
11006 + return; /* Then ignore it for now */
11008 + timestamp = 0;
11009 + capability = le16_to_cpu(bss->a.capabilities);
11010 + beacon_interval = le16_to_cpu(bss->a.beacon_interv);
11011 + signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level));
11013 + cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
11014 + bss->a.bssid, timestamp, capability,
11015 + beacon_interval, ie_buf, ie_len, signal,
11016 + GFP_KERNEL);
11017 + cfg80211_put_bss(wiphy, cbss);
11020 +void orinoco_add_extscan_result(struct orinoco_private *priv,
11021 + struct agere_ext_scan_info *bss,
11022 + size_t len)
11024 + struct wiphy *wiphy = priv_to_wiphy(priv);
11025 + struct ieee80211_channel *channel;
11026 + struct cfg80211_bss *cbss;
11027 + const u8 *ie;
11028 + u64 timestamp;
11029 + s32 signal;
11030 + u16 capability;
11031 + u16 beacon_interval;
11032 + size_t ie_len;
11033 + int chan, freq;
11035 + ie_len = len - sizeof(*bss);
11036 + ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len);
11037 + chan = ie ? ie[2] : 0;
11038 + freq = ieee80211_channel_to_frequency(chan, NL80211_BAND_2GHZ);
11039 + channel = ieee80211_get_channel(wiphy, freq);
11041 + timestamp = le64_to_cpu(bss->timestamp);
11042 + capability = le16_to_cpu(bss->capabilities);
11043 + beacon_interval = le16_to_cpu(bss->beacon_interval);
11044 + ie = bss->data;
11045 + signal = SIGNAL_TO_MBM(bss->level);
11047 + cbss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN,
11048 + bss->bssid, timestamp, capability,
11049 + beacon_interval, ie, ie_len, signal,
11050 + GFP_KERNEL);
11051 + cfg80211_put_bss(wiphy, cbss);
11054 +void orinoco_add_hostscan_results(struct orinoco_private *priv,
11055 + unsigned char *buf,
11056 + size_t len)
11058 + int offset; /* In the scan data */
11059 + size_t atom_len;
11060 + bool abort = false;
11062 + switch (priv->firmware_type) {
11063 + case FIRMWARE_TYPE_AGERE:
11064 + atom_len = sizeof(struct agere_scan_apinfo);
11065 + offset = 0;
11066 + break;
11068 + case FIRMWARE_TYPE_SYMBOL:
11069 + /* Lack of documentation necessitates this hack.
11070 + * Different firmwares have 68 or 76 byte long atoms.
11071 + * We try modulo first. If the length divides by both,
11072 + * we check what would be the channel in the second
11073 + * frame for a 68-byte atom. 76-byte atoms have 0 there.
11074 + * Valid channel cannot be 0. */
11075 + if (len % 76)
11076 + atom_len = 68;
11077 + else if (len % 68)
11078 + atom_len = 76;
11079 + else if (len >= 1292 && buf[68] == 0)
11080 + atom_len = 76;
11081 + else
11082 + atom_len = 68;
11083 + offset = 0;
11084 + break;
11086 + case FIRMWARE_TYPE_INTERSIL:
11087 + offset = 4;
11088 + if (priv->has_hostscan) {
11089 + atom_len = le16_to_cpup((__le16 *)buf);
11090 + /* Sanity check for atom_len */
11091 + if (atom_len < sizeof(struct prism2_scan_apinfo)) {
11092 + printk(KERN_ERR "%s: Invalid atom_len in scan "
11093 + "data: %zu\n", priv->ndev->name,
11094 + atom_len);
11095 + abort = true;
11096 + goto scan_abort;
11098 + } else
11099 + atom_len = offsetof(struct prism2_scan_apinfo, atim);
11100 + break;
11102 + default:
11103 + abort = true;
11104 + goto scan_abort;
11107 + /* Check that we got an whole number of atoms */
11108 + if ((len - offset) % atom_len) {
11109 + printk(KERN_ERR "%s: Unexpected scan data length %zu, "
11110 + "atom_len %zu, offset %d\n", priv->ndev->name, len,
11111 + atom_len, offset);
11112 + abort = true;
11113 + goto scan_abort;
11116 + /* Process the entries one by one */
11117 + for (; offset + atom_len <= len; offset += atom_len) {
11118 + union hermes_scan_info *atom;
11120 + atom = (union hermes_scan_info *) (buf + offset);
11122 + orinoco_add_hostscan_result(priv, atom);
11125 + scan_abort:
11126 + if (priv->scan_request) {
11127 + struct cfg80211_scan_info info = {
11128 + .aborted = abort,
11129 + };
11131 + cfg80211_scan_done(priv->scan_request, &info);
11132 + priv->scan_request = NULL;
11136 +void orinoco_scan_done(struct orinoco_private *priv, bool abort)
11138 + if (priv->scan_request) {
11139 + struct cfg80211_scan_info info = {
11140 + .aborted = abort,
11141 + };
11143 + cfg80211_scan_done(priv->scan_request, &info);
11144 + priv->scan_request = NULL;
11147 --- /dev/null
11148 +++ a/drivers/net/wireless/intersil/orinoco/scan.h
11149 @@ -0,0 +1,21 @@
11150 +/* Helpers for managing scan queues
11152 + * See copyright notice in main.c
11153 + */
11154 +#ifndef _ORINOCO_SCAN_H_
11155 +#define _ORINOCO_SCAN_H_
11157 +/* Forward declarations */
11158 +struct orinoco_private;
11159 +struct agere_ext_scan_info;
11161 +/* Add scan results */
11162 +void orinoco_add_extscan_result(struct orinoco_private *priv,
11163 + struct agere_ext_scan_info *atom,
11164 + size_t len);
11165 +void orinoco_add_hostscan_results(struct orinoco_private *dev,
11166 + unsigned char *buf,
11167 + size_t len);
11168 +void orinoco_scan_done(struct orinoco_private *priv, bool abort);
11170 +#endif /* _ORINOCO_SCAN_H_ */
11171 --- /dev/null
11172 +++ a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
11173 @@ -0,0 +1,328 @@
11175 + * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
11176 + * Symbol Wireless Networker LA4137, CompactFlash cards by Socket
11177 + * Communications and Intel PRO/Wireless 2011B.
11179 + * The driver implements Symbol firmware download. The rest is handled
11180 + * in hermes.c and main.c.
11182 + * Utilities for downloading the Symbol firmware are available at
11183 + * http://sourceforge.net/projects/orinoco/
11185 + * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
11186 + * Portions based on orinoco_cs.c:
11187 + * Copyright (C) David Gibson, Linuxcare Australia
11188 + * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
11189 + * Copyright (C) Symbol Technologies.
11191 + * See copyright notice in file main.c.
11192 + */
11194 +#define DRIVER_NAME "spectrum_cs"
11195 +#define PFX DRIVER_NAME ": "
11197 +#include <linux/module.h>
11198 +#include <linux/kernel.h>
11199 +#include <linux/delay.h>
11200 +#include <pcmcia/cistpl.h>
11201 +#include <pcmcia/cisreg.h>
11202 +#include <pcmcia/ds.h>
11204 +#include "orinoco.h"
11206 +/********************************************************************/
11207 +/* Module stuff */
11208 +/********************************************************************/
11210 +MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
11211 +MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
11212 +MODULE_LICENSE("Dual MPL/GPL");
11214 +/* Module parameters */
11216 +/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
11217 + * don't have any CIS entry for it. This workaround it... */
11218 +static int ignore_cis_vcc; /* = 0 */
11219 +module_param(ignore_cis_vcc, int, 0);
11220 +MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
11222 +/********************************************************************/
11223 +/* Data structures */
11224 +/********************************************************************/
11226 +/* PCMCIA specific device information (goes in the card field of
11227 + * struct orinoco_private */
11228 +struct orinoco_pccard {
11229 + struct pcmcia_device *p_dev;
11232 +/********************************************************************/
11233 +/* Function prototypes */
11234 +/********************************************************************/
11236 +static int spectrum_cs_config(struct pcmcia_device *link);
11237 +static void spectrum_cs_release(struct pcmcia_device *link);
11239 +/* Constants for the CISREG_CCSR register */
11240 +#define HCR_RUN 0x07 /* run firmware after reset */
11241 +#define HCR_IDLE 0x0E /* don't run firmware after reset */
11242 +#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
11246 + * Reset the card using configuration registers COR and CCSR.
11247 + * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
11248 + */
11249 +static int
11250 +spectrum_reset(struct pcmcia_device *link, int idle)
11252 + int ret;
11253 + u8 save_cor;
11254 + u8 ccsr;
11256 + /* Doing it if hardware is gone is guaranteed crash */
11257 + if (!pcmcia_dev_present(link))
11258 + return -ENODEV;
11260 + /* Save original COR value */
11261 + ret = pcmcia_read_config_byte(link, CISREG_COR, &save_cor);
11262 + if (ret)
11263 + goto failed;
11265 + /* Soft-Reset card */
11266 + ret = pcmcia_write_config_byte(link, CISREG_COR,
11267 + (save_cor | COR_SOFT_RESET));
11268 + if (ret)
11269 + goto failed;
11270 + udelay(1000);
11272 + /* Read CCSR */
11273 + ret = pcmcia_read_config_byte(link, CISREG_CCSR, &ccsr);
11274 + if (ret)
11275 + goto failed;
11277 + /*
11278 + * Start or stop the firmware. Memory width bit should be
11279 + * preserved from the value we've just read.
11280 + */
11281 + ccsr = (idle ? HCR_IDLE : HCR_RUN) | (ccsr & HCR_MEM16);
11282 + ret = pcmcia_write_config_byte(link, CISREG_CCSR, ccsr);
11283 + if (ret)
11284 + goto failed;
11285 + udelay(1000);
11287 + /* Restore original COR configuration index */
11288 + ret = pcmcia_write_config_byte(link, CISREG_COR,
11289 + (save_cor & ~COR_SOFT_RESET));
11290 + if (ret)
11291 + goto failed;
11292 + udelay(1000);
11293 + return 0;
11295 +failed:
11296 + return -ENODEV;
11299 +/********************************************************************/
11300 +/* Device methods */
11301 +/********************************************************************/
11303 +static int
11304 +spectrum_cs_hard_reset(struct orinoco_private *priv)
11306 + struct orinoco_pccard *card = priv->card;
11307 + struct pcmcia_device *link = card->p_dev;
11309 + /* Soft reset using COR and HCR */
11310 + spectrum_reset(link, 0);
11312 + return 0;
11315 +static int
11316 +spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
11318 + struct orinoco_pccard *card = priv->card;
11319 + struct pcmcia_device *link = card->p_dev;
11321 + return spectrum_reset(link, idle);
11324 +/********************************************************************/
11325 +/* PCMCIA stuff */
11326 +/********************************************************************/
11328 +static int
11329 +spectrum_cs_probe(struct pcmcia_device *link)
11331 + struct orinoco_private *priv;
11332 + struct orinoco_pccard *card;
11333 + int ret;
11335 + priv = alloc_orinocodev(sizeof(*card), &link->dev,
11336 + spectrum_cs_hard_reset,
11337 + spectrum_cs_stop_firmware);
11338 + if (!priv)
11339 + return -ENOMEM;
11340 + card = priv->card;
11342 + /* Link both structures together */
11343 + card->p_dev = link;
11344 + link->priv = priv;
11346 + ret = spectrum_cs_config(link);
11347 + if (ret)
11348 + goto err_free_orinocodev;
11350 + return 0;
11352 +err_free_orinocodev:
11353 + free_orinocodev(priv);
11354 + return ret;
11357 +static void spectrum_cs_detach(struct pcmcia_device *link)
11359 + struct orinoco_private *priv = link->priv;
11361 + orinoco_if_del(priv);
11363 + spectrum_cs_release(link);
11365 + free_orinocodev(priv);
11366 +} /* spectrum_cs_detach */
11368 +static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
11369 + void *priv_data)
11371 + if (p_dev->config_index == 0)
11372 + return -EINVAL;
11374 + return pcmcia_request_io(p_dev);
11377 +static int
11378 +spectrum_cs_config(struct pcmcia_device *link)
11380 + struct orinoco_private *priv = link->priv;
11381 + struct hermes *hw = &priv->hw;
11382 + int ret;
11383 + void __iomem *mem;
11385 + link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
11386 + CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
11387 + if (ignore_cis_vcc)
11388 + link->config_flags &= ~CONF_AUTO_CHECK_VCC;
11389 + ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
11390 + if (ret) {
11391 + if (!ignore_cis_vcc)
11392 + printk(KERN_ERR PFX "GetNextTuple(): No matching "
11393 + "CIS configuration. Maybe you need the "
11394 + "ignore_cis_vcc=1 parameter.\n");
11395 + goto failed;
11398 + mem = ioport_map(link->resource[0]->start,
11399 + resource_size(link->resource[0]));
11400 + if (!mem)
11401 + goto failed;
11403 + /* We initialize the hermes structure before completing PCMCIA
11404 + * configuration just in case the interrupt handler gets
11405 + * called. */
11406 + hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
11407 + hw->eeprom_pda = true;
11409 + ret = pcmcia_request_irq(link, orinoco_interrupt);
11410 + if (ret)
11411 + goto failed;
11413 + ret = pcmcia_enable_device(link);
11414 + if (ret)
11415 + goto failed;
11417 + /* Reset card */
11418 + if (spectrum_cs_hard_reset(priv) != 0)
11419 + goto failed;
11421 + /* Initialise the main driver */
11422 + if (orinoco_init(priv) != 0) {
11423 + printk(KERN_ERR PFX "orinoco_init() failed\n");
11424 + goto failed;
11427 + /* Register an interface with the stack */
11428 + if (orinoco_if_add(priv, link->resource[0]->start,
11429 + link->irq, NULL) != 0) {
11430 + printk(KERN_ERR PFX "orinoco_if_add() failed\n");
11431 + goto failed;
11434 + return 0;
11436 + failed:
11437 + spectrum_cs_release(link);
11438 + return -ENODEV;
11439 +} /* spectrum_cs_config */
11441 +static void
11442 +spectrum_cs_release(struct pcmcia_device *link)
11444 + struct orinoco_private *priv = link->priv;
11445 + unsigned long flags;
11447 + /* We're committed to taking the device away now, so mark the
11448 + * hardware as unavailable */
11449 + priv->hw.ops->lock_irqsave(&priv->lock, &flags);
11450 + priv->hw_unavailable++;
11451 + priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
11453 + pcmcia_disable_device(link);
11454 + if (priv->hw.iobase)
11455 + ioport_unmap(priv->hw.iobase);
11456 +} /* spectrum_cs_release */
11459 +static int
11460 +spectrum_cs_suspend(struct pcmcia_device *link)
11462 + struct orinoco_private *priv = link->priv;
11464 + /* Mark the device as stopped, to block IO until later */
11465 + orinoco_down(priv);
11467 + return 0;
11470 +static int
11471 +spectrum_cs_resume(struct pcmcia_device *link)
11473 + struct orinoco_private *priv = link->priv;
11474 + int err = orinoco_up(priv);
11476 + return err;
11480 +/********************************************************************/
11481 +/* Module initialization */
11482 +/********************************************************************/
11484 +static const struct pcmcia_device_id spectrum_cs_ids[] = {
11485 + PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
11486 + PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
11487 + PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
11488 + PCMCIA_DEVICE_NULL,
11490 +MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
11492 +static struct pcmcia_driver orinoco_driver = {
11493 + .owner = THIS_MODULE,
11494 + .name = DRIVER_NAME,
11495 + .probe = spectrum_cs_probe,
11496 + .remove = spectrum_cs_detach,
11497 + .suspend = spectrum_cs_suspend,
11498 + .resume = spectrum_cs_resume,
11499 + .id_table = spectrum_cs_ids,
11501 +module_pcmcia_driver(orinoco_driver);
11502 --- /dev/null
11503 +++ a/drivers/net/wireless/intersil/orinoco/wext.c
11504 @@ -0,0 +1,1428 @@
11505 +/* Wireless extensions support.
11507 + * See copyright notice in main.c
11508 + */
11509 +#include <linux/slab.h>
11510 +#include <linux/kernel.h>
11511 +#include <linux/if_arp.h>
11512 +#include <linux/wireless.h>
11513 +#include <linux/ieee80211.h>
11514 +#include <linux/etherdevice.h>
11515 +#include <net/iw_handler.h>
11516 +#include <net/cfg80211.h>
11517 +#include <net/cfg80211-wext.h>
11519 +#include "hermes.h"
11520 +#include "hermes_rid.h"
11521 +#include "orinoco.h"
11523 +#include "hw.h"
11524 +#include "mic.h"
11525 +#include "scan.h"
11526 +#include "main.h"
11528 +#include "wext.h"
11530 +#define MAX_RID_LEN 1024
11532 +/* Helper routine to record keys
11533 + * It is called under orinoco_lock so it may not sleep */
11534 +static int orinoco_set_key(struct orinoco_private *priv, int index,
11535 + enum orinoco_alg alg, const u8 *key, int key_len,
11536 + const u8 *seq, int seq_len)
11538 + kfree_sensitive(priv->keys[index].key);
11539 + kfree_sensitive(priv->keys[index].seq);
11541 + if (key_len) {
11542 + priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
11543 + if (!priv->keys[index].key)
11544 + goto nomem;
11545 + } else
11546 + priv->keys[index].key = NULL;
11548 + if (seq_len) {
11549 + priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
11550 + if (!priv->keys[index].seq)
11551 + goto free_key;
11552 + } else
11553 + priv->keys[index].seq = NULL;
11555 + priv->keys[index].key_len = key_len;
11556 + priv->keys[index].seq_len = seq_len;
11558 + if (key_len)
11559 + memcpy((void *)priv->keys[index].key, key, key_len);
11560 + if (seq_len)
11561 + memcpy((void *)priv->keys[index].seq, seq, seq_len);
11563 + switch (alg) {
11564 + case ORINOCO_ALG_TKIP:
11565 + priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
11566 + break;
11568 + case ORINOCO_ALG_WEP:
11569 + priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
11570 + WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
11571 + break;
11573 + case ORINOCO_ALG_NONE:
11574 + default:
11575 + priv->keys[index].cipher = 0;
11576 + break;
11579 + return 0;
11581 +free_key:
11582 + kfree(priv->keys[index].key);
11583 + priv->keys[index].key = NULL;
11585 +nomem:
11586 + priv->keys[index].key_len = 0;
11587 + priv->keys[index].seq_len = 0;
11588 + priv->keys[index].cipher = 0;
11590 + return -ENOMEM;
11593 +static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
11595 + struct orinoco_private *priv = ndev_priv(dev);
11596 + struct hermes *hw = &priv->hw;
11597 + struct iw_statistics *wstats = &priv->wstats;
11598 + int err;
11599 + unsigned long flags;
11601 + if (!netif_device_present(dev)) {
11602 + printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
11603 + dev->name);
11604 + return NULL; /* FIXME: Can we do better than this? */
11607 + /* If busy, return the old stats. Returning NULL may cause
11608 + * the interface to disappear from /proc/net/wireless */
11609 + if (orinoco_lock(priv, &flags) != 0)
11610 + return wstats;
11612 + /* We can't really wait for the tallies inquiry command to
11613 + * complete, so we just use the previous results and trigger
11614 + * a new tallies inquiry command for next time - Jean II */
11615 + /* FIXME: Really we should wait for the inquiry to come back -
11616 + * as it is the stats we give don't make a whole lot of sense.
11617 + * Unfortunately, it's not clear how to do that within the
11618 + * wireless extensions framework: I think we're in user
11619 + * context, but a lock seems to be held by the time we get in
11620 + * here so we're not safe to sleep here. */
11621 + hermes_inquire(hw, HERMES_INQ_TALLIES);
11623 + if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
11624 + memset(&wstats->qual, 0, sizeof(wstats->qual));
11625 + /* If a spy address is defined, we report stats of the
11626 + * first spy address - Jean II */
11627 + if (SPY_NUMBER(priv)) {
11628 + wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
11629 + wstats->qual.level = priv->spy_data.spy_stat[0].level;
11630 + wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
11631 + wstats->qual.updated =
11632 + priv->spy_data.spy_stat[0].updated;
11634 + } else {
11635 + struct {
11636 + __le16 qual, signal, noise, unused;
11637 + } __packed cq;
11639 + err = HERMES_READ_RECORD(hw, USER_BAP,
11640 + HERMES_RID_COMMSQUALITY, &cq);
11642 + if (!err) {
11643 + wstats->qual.qual = (int)le16_to_cpu(cq.qual);
11644 + wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
11645 + wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
11646 + wstats->qual.updated =
11647 + IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
11651 + orinoco_unlock(priv, &flags);
11652 + return wstats;
11655 +/********************************************************************/
11656 +/* Wireless extensions */
11657 +/********************************************************************/
11659 +static int orinoco_ioctl_setwap(struct net_device *dev,
11660 + struct iw_request_info *info,
11661 + union iwreq_data *wrqu,
11662 + char *extra)
11664 + struct sockaddr *ap_addr = &wrqu->ap_addr;
11665 + struct orinoco_private *priv = ndev_priv(dev);
11666 + int err = -EINPROGRESS; /* Call commit handler */
11667 + unsigned long flags;
11669 + if (orinoco_lock(priv, &flags) != 0)
11670 + return -EBUSY;
11672 + /* Enable automatic roaming - no sanity checks are needed */
11673 + if (is_zero_ether_addr(ap_addr->sa_data) ||
11674 + is_broadcast_ether_addr(ap_addr->sa_data)) {
11675 + priv->bssid_fixed = 0;
11676 + eth_zero_addr(priv->desired_bssid);
11678 + /* "off" means keep existing connection */
11679 + if (ap_addr->sa_data[0] == 0) {
11680 + __orinoco_hw_set_wap(priv);
11681 + err = 0;
11683 + goto out;
11686 + if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
11687 + printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
11688 + "support manual roaming\n",
11689 + dev->name);
11690 + err = -EOPNOTSUPP;
11691 + goto out;
11694 + if (priv->iw_mode != NL80211_IFTYPE_STATION) {
11695 + printk(KERN_WARNING "%s: Manual roaming supported only in "
11696 + "managed mode\n", dev->name);
11697 + err = -EOPNOTSUPP;
11698 + goto out;
11701 + /* Intersil firmware hangs without Desired ESSID */
11702 + if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
11703 + strlen(priv->desired_essid) == 0) {
11704 + printk(KERN_WARNING "%s: Desired ESSID must be set for "
11705 + "manual roaming\n", dev->name);
11706 + err = -EOPNOTSUPP;
11707 + goto out;
11710 + /* Finally, enable manual roaming */
11711 + priv->bssid_fixed = 1;
11712 + memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
11714 + out:
11715 + orinoco_unlock(priv, &flags);
11716 + return err;
11719 +static int orinoco_ioctl_getwap(struct net_device *dev,
11720 + struct iw_request_info *info,
11721 + union iwreq_data *wrqu,
11722 + char *extra)
11724 + struct sockaddr *ap_addr = &wrqu->ap_addr;
11725 + struct orinoco_private *priv = ndev_priv(dev);
11727 + int err = 0;
11728 + unsigned long flags;
11730 + if (orinoco_lock(priv, &flags) != 0)
11731 + return -EBUSY;
11733 + ap_addr->sa_family = ARPHRD_ETHER;
11734 + err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
11736 + orinoco_unlock(priv, &flags);
11738 + return err;
11741 +static int orinoco_ioctl_setiwencode(struct net_device *dev,
11742 + struct iw_request_info *info,
11743 + union iwreq_data *wrqu,
11744 + char *keybuf)
11746 + struct iw_point *erq = &wrqu->encoding;
11747 + struct orinoco_private *priv = ndev_priv(dev);
11748 + int index = (erq->flags & IW_ENCODE_INDEX) - 1;
11749 + int setindex = priv->tx_key;
11750 + enum orinoco_alg encode_alg = priv->encode_alg;
11751 + int restricted = priv->wep_restrict;
11752 + int err = -EINPROGRESS; /* Call commit handler */
11753 + unsigned long flags;
11755 + if (!priv->has_wep)
11756 + return -EOPNOTSUPP;
11758 + if (erq->pointer) {
11759 + /* We actually have a key to set - check its length */
11760 + if (erq->length > LARGE_KEY_SIZE)
11761 + return -E2BIG;
11763 + if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
11764 + return -E2BIG;
11767 + if (orinoco_lock(priv, &flags) != 0)
11768 + return -EBUSY;
11770 + /* Clear any TKIP key we have */
11771 + if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
11772 + (void) orinoco_clear_tkip_key(priv, setindex);
11774 + if (erq->length > 0) {
11775 + if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
11776 + index = priv->tx_key;
11778 + /* Switch on WEP if off */
11779 + if (encode_alg != ORINOCO_ALG_WEP) {
11780 + setindex = index;
11781 + encode_alg = ORINOCO_ALG_WEP;
11783 + } else {
11784 + /* Important note : if the user do "iwconfig eth0 enc off",
11785 + * we will arrive there with an index of -1. This is valid
11786 + * but need to be taken care off... Jean II */
11787 + if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
11788 + if ((index != -1) || (erq->flags == 0)) {
11789 + err = -EINVAL;
11790 + goto out;
11792 + } else {
11793 + /* Set the index : Check that the key is valid */
11794 + if (priv->keys[index].key_len == 0) {
11795 + err = -EINVAL;
11796 + goto out;
11798 + setindex = index;
11802 + if (erq->flags & IW_ENCODE_DISABLED)
11803 + encode_alg = ORINOCO_ALG_NONE;
11804 + if (erq->flags & IW_ENCODE_OPEN)
11805 + restricted = 0;
11806 + if (erq->flags & IW_ENCODE_RESTRICTED)
11807 + restricted = 1;
11809 + if (erq->pointer && erq->length > 0) {
11810 + err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
11811 + erq->length, NULL, 0);
11813 + priv->tx_key = setindex;
11815 + /* Try fast key change if connected and only keys are changed */
11816 + if ((priv->encode_alg == encode_alg) &&
11817 + (priv->wep_restrict == restricted) &&
11818 + netif_carrier_ok(dev)) {
11819 + err = __orinoco_hw_setup_wepkeys(priv);
11820 + /* No need to commit if successful */
11821 + goto out;
11824 + priv->encode_alg = encode_alg;
11825 + priv->wep_restrict = restricted;
11827 + out:
11828 + orinoco_unlock(priv, &flags);
11830 + return err;
11833 +static int orinoco_ioctl_getiwencode(struct net_device *dev,
11834 + struct iw_request_info *info,
11835 + union iwreq_data *wrqu,
11836 + char *keybuf)
11838 + struct iw_point *erq = &wrqu->encoding;
11839 + struct orinoco_private *priv = ndev_priv(dev);
11840 + int index = (erq->flags & IW_ENCODE_INDEX) - 1;
11841 + unsigned long flags;
11843 + if (!priv->has_wep)
11844 + return -EOPNOTSUPP;
11846 + if (orinoco_lock(priv, &flags) != 0)
11847 + return -EBUSY;
11849 + if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
11850 + index = priv->tx_key;
11852 + erq->flags = 0;
11853 + if (!priv->encode_alg)
11854 + erq->flags |= IW_ENCODE_DISABLED;
11855 + erq->flags |= index + 1;
11857 + if (priv->wep_restrict)
11858 + erq->flags |= IW_ENCODE_RESTRICTED;
11859 + else
11860 + erq->flags |= IW_ENCODE_OPEN;
11862 + erq->length = priv->keys[index].key_len;
11864 + memcpy(keybuf, priv->keys[index].key, erq->length);
11866 + orinoco_unlock(priv, &flags);
11867 + return 0;
11870 +static int orinoco_ioctl_setessid(struct net_device *dev,
11871 + struct iw_request_info *info,
11872 + union iwreq_data *wrqu,
11873 + char *essidbuf)
11875 + struct iw_point *erq = &wrqu->essid;
11876 + struct orinoco_private *priv = ndev_priv(dev);
11877 + unsigned long flags;
11879 + /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
11880 + * anyway... - Jean II */
11882 + /* Hum... Should not use Wireless Extension constant (may change),
11883 + * should use our own... - Jean II */
11884 + if (erq->length > IW_ESSID_MAX_SIZE)
11885 + return -E2BIG;
11887 + if (orinoco_lock(priv, &flags) != 0)
11888 + return -EBUSY;
11890 + /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
11891 + memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
11893 + /* If not ANY, get the new ESSID */
11894 + if (erq->flags)
11895 + memcpy(priv->desired_essid, essidbuf, erq->length);
11897 + orinoco_unlock(priv, &flags);
11899 + return -EINPROGRESS; /* Call commit handler */
11902 +static int orinoco_ioctl_getessid(struct net_device *dev,
11903 + struct iw_request_info *info,
11904 + union iwreq_data *wrqu,
11905 + char *essidbuf)
11907 + struct iw_point *erq = &wrqu->essid;
11908 + struct orinoco_private *priv = ndev_priv(dev);
11909 + int active;
11910 + int err = 0;
11911 + unsigned long flags;
11913 + if (netif_running(dev)) {
11914 + err = orinoco_hw_get_essid(priv, &active, essidbuf);
11915 + if (err < 0)
11916 + return err;
11917 + erq->length = err;
11918 + } else {
11919 + if (orinoco_lock(priv, &flags) != 0)
11920 + return -EBUSY;
11921 + memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
11922 + erq->length = strlen(priv->desired_essid);
11923 + orinoco_unlock(priv, &flags);
11926 + erq->flags = 1;
11928 + return 0;
11931 +static int orinoco_ioctl_setfreq(struct net_device *dev,
11932 + struct iw_request_info *info,
11933 + union iwreq_data *wrqu,
11934 + char *extra)
11936 + struct iw_freq *frq = &wrqu->freq;
11937 + struct orinoco_private *priv = ndev_priv(dev);
11938 + int chan = -1;
11939 + unsigned long flags;
11940 + int err = -EINPROGRESS; /* Call commit handler */
11942 + /* In infrastructure mode the AP sets the channel */
11943 + if (priv->iw_mode == NL80211_IFTYPE_STATION)
11944 + return -EBUSY;
11946 + if ((frq->e == 0) && (frq->m <= 1000)) {
11947 + /* Setting by channel number */
11948 + chan = frq->m;
11949 + } else {
11950 + /* Setting by frequency */
11951 + int denom = 1;
11952 + int i;
11954 + /* Calculate denominator to rescale to MHz */
11955 + for (i = 0; i < (6 - frq->e); i++)
11956 + denom *= 10;
11958 + chan = ieee80211_frequency_to_channel(frq->m / denom);
11961 + if ((chan < 1) || (chan > NUM_CHANNELS) ||
11962 + !(priv->channel_mask & (1 << (chan - 1))))
11963 + return -EINVAL;
11965 + if (orinoco_lock(priv, &flags) != 0)
11966 + return -EBUSY;
11968 + priv->channel = chan;
11969 + if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
11970 + /* Fast channel change - no commit if successful */
11971 + struct hermes *hw = &priv->hw;
11972 + err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
11973 + HERMES_TEST_SET_CHANNEL,
11974 + chan, NULL);
11976 + orinoco_unlock(priv, &flags);
11978 + return err;
11981 +static int orinoco_ioctl_getfreq(struct net_device *dev,
11982 + struct iw_request_info *info,
11983 + union iwreq_data *wrqu,
11984 + char *extra)
11986 + struct iw_freq *frq = &wrqu->freq;
11987 + struct orinoco_private *priv = ndev_priv(dev);
11988 + int tmp;
11990 + /* Locking done in there */
11991 + tmp = orinoco_hw_get_freq(priv);
11992 + if (tmp < 0)
11993 + return tmp;
11995 + frq->m = tmp * 100000;
11996 + frq->e = 1;
11998 + return 0;
12001 +static int orinoco_ioctl_getsens(struct net_device *dev,
12002 + struct iw_request_info *info,
12003 + union iwreq_data *wrqu,
12004 + char *extra)
12006 + struct iw_param *srq = &wrqu->sens;
12007 + struct orinoco_private *priv = ndev_priv(dev);
12008 + struct hermes *hw = &priv->hw;
12009 + u16 val;
12010 + int err;
12011 + unsigned long flags;
12013 + if (!priv->has_sensitivity)
12014 + return -EOPNOTSUPP;
12016 + if (orinoco_lock(priv, &flags) != 0)
12017 + return -EBUSY;
12018 + err = hermes_read_wordrec(hw, USER_BAP,
12019 + HERMES_RID_CNFSYSTEMSCALE, &val);
12020 + orinoco_unlock(priv, &flags);
12022 + if (err)
12023 + return err;
12025 + srq->value = val;
12026 + srq->fixed = 0; /* auto */
12028 + return 0;
12031 +static int orinoco_ioctl_setsens(struct net_device *dev,
12032 + struct iw_request_info *info,
12033 + union iwreq_data *wrqu,
12034 + char *extra)
12036 + struct iw_param *srq = &wrqu->sens;
12037 + struct orinoco_private *priv = ndev_priv(dev);
12038 + int val = srq->value;
12039 + unsigned long flags;
12041 + if (!priv->has_sensitivity)
12042 + return -EOPNOTSUPP;
12044 + if ((val < 1) || (val > 3))
12045 + return -EINVAL;
12047 + if (orinoco_lock(priv, &flags) != 0)
12048 + return -EBUSY;
12049 + priv->ap_density = val;
12050 + orinoco_unlock(priv, &flags);
12052 + return -EINPROGRESS; /* Call commit handler */
12055 +static int orinoco_ioctl_setrate(struct net_device *dev,
12056 + struct iw_request_info *info,
12057 + union iwreq_data *wrqu,
12058 + char *extra)
12060 + struct iw_param *rrq = &wrqu->bitrate;
12061 + struct orinoco_private *priv = ndev_priv(dev);
12062 + int ratemode;
12063 + int bitrate; /* 100s of kilobits */
12064 + unsigned long flags;
12066 + /* As the user space doesn't know our highest rate, it uses -1
12067 + * to ask us to set the highest rate. Test it using "iwconfig
12068 + * ethX rate auto" - Jean II */
12069 + if (rrq->value == -1)
12070 + bitrate = 110;
12071 + else {
12072 + if (rrq->value % 100000)
12073 + return -EINVAL;
12074 + bitrate = rrq->value / 100000;
12077 + ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed);
12079 + if (ratemode == -1)
12080 + return -EINVAL;
12082 + if (orinoco_lock(priv, &flags) != 0)
12083 + return -EBUSY;
12084 + priv->bitratemode = ratemode;
12085 + orinoco_unlock(priv, &flags);
12087 + return -EINPROGRESS;
12090 +static int orinoco_ioctl_getrate(struct net_device *dev,
12091 + struct iw_request_info *info,
12092 + union iwreq_data *wrqu,
12093 + char *extra)
12095 + struct iw_param *rrq = &wrqu->bitrate;
12096 + struct orinoco_private *priv = ndev_priv(dev);
12097 + int err = 0;
12098 + int bitrate, automatic;
12099 + unsigned long flags;
12101 + if (orinoco_lock(priv, &flags) != 0)
12102 + return -EBUSY;
12104 + orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic);
12106 + /* If the interface is running we try to find more about the
12107 + current mode */
12108 + if (netif_running(dev)) {
12109 + int act_bitrate;
12110 + int lerr;
12112 + /* Ignore errors if we can't get the actual bitrate */
12113 + lerr = orinoco_hw_get_act_bitrate(priv, &act_bitrate);
12114 + if (!lerr)
12115 + bitrate = act_bitrate;
12118 + orinoco_unlock(priv, &flags);
12120 + rrq->value = bitrate;
12121 + rrq->fixed = !automatic;
12122 + rrq->disabled = 0;
12124 + return err;
12127 +static int orinoco_ioctl_setpower(struct net_device *dev,
12128 + struct iw_request_info *info,
12129 + union iwreq_data *wrqu,
12130 + char *extra)
12132 + struct iw_param *prq = &wrqu->power;
12133 + struct orinoco_private *priv = ndev_priv(dev);
12134 + int err = -EINPROGRESS; /* Call commit handler */
12135 + unsigned long flags;
12137 + if (orinoco_lock(priv, &flags) != 0)
12138 + return -EBUSY;
12140 + if (prq->disabled) {
12141 + priv->pm_on = 0;
12142 + } else {
12143 + switch (prq->flags & IW_POWER_MODE) {
12144 + case IW_POWER_UNICAST_R:
12145 + priv->pm_mcast = 0;
12146 + priv->pm_on = 1;
12147 + break;
12148 + case IW_POWER_ALL_R:
12149 + priv->pm_mcast = 1;
12150 + priv->pm_on = 1;
12151 + break;
12152 + case IW_POWER_ON:
12153 + /* No flags : but we may have a value - Jean II */
12154 + break;
12155 + default:
12156 + err = -EINVAL;
12157 + goto out;
12160 + if (prq->flags & IW_POWER_TIMEOUT) {
12161 + priv->pm_on = 1;
12162 + priv->pm_timeout = prq->value / 1000;
12164 + if (prq->flags & IW_POWER_PERIOD) {
12165 + priv->pm_on = 1;
12166 + priv->pm_period = prq->value / 1000;
12168 + /* It's valid to not have a value if we are just toggling
12169 + * the flags... Jean II */
12170 + if (!priv->pm_on) {
12171 + err = -EINVAL;
12172 + goto out;
12176 + out:
12177 + orinoco_unlock(priv, &flags);
12179 + return err;
12182 +static int orinoco_ioctl_getpower(struct net_device *dev,
12183 + struct iw_request_info *info,
12184 + union iwreq_data *wrqu,
12185 + char *extra)
12187 + struct iw_param *prq = &wrqu->power;
12188 + struct orinoco_private *priv = ndev_priv(dev);
12189 + struct hermes *hw = &priv->hw;
12190 + int err = 0;
12191 + u16 enable, period, timeout, mcast;
12192 + unsigned long flags;
12194 + if (orinoco_lock(priv, &flags) != 0)
12195 + return -EBUSY;
12197 + err = hermes_read_wordrec(hw, USER_BAP,
12198 + HERMES_RID_CNFPMENABLED, &enable);
12199 + if (err)
12200 + goto out;
12202 + err = hermes_read_wordrec(hw, USER_BAP,
12203 + HERMES_RID_CNFMAXSLEEPDURATION, &period);
12204 + if (err)
12205 + goto out;
12207 + err = hermes_read_wordrec(hw, USER_BAP,
12208 + HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
12209 + if (err)
12210 + goto out;
12212 + err = hermes_read_wordrec(hw, USER_BAP,
12213 + HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
12214 + if (err)
12215 + goto out;
12217 + prq->disabled = !enable;
12218 + /* Note : by default, display the period */
12219 + if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
12220 + prq->flags = IW_POWER_TIMEOUT;
12221 + prq->value = timeout * 1000;
12222 + } else {
12223 + prq->flags = IW_POWER_PERIOD;
12224 + prq->value = period * 1000;
12226 + if (mcast)
12227 + prq->flags |= IW_POWER_ALL_R;
12228 + else
12229 + prq->flags |= IW_POWER_UNICAST_R;
12231 + out:
12232 + orinoco_unlock(priv, &flags);
12234 + return err;
12237 +static int orinoco_ioctl_set_encodeext(struct net_device *dev,
12238 + struct iw_request_info *info,
12239 + union iwreq_data *wrqu,
12240 + char *extra)
12242 + struct orinoco_private *priv = ndev_priv(dev);
12243 + struct iw_point *encoding = &wrqu->encoding;
12244 + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
12245 + int idx, alg = ext->alg, set_key = 1;
12246 + unsigned long flags;
12247 + int err = -EINVAL;
12249 + if (orinoco_lock(priv, &flags) != 0)
12250 + return -EBUSY;
12252 + /* Determine and validate the key index */
12253 + idx = encoding->flags & IW_ENCODE_INDEX;
12254 + if (idx) {
12255 + if ((idx < 1) || (idx > 4))
12256 + goto out;
12257 + idx--;
12258 + } else
12259 + idx = priv->tx_key;
12261 + if (encoding->flags & IW_ENCODE_DISABLED)
12262 + alg = IW_ENCODE_ALG_NONE;
12264 + if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
12265 + /* Clear any TKIP TX key we had */
12266 + (void) orinoco_clear_tkip_key(priv, priv->tx_key);
12269 + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
12270 + priv->tx_key = idx;
12271 + set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
12272 + (ext->key_len > 0)) ? 1 : 0;
12275 + if (set_key) {
12276 + /* Set the requested key first */
12277 + switch (alg) {
12278 + case IW_ENCODE_ALG_NONE:
12279 + priv->encode_alg = ORINOCO_ALG_NONE;
12280 + err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
12281 + NULL, 0, NULL, 0);
12282 + break;
12284 + case IW_ENCODE_ALG_WEP:
12285 + if (ext->key_len <= 0)
12286 + goto out;
12288 + priv->encode_alg = ORINOCO_ALG_WEP;
12289 + err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
12290 + ext->key, ext->key_len, NULL, 0);
12291 + break;
12293 + case IW_ENCODE_ALG_TKIP:
12295 + u8 *tkip_iv = NULL;
12297 + if (!priv->has_wpa ||
12298 + (ext->key_len > sizeof(struct orinoco_tkip_key)))
12299 + goto out;
12301 + priv->encode_alg = ORINOCO_ALG_TKIP;
12303 + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
12304 + tkip_iv = &ext->rx_seq[0];
12306 + err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
12307 + ext->key, ext->key_len, tkip_iv,
12308 + ORINOCO_SEQ_LEN);
12310 + err = __orinoco_hw_set_tkip_key(priv, idx,
12311 + ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
12312 + priv->keys[idx].key, priv->keys[idx].key_len,
12313 + tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
12314 + if (err)
12315 + printk(KERN_ERR "%s: Error %d setting TKIP key"
12316 + "\n", dev->name, err);
12318 + goto out;
12320 + default:
12321 + goto out;
12324 + err = -EINPROGRESS;
12325 + out:
12326 + orinoco_unlock(priv, &flags);
12328 + return err;
12331 +static int orinoco_ioctl_get_encodeext(struct net_device *dev,
12332 + struct iw_request_info *info,
12333 + union iwreq_data *wrqu,
12334 + char *extra)
12336 + struct orinoco_private *priv = ndev_priv(dev);
12337 + struct iw_point *encoding = &wrqu->encoding;
12338 + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
12339 + int idx, max_key_len;
12340 + unsigned long flags;
12341 + int err;
12343 + if (orinoco_lock(priv, &flags) != 0)
12344 + return -EBUSY;
12346 + err = -EINVAL;
12347 + max_key_len = encoding->length - sizeof(*ext);
12348 + if (max_key_len < 0)
12349 + goto out;
12351 + idx = encoding->flags & IW_ENCODE_INDEX;
12352 + if (idx) {
12353 + if ((idx < 1) || (idx > 4))
12354 + goto out;
12355 + idx--;
12356 + } else
12357 + idx = priv->tx_key;
12359 + encoding->flags = idx + 1;
12360 + memset(ext, 0, sizeof(*ext));
12362 + switch (priv->encode_alg) {
12363 + case ORINOCO_ALG_NONE:
12364 + ext->alg = IW_ENCODE_ALG_NONE;
12365 + ext->key_len = 0;
12366 + encoding->flags |= IW_ENCODE_DISABLED;
12367 + break;
12368 + case ORINOCO_ALG_WEP:
12369 + ext->alg = IW_ENCODE_ALG_WEP;
12370 + ext->key_len = min(priv->keys[idx].key_len, max_key_len);
12371 + memcpy(ext->key, priv->keys[idx].key, ext->key_len);
12372 + encoding->flags |= IW_ENCODE_ENABLED;
12373 + break;
12374 + case ORINOCO_ALG_TKIP:
12375 + ext->alg = IW_ENCODE_ALG_TKIP;
12376 + ext->key_len = min(priv->keys[idx].key_len, max_key_len);
12377 + memcpy(ext->key, priv->keys[idx].key, ext->key_len);
12378 + encoding->flags |= IW_ENCODE_ENABLED;
12379 + break;
12382 + err = 0;
12383 + out:
12384 + orinoco_unlock(priv, &flags);
12386 + return err;
12389 +static int orinoco_ioctl_set_auth(struct net_device *dev,
12390 + struct iw_request_info *info,
12391 + union iwreq_data *wrqu, char *extra)
12393 + struct orinoco_private *priv = ndev_priv(dev);
12394 + struct hermes *hw = &priv->hw;
12395 + struct iw_param *param = &wrqu->param;
12396 + unsigned long flags;
12397 + int ret = -EINPROGRESS;
12399 + if (orinoco_lock(priv, &flags) != 0)
12400 + return -EBUSY;
12402 + switch (param->flags & IW_AUTH_INDEX) {
12403 + case IW_AUTH_WPA_VERSION:
12404 + case IW_AUTH_CIPHER_PAIRWISE:
12405 + case IW_AUTH_CIPHER_GROUP:
12406 + case IW_AUTH_RX_UNENCRYPTED_EAPOL:
12407 + case IW_AUTH_PRIVACY_INVOKED:
12408 + case IW_AUTH_DROP_UNENCRYPTED:
12409 + /*
12410 + * orinoco does not use these parameters
12411 + */
12412 + break;
12414 + case IW_AUTH_MFP:
12415 + /* Management Frame Protection not supported.
12416 + * Only fail if set to required.
12417 + */
12418 + if (param->value == IW_AUTH_MFP_REQUIRED)
12419 + ret = -EINVAL;
12420 + break;
12422 + case IW_AUTH_KEY_MGMT:
12423 + /* wl_lkm implies value 2 == PSK for Hermes I
12424 + * which ties in with WEXT
12425 + * no other hints tho :(
12426 + */
12427 + priv->key_mgmt = param->value;
12428 + break;
12430 + case IW_AUTH_TKIP_COUNTERMEASURES:
12431 + /* When countermeasures are enabled, shut down the
12432 + * card; when disabled, re-enable the card. This must
12433 + * take effect immediately.
12435 + * TODO: Make sure that the EAPOL message is getting
12436 + * out before card disabled
12437 + */
12438 + if (param->value) {
12439 + priv->tkip_cm_active = 1;
12440 + ret = hermes_disable_port(hw, 0);
12441 + } else {
12442 + priv->tkip_cm_active = 0;
12443 + ret = hermes_enable_port(hw, 0);
12445 + break;
12447 + case IW_AUTH_80211_AUTH_ALG:
12448 + if (param->value & IW_AUTH_ALG_SHARED_KEY)
12449 + priv->wep_restrict = 1;
12450 + else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
12451 + priv->wep_restrict = 0;
12452 + else
12453 + ret = -EINVAL;
12454 + break;
12456 + case IW_AUTH_WPA_ENABLED:
12457 + if (priv->has_wpa) {
12458 + priv->wpa_enabled = param->value ? 1 : 0;
12459 + } else {
12460 + if (param->value)
12461 + ret = -EOPNOTSUPP;
12462 + /* else silently accept disable of WPA */
12463 + priv->wpa_enabled = 0;
12465 + break;
12467 + default:
12468 + ret = -EOPNOTSUPP;
12471 + orinoco_unlock(priv, &flags);
12472 + return ret;
12475 +static int orinoco_ioctl_get_auth(struct net_device *dev,
12476 + struct iw_request_info *info,
12477 + union iwreq_data *wrqu, char *extra)
12479 + struct orinoco_private *priv = ndev_priv(dev);
12480 + struct iw_param *param = &wrqu->param;
12481 + unsigned long flags;
12482 + int ret = 0;
12484 + if (orinoco_lock(priv, &flags) != 0)
12485 + return -EBUSY;
12487 + switch (param->flags & IW_AUTH_INDEX) {
12488 + case IW_AUTH_KEY_MGMT:
12489 + param->value = priv->key_mgmt;
12490 + break;
12492 + case IW_AUTH_TKIP_COUNTERMEASURES:
12493 + param->value = priv->tkip_cm_active;
12494 + break;
12496 + case IW_AUTH_80211_AUTH_ALG:
12497 + if (priv->wep_restrict)
12498 + param->value = IW_AUTH_ALG_SHARED_KEY;
12499 + else
12500 + param->value = IW_AUTH_ALG_OPEN_SYSTEM;
12501 + break;
12503 + case IW_AUTH_WPA_ENABLED:
12504 + param->value = priv->wpa_enabled;
12505 + break;
12507 + default:
12508 + ret = -EOPNOTSUPP;
12511 + orinoco_unlock(priv, &flags);
12512 + return ret;
12515 +static int orinoco_ioctl_set_genie(struct net_device *dev,
12516 + struct iw_request_info *info,
12517 + union iwreq_data *wrqu, char *extra)
12519 + struct orinoco_private *priv = ndev_priv(dev);
12520 + u8 *buf;
12521 + unsigned long flags;
12523 + /* cut off at IEEE80211_MAX_DATA_LEN */
12524 + if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
12525 + (wrqu->data.length && (extra == NULL)))
12526 + return -EINVAL;
12528 + if (wrqu->data.length) {
12529 + buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL);
12530 + if (buf == NULL)
12531 + return -ENOMEM;
12532 + } else
12533 + buf = NULL;
12535 + if (orinoco_lock(priv, &flags) != 0) {
12536 + kfree(buf);
12537 + return -EBUSY;
12540 + kfree(priv->wpa_ie);
12541 + priv->wpa_ie = buf;
12542 + priv->wpa_ie_len = wrqu->data.length;
12544 + if (priv->wpa_ie) {
12545 + /* Looks like wl_lkm wants to check the auth alg, and
12546 + * somehow pass it to the firmware.
12547 + * Instead it just calls the key mgmt rid
12548 + * - we do this in set auth.
12549 + */
12552 + orinoco_unlock(priv, &flags);
12553 + return 0;
12556 +static int orinoco_ioctl_get_genie(struct net_device *dev,
12557 + struct iw_request_info *info,
12558 + union iwreq_data *wrqu, char *extra)
12560 + struct orinoco_private *priv = ndev_priv(dev);
12561 + unsigned long flags;
12562 + int err = 0;
12564 + if (orinoco_lock(priv, &flags) != 0)
12565 + return -EBUSY;
12567 + if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
12568 + wrqu->data.length = 0;
12569 + goto out;
12572 + if (wrqu->data.length < priv->wpa_ie_len) {
12573 + err = -E2BIG;
12574 + goto out;
12577 + wrqu->data.length = priv->wpa_ie_len;
12578 + memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
12580 +out:
12581 + orinoco_unlock(priv, &flags);
12582 + return err;
12585 +static int orinoco_ioctl_set_mlme(struct net_device *dev,
12586 + struct iw_request_info *info,
12587 + union iwreq_data *wrqu, char *extra)
12589 + struct orinoco_private *priv = ndev_priv(dev);
12590 + struct iw_mlme *mlme = (struct iw_mlme *)extra;
12591 + unsigned long flags;
12592 + int ret = 0;
12594 + if (orinoco_lock(priv, &flags) != 0)
12595 + return -EBUSY;
12597 + switch (mlme->cmd) {
12598 + case IW_MLME_DEAUTH:
12599 + /* silently ignore */
12600 + break;
12602 + case IW_MLME_DISASSOC:
12604 + ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
12605 + mlme->reason_code);
12606 + break;
12608 + default:
12609 + ret = -EOPNOTSUPP;
12612 + orinoco_unlock(priv, &flags);
12613 + return ret;
12616 +static int orinoco_ioctl_reset(struct net_device *dev,
12617 + struct iw_request_info *info,
12618 + union iwreq_data *wrqu,
12619 + char *extra)
12621 + struct orinoco_private *priv = ndev_priv(dev);
12623 + if (!capable(CAP_NET_ADMIN))
12624 + return -EPERM;
12626 + if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
12627 + printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
12629 + /* Firmware reset */
12630 + orinoco_reset(&priv->reset_work);
12631 + } else {
12632 + printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
12634 + schedule_work(&priv->reset_work);
12637 + return 0;
12640 +static int orinoco_ioctl_setibssport(struct net_device *dev,
12641 + struct iw_request_info *info,
12642 + union iwreq_data *wrqu,
12643 + char *extra)
12646 + struct orinoco_private *priv = ndev_priv(dev);
12647 + int val = *((int *) extra);
12648 + unsigned long flags;
12650 + if (orinoco_lock(priv, &flags) != 0)
12651 + return -EBUSY;
12653 + priv->ibss_port = val;
12655 + /* Actually update the mode we are using */
12656 + set_port_type(priv);
12658 + orinoco_unlock(priv, &flags);
12659 + return -EINPROGRESS; /* Call commit handler */
12662 +static int orinoco_ioctl_getibssport(struct net_device *dev,
12663 + struct iw_request_info *info,
12664 + union iwreq_data *wrqu,
12665 + char *extra)
12667 + struct orinoco_private *priv = ndev_priv(dev);
12668 + int *val = (int *) extra;
12670 + *val = priv->ibss_port;
12671 + return 0;
12674 +static int orinoco_ioctl_setport3(struct net_device *dev,
12675 + struct iw_request_info *info,
12676 + union iwreq_data *wrqu,
12677 + char *extra)
12679 + struct orinoco_private *priv = ndev_priv(dev);
12680 + int val = *((int *) extra);
12681 + int err = 0;
12682 + unsigned long flags;
12684 + if (orinoco_lock(priv, &flags) != 0)
12685 + return -EBUSY;
12687 + switch (val) {
12688 + case 0: /* Try to do IEEE ad-hoc mode */
12689 + if (!priv->has_ibss) {
12690 + err = -EINVAL;
12691 + break;
12693 + priv->prefer_port3 = 0;
12695 + break;
12697 + case 1: /* Try to do Lucent proprietary ad-hoc mode */
12698 + if (!priv->has_port3) {
12699 + err = -EINVAL;
12700 + break;
12702 + priv->prefer_port3 = 1;
12703 + break;
12705 + default:
12706 + err = -EINVAL;
12709 + if (!err) {
12710 + /* Actually update the mode we are using */
12711 + set_port_type(priv);
12712 + err = -EINPROGRESS;
12715 + orinoco_unlock(priv, &flags);
12717 + return err;
12720 +static int orinoco_ioctl_getport3(struct net_device *dev,
12721 + struct iw_request_info *info,
12722 + union iwreq_data *wrqu,
12723 + char *extra)
12725 + struct orinoco_private *priv = ndev_priv(dev);
12726 + int *val = (int *) extra;
12728 + *val = priv->prefer_port3;
12729 + return 0;
12732 +static int orinoco_ioctl_setpreamble(struct net_device *dev,
12733 + struct iw_request_info *info,
12734 + union iwreq_data *wrqu,
12735 + char *extra)
12737 + struct orinoco_private *priv = ndev_priv(dev);
12738 + unsigned long flags;
12739 + int val;
12741 + if (!priv->has_preamble)
12742 + return -EOPNOTSUPP;
12744 + /* 802.11b has recently defined some short preamble.
12745 + * Basically, the Phy header has been reduced in size.
12746 + * This increase performance, especially at high rates
12747 + * (the preamble is transmitted at 1Mb/s), unfortunately
12748 + * this give compatibility troubles... - Jean II */
12749 + val = *((int *) extra);
12751 + if (orinoco_lock(priv, &flags) != 0)
12752 + return -EBUSY;
12754 + if (val)
12755 + priv->preamble = 1;
12756 + else
12757 + priv->preamble = 0;
12759 + orinoco_unlock(priv, &flags);
12761 + return -EINPROGRESS; /* Call commit handler */
12764 +static int orinoco_ioctl_getpreamble(struct net_device *dev,
12765 + struct iw_request_info *info,
12766 + union iwreq_data *wrqu,
12767 + char *extra)
12769 + struct orinoco_private *priv = ndev_priv(dev);
12770 + int *val = (int *) extra;
12772 + if (!priv->has_preamble)
12773 + return -EOPNOTSUPP;
12775 + *val = priv->preamble;
12776 + return 0;
12779 +/* ioctl interface to hermes_read_ltv()
12780 + * To use with iwpriv, pass the RID as the token argument, e.g.
12781 + * iwpriv get_rid [0xfc00]
12782 + * At least Wireless Tools 25 is required to use iwpriv.
12783 + * For Wireless Tools 25 and 26 append "dummy" are the end. */
12784 +static int orinoco_ioctl_getrid(struct net_device *dev,
12785 + struct iw_request_info *info,
12786 + union iwreq_data *wrqu,
12787 + char *extra)
12789 + struct iw_point *data = &wrqu->data;
12790 + struct orinoco_private *priv = ndev_priv(dev);
12791 + struct hermes *hw = &priv->hw;
12792 + int rid = data->flags;
12793 + u16 length;
12794 + int err;
12795 + unsigned long flags;
12797 + /* It's a "get" function, but we don't want users to access the
12798 + * WEP key and other raw firmware data */
12799 + if (!capable(CAP_NET_ADMIN))
12800 + return -EPERM;
12802 + if (rid < 0xfc00 || rid > 0xffff)
12803 + return -EINVAL;
12805 + if (orinoco_lock(priv, &flags) != 0)
12806 + return -EBUSY;
12808 + err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
12809 + extra);
12810 + if (err)
12811 + goto out;
12813 + data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
12814 + MAX_RID_LEN);
12816 + out:
12817 + orinoco_unlock(priv, &flags);
12818 + return err;
12822 +/* Commit handler, called after set operations */
12823 +static int orinoco_ioctl_commit(struct net_device *dev,
12824 + struct iw_request_info *info,
12825 + union iwreq_data *wrqu,
12826 + char *extra)
12828 + struct orinoco_private *priv = ndev_priv(dev);
12829 + unsigned long flags;
12830 + int err = 0;
12832 + if (!priv->open)
12833 + return 0;
12835 + if (orinoco_lock(priv, &flags) != 0)
12836 + return err;
12838 + err = orinoco_commit(priv);
12840 + orinoco_unlock(priv, &flags);
12841 + return err;
12844 +static const struct iw_priv_args orinoco_privtab[] = {
12845 + { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
12846 + { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
12847 + { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
12848 + 0, "set_port3" },
12849 + { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
12850 + "get_port3" },
12851 + { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
12852 + 0, "set_preamble" },
12853 + { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
12854 + "get_preamble" },
12855 + { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
12856 + 0, "set_ibssport" },
12857 + { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
12858 + "get_ibssport" },
12859 + { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
12860 + "get_rid" },
12865 + * Structures to export the Wireless Handlers
12866 + */
12868 +static const iw_handler orinoco_handler[] = {
12869 + IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
12870 + IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname),
12871 + IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
12872 + IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
12873 + IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode),
12874 + IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode),
12875 + IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
12876 + IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
12877 + IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange),
12878 + IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
12879 + IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
12880 + IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
12881 + IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
12882 + IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
12883 + IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
12884 + IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan),
12885 + IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan),
12886 + IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
12887 + IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
12888 + IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
12889 + IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
12890 + IW_HANDLER(SIOCSIWRTS, cfg80211_wext_siwrts),
12891 + IW_HANDLER(SIOCGIWRTS, cfg80211_wext_giwrts),
12892 + IW_HANDLER(SIOCSIWFRAG, cfg80211_wext_siwfrag),
12893 + IW_HANDLER(SIOCGIWFRAG, cfg80211_wext_giwfrag),
12894 + IW_HANDLER(SIOCGIWRETRY, cfg80211_wext_giwretry),
12895 + IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
12896 + IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
12897 + IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
12898 + IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower),
12899 + IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
12900 + IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
12901 + IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
12902 + IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
12903 + IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
12904 + IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
12905 + IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
12910 + Added typecasting since we no longer use iwreq_data -- Moustafa
12911 + */
12912 +static const iw_handler orinoco_private_handler[] = {
12913 + [0] = orinoco_ioctl_reset,
12914 + [1] = orinoco_ioctl_reset,
12915 + [2] = orinoco_ioctl_setport3,
12916 + [3] = orinoco_ioctl_getport3,
12917 + [4] = orinoco_ioctl_setpreamble,
12918 + [5] = orinoco_ioctl_getpreamble,
12919 + [6] = orinoco_ioctl_setibssport,
12920 + [7] = orinoco_ioctl_getibssport,
12921 + [9] = orinoco_ioctl_getrid,
12924 +const struct iw_handler_def orinoco_handler_def = {
12925 + .num_standard = ARRAY_SIZE(orinoco_handler),
12926 + .num_private = ARRAY_SIZE(orinoco_private_handler),
12927 + .num_private_args = ARRAY_SIZE(orinoco_privtab),
12928 + .standard = orinoco_handler,
12929 + .private = orinoco_private_handler,
12930 + .private_args = orinoco_privtab,
12931 + .get_wireless_stats = orinoco_get_wireless_stats,
12933 --- /dev/null
12934 +++ a/drivers/net/wireless/intersil/orinoco/wext.h
12935 @@ -0,0 +1,13 @@
12936 +/* Wireless extensions support.
12938 + * See copyright notice in main.c
12939 + */
12940 +#ifndef _ORINOCO_WEXT_H_
12941 +#define _ORINOCO_WEXT_H_
12943 +#include <net/iw_handler.h>
12945 +/* Structure defining all our WEXT handlers */
12946 +extern const struct iw_handler_def orinoco_handler_def;
12948 +#endif /* _ORINOCO_WEXT_H_ */