summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intersil
diff options
context:
space:
mode:
authorKalle Valo <kvalo@codeaurora.org>2015-11-18 09:57:18 +0200
committerKalle Valo <kvalo@codeaurora.org>2015-11-18 14:28:31 +0200
commit2be45b66dee080326d0f240aa4f18ef932cc3deb (patch)
tree2892a95ff9ae89065f3d554c8b72e704bdeec679 /drivers/net/wireless/intersil
parentd3466830c165a298419788b88086ea99974e63ff (diff)
orinoco: move under intersil vendor directory
Part of reorganising wireless drivers directory and Kconfig. Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/intersil')
-rw-r--r--drivers/net/wireless/intersil/Kconfig1
-rw-r--r--drivers/net/wireless/intersil/Makefile1
-rw-r--r--drivers/net/wireless/intersil/orinoco/Kconfig142
-rw-r--r--drivers/net/wireless/intersil/orinoco/Makefile17
-rw-r--r--drivers/net/wireless/intersil/orinoco/airport.c267
-rw-r--r--drivers/net/wireless/intersil/orinoco/cfg.c291
-rw-r--r--drivers/net/wireless/intersil/orinoco/cfg.h15
-rw-r--r--drivers/net/wireless/intersil/orinoco/fw.c387
-rw-r--r--drivers/net/wireless/intersil/orinoco/fw.h21
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes.c777
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes.h520
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes_dld.c477
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes_dld.h52
-rw-r--r--drivers/net/wireless/intersil/orinoco/hermes_rid.h165
-rw-r--r--drivers/net/wireless/intersil/orinoco/hw.c1356
-rw-r--r--drivers/net/wireless/intersil/orinoco/hw.h59
-rw-r--r--drivers/net/wireless/intersil/orinoco/main.c2429
-rw-r--r--drivers/net/wireless/intersil/orinoco/main.h50
-rw-r--r--drivers/net/wireless/intersil/orinoco/mic.c79
-rw-r--r--drivers/net/wireless/intersil/orinoco/mic.h22
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco.h253
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_cs.c341
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_nortel.c323
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_pci.c266
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_pci.h68
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_plx.c371
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_tmd.c246
-rw-r--r--drivers/net/wireless/intersil/orinoco/orinoco_usb.c1748
-rw-r--r--drivers/net/wireless/intersil/orinoco/scan.c251
-rw-r--r--drivers/net/wireless/intersil/orinoco/scan.h21
-rw-r--r--drivers/net/wireless/intersil/orinoco/spectrum_cs.c320
-rw-r--r--drivers/net/wireless/intersil/orinoco/wext.c1413
-rw-r--r--drivers/net/wireless/intersil/orinoco/wext.h13
33 files changed, 12762 insertions, 0 deletions
diff --git a/drivers/net/wireless/intersil/Kconfig b/drivers/net/wireless/intersil/Kconfig
index 4bc3688bfa93..2b056b6daef8 100644
--- a/drivers/net/wireless/intersil/Kconfig
+++ b/drivers/net/wireless/intersil/Kconfig
@@ -12,6 +12,7 @@ config WLAN_VENDOR_INTERSIL
if WLAN_VENDOR_INTERSIL
source "drivers/net/wireless/intersil/hostap/Kconfig"
+source "drivers/net/wireless/intersil/orinoco/Kconfig"
source "drivers/net/wireless/intersil/p54/Kconfig"
endif # WLAN_VENDOR_INTERSIL
diff --git a/drivers/net/wireless/intersil/Makefile b/drivers/net/wireless/intersil/Makefile
index 90a72830b1ae..aedb713da746 100644
--- a/drivers/net/wireless/intersil/Makefile
+++ b/drivers/net/wireless/intersil/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_HOSTAP) += hostap/
+obj-$(CONFIG_HERMES) += orinoco/
obj-$(CONFIG_P54_COMMON) += p54/
diff --git a/drivers/net/wireless/intersil/orinoco/Kconfig b/drivers/net/wireless/intersil/orinoco/Kconfig
new file mode 100644
index 000000000000..f6fa3f4e294f
--- /dev/null
+++ b/drivers/net/wireless/intersil/orinoco/Kconfig
@@ -0,0 +1,142 @@
+config HERMES
+ tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
+ depends on (PPC_PMAC || PCI || PCMCIA)
+ depends on CFG80211
+ select CFG80211_WEXT_EXPORT
+ select WIRELESS_EXT
+ select WEXT_SPY
+ select WEXT_PRIV
+ select FW_LOADER
+ select CRYPTO
+ select CRYPTO_MICHAEL_MIC
+ ---help---
+ A driver for 802.11b wireless cards based on the "Hermes" or
+ Intersil HFA384x (Prism 2) MAC controller. This includes the vast
+ majority of the PCMCIA 802.11b cards (which are nearly all rebadges)
+ - except for the Cisco/Aironet cards. Cards supported include the
+ Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco,
+ Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya,
+ IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear
+ MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel
+ IPW2011, and Symbol Spectrum24 High Rate amongst others.
+
+ This option includes the guts of the driver, but in order to
+ actually use a card you will also need to enable support for PCMCIA
+ Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below.
+
+ You will also very likely also need the Wireless Tools in order to
+ configure your card and that /etc/pcmcia/wireless.opts works :
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
+
+config HERMES_PRISM
+ bool "Support Prism 2/2.5 chipset"
+ depends on HERMES
+ ---help---
+
+ Say Y to enable support for Prism 2 and 2.5 chipsets. These
+ chipsets are better handled by the hostap driver. This driver
+ would not support WPA or firmware download for Prism chipset.
+
+ If you are not sure, say N.
+
+config HERMES_CACHE_FW_ON_INIT
+ bool "Cache Hermes firmware on driver initialisation"
+ depends on HERMES
+ default y
+ ---help---
+ Say Y to cache any firmware required by the Hermes drivers
+ on startup. The firmware will remain cached until the
+ driver is unloaded. The cache uses 64K of RAM.
+
+ Otherwise load the firmware from userspace as required. In
+ this case the driver should be unloaded and restarted
+ whenever the firmware is changed.
+
+ If you are not sure, say Y.
+
+config APPLE_AIRPORT
+ tristate "Apple Airport support (built-in)"
+ depends on PPC_PMAC && HERMES
+ help
+ Say Y here to support the Airport 802.11b wireless Ethernet hardware
+ built into the Macintosh iBook and other recent PowerPC-based
+ Macintosh machines. This is essentially a Lucent Orinoco card with
+ a non-standard interface.
+
+ This driver does not support the Airport Extreme (802.11b/g). Use
+ the BCM43xx driver for Airport Extreme cards.
+
+config PLX_HERMES
+ tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)"
+ depends on PCI && HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco) driver when used in PLX9052 based PCI adaptors. These
+ adaptors are not a full PCMCIA controller but act as a more limited
+ PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
+ 802.11b PCMCIA cards can be used in desktop machines. The Netgear
+ MA301 is such an adaptor.
+
+config TMD_HERMES
+ tristate "Hermes in TMD7160 based PCI adaptor support"
+ depends on PCI && HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco) driver when used in TMD7160 based PCI adaptors. These
+ adaptors are not a full PCMCIA controller but act as a more limited
+ PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that
+ 802.11b PCMCIA cards can be used in desktop machines.
+
+config NORTEL_HERMES
+ tristate "Nortel emobility PCI adaptor support"
+ depends on PCI && HERMES
+ help
+ Enable support for PCMCIA cards supported by the "Hermes" (aka
+ orinoco) driver when used in Nortel emobility PCI adaptors. These
+ adaptors are not full PCMCIA controllers, but act as a more limited
+ PCI <-> PCMCIA bridge.
+
+config PCI_HERMES
+ tristate "Prism 2.5 PCI 802.11b adaptor support"
+ depends on PCI && HERMES && HERMES_PRISM
+ help
+ Enable support for PCI and mini-PCI 802.11b wireless NICs based on
+ the Prism 2.5 chipset. These are true PCI cards, not the 802.11b
+ PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also
+ common. Some of the built-in wireless adaptors in laptops are of
+ this variety.
+
+config PCMCIA_HERMES
+ tristate "Hermes PCMCIA card support"
+ depends on PCMCIA && HERMES && HAS_IOPORT_MAP
+ ---help---
+ A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
+ as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
+ EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and
+ others). It should also be usable on various Prism II based cards
+ such as the Linksys, D-Link and Farallon Skyline. It should also
+ work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN.
+
+ You will very likely need the Wireless Tools in order to
+ configure your card and that /etc/pcmcia/wireless.opts works:
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+config PCMCIA_SPECTRUM
+ tristate "Symbol Spectrum24 Trilogy PCMCIA card support"
+ depends on PCMCIA && HERMES && HAS_IOPORT_MAP
+ ---help---
+
+ This is a driver for 802.11b cards using RAM-loadable Symbol
+ firmware, such as Symbol Wireless Networker LA4100, CompactFlash
+ cards by Socket Communications and Intel PRO/Wireless 2011B.
+
+ This driver requires firmware download on startup. Utilities
+ for downloading Symbol firmware are available at
+ <http://sourceforge.net/projects/orinoco/>
+
+config ORINOCO_USB
+ tristate "Agere Orinoco USB support"
+ depends on USB && HERMES
+ select FW_LOADER
+ ---help---
+ This driver is for USB versions of the Agere Orinoco card.
diff --git a/drivers/net/wireless/intersil/orinoco/Makefile b/drivers/net/wireless/intersil/orinoco/Makefile
new file mode 100644
index 000000000000..bfdefb85abcd
--- /dev/null
+++ b/drivers/net/wireless/intersil/orinoco/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the orinoco wireless device drivers.
+#
+orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o hermes_dld.o hermes.o cfg.o
+
+obj-$(CONFIG_HERMES) += orinoco.o
+obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
+obj-$(CONFIG_APPLE_AIRPORT) += airport.o
+obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
+obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
+obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
+obj-$(CONFIG_ORINOCO_USB) += orinoco_usb.o
+
+# Orinoco should be endian clean.
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/intersil/orinoco/airport.c b/drivers/net/wireless/intersil/orinoco/airport.c
new file mode 100644
index 000000000000..77e6c53040a3
--- /dev/null
+++ b/drivers/net/wireless/intersil/orinoco/airport.c
@@ -0,0 +1,267 @@
+/* airport.c
+ *
+ * A driver for "Hermes" chipset based Apple Airport wireless
+ * card.
+ *
+ * Copyright notice & release notes in file main.c
+ *
+ * Note specific to airport stub:
+ *
+ * 0.05 : first version of the new split driver
+ * 0.06 : fix possible hang on powerup, add sleep support
+ */
+
+#define DRIVER_NAME "airport"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/pmac_feature.h>
+
+#include "orinoco.h"
+
+#define AIRPORT_IO_LEN (0x1000) /* one page */
+
+struct airport {
+ struct macio_dev *mdev;
+ void __iomem *vaddr;
+ unsigned int irq;
+ int irq_requested;
+ int ndev_registered;
+};
+
+static int
+airport_suspend(struct macio_dev *mdev, pm_message_t state)
+{
+ struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
+ struct net_device *dev = priv->ndev;
+ struct airport *card = priv->card;
+ unsigned long flags;
+ int err;
+
+ printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
+
+ err = orinoco_lock(priv, &flags);
+ if (err) {
+ printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
+ dev->name);
+ return 0;
+ }
+
+ orinoco_down(priv);
+ orinoco_unlock(priv, &flags);
+
+ disable_irq(card->irq);
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
+ macio_get_of_node(mdev), 0, 0);
+
+ return 0;
+}
+
+static int
+airport_resume(struct macio_dev *mdev)
+{
+ struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
+ struct net_device *dev = priv->ndev;
+ struct airport *card = priv->card;
+ unsigned long flags;
+ int err;
+
+ printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
+
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
+ macio_get_of_node(mdev), 0, 1);
+ msleep(200);
+
+ enable_irq(card->irq);
+
+ priv->hw.ops->lock_irqsave(&priv->lock, &flags);
+ err = orinoco_up(priv);
+ priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
+
+ return err;
+}
+
+static int
+airport_detach(struct macio_dev *mdev)
+{
+ struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
+ struct airport *card = priv->card;
+
+ if (card->ndev_registered)
+ orinoco_if_del(priv);
+ card->ndev_registered = 0;
+
+ if (card->irq_requested)
+ free_irq(card->irq, priv);
+ card->irq_requested = 0;
+
+ if (card->vaddr)
+ iounmap(card->vaddr);
+ card->vaddr = NULL;
+
+ macio_release_resource(mdev, 0);
+
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
+ macio_get_of_node(mdev), 0, 0);
+ ssleep(1);
+
+ macio_set_drvdata(mdev, NULL);
+ free_orinocodev(priv);
+
+ return 0;
+}
+
+static int airport_hard_reset(struct orinoco_private *priv)
+{
+ /* It would be nice to power cycle the Airport for a real hard
+ * reset, but for some reason although it appears to
+ * re-initialize properly, it falls in a screaming heap
+ * shortly afterwards. */
+#if 0
+ struct airport *card = priv->card;
+
+ /* Vitally important. If we don't do this it seems we get an
+ * interrupt somewhere during the power cycle, since
+ * hw_unavailable is already set it doesn't get ACKed, we get
+ * into an interrupt loop and the PMU decides to turn us
+ * off. */
+ disable_irq(card->irq);
+
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
+ macio_get_of_node(card->mdev), 0, 0);
+ ssleep(1);
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
+ macio_get_of_node(card->mdev), 0, 1);
+ ssleep(1);
+
+ enable_irq(card->irq);
+ ssleep(1);
+#endif
+
+ return 0;
+}
+
+static int
+airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
+{
+ struct orinoco_private *priv;
+ struct airport *card;
+ unsigned long phys_addr;
+ struct hermes *hw;
+
+ if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
+ printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
+ return -ENODEV;
+ }
+
+ /* Allocate space for private device-specific data */
+ priv = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
+ airport_hard_reset, NULL);
+ if (!priv) {
+ printk(KERN_ERR PFX "Cannot allocate network device\n");
+ return -ENODEV;
+ }
+ card = priv->card;
+
+ hw = &priv->hw;
+ card->mdev = mdev;
+
+ if (macio_request_resource(mdev, 0, DRIVER_NAME)) {
+ printk(KERN_ERR PFX "can't request IO resource !\n");
+ free_orinocodev(priv);
+ return -EBUSY;
+ }
+
+ macio_set_drvdata(mdev, priv);
+
+ /* Setup interrupts & base address */
+ card->irq = macio_irq(mdev, 0);
+ phys_addr = macio_resource_start(mdev, 0); /* Physical address */
+ printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
+ card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
+ if (!card->vaddr) {
+ printk(KERN_ERR PFX "ioremap() failed\n");
+ goto failed;
+ }
+
+ hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
+
+ /* Power up card */
+ pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
+ macio_get_of_node(mdev), 0, 1);
+ ssleep(1);
+
+ /* Reset it before we get the interrupt */
+ hw->ops->init(hw);
+
+ if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
+ printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
+ goto failed;
+ }
+ card->irq_requested = 1;
+
+ /* Initialise the main driver */
+ if (orinoco_init(priv) != 0) {
+ printk(KERN_ERR PFX "orinoco_init() failed\n");
+ goto failed;
+ }
+
+ /* Register an interface with the stack */
+ if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
+ printk(KERN_ERR PFX "orinoco_if_add() failed\n");
+ goto failed;
+ }
+ card->ndev_registered = 1;
+ return 0;
+ failed:
+ airport_detach(mdev);
+ return -ENODEV;
+} /* airport_attach */
+
+
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+ " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
+MODULE_LICENSE("Dual MPL/GPL");
+
+static const struct of_device_id airport_match[] = {
+ {
+ .name = "radio",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, airport_match);
+
+static struct macio_driver airport_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = airport_match,
+ },
+ .probe = airport_attach,
+ .remove = airport_detach,
+ .suspend = airport_suspend,
+ .resume = airport_resume,
+};
+
+static int __init
+init_airport(void)
+{
+ printk(KERN_DEBUG "%s\n", version);
+
+ return macio_register_driver(&airport_driver);
+}
+
+static void __exit
+exit_airport(void)
+{
+ macio_unregister_driver(&airport_driver);
+}
+
+module_init(init_airport);
+module_exit(exit_airport);
diff --git a/drivers/net/wireless/intersil/orinoco/cfg.c b/drivers/net/wireless/intersil/orinoco/cfg.c
new file mode 100644
index 000000000000..0f6ea316e38e
--- /dev/null
+++ b/drivers/net/wireless/intersil/orinoco/cfg.c
@@ -0,0 +1,291 @@
+/* cfg80211 support
+ *
+ * See copyright notice in main.c
+ */
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include "hw.h"
+#include "main.h"
+#include "orinoco.h"
+
+#include "cfg.h"
+
+/* Supported bitrates. Must agree with hw.c */
+static struct ieee80211_rate orinoco_rates[] = {
+ { .bitrate = 10 },
+ { .bitrate = 20 },
+ { .bitrate = 55 },
+ { .bitrate = 110 },
+};
+
+static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
+
+/* Called after orinoco_private is allocated. */
+void orinoco_wiphy_init(struct wiphy *wiphy)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+
+ wiphy->privid = orinoco_wiphy_privid;
+
+ set_wiphy_dev(wiphy, priv->dev);
+}
+
+/* Called after firmware is initialised */
+int orinoco_wiphy_register(struct wiphy *wiphy)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int i, channels = 0;
+
+ if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
+ wiphy->max_scan_ssids = 1;
+ else
+ wiphy->max_scan_ssids = 0;
+
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ /* TODO: should we set if we only have demo ad-hoc?
+ * (priv->has_port3)
+ */
+ if (priv->has_ibss)
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
+
+ if (!priv->broken_monitor || force_monitor)
+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+
+ priv->band.bitrates = orinoco_rates;
+ priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
+
+ /* Only support channels allowed by the card EEPROM */
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ if (priv->channel_mask & (1 << i)) {
+ priv->channels[i].center_freq =
+ ieee80211_channel_to_frequency(i + 1,
+ IEEE80211_BAND_2GHZ);
+ channels++;
+ }
+ }
+ priv->band.channels = priv->channels;
+ priv->band.n_channels = channels;
+
+ wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+ i = 0;
+ if (priv->has_wep) {
+ priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
+ i++;
+
+ if (priv->has_big_wep) {
+ priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
+ i++;
+ }
+ }
+ if (priv->has_wpa) {
+ priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
+ i++;
+ }
+ wiphy->cipher_suites = priv->cipher_suites;
+ wiphy->n_cipher_suites = i;
+
+ wiphy->rts_threshold = priv->rts_thresh;
+ if (!priv->has_mwo)
+ wiphy->frag_threshold = priv->frag_thresh + 1;
+ wiphy->retry_short = priv->short_retry_limit;
+ wiphy->retry_long = priv->long_retry_limit;
+
+ return wiphy_register(wiphy);
+}
+
+static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
+ enum nl80211_iftype type, u32 *flags,
+ struct vif_params *params)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long lock;
+
+ if (orinoco_lock(priv, &lock) != 0)
+ return -EBUSY;
+
+ switch (type) {
+ case NL80211_IFTYPE_ADHOC:
+ if (!priv->has_ibss && !priv->has_port3)
+ err = -EINVAL;
+ break;
+
+ case NL80211_IFTYPE_STATION:
+ break;
+
+ case NL80211_IFTYPE_MONITOR:
+ if (priv->broken_monitor && !force_monitor) {
+ wiphy_warn(wiphy,
+ "Monitor mode support is buggy in this firmware, not enabling\n");
+ err = -EINVAL;
+ }
+ break;
+
+ default:
+ err = -EINVAL;
+ }
+
+ if (!err) {
+ priv->iw_mode = type;
+ set_port_type(priv);
+ err = orinoco_commit(priv);
+ }
+
+ orinoco_unlock(priv, &lock);
+
+ return err;
+}
+
+static int orinoco_scan(struct wiphy *wiphy,
+ struct cfg80211_scan_request *request)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err;
+
+ if (!request)
+ return -EINVAL;
+
+ if (priv->scan_request && priv->scan_request != request)
+ return -EBUSY;
+
+ priv->scan_request = request;
+
+ err = orinoco_hw_trigger_scan(priv, request->ssids);
+ /* On error the we aren't processing the request */
+ if (err)
+ priv->scan_request = NULL;
+
+ return err;
+}
+
+static int orinoco_set_monitor_channel(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int err = 0;
+ unsigned long flags;
+ int channel;
+
+ if (!chandef->chan)
+ return -EINVAL;
+
+ if (cfg80211_get_chandef_type(chandef) != NL80211_CHAN_NO_HT)
+ return -EINVAL;
+
+ if (chandef->chan->band != IEEE80211_BAND_2GHZ)
+ return -EINVAL;
+
+ channel = ieee80211_frequency_to_channel(chandef->chan->center_freq);
+
+ if ((channel < 1) || (channel > NUM_CHANNELS) ||
+ !(priv->channel_mask & (1 << (channel - 1))))
+ return -EINVAL;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ priv->channel = channel;
+ if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
+ /* Fast channel change - no commit if successful */
+ struct hermes *hw = &priv->hw;
+ err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
+ HERMES_TEST_SET_CHANNEL,
+ channel, NULL);
+ }
+ orinoco_unlock(priv, &flags);
+
+ return err;
+}
+
+static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
+{
+ struct orinoco_private *priv = wiphy_priv(wiphy);
+ int frag_value = -1;
+ int rts_value = -1;
+ int err = 0;
+
+ if (changed & WIPHY_PARAM_RETRY_SHORT) {
+ /* Setting short retry not supported */
+ err = -EINVAL;
+ }
+
+ if (changed & WIPHY_PARAM_RETRY_LONG) {
+ /* Setting long retry not supported */
+ err = -EINVAL;
+ }
+
+ if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
+ /* Set fragmentation */
+ if (priv->has_mwo) {
+ if (wiphy->frag_threshold == -1)
+ frag_value = 0;
+ else {
+ printk(KERN_WARNING "%s: Fixed fragmentation "
+ "is not supported on this firmware. "
+ "Using MWO robust instead.\n",
+ priv->ndev->name);
+ frag_value = 1;
+ }
+ } else {
+ if (wiphy->frag_threshold == -1)
+ frag_value = 2346;
+ else if ((wiphy->frag_threshold < 257) ||
+ (wiphy->frag_threshold > 2347))
+ err = -EINVAL;
+ else
+ /* cfg80211 value is 257-2347 (odd only)
+ * orinoco rid has range 256-2346 (even only) */
+ frag_value = wiphy->frag_threshold & ~0x1;
+ }
+ }
+
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+ /* Set RTS.
+ *
+ * Prism documentation suggests default of 2432,
+ * and a range of 0-3000.
+ *
+ * Current implementation uses 2347 as the default and
+ * the upper limit.
+ */
+
+ if (wiphy->rts_threshold == -1)
+ rts_value = 2347;
+ else if (wiphy->rts_threshold > 2347)
+ err = -EINVAL;
+ else
+ rts_value = wiphy->rts_threshold;
+ }
+
+ if (!err) {
+ unsigned long flags;
+
+ if (orinoco_lock(priv, &flags) != 0)
+ return -EBUSY;
+
+ if (frag_value >= 0) {
+ if (priv->has_mwo)
+ priv->mwo_robust = frag_value;
+ else
+ priv->frag_thresh = frag_value;
+ }
+ if (rts_value >= 0)
+ priv->rts_thresh = rts_value;
+
+ err = orinoco_commit(priv);
+
+ orinoco_unlock(priv, &flags);
+ }
+
+ return err;
+}
+
+const struct cfg80211_ops orinoco_cfg_ops = {
+ .change_virtual_intf = orinoco_change_vif,
+ .set_monitor_channel = orinoco_set_monitor_channel,
+ .scan = orinoco_scan,
+ .set_wiphy_params = orinoco_set_wiphy_params,
+};
diff --git a/drivers/net/wireless/intersil/orinoco/cfg.h b/drivers/net/wireless/intersil/orinoco/cfg.h
new file mode 100644
index 000000000000..3ddc96a06cd7
--- /dev/null
+++ b/drivers/net/wireless/intersil/orinoco/cfg.h
@@ -0,0 +1,15 @@
+/* cfg80211 support.
+ *
+ * See copyright notice in main.c
+ */
+#ifndef ORINOCO_CFG_H
+#define ORINOCO_CFG_H
+
+#include <net/cfg80211.h>
+
+extern const struct cfg80211_ops orinoco_cfg_ops;
+
+void orinoco_wiphy_init(struct wiphy *wiphy);
+int orinoco_wiphy_register(struct wiphy *wiphy);
+
+#endif /* ORINOCO_CFG_H */
diff --git a/drivers/net/wireless/intersil/orinoco/fw.c b/drivers/net/wireless/intersil/orinoco/fw.c
new file mode 100644
index 000000000000..400a35217644
--- /dev/null
+++ b/drivers/net/wireless/intersil/orinoco/fw.c
@@ -0,0 +1,387 @@
+/* Firmware file reading and download helpers
+ *
+ * See copyright notice in main.c
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include "hermes.h"
+#include "hermes_dld.h"
+#include "orinoco.h"
+
+#include "fw.h"
+
+/* End markers (for Symbol firmware only) */
+#define TEXT_END 0x1A /* End of text header */
+
+struct fw_info {
+ char *pri_fw;
+ char *sta_fw;
+ char *ap_fw;
+ u32 pda_addr;
+ u16 pda_size;
+};
+
+static const struct fw_info orinoco_fw[] = {
+ { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
+ { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
+ { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
+};
+MODULE_FIRMWARE("agere_sta_fw.bin");
+MODULE_FIRMWARE("agere_ap_fw.bin");
+MODULE_FIRMWARE("prism_sta_fw.bin");
+MODULE_FIRMWARE("prism_ap_fw.bin");
+MODULE_FIRMWARE("symbol_sp24t_prim_fw");
+MODULE_FIRMWARE("symbol_sp24t_sec_fw");
+
+/* Structure used to access fields in FW
+ * Make sure LE decoding macros are used
+ */
+struct orinoco_fw_header {
+ char hdr_vers[6]; /* ASCII string for header version */
+ __le16 headersize; /* Total length of header */
+ __le32 entry_point; /* NIC entry point */
+ __le32 blocks; /* Number of blocks to program */
+ __le32 block_offset; /* Offset of block data from eof header */
+ __le32 pdr_offset; /* Offset to PDR data from eof header */
+ __le32 pri_offset; /* Offset to primary plug data */
+ __le32 compat_offset; /* Offset to compatibility data*/
+ char signature[0]; /* FW signature length headersize-20 */
+} __packed;
+
+/* Check th