linux/drivers/net/wireless/orinoco.c
<<
>>
Prefs
   1/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c)
   2 *
   3 * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
   4 * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
   5 *
   6 * Current maintainers (as of 29 September 2003) are:
   7 *      Pavel Roskin <proski AT gnu.org>
   8 * and  David Gibson <hermes AT gibson.dropbear.id.au>
   9 *
  10 * (C) Copyright David Gibson, IBM Corporation 2001-2003.
  11 * Copyright (C) 2000 David Gibson, Linuxcare Australia.
  12 *      With some help from :
  13 * Copyright (C) 2001 Jean Tourrilhes, HP Labs
  14 * Copyright (C) 2001 Benjamin Herrenschmidt
  15 *
  16 * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
  17 *
  18 * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
  19 * AT fasta.fh-dortmund.de>
  20 *      http://www.stud.fh-dortmund.de/~andy/wvlan/
  21 *
  22 * The contents of this file are subject to the Mozilla Public License
  23 * Version 1.1 (the "License"); you may not use this file except in
  24 * compliance with the License. You may obtain a copy of the License
  25 * at http://www.mozilla.org/MPL/
  26 *
  27 * Software distributed under the License is distributed on an "AS IS"
  28 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  29 * the License for the specific language governing rights and
  30 * limitations under the License.
  31 *
  32 * The initial developer of the original code is David A. Hinds
  33 * <dahinds AT users.sourceforge.net>.  Portions created by David
  34 * A. Hinds are Copyright (C) 1999 David A. Hinds.  All Rights
  35 * Reserved.
  36 *
  37 * Alternatively, the contents of this file may be used under the
  38 * terms of the GNU General Public License version 2 (the "GPL"), in
  39 * which case the provisions of the GPL are applicable instead of the
  40 * above.  If you wish to allow the use of your version of this file
  41 * only under the terms of the GPL and not to allow others to use your
  42 * version of this file under the MPL, indicate your decision by
  43 * deleting the provisions above and replace them with the notice and
  44 * other provisions required by the GPL.  If you do not delete the
  45 * provisions above, a recipient may use your version of this file
  46 * under either the MPL or the GPL.  */
  47
  48/*
  49 * TODO
  50 *      o Handle de-encapsulation within network layer, provide 802.11
  51 *        headers (patch from Thomas 'Dent' Mirlacher)
  52 *      o Fix possible races in SPY handling.
  53 *      o Disconnect wireless extensions from fundamental configuration.
  54 *      o (maybe) Software WEP support (patch from Stano Meduna).
  55 *      o (maybe) Use multiple Tx buffers - driver handling queue
  56 *        rather than firmware.
  57 */
  58
  59/* Locking and synchronization:
  60 *
  61 * The basic principle is that everything is serialized through a
  62 * single spinlock, priv->lock.  The lock is used in user, bh and irq
  63 * context, so when taken outside hardirq context it should always be
  64 * taken with interrupts disabled.  The lock protects both the
  65 * hardware and the struct orinoco_private.
  66 *
  67 * Another flag, priv->hw_unavailable indicates that the hardware is
  68 * unavailable for an extended period of time (e.g. suspended, or in
  69 * the middle of a hard reset).  This flag is protected by the
  70 * spinlock.  All code which touches the hardware should check the
  71 * flag after taking the lock, and if it is set, give up on whatever
  72 * they are doing and drop the lock again.  The orinoco_lock()
  73 * function handles this (it unlocks and returns -EBUSY if
  74 * hw_unavailable is non-zero).
  75 */
  76
  77#define DRIVER_NAME "orinoco"
  78
  79#include <linux/module.h>
  80#include <linux/kernel.h>
  81#include <linux/init.h>
  82#include <linux/netdevice.h>
  83#include <linux/etherdevice.h>
  84#include <linux/ethtool.h>
  85#include <linux/if_arp.h>
  86#include <linux/wireless.h>
  87#include <net/iw_handler.h>
  88#include <net/ieee80211.h>
  89
  90#include "hermes_rid.h"
  91#include "orinoco.h"
  92
  93/********************************************************************/
  94/* Module information                                               */
  95/********************************************************************/
  96
  97MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
  98MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
  99MODULE_LICENSE("Dual MPL/GPL");
 100
 101/* Level of debugging. Used in the macros in orinoco.h */
 102#ifdef ORINOCO_DEBUG
 103int orinoco_debug = ORINOCO_DEBUG;
 104module_param(orinoco_debug, int, 0644);
 105MODULE_PARM_DESC(orinoco_debug, "Debug level");
 106EXPORT_SYMBOL(orinoco_debug);
 107#endif
 108
 109static int suppress_linkstatus; /* = 0 */
 110module_param(suppress_linkstatus, bool, 0644);
 111MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
 112static int ignore_disconnect; /* = 0 */
 113module_param(ignore_disconnect, int, 0644);
 114MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
 115
 116static int force_monitor; /* = 0 */
 117module_param(force_monitor, int, 0644);
 118MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
 119
 120/********************************************************************/
 121/* Compile time configuration and compatibility stuff               */
 122/********************************************************************/
 123
 124/* We do this this way to avoid ifdefs in the actual code */
 125#ifdef WIRELESS_SPY
 126#define SPY_NUMBER(priv)        (priv->spy_data.spy_number)
 127#else
 128#define SPY_NUMBER(priv)        0
 129#endif /* WIRELESS_SPY */
 130
 131/********************************************************************/
 132/* Internal constants                                               */
 133/********************************************************************/
 134
 135/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
 136static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
 137#define ENCAPS_OVERHEAD         (sizeof(encaps_hdr) + 2)
 138
 139#define ORINOCO_MIN_MTU         256
 140#define ORINOCO_MAX_MTU         (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
 141
 142#define SYMBOL_MAX_VER_LEN      (14)
 143#define USER_BAP                0
 144#define IRQ_BAP                 1
 145#define MAX_IRQLOOPS_PER_IRQ    10
 146#define MAX_IRQLOOPS_PER_JIFFY  (20000/HZ) /* Based on a guestimate of
 147                                            * how many events the
 148                                            * device could
 149                                            * legitimately generate */
 150#define SMALL_KEY_SIZE          5
 151#define LARGE_KEY_SIZE          13
 152#define TX_NICBUF_SIZE_BUG      1585            /* Bug in Symbol firmware */
 153
 154#define DUMMY_FID               0xFFFF
 155
 156/*#define MAX_MULTICAST(priv)   (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
 157  HERMES_MAX_MULTICAST : 0)*/
 158#define MAX_MULTICAST(priv)     (HERMES_MAX_MULTICAST)
 159
 160#define ORINOCO_INTEN           (HERMES_EV_RX | HERMES_EV_ALLOC \
 161                                 | HERMES_EV_TX | HERMES_EV_TXEXC \
 162                                 | HERMES_EV_WTERR | HERMES_EV_INFO \
 163                                 | HERMES_EV_INFDROP )
 164
 165#define MAX_RID_LEN 1024
 166
 167static const struct iw_handler_def orinoco_handler_def;
 168static const struct ethtool_ops orinoco_ethtool_ops;
 169
 170/********************************************************************/
 171/* Data tables                                                      */
 172/********************************************************************/
 173
 174/* The frequency of each channel in MHz */
 175static const long channel_frequency[] = {
 176        2412, 2417, 2422, 2427, 2432, 2437, 2442,
 177        2447, 2452, 2457, 2462, 2467, 2472, 2484
 178};
 179#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
 180
 181/* This tables gives the actual meanings of the bitrate IDs returned
 182 * by the firmware. */
 183static struct {
 184        int bitrate; /* in 100s of kilobits */
 185        int automatic;
 186        u16 agere_txratectrl;
 187        u16 intersil_txratectrl;
 188} bitrate_table[] = {
 189        {110, 1,  3, 15}, /* Entry 0 is the default */
 190        {10,  0,  1,  1},
 191        {10,  1,  1,  1},
 192        {20,  0,  2,  2},
 193        {20,  1,  6,  3},
 194        {55,  0,  4,  4},
 195        {55,  1,  7,  7},
 196        {110, 0,  5,  8},
 197};
 198#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
 199
 200/********************************************************************/
 201/* Data types                                                       */
 202/********************************************************************/
 203
 204/* Beginning of the Tx descriptor, used in TxExc handling */
 205struct hermes_txexc_data {
 206        struct hermes_tx_descriptor desc;
 207        __le16 frame_ctl;
 208        __le16 duration_id;
 209        u8 addr1[ETH_ALEN];
 210} __attribute__ ((packed));
 211
 212/* Rx frame header except compatibility 802.3 header */
 213struct hermes_rx_descriptor {
 214        /* Control */
 215        __le16 status;
 216        __le32 time;
 217        u8 silence;
 218        u8 signal;
 219        u8 rate;
 220        u8 rxflow;
 221        __le32 reserved;
 222
 223        /* 802.11 header */
 224        __le16 frame_ctl;
 225        __le16 duration_id;
 226        u8 addr1[ETH_ALEN];
 227        u8 addr2[ETH_ALEN];
 228        u8 addr3[ETH_ALEN];
 229        __le16 seq_ctl;
 230        u8 addr4[ETH_ALEN];
 231
 232        /* Data length */
 233        __le16 data_len;
 234} __attribute__ ((packed));
 235
 236/********************************************************************/
 237/* Function prototypes                                              */
 238/********************************************************************/
 239
 240static int __orinoco_program_rids(struct net_device *dev);
 241static void __orinoco_set_multicast_list(struct net_device *dev);
 242
 243/********************************************************************/
 244/* Internal helper functions                                        */
 245/********************************************************************/
 246
 247static inline void set_port_type(struct orinoco_private *priv)
 248{
 249        switch (priv->iw_mode) {
 250        case IW_MODE_INFRA:
 251                priv->port_type = 1;
 252                priv->createibss = 0;
 253                break;
 254        case IW_MODE_ADHOC:
 255                if (priv->prefer_port3) {
 256                        priv->port_type = 3;
 257                        priv->createibss = 0;
 258                } else {
 259                        priv->port_type = priv->ibss_port;
 260                        priv->createibss = 1;
 261                }
 262                break;
 263        case IW_MODE_MONITOR:
 264                priv->port_type = 3;
 265                priv->createibss = 0;
 266                break;
 267        default:
 268                printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
 269                       priv->ndev->name);
 270        }
 271}
 272
 273#define ORINOCO_MAX_BSS_COUNT   64
 274static int orinoco_bss_data_allocate(struct orinoco_private *priv)
 275{
 276        if (priv->bss_data)
 277                return 0;
 278
 279        priv->bss_data =
 280            kzalloc(ORINOCO_MAX_BSS_COUNT * sizeof(bss_element), GFP_KERNEL);
 281        if (!priv->bss_data) {
 282                printk(KERN_WARNING "Out of memory allocating beacons");
 283                return -ENOMEM;
 284        }
 285        return 0;
 286}
 287
 288static void orinoco_bss_data_free(struct orinoco_private *priv)
 289{
 290        kfree(priv->bss_data);
 291        priv->bss_data = NULL;
 292}
 293
 294static void orinoco_bss_data_init(struct orinoco_private *priv)
 295{
 296        int i;
 297
 298        INIT_LIST_HEAD(&priv->bss_free_list);
 299        INIT_LIST_HEAD(&priv->bss_list);
 300        for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
 301                list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list);
 302}
 303
 304/********************************************************************/
 305/* Device methods                                                   */
 306/********************************************************************/
 307
 308static int orinoco_open(struct net_device *dev)
 309{
 310        struct orinoco_private *priv = netdev_priv(dev);
 311        unsigned long flags;
 312        int err;
 313
 314        if (orinoco_lock(priv, &flags) != 0)
 315                return -EBUSY;
 316
 317        err = __orinoco_up(dev);
 318
 319        if (! err)
 320                priv->open = 1;
 321
 322        orinoco_unlock(priv, &flags);
 323
 324        return err;
 325}
 326
 327static int orinoco_stop(struct net_device *dev)
 328{
 329        struct orinoco_private *priv = netdev_priv(dev);
 330        int err = 0;
 331
 332        /* We mustn't use orinoco_lock() here, because we need to be
 333           able to close the interface even if hw_unavailable is set
 334           (e.g. as we're released after a PC Card removal) */
 335        spin_lock_irq(&priv->lock);
 336
 337        priv->open = 0;
 338
 339        err = __orinoco_down(dev);
 340
 341        spin_unlock_irq(&priv->lock);
 342
 343        return err;
 344}
 345
 346static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
 347{
 348        struct orinoco_private *priv = netdev_priv(dev);
 349        
 350        return &priv->stats;
 351}
 352
 353static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 354{
 355        struct orinoco_private *priv = netdev_priv(dev);
 356        hermes_t *hw = &priv->hw;
 357        struct iw_statistics *wstats = &priv->wstats;
 358        int err;
 359        unsigned long flags;
 360
 361        if (! netif_device_present(dev)) {
 362                printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
 363                       dev->name);
 364                return NULL; /* FIXME: Can we do better than this? */
 365        }
 366
 367        /* If busy, return the old stats.  Returning NULL may cause
 368         * the interface to disappear from /proc/net/wireless */
 369        if (orinoco_lock(priv, &flags) != 0)
 370                return wstats;
 371
 372        /* We can't really wait for the tallies inquiry command to
 373         * complete, so we just use the previous results and trigger
 374         * a new tallies inquiry command for next time - Jean II */
 375        /* FIXME: Really we should wait for the inquiry to come back -
 376         * as it is the stats we give don't make a whole lot of sense.
 377         * Unfortunately, it's not clear how to do that within the
 378         * wireless extensions framework: I think we're in user
 379         * context, but a lock seems to be held by the time we get in
 380         * here so we're not safe to sleep here. */
 381        hermes_inquire(hw, HERMES_INQ_TALLIES);
 382
 383        if (priv->iw_mode == IW_MODE_ADHOC) {
 384                memset(&wstats->qual, 0, sizeof(wstats->qual));
 385                /* If a spy address is defined, we report stats of the
 386                 * first spy address - Jean II */
 387                if (SPY_NUMBER(priv)) {
 388                        wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
 389                        wstats->qual.level = priv->spy_data.spy_stat[0].level;
 390                        wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
 391                        wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
 392                }
 393        } else {
 394                struct {
 395                        __le16 qual, signal, noise, unused;
 396                } __attribute__ ((packed)) cq;
 397
 398                err = HERMES_READ_RECORD(hw, USER_BAP,
 399                                         HERMES_RID_COMMSQUALITY, &cq);
 400
 401                if (!err) {
 402                        wstats->qual.qual = (int)le16_to_cpu(cq.qual);
 403                        wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
 404                        wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
 405                        wstats->qual.updated = 7;
 406                }
 407        }
 408
 409        orinoco_unlock(priv, &flags);
 410        return wstats;
 411}
 412
 413static void orinoco_set_multicast_list(struct net_device *dev)
 414{
 415        struct orinoco_private *priv = netdev_priv(dev);
 416        unsigned long flags;
 417
 418        if (orinoco_lock(priv, &flags) != 0) {
 419                printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
 420                       "called when hw_unavailable\n", dev->name);
 421                return;
 422        }
 423
 424        __orinoco_set_multicast_list(dev);
 425        orinoco_unlock(priv, &flags);
 426}
 427
 428static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
 429{
 430        struct orinoco_private *priv = netdev_priv(dev);
 431
 432        if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
 433                return -EINVAL;
 434
 435        if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
 436             (priv->nicbuf_size - ETH_HLEN) )
 437                return -EINVAL;
 438
 439        dev->mtu = new_mtu;
 440
 441        return 0;
 442}
 443
 444/********************************************************************/
 445/* Tx path                                                          */
 446/********************************************************************/
 447
 448static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 449{
 450        struct orinoco_private *priv = netdev_priv(dev);
 451        struct net_device_stats *stats = &priv->stats;
 452        hermes_t *hw = &priv->hw;
 453        int err = 0;
 454        u16 txfid = priv->txfid;
 455        struct ethhdr *eh;
 456        int data_off;
 457        struct hermes_tx_descriptor desc;
 458        unsigned long flags;
 459
 460        if (! netif_running(dev)) {
 461                printk(KERN_ERR "%s: Tx on stopped device!\n",
 462                       dev->name);
 463                return NETDEV_TX_BUSY;
 464        }
 465        
 466        if (netif_queue_stopped(dev)) {
 467                printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
 468                       dev->name);
 469                return NETDEV_TX_BUSY;
 470        }
 471        
 472        if (orinoco_lock(priv, &flags) != 0) {
 473                printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
 474                       dev->name);
 475                return NETDEV_TX_BUSY;
 476        }
 477
 478        if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
 479                /* Oops, the firmware hasn't established a connection,
 480                   silently drop the packet (this seems to be the
 481                   safest approach). */
 482                goto drop;
 483        }
 484
 485        /* Check packet length */
 486        if (skb->len < ETH_HLEN)
 487                goto drop;
 488
 489        eh = (struct ethhdr *)skb->data;
 490
 491        memset(&desc, 0, sizeof(desc));
 492        desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
 493        err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
 494        if (err) {
 495                if (net_ratelimit())
 496                        printk(KERN_ERR "%s: Error %d writing Tx descriptor "
 497                               "to BAP\n", dev->name, err);
 498                goto busy;
 499        }
 500
 501        /* Clear the 802.11 header and data length fields - some
 502         * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
 503         * if this isn't done. */
 504        hermes_clear_words(hw, HERMES_DATA0,
 505                           HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
 506
 507        /* Encapsulate Ethernet-II frames */
 508        if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
 509                struct header_struct {
 510                        struct ethhdr eth;      /* 802.3 header */
 511                        u8 encap[6];            /* 802.2 header */
 512                } __attribute__ ((packed)) hdr;
 513
 514                /* Strip destination and source from the data */
 515                skb_pull(skb, 2 * ETH_ALEN);
 516                data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
 517
 518                /* And move them to a separate header */
 519                memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
 520                hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
 521                memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
 522
 523                err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
 524                                        txfid, HERMES_802_3_OFFSET);
 525                if (err) {
 526                        if (net_ratelimit())
 527                                printk(KERN_ERR "%s: Error %d writing packet "
 528                                       "header to BAP\n", dev->name, err);
 529                        goto busy;
 530                }
 531        } else { /* IEEE 802.3 frame */
 532                data_off = HERMES_802_3_OFFSET;
 533        }
 534
 535        err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
 536                                txfid, data_off);
 537        if (err) {
 538                printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
 539                       dev->name, err);
 540                goto busy;
 541        }
 542
 543        /* Finally, we actually initiate the send */
 544        netif_stop_queue(dev);
 545
 546        err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
 547                                txfid, NULL);
 548        if (err) {
 549                netif_start_queue(dev);
 550                if (net_ratelimit())
 551                        printk(KERN_ERR "%s: Error %d transmitting packet\n",
 552                                dev->name, err);
 553                goto busy;
 554        }
 555
 556        dev->trans_start = jiffies;
 557        stats->tx_bytes += data_off + skb->len;
 558        goto ok;
 559
 560 drop:
 561        stats->tx_errors++;
 562        stats->tx_dropped++;
 563
 564 ok:
 565        orinoco_unlock(priv, &flags);
 566        dev_kfree_skb(skb);
 567        return NETDEV_TX_OK;
 568
 569 busy:
 570        if (err == -EIO)
 571                schedule_work(&priv->reset_work);
 572        orinoco_unlock(priv, &flags);
 573        return NETDEV_TX_BUSY;
 574}
 575
 576static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
 577{
 578        struct orinoco_private *priv = netdev_priv(dev);
 579        u16 fid = hermes_read_regn(hw, ALLOCFID);
 580
 581        if (fid != priv->txfid) {
 582                if (fid != DUMMY_FID)
 583                        printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
 584                               dev->name, fid);
 585                return;
 586        }
 587
 588        hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
 589}
 590
 591static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
 592{
 593        struct orinoco_private *priv = netdev_priv(dev);
 594        struct net_device_stats *stats = &priv->stats;
 595
 596        stats->tx_packets++;
 597
 598        netif_wake_queue(dev);
 599
 600        hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 601}
 602
 603static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
 604{
 605        struct orinoco_private *priv = netdev_priv(dev);
 606        struct net_device_stats *stats = &priv->stats;
 607        u16 fid = hermes_read_regn(hw, TXCOMPLFID);
 608        u16 status;
 609        struct hermes_txexc_data hdr;
 610        int err = 0;
 611
 612        if (fid == DUMMY_FID)
 613                return; /* Nothing's really happened */
 614
 615        /* Read part of the frame header - we need status and addr1 */
 616        err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
 617                               sizeof(struct hermes_txexc_data),
 618                               fid, 0);
 619
 620        hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 621        stats->tx_errors++;
 622
 623        if (err) {
 624                printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
 625                       "(FID=%04X error %d)\n",
 626                       dev->name, fid, err);
 627                return;
 628        }
 629        
 630        DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
 631              err, fid);
 632    
 633        /* We produce a TXDROP event only for retry or lifetime
 634         * exceeded, because that's the only status that really mean
 635         * that this particular node went away.
 636         * Other errors means that *we* screwed up. - Jean II */
 637        status = le16_to_cpu(hdr.desc.status);
 638        if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
 639                union iwreq_data        wrqu;
 640
 641                /* Copy 802.11 dest address.
 642                 * We use the 802.11 header because the frame may
 643                 * not be 802.3 or may be mangled...
 644                 * In Ad-Hoc mode, it will be the node address.
 645                 * In managed mode, it will be most likely the AP addr
 646                 * User space will figure out how to convert it to
 647                 * whatever it needs (IP address or else).
 648                 * - Jean II */
 649                memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
 650                wrqu.addr.sa_family = ARPHRD_ETHER;
 651
 652                /* Send event to user space */
 653                wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
 654        }
 655
 656        netif_wake_queue(dev);
 657}
 658
 659static void orinoco_tx_timeout(struct net_device *dev)
 660{
 661        struct orinoco_private *priv = netdev_priv(dev);
 662        struct net_device_stats *stats = &priv->stats;
 663        struct hermes *hw = &priv->hw;
 664
 665        printk(KERN_WARNING "%s: Tx timeout! "
 666               "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
 667               dev->name, hermes_read_regn(hw, ALLOCFID),
 668               hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
 669
 670        stats->tx_errors++;
 671
 672        schedule_work(&priv->reset_work);
 673}
 674
 675/********************************************************************/
 676/* Rx path (data frames)                                            */
 677/********************************************************************/
 678
 679/* Does the frame have a SNAP header indicating it should be
 680 * de-encapsulated to Ethernet-II? */
 681static inline int is_ethersnap(void *_hdr)
 682{
 683        u8 *hdr = _hdr;
 684
 685        /* We de-encapsulate all packets which, a) have SNAP headers
 686         * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
 687         * and where b) the OUI of the SNAP header is 00:00:00 or
 688         * 00:00:f8 - we need both because different APs appear to use
 689         * different OUIs for some reason */
 690        return (memcmp(hdr, &encaps_hdr, 5) == 0)
 691                && ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );
 692}
 693
 694static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
 695                                      int level, int noise)
 696{
 697        struct iw_quality wstats;
 698        wstats.level = level - 0x95;
 699        wstats.noise = noise - 0x95;
 700        wstats.qual = (level > noise) ? (level - noise) : 0;
 701        wstats.updated = 7;
 702        /* Update spy records */
 703        wireless_spy_update(dev, mac, &wstats);
 704}
 705
 706static void orinoco_stat_gather(struct net_device *dev,
 707                                struct sk_buff *skb,
 708                                struct hermes_rx_descriptor *desc)
 709{
 710        struct orinoco_private *priv = netdev_priv(dev);
 711
 712        /* Using spy support with lots of Rx packets, like in an
 713         * infrastructure (AP), will really slow down everything, because
 714         * the MAC address must be compared to each entry of the spy list.
 715         * If the user really asks for it (set some address in the
 716         * spy list), we do it, but he will pay the price.
 717         * Note that to get here, you need both WIRELESS_SPY
 718         * compiled in AND some addresses in the list !!!
 719         */
 720        /* Note : gcc will optimise the whole section away if
 721         * WIRELESS_SPY is not defined... - Jean II */
 722        if (SPY_NUMBER(priv)) {
 723                orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN,
 724                                   desc->signal, desc->silence);
 725        }
 726}
 727
 728/*
 729 * orinoco_rx_monitor - handle received monitor frames.
 730 *
 731 * Arguments:
 732 *      dev             network device
 733 *      rxfid           received FID
 734 *      desc            rx descriptor of the frame
 735 *
 736 * Call context: interrupt
 737 */
 738static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
 739                               struct hermes_rx_descriptor *desc)
 740{
 741        u32 hdrlen = 30;        /* return full header by default */
 742        u32 datalen = 0;
 743        u16 fc;
 744        int err;
 745        int len;
 746        struct sk_buff *skb;
 747        struct orinoco_private *priv = netdev_priv(dev);
 748        struct net_device_stats *stats = &priv->stats;
 749        hermes_t *hw = &priv->hw;
 750
 751        len = le16_to_cpu(desc->data_len);
 752
 753        /* Determine the size of the header and the data */
 754        fc = le16_to_cpu(desc->frame_ctl);
 755        switch (fc & IEEE80211_FCTL_FTYPE) {
 756        case IEEE80211_FTYPE_DATA:
 757                if ((fc & IEEE80211_FCTL_TODS)
 758                    && (fc & IEEE80211_FCTL_FROMDS))
 759                        hdrlen = 30;
 760                else
 761                        hdrlen = 24;
 762                datalen = len;
 763                break;
 764        case IEEE80211_FTYPE_MGMT:
 765                hdrlen = 24;
 766                datalen = len;
 767                break;
 768        case IEEE80211_FTYPE_CTL:
 769                switch (fc & IEEE80211_FCTL_STYPE) {
 770                case IEEE80211_STYPE_PSPOLL:
 771                case IEEE80211_STYPE_RTS:
 772                case IEEE80211_STYPE_CFEND:
 773                case IEEE80211_STYPE_CFENDACK:
 774                        hdrlen = 16;
 775                        break;
 776                case IEEE80211_STYPE_CTS:
 777                case IEEE80211_STYPE_ACK:
 778                        hdrlen = 10;
 779                        break;
 780                }
 781                break;
 782        default:
 783                /* Unknown frame type */
 784                break;
 785        }
 786
 787        /* sanity check the length */
 788        if (datalen > IEEE80211_DATA_LEN + 12) {
 789                printk(KERN_DEBUG "%s: oversized monitor frame, "
 790                       "data length = %d\n", dev->name, datalen);
 791                stats->rx_length_errors++;
 792                goto update_stats;
 793        }
 794
 795        skb = dev_alloc_skb(hdrlen + datalen);
 796        if (!skb) {
 797                printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
 798                       dev->name);
 799                goto update_stats;
 800        }
 801
 802        /* Copy the 802.11 header to the skb */
 803        memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
 804        skb_reset_mac_header(skb);
 805
 806        /* If any, copy the data from the card to the skb */
 807        if (datalen > 0) {
 808                err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
 809                                       ALIGN(datalen, 2), rxfid,
 810                                       HERMES_802_2_OFFSET);
 811                if (err) {
 812                        printk(KERN_ERR "%s: error %d reading monitor frame\n",
 813                               dev->name, err);
 814                        goto drop;
 815                }
 816        }
 817
 818        skb->dev = dev;
 819        skb->ip_summed = CHECKSUM_NONE;
 820        skb->pkt_type = PACKET_OTHERHOST;
 821        skb->protocol = __constant_htons(ETH_P_802_2);
 822        
 823        dev->last_rx = jiffies;
 824        stats->rx_packets++;
 825        stats->rx_bytes += skb->len;
 826
 827        netif_rx(skb);
 828        return;
 829
 830 drop:
 831        dev_kfree_skb_irq(skb);
 832 update_stats:
 833        stats->rx_errors++;
 834        stats->rx_dropped++;
 835}
 836
 837static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
 838{
 839        struct orinoco_private *priv = netdev_priv(dev);
 840        struct net_device_stats *stats = &priv->stats;
 841        struct iw_statistics *wstats = &priv->wstats;
 842        struct sk_buff *skb = NULL;
 843        u16 rxfid, status, fc;
 844        int length;
 845        struct hermes_rx_descriptor desc;
 846        struct ethhdr *hdr;
 847        int err;
 848
 849        rxfid = hermes_read_regn(hw, RXFID);
 850
 851        err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
 852                               rxfid, 0);
 853        if (err) {
 854                printk(KERN_ERR "%s: error %d reading Rx descriptor. "
 855                       "Frame dropped.\n", dev->name, err);
 856                goto update_stats;
 857        }
 858
 859        status = le16_to_cpu(desc.status);
 860
 861        if (status & HERMES_RXSTAT_BADCRC) {
 862                DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
 863                      dev->name);
 864                stats->rx_crc_errors++;
 865                goto update_stats;
 866        }
 867
 868        /* Handle frames in monitor mode */
 869        if (priv->iw_mode == IW_MODE_MONITOR) {
 870                orinoco_rx_monitor(dev, rxfid, &desc);
 871                return;
 872        }
 873
 874        if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
 875                DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
 876                      dev->name);
 877                wstats->discard.code++;
 878                goto update_stats;
 879        }
 880
 881        length = le16_to_cpu(desc.data_len);
 882        fc = le16_to_cpu(desc.frame_ctl);
 883
 884        /* Sanity checks */
 885        if (length < 3) { /* No for even an 802.2 LLC header */
 886                /* At least on Symbol firmware with PCF we get quite a
 887                   lot of these legitimately - Poll frames with no
 888                   data. */
 889                return;
 890        }
 891        if (length > IEEE80211_DATA_LEN) {
 892                printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
 893                       dev->name, length);
 894                stats->rx_length_errors++;
 895                goto update_stats;
 896        }
 897
 898        /* We need space for the packet data itself, plus an ethernet
 899           header, plus 2 bytes so we can align the IP header on a
 900           32bit boundary, plus 1 byte so we can read in odd length
 901           packets from the card, which has an IO granularity of 16
 902           bits */  
 903        skb = dev_alloc_skb(length+ETH_HLEN+2+1);
 904        if (!skb) {
 905                printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
 906                       dev->name);
 907                goto update_stats;
 908        }
 909
 910        /* We'll prepend the header, so reserve space for it.  The worst
 911           case is no decapsulation, when 802.3 header is prepended and
 912           nothing is removed.  2 is for aligning the IP header.  */
 913        skb_reserve(skb, ETH_HLEN + 2);
 914
 915        err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
 916                               ALIGN(length, 2), rxfid,
 917                               HERMES_802_2_OFFSET);
 918        if (err) {
 919                printk(KERN_ERR "%s: error %d reading frame. "
 920                       "Frame dropped.\n", dev->name, err);
 921                goto drop;
 922        }
 923
 924        /* Handle decapsulation
 925         * In most cases, the firmware tell us about SNAP frames.
 926         * For some reason, the SNAP frames sent by LinkSys APs
 927         * are not properly recognised by most firmwares.
 928         * So, check ourselves */
 929        if (length >= ENCAPS_OVERHEAD &&
 930            (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
 931             ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
 932             is_ethersnap(skb->data))) {
 933                /* These indicate a SNAP within 802.2 LLC within
 934                   802.11 frame which we'll need to de-encapsulate to
 935                   the original EthernetII frame. */
 936                hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
 937        } else {
 938                /* 802.3 frame - prepend 802.3 header as is */
 939                hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
 940                hdr->h_proto = htons(length);
 941        }
 942        memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
 943        if (fc & IEEE80211_FCTL_FROMDS)
 944                memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
 945        else
 946                memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
 947
 948        dev->last_rx = jiffies;
 949        skb->protocol = eth_type_trans(skb, dev);
 950        skb->ip_summed = CHECKSUM_NONE;
 951        if (fc & IEEE80211_FCTL_TODS)
 952                skb->pkt_type = PACKET_OTHERHOST;
 953        
 954        /* Process the wireless stats if needed */
 955        orinoco_stat_gather(dev, skb, &desc);
 956
 957        /* Pass the packet to the networking stack */
 958        netif_rx(skb);
 959        stats->rx_packets++;
 960        stats->rx_bytes += length;
 961
 962        return;
 963
 964 drop:  
 965        dev_kfree_skb_irq(skb);
 966 update_stats:
 967        stats->rx_errors++;
 968        stats->rx_dropped++;
 969}
 970
 971/********************************************************************/
 972/* Rx path (info frames)                                            */
 973/********************************************************************/
 974
 975static void print_linkstatus(struct net_device *dev, u16 status)
 976{
 977        char * s;
 978
 979        if (suppress_linkstatus)
 980                return;
 981
 982        switch (status) {
 983        case HERMES_LINKSTATUS_NOT_CONNECTED:
 984                s = "Not Connected";
 985                break;
 986        case HERMES_LINKSTATUS_CONNECTED:
 987                s = "Connected";
 988                break;
 989        case HERMES_LINKSTATUS_DISCONNECTED:
 990                s = "Disconnected";
 991                break;
 992        case HERMES_LINKSTATUS_AP_CHANGE:
 993                s = "AP Changed";
 994                break;
 995        case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
 996                s = "AP Out of Range";
 997                break;
 998        case HERMES_LINKSTATUS_AP_IN_RANGE:
 999                s = "AP In Range";
1000                break;
1001        case HERMES_LINKSTATUS_ASSOC_FAILED:
1002                s = "Association Failed";
1003                break;
1004        default:
1005                s = "UNKNOWN";
1006        }
1007        
1008        printk(KERN_INFO "%s: New link status: %s (%04x)\n",
1009               dev->name, s, status);
1010}
1011
1012/* Search scan results for requested BSSID, join it if found */
1013static void orinoco_join_ap(struct work_struct *work)
1014{
1015        struct orinoco_private *priv =
1016                container_of(work, struct orinoco_private, join_work);
1017        struct net_device *dev = priv->ndev;
1018        struct hermes *hw = &priv->hw;
1019        int err;
1020        unsigned long flags;
1021        struct join_req {
1022                u8 bssid[ETH_ALEN];
1023                __le16 channel;
1024        } __attribute__ ((packed)) req;
1025        const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
1026        struct prism2_scan_apinfo *atom = NULL;
1027        int offset = 4;
1028        int found = 0;
1029        u8 *buf;
1030        u16 len;
1031
1032        /* Allocate buffer for scan results */
1033        buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
1034        if (! buf)
1035                return;
1036
1037        if (orinoco_lock(priv, &flags) != 0)
1038                goto fail_lock;
1039
1040        /* Sanity checks in case user changed something in the meantime */
1041        if (! priv->bssid_fixed)
1042                goto out;
1043
1044        if (strlen(priv->desired_essid) == 0)
1045                goto out;
1046
1047        /* Read scan results from the firmware */
1048        err = hermes_read_ltv(hw, USER_BAP,
1049                              HERMES_RID_SCANRESULTSTABLE,
1050                              MAX_SCAN_LEN, &len, buf);
1051        if (err) {
1052                printk(KERN_ERR "%s: Cannot read scan results\n",
1053                       dev->name);
1054                goto out;
1055        }
1056
1057        len = HERMES_RECLEN_TO_BYTES(len);
1058
1059        /* Go through the scan results looking for the channel of the AP
1060         * we were requested to join */
1061        for (; offset + atom_len <= len; offset += atom_len) {
1062                atom = (struct prism2_scan_apinfo *) (buf + offset);
1063                if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
1064                        found = 1;
1065                        break;
1066                }
1067        }
1068
1069        if (! found) {
1070                DEBUG(1, "%s: Requested AP not found in scan results\n",
1071                      dev->name);
1072                goto out;
1073        }
1074
1075        memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
1076        req.channel = atom->channel;    /* both are little-endian */
1077        err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
1078                                  &req);
1079        if (err)
1080                printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
1081
1082 out:
1083        orinoco_unlock(priv, &flags);
1084
1085 fail_lock:
1086        kfree(buf);
1087}
1088
1089/* Send new BSSID to userspace */
1090static void orinoco_send_wevents(struct work_struct *work)
1091{
1092        struct orinoco_private *priv =
1093                container_of(work, struct orinoco_private, wevent_work);
1094        struct net_device *dev = priv->ndev;
1095        struct hermes *hw = &priv->hw;
1096        union iwreq_data wrqu;
1097        int err;
1098        unsigned long flags;
1099
1100        if (orinoco_lock(priv, &flags) != 0)
1101                return;
1102
1103        err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
1104                              ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
1105        if (err != 0)
1106                goto out;
1107
1108        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1109
1110        /* Send event to user space */
1111        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
1112
1113 out:
1114        orinoco_unlock(priv, &flags);
1115}
1116
1117
1118static inline void orinoco_clear_scan_results(struct orinoco_private *priv,
1119                                              unsigned long scan_age)
1120{
1121        bss_element *bss;
1122        bss_element *tmp_bss;
1123
1124        /* Blow away current list of scan results */
1125        list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
1126                if (!scan_age ||
1127                    time_after(jiffies, bss->last_scanned + scan_age)) {
1128                        list_move_tail(&bss->list, &priv->bss_free_list);
1129                        /* Don't blow away ->list, just BSS data */
1130                        memset(bss, 0, sizeof(bss->bss));
1131                        bss->last_scanned = 0;
1132                }
1133        }
1134}
1135
1136static int orinoco_process_scan_results(struct net_device *dev,
1137                                        unsigned char *buf,
1138                                        int len)
1139{
1140        struct orinoco_private *priv = netdev_priv(dev);
1141        int                     offset;         /* In the scan data */
1142        union hermes_scan_info *atom;
1143        int                     atom_len;
1144
1145        switch (priv->firmware_type) {
1146        case FIRMWARE_TYPE_AGERE:
1147                atom_len = sizeof(struct agere_scan_apinfo);
1148                offset = 0;
1149                break;
1150        case FIRMWARE_TYPE_SYMBOL:
1151                /* Lack of documentation necessitates this hack.
1152                 * Different firmwares have 68 or 76 byte long atoms.
1153                 * We try modulo first.  If the length divides by both,
1154                 * we check what would be the channel in the second
1155                 * frame for a 68-byte atom.  76-byte atoms have 0 there.
1156                 * Valid channel cannot be 0.  */
1157                if (len % 76)
1158                        atom_len = 68;
1159                else if (len % 68)
1160                        atom_len = 76;
1161                else if (len >= 1292 && buf[68] == 0)
1162                        atom_len = 76;
1163                else
1164                        atom_len = 68;
1165                offset = 0;
1166                break;
1167        case FIRMWARE_TYPE_INTERSIL:
1168                offset = 4;
1169                if (priv->has_hostscan) {
1170                        atom_len = le16_to_cpup((__le16 *)buf);
1171                        /* Sanity check for atom_len */
1172                        if (atom_len < sizeof(struct prism2_scan_apinfo)) {
1173                                printk(KERN_ERR "%s: Invalid atom_len in scan "
1174                                       "data: %d\n", dev->name, atom_len);
1175                                return -EIO;
1176                        }
1177                } else
1178                        atom_len = offsetof(struct prism2_scan_apinfo, atim);
1179                break;
1180        default:
1181                return -EOPNOTSUPP;
1182        }
1183
1184        /* Check that we got an whole number of atoms */
1185        if ((len - offset) % atom_len) {
1186                printk(KERN_ERR "%s: Unexpected scan data length %d, "
1187                       "atom_len %d, offset %d\n", dev->name, len,
1188                       atom_len, offset);
1189                return -EIO;
1190        }
1191
1192        orinoco_clear_scan_results(priv, msecs_to_jiffies(15000));
1193
1194        /* Read the entries one by one */
1195        for (; offset + atom_len <= len; offset += atom_len) {
1196                int found = 0;
1197                bss_element *bss = NULL;
1198
1199                /* Get next atom */
1200                atom = (union hermes_scan_info *) (buf + offset);
1201
1202                /* Try to update an existing bss first */
1203                list_for_each_entry(bss, &priv->bss_list, list) {
1204                        if (compare_ether_addr(bss->bss.a.bssid, atom->a.bssid))
1205                                continue;
1206                        if (le16_to_cpu(bss->bss.a.essid_len) !=
1207                              le16_to_cpu(atom->a.essid_len))
1208                                continue;
1209                        if (memcmp(bss->bss.a.essid, atom->a.essid,
1210                              le16_to_cpu(atom->a.essid_len)))
1211                                continue;
1212                        found = 1;
1213                        break;
1214                }
1215
1216                /* Grab a bss off the free list */
1217                if (!found && !list_empty(&priv->bss_free_list)) {
1218                        bss = list_entry(priv->bss_free_list.next,
1219                                         bss_element, list);
1220                        list_del(priv->bss_free_list.next);
1221
1222                        list_add_tail(&bss->list, &priv->bss_list);
1223                }
1224
1225                if (bss) {
1226                        /* Always update the BSS to get latest beacon info */
1227                        memcpy(&bss->bss, atom, sizeof(bss->bss));
1228                        bss->last_scanned = jiffies;
1229                }
1230        }
1231
1232        return 0;
1233}
1234
1235static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1236{
1237        struct orinoco_private *priv = netdev_priv(dev);
1238        u16 infofid;
1239        struct {
1240                __le16 len;
1241                __le16 type;
1242        } __attribute__ ((packed)) info;
1243        int len, type;
1244        int err;
1245
1246        /* This is an answer to an INQUIRE command that we did earlier,
1247         * or an information "event" generated by the card
1248         * The controller return to us a pseudo frame containing
1249         * the information in question - Jean II */
1250        infofid = hermes_read_regn(hw, INFOFID);
1251
1252        /* Read the info frame header - don't try too hard */
1253        err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
1254                               infofid, 0);
1255        if (err) {
1256                printk(KERN_ERR "%s: error %d reading info frame. "
1257                       "Frame dropped.\n", dev->name, err);
1258                return;
1259        }
1260        
1261        len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
1262        type = le16_to_cpu(info.type);
1263
1264        switch (type) {
1265        case HERMES_INQ_TALLIES: {
1266                struct hermes_tallies_frame tallies;
1267                struct iw_statistics *wstats = &priv->wstats;
1268                
1269                if (len > sizeof(tallies)) {
1270                        printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
1271                               dev->name, len);
1272                        len = sizeof(tallies);
1273                }
1274                
1275                err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
1276                                       infofid, sizeof(info));
1277                if (err)
1278                        break;
1279                
1280                /* Increment our various counters */
1281                /* wstats->discard.nwid - no wrong BSSID stuff */
1282                wstats->discard.code +=
1283                        le16_to_cpu(tallies.RxWEPUndecryptable);
1284                if (len == sizeof(tallies))  
1285                        wstats->discard.code +=
1286                                le16_to_cpu(tallies.RxDiscards_WEPICVError) +
1287                                le16_to_cpu(tallies.RxDiscards_WEPExcluded);
1288                wstats->discard.misc +=
1289                        le16_to_cpu(tallies.TxDiscardsWrongSA);
1290                wstats->discard.fragment +=
1291                        le16_to_cpu(tallies.RxMsgInBadMsgFragments);
1292                wstats->discard.retries +=
1293                        le16_to_cpu(tallies.TxRetryLimitExceeded);
1294                /* wstats->miss.beacon - no match */
1295        }
1296        break;
1297        case HERMES_INQ_LINKSTATUS: {
1298                struct hermes_linkstatus linkstatus;
1299                u16 newstatus;
1300                int connected;
1301
1302                if (priv->iw_mode == IW_MODE_MONITOR)
1303                        break;
1304
1305                if (len != sizeof(linkstatus)) {
1306                        printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1307                               dev->name, len);
1308                        break;
1309                }
1310
1311                err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
1312                                       infofid, sizeof(info));
1313                if (err)
1314                        break;
1315                newstatus = le16_to_cpu(linkstatus.linkstatus);
1316
1317                /* Symbol firmware uses "out of range" to signal that
1318                 * the hostscan frame can be requested.  */
1319                if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
1320                    priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
1321                    priv->has_hostscan && priv->scan_inprogress) {
1322                        hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
1323                        break;
1324                }
1325
1326                connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
1327                        || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1328                        || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
1329
1330                if (connected)
1331                        netif_carrier_on(dev);
1332                else if (!ignore_disconnect)
1333                        netif_carrier_off(dev);
1334
1335                if (newstatus != priv->last_linkstatus) {
1336                        priv->last_linkstatus = newstatus;
1337                        print_linkstatus(dev, newstatus);
1338                        /* The info frame contains only one word which is the
1339                         * status (see hermes.h). The status is pretty boring
1340                         * in itself, that's why we export the new BSSID...
1341                         * Jean II */
1342                        schedule_work(&priv->wevent_work);
1343                }
1344        }
1345        break;
1346        case HERMES_INQ_SCAN:
1347                if (!priv->scan_inprogress && priv->bssid_fixed &&
1348                    priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
1349                        schedule_work(&priv->join_work);
1350                        break;
1351                }
1352                /* fall through */
1353        case HERMES_INQ_HOSTSCAN:
1354        case HERMES_INQ_HOSTSCAN_SYMBOL: {
1355                /* Result of a scanning. Contains information about
1356                 * cells in the vicinity - Jean II */
1357                union iwreq_data        wrqu;
1358                unsigned char *buf;
1359
1360                /* Scan is no longer in progress */
1361                priv->scan_inprogress = 0;
1362
1363                /* Sanity check */
1364                if (len > 4096) {
1365                        printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
1366                               dev->name, len);
1367                        break;
1368                }
1369
1370                /* Allocate buffer for results */
1371                buf = kmalloc(len, GFP_ATOMIC);
1372                if (buf == NULL)
1373                        /* No memory, so can't printk()... */
1374                        break;
1375
1376                /* Read scan data */
1377                err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
1378                                       infofid, sizeof(info));
1379                if (err) {
1380                        kfree(buf);
1381                        break;
1382                }
1383
1384#ifdef ORINOCO_DEBUG
1385                {
1386                        int     i;
1387                        printk(KERN_DEBUG "Scan result [%02X", buf[0]);
1388                        for(i = 1; i < (len * 2); i++)
1389                                printk(":%02X", buf[i]);
1390                        printk("]\n");
1391                }
1392#endif  /* ORINOCO_DEBUG */
1393
1394                if (orinoco_process_scan_results(dev, buf, len) == 0) {
1395                        /* Send an empty event to user space.
1396                         * We don't send the received data on the event because
1397                         * it would require us to do complex transcoding, and
1398                         * we want to minimise the work done in the irq handler
1399                         * Use a request to extract the data - Jean II */
1400                        wrqu.data.length = 0;
1401                        wrqu.data.flags = 0;
1402                        wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
1403                }
1404                kfree(buf);
1405        }
1406        break;
1407        case HERMES_INQ_SEC_STAT_AGERE:
1408                /* Security status (Agere specific) */
1409                /* Ignore this frame for now */
1410                if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
1411                        break;
1412                /* fall through */
1413        default:
1414                printk(KERN_DEBUG "%s: Unknown information frame received: "
1415                       "type 0x%04x, length %d\n", dev->name, type, len);
1416                /* We don't actually do anything about it */
1417                break;
1418        }
1419}
1420
1421static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
1422{
1423        if (net_ratelimit())
1424                printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
1425}
1426
1427/********************************************************************/
1428/* Internal hardware control routines                               */
1429/********************************************************************/
1430
1431int __orinoco_up(struct net_device *dev)
1432{
1433        struct orinoco_private *priv = netdev_priv(dev);
1434        struct hermes *hw = &priv->hw;
1435        int err;
1436
1437        netif_carrier_off(dev); /* just to make sure */
1438
1439        err = __orinoco_program_rids(dev);
1440        if (err) {
1441                printk(KERN_ERR "%s: Error %d configuring card\n",
1442                       dev->name, err);
1443                return err;
1444        }
1445
1446        /* Fire things up again */
1447        hermes_set_irqmask(hw, ORINOCO_INTEN);
1448        err = hermes_enable_port(hw, 0);
1449        if (err) {
1450                printk(KERN_ERR "%s: Error %d enabling MAC port\n",
1451                       dev->name, err);
1452                return err;
1453        }
1454
1455        netif_start_queue(dev);
1456
1457        return 0;
1458}
1459
1460int __orinoco_down(struct net_device *dev)
1461{
1462        struct orinoco_private *priv = netdev_priv(dev);
1463        struct hermes *hw = &priv->hw;
1464        int err;
1465
1466        netif_stop_queue(dev);
1467
1468        if (! priv->hw_unavailable) {
1469                if (! priv->broken_disableport) {
1470                        err = hermes_disable_port(hw, 0);
1471                        if (err) {
1472                                /* Some firmwares (e.g. Intersil 1.3.x) seem
1473                                 * to have problems disabling the port, oh
1474                                 * well, too bad. */
1475                                printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
1476                                       dev->name, err);
1477                                priv->broken_disableport = 1;
1478                        }
1479                }
1480                hermes_set_irqmask(hw, 0);
1481                hermes_write_regn(hw, EVACK, 0xffff);
1482        }
1483        
1484        /* firmware will have to reassociate */
1485        netif_carrier_off(dev);
1486        priv->last_linkstatus = 0xffff;
1487
1488        return 0;
1489}
1490
1491static int orinoco_allocate_fid(struct net_device *dev)
1492{
1493        struct orinoco_private *priv = netdev_priv(dev);
1494        struct hermes *hw = &priv->hw;
1495        int err;
1496
1497        err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
1498        if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
1499                /* Try workaround for old Symbol firmware bug */
1500                printk(KERN_WARNING "%s: firmware ALLOC bug detected "
1501                       "(old Symbol firmware?). Trying to work around... ",
1502                       dev->name);
1503                
1504                priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
1505                err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
1506                if (err)
1507                        printk("failed!\n");
1508                else
1509                        printk("ok.\n");
1510        }
1511
1512        return err;
1513}
1514
1515int orinoco_reinit_firmware(struct net_device *dev)
1516{
1517        struct orinoco_private *priv = netdev_priv(dev);
1518        struct hermes *hw = &priv->hw;
1519        int err;
1520
1521        err = hermes_init(hw);
1522        if (!err)
1523                err = orinoco_allocate_fid(dev);
1524
1525        return err;
1526}
1527
1528static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
1529{
1530        hermes_t *hw = &priv->hw;
1531        int err = 0;
1532
1533        if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
1534                printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
1535                       priv->ndev->name, priv->bitratemode);
1536                return -EINVAL;
1537        }
1538
1539        switch (priv->firmware_type) {
1540        case FIRMWARE_TYPE_AGERE:
1541                err = hermes_write_wordrec(hw, USER_BAP,
1542                                           HERMES_RID_CNFTXRATECONTROL,
1543                                           bitrate_table[priv->bitratemode].agere_txratectrl);
1544                break;
1545        case FIRMWARE_TYPE_INTERSIL:
1546        case FIRMWARE_TYPE_SYMBOL:
1547                err = hermes_write_wordrec(hw, USER_BAP,
1548                                           HERMES_RID_CNFTXRATECONTROL,
1549                                           bitrate_table[priv->bitratemode].intersil_txratectrl);
1550                break;
1551        default:
1552                BUG();
1553        }
1554
1555        return err;
1556}
1557
1558/* Set fixed AP address */
1559static int __orinoco_hw_set_wap(struct orinoco_private *priv)
1560{
1561        int roaming_flag;
1562        int err = 0;
1563        hermes_t *hw = &priv->hw;
1564
1565        switch (priv->firmware_type) {
1566        case FIRMWARE_TYPE_AGERE:
1567                /* not supported */
1568                break;
1569        case FIRMWARE_TYPE_INTERSIL:
1570                if (priv->bssid_fixed)
1571                        roaming_flag = 2;
1572                else
1573                        roaming_flag = 1;
1574
1575                err = hermes_write_wordrec(hw, USER_BAP,
1576                                           HERMES_RID_CNFROAMINGMODE,
1577                                           roaming_flag);
1578                break;
1579        case FIRMWARE_TYPE_SYMBOL:
1580                err = HERMES_WRITE_RECORD(hw, USER_BAP,
1581                                          HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
1582                                          &priv->desired_bssid);
1583                break;
1584        }
1585        return err;
1586}
1587
1588/* Change the WEP keys and/or the current keys.  Can be called
1589 * either from __orinoco_hw_setup_wep() or directly from
1590 * orinoco_ioctl_setiwencode().  In the later case the association
1591 * with the AP is not broken (if the firmware can handle it),
1592 * which is needed for 802.1x implementations. */
1593static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
1594{
1595        hermes_t *hw = &priv->hw;
1596        int err = 0;
1597
1598        switch (priv->firmware_type) {
1599        case FIRMWARE_TYPE_AGERE:
1600                err = HERMES_WRITE_RECORD(hw, USER_BAP,
1601                                          HERMES_RID_CNFWEPKEYS_AGERE,
1602                                          &priv->keys);
1603                if (err)
1604                        return err;
1605                err = hermes_write_wordrec(hw, USER_BAP,
1606                                           HERMES_RID_CNFTXKEY_AGERE,
1607                                           priv->tx_key);
1608                if (err)
1609                        return err;
1610                break;
1611        case FIRMWARE_TYPE_INTERSIL:
1612        case FIRMWARE_TYPE_SYMBOL:
1613                {
1614                        int keylen;
1615                        int i;
1616
1617                        /* Force uniform key length to work around firmware bugs */
1618                        keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
1619                        
1620                        if (keylen > LARGE_KEY_SIZE) {
1621                                printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
1622                                       priv->ndev->name, priv->tx_key, keylen);
1623                                return -E2BIG;
1624                        }
1625
1626                        /* Write all 4 keys */
1627                        for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
1628                                err = hermes_write_ltv(hw, USER_BAP,
1629                                                       HERMES_RID_CNFDEFAULTKEY0 + i,
1630                                                       HERMES_BYTES_TO_RECLEN(keylen),
1631                                                       priv->keys[i].data);
1632                                if (err)
1633                                        return err;
1634                        }
1635
1636                        /* Write the index of the key used in transmission */
1637                        err = hermes_write_wordrec(hw, USER_BAP,
1638                                                   HERMES_RID_CNFWEPDEFAULTKEYID,
1639                                                   priv->tx_key);
1640                        if (err)
1641                                return err;
1642                }
1643                break;
1644        }
1645
1646        return 0;
1647}
1648
1649static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
1650{
1651        hermes_t *hw = &priv->hw;
1652        int err = 0;
1653        int master_wep_flag;
1654        int auth_flag;
1655
1656        if (priv->wep_on)
1657                __orinoco_hw_setup_wepkeys(priv);
1658
1659        if (priv->wep_restrict)
1660                auth_flag = HERMES_AUTH_SHARED_KEY;
1661        else
1662                auth_flag = HERMES_AUTH_OPEN;
1663
1664        switch (priv->firmware_type) {
1665        case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
1666                if (priv->wep_on) {
1667                        /* Enable the shared-key authentication. */
1668                        err = hermes_write_wordrec(hw, USER_BAP,
1669                                                   HERMES_RID_CNFAUTHENTICATION_AGERE,
1670                                                   auth_flag);
1671                }
1672                err = hermes_write_wordrec(hw, USER_BAP,
1673                                           HERMES_RID_CNFWEPENABLED_AGERE,
1674                                           priv->wep_on);
1675                if (err)
1676                        return err;
1677                break;
1678
1679        case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
1680        case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
1681                if (priv->wep_on) {
1682                        if (priv->wep_restrict ||
1683                            (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
1684                                master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
1685                                                  HERMES_WEP_EXCL_UNENCRYPTED;
1686                        else
1687                                master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
1688
1689                        err = hermes_write_wordrec(hw, USER_BAP,
1690                                                   HERMES_RID_CNFAUTHENTICATION,
1691                                                   auth_flag);
1692                        if (err)
1693                                return err;
1694                } else
1695                        master_wep_flag = 0;
1696
1697                if (priv->iw_mode == IW_MODE_MONITOR)
1698                        master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
1699
1700                /* Master WEP setting : on/off */
1701                err = hermes_write_wordrec(hw, USER_BAP,
1702                                           HERMES_RID_CNFWEPFLAGS_INTERSIL,
1703                                           master_wep_flag);
1704                if (err)
1705                        return err;     
1706
1707                break;
1708        }
1709
1710        return 0;
1711}
1712
1713static int __orinoco_program_rids(struct net_device *dev)
1714{
1715        struct orinoco_private *priv = netdev_priv(dev);
1716        hermes_t *hw = &priv->hw;
1717        int err;
1718        struct hermes_idstring idbuf;
1719
1720        /* Set the MAC address */
1721        err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
1722                               HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
1723        if (err) {
1724                printk(KERN_ERR "%s: Error %d setting MAC address\n",
1725                       dev->name, err);
1726                return err;
1727        }
1728
1729        /* Set up the link mode */
1730        err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
1731                                   priv->port_type);
1732        if (err) {
1733                printk(KERN_ERR "%s: Error %d setting port type\n",
1734                       dev->name, err);
1735                return err;
1736        }
1737        /* Set the channel/frequency */
1738        if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
1739                err = hermes_write_wordrec(hw, USER_BAP,
1740                                           HERMES_RID_CNFOWNCHANNEL,
1741                                           priv->channel);
1742                if (err) {
1743                        printk(KERN_ERR "%s: Error %d setting channel %d\n",
1744                               dev->name, err, priv->channel);
1745                        return err;
1746                }
1747        }
1748
1749        if (priv->has_ibss) {
1750                u16 createibss;
1751
1752                if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
1753                        printk(KERN_WARNING "%s: This firmware requires an "
1754                               "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
1755                        /* With wvlan_cs, in this case, we would crash.
1756                         * hopefully, this driver will behave better...
1757                         * Jean II */
1758                        createibss = 0;
1759                } else {
1760                        createibss = priv->createibss;
1761                }
1762                
1763                err = hermes_write_wordrec(hw, USER_BAP,
1764                                           HERMES_RID_CNFCREATEIBSS,
1765                                           createibss);
1766                if (err) {
1767                        printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
1768                               dev->name, err);
1769                        return err;
1770                }
1771        }
1772
1773        /* Set the desired BSSID */
1774        err = __orinoco_hw_set_wap(priv);
1775        if (err) {
1776                printk(KERN_ERR "%s: Error %d setting AP address\n",
1777                       dev->name, err);
1778                return err;
1779        }
1780        /* Set the desired ESSID */
1781        idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
1782        memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
1783        /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
1784        err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
1785                               HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
1786                               &idbuf);
1787        if (err) {
1788                printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
1789                       dev->name, err);
1790                return err;
1791        }
1792        err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
1793                               HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
1794                               &idbuf);
1795        if (err) {
1796                printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
1797                       dev->name, err);
1798                return err;
1799        }
1800
1801        /* Set the station name */
1802        idbuf.len = cpu_to_le16(strlen(priv->nick));
1803        memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
1804        err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
1805                               HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
1806                               &idbuf);
1807        if (err) {
1808                printk(KERN_ERR "%s: Error %d setting nickname\n",
1809                       dev->name, err);
1810                return err;
1811        }
1812
1813        /* Set AP density */
1814        if (priv->has_sensitivity) {
1815                err = hermes_write_wordrec(hw, USER_BAP,
1816                                           HERMES_RID_CNFSYSTEMSCALE,
1817                                           priv->ap_density);
1818                if (err) {
1819                        printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE.  "
1820                               "Disabling sensitivity control\n",
1821                               dev->name, err);
1822
1823                        priv->has_sensitivity = 0;
1824                }
1825        }
1826
1827        /* Set RTS threshold */
1828        err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
1829                                   priv->rts_thresh);
1830        if (err) {
1831                printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
1832                       dev->name, err);
1833                return err;
1834        }
1835
1836        /* Set fragmentation threshold or MWO robustness */
1837        if (priv->has_mwo)
1838                err = hermes_write_wordrec(hw, USER_BAP,
1839                                           HERMES_RID_CNFMWOROBUST_AGERE,
1840                                           priv->mwo_robust);
1841        else
1842                err = hermes_write_wordrec(hw, USER_BAP,
1843                                           HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
1844                                           priv->frag_thresh);
1845        if (err) {
1846                printk(KERN_ERR "%s: Error %d setting fragmentation\n",
1847                       dev->name, err);
1848                return err;
1849        }
1850
1851        /* Set bitrate */
1852        err = __orinoco_hw_set_bitrate(priv);
1853        if (err) {
1854                printk(KERN_ERR "%s: Error %d setting bitrate\n",
1855                       dev->name, err);
1856                return err;
1857        }
1858
1859        /* Set power management */
1860        if (priv->has_pm) {
1861                err = hermes_write_wordrec(hw, USER_BAP,
1862                                           HERMES_RID_CNFPMENABLED,
1863                                           priv->pm_on);
1864                if (err) {
1865                        printk(KERN_ERR "%s: Error %d setting up PM\n",
1866                               dev->name, err);
1867                        return err;
1868                }
1869
1870                err = hermes_write_wordrec(hw, USER_BAP,
1871                                           HERMES_RID_CNFMULTICASTRECEIVE,
1872                                           priv->pm_mcast);
1873                if (err) {
1874                        printk(KERN_ERR "%s: Error %d setting up PM\n",
1875                               dev->name, err);
1876                        return err;
1877                }
1878                err = hermes_write_wordrec(hw, USER_BAP,
1879                                           HERMES_RID_CNFMAXSLEEPDURATION,
1880                                           priv->pm_period);
1881                if (err) {
1882                        printk(KERN_ERR "%s: Error %d setting up PM\n",
1883                               dev->name, err);
1884                        return err;
1885                }
1886                err = hermes_write_wordrec(hw, USER_BAP,
1887                                           HERMES_RID_CNFPMHOLDOVERDURATION,
1888                                           priv->pm_timeout);
1889                if (err) {
1890                        printk(KERN_ERR "%s: Error %d setting up PM\n",
1891                               dev->name, err);
1892                        return err;
1893                }
1894        }
1895
1896        /* Set preamble - only for Symbol so far... */
1897        if (priv->has_preamble) {
1898                err = hermes_write_wordrec(hw, USER_BAP,
1899                                           HERMES_RID_CNFPREAMBLE_SYMBOL,
1900                                           priv->preamble);
1901                if (err) {
1902                        printk(KERN_ERR "%s: Error %d setting preamble\n",
1903                               dev->name, err);
1904                        return err;
1905                }
1906        }
1907
1908        /* Set up encryption */
1909        if (priv->has_wep) {
1910                err = __orinoco_hw_setup_wep(priv);
1911                if (err) {
1912                        printk(KERN_ERR "%s: Error %d activating WEP\n",
1913                               dev->name, err);
1914                        return err;
1915                }
1916        }
1917
1918        if (priv->iw_mode == IW_MODE_MONITOR) {
1919                /* Enable monitor mode */
1920                dev->type = ARPHRD_IEEE80211;
1921                err = hermes_docmd_wait(hw, HERMES_CMD_TEST | 
1922                                            HERMES_TEST_MONITOR, 0, NULL);
1923        } else {
1924                /* Disable monitor mode */
1925                dev->type = ARPHRD_ETHER;
1926                err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1927                                            HERMES_TEST_STOP, 0, NULL);
1928        }
1929        if (err)
1930                return err;
1931
1932        /* Set promiscuity / multicast*/
1933        priv->promiscuous = 0;
1934        priv->mc_count = 0;
1935
1936        /* FIXME: what about netif_tx_lock */
1937        __orinoco_set_multicast_list(dev);
1938
1939        return 0;
1940}
1941
1942/* FIXME: return int? */
1943static void
1944__orinoco_set_multicast_list(struct net_device *dev)
1945{
1946        struct orinoco_private *priv = netdev_priv(dev);
1947        hermes_t *hw = &priv->hw;
1948        int err = 0;
1949        int promisc, mc_count;
1950
1951        /* The Hermes doesn't seem to have an allmulti mode, so we go
1952         * into promiscuous mode and let the upper levels deal. */
1953        if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
1954             (dev->mc_count > MAX_MULTICAST(priv)) ) {
1955                promisc = 1;
1956                mc_count = 0;
1957        } else {
1958                promisc = 0;
1959                mc_count = dev->mc_count;
1960        }
1961
1962        if (promisc != priv->promiscuous) {
1963                err = hermes_write_wordrec(hw, USER_BAP,
1964                                           HERMES_RID_CNFPROMISCUOUSMODE,
1965                                           promisc);
1966                if (err) {
1967                        printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
1968                               dev->name, err);
1969                } else 
1970                        priv->promiscuous = promisc;
1971        }
1972
1973        /* If we're not in promiscuous mode, then we need to set the
1974         * group address if either we want to multicast, or if we were
1975         * multicasting and want to stop */
1976        if (! promisc && (mc_count || priv->mc_count) ) {
1977                struct dev_mc_list *p = dev->mc_list;
1978                struct hermes_multicast mclist;
1979                int i;
1980
1981                for (i = 0; i < mc_count; i++) {
1982                        /* paranoia: is list shorter than mc_count? */
1983                        BUG_ON(! p);
1984                        /* paranoia: bad address size in list? */
1985                        BUG_ON(p->dmi_addrlen != ETH_ALEN);
1986                        
1987                        memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
1988                        p = p->next;
1989                }
1990                
1991                if (p)
1992                        printk(KERN_WARNING "%s: Multicast list is "
1993                               "longer than mc_count\n", dev->name);
1994
1995                err = hermes_write_ltv(hw, USER_BAP,
1996                                   HERMES_RID_CNFGROUPADDRESSES,
1997                                   HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
1998                                   &mclist);
1999                if (err)
2000                        printk(KERN_ERR "%s: Error %d setting multicast list.\n",
2001                               dev->name, err);
2002                else
2003                        priv->mc_count = mc_count;
2004        }
2005}
2006
2007/* This must be called from user context, without locks held - use
2008 * schedule_work() */
2009static void orinoco_reset(struct work_struct *work)
2010{
2011        struct orinoco_private *priv =
2012                container_of(work, struct orinoco_private, reset_work);
2013        struct net_device *dev = priv->ndev;
2014        struct hermes *hw = &priv->hw;
2015        int err;
2016        unsigned long flags;
2017
2018        if (orinoco_lock(priv, &flags) != 0)
2019                /* When the hardware becomes available again, whatever
2020                 * detects that is responsible for re-initializing
2021                 * it. So no need for anything further */
2022                return;
2023
2024        netif_stop_queue(dev);
2025
2026        /* Shut off interrupts.  Depending on what state the hardware
2027         * is in, this might not work, but we'll try anyway */
2028        hermes_set_irqmask(hw, 0);
2029        hermes_write_regn(hw, EVACK, 0xffff);
2030
2031        priv->hw_unavailable++;
2032        priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
2033        netif_carrier_off(dev);
2034
2035        orinoco_unlock(priv, &flags);
2036
2037        /* Scanning support: Cleanup of driver struct */
2038        orinoco_clear_scan_results(priv, 0);
2039        priv->scan_inprogress = 0;
2040
2041        if (priv->hard_reset) {
2042                err = (*priv->hard_reset)(priv);
2043                if (err) {
2044                        printk(KERN_ERR "%s: orinoco_reset: Error %d "
2045                               "performing hard reset\n", dev->name, err);
2046                        goto disable;
2047                }
2048        }
2049
2050        err = orinoco_reinit_firmware(dev);
2051        if (err) {
2052                printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
2053                       dev->name, err);
2054                goto disable;
2055        }
2056
2057        spin_lock_irq(&priv->lock); /* This has to be called from user context */
2058
2059        priv->hw_unavailable--;
2060
2061        /* priv->open or priv->hw_unavailable might have changed while
2062         * we dropped the lock */
2063        if (priv->open && (! priv->hw_unavailable)) {
2064                err = __orinoco_up(dev);
2065                if (err) {
2066                        printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
2067                               dev->name, err);
2068                } else
2069                        dev->trans_start = jiffies;
2070        }
2071
2072        spin_unlock_irq(&priv->lock);
2073
2074        return;
2075 disable:
2076        hermes_set_irqmask(hw, 0);
2077        netif_device_detach(dev);
2078        printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
2079}
2080
2081/********************************************************************/
2082/* Interrupt handler                                                */
2083/********************************************************************/
2084
2085static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
2086{
2087        printk(KERN_DEBUG "%s: TICK\n", dev->name);
2088}
2089
2090static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
2091{
2092        /* This seems to happen a fair bit under load, but ignoring it
2093           seems to work fine...*/
2094        printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
2095               dev->name);
2096}
2097
2098irqreturn_t orinoco_interrupt(int irq, void *dev_id)
2099{
2100        struct net_device *dev = dev_id;
2101        struct orinoco_private *priv = netdev_priv(dev);
2102        hermes_t *hw = &priv->hw;
2103        int count = MAX_IRQLOOPS_PER_IRQ;
2104        u16 evstat, events;
2105        /* These are used to detect a runaway interrupt situation */
2106        /* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
2107         * we panic and shut down the hardware */
2108        static int last_irq_jiffy = 0; /* jiffies value the last time
2109                                        * we were called */
2110        static int loops_this_jiffy = 0;
2111        unsigned long flags;
2112
2113        if (orinoco_lock(priv, &flags) != 0) {
2114                /* If hw is unavailable - we don't know if the irq was
2115                 * for us or not */
2116                return IRQ_HANDLED;
2117        }
2118
2119        evstat = hermes_read_regn(hw, EVSTAT);
2120        events = evstat & hw->inten;
2121        if (! events) {
2122                orinoco_unlock(priv, &flags);
2123                return IRQ_NONE;
2124        }
2125        
2126        if (jiffies != last_irq_jiffy)
2127                loops_this_jiffy = 0;
2128        last_irq_jiffy = jiffies;
2129
2130        while (events && count--) {
2131                if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
2132                        printk(KERN_WARNING "%s: IRQ handler is looping too "
2133                               "much! Resetting.\n", dev->name);
2134                        /* Disable interrupts for now */
2135                        hermes_set_irqmask(hw, 0);
2136                        schedule_work(&priv->reset_work);
2137                        break;
2138                }
2139
2140                /* Check the card hasn't been removed */
2141                if (! hermes_present(hw)) {
2142                        DEBUG(0, "orinoco_interrupt(): card removed\n");
2143                        break;
2144                }
2145
2146                if (events & HERMES_EV_TICK)
2147                        __orinoco_ev_tick(dev, hw);
2148                if (events & HERMES_EV_WTERR)
2149                        __orinoco_ev_wterr(dev, hw);
2150                if (events & HERMES_EV_INFDROP)
2151                        __orinoco_ev_infdrop(dev, hw);
2152                if (events & HERMES_EV_INFO)
2153                        __orinoco_ev_info(dev, hw);
2154                if (events & HERMES_EV_RX)
2155                        __orinoco_ev_rx(dev, hw);
2156                if (events & HERMES_EV_TXEXC)
2157                        __orinoco_ev_txexc(dev, hw);
2158                if (events & HERMES_EV_TX)
2159                        __orinoco_ev_tx(dev, hw);
2160                if (events & HERMES_EV_ALLOC)
2161                        __orinoco_ev_alloc(dev, hw);
2162                
2163                hermes_write_regn(hw, EVACK, evstat);
2164
2165                evstat = hermes_read_regn(hw, EVSTAT);
2166                events = evstat & hw->inten;
2167        };
2168
2169        orinoco_unlock(priv, &flags);
2170        return IRQ_HANDLED;
2171}
2172
2173/********************************************************************/
2174/* Initialization                                                   */
2175/********************************************************************/
2176
2177struct comp_id {
2178        u16 id, variant, major, minor;
2179} __attribute__ ((packed));
2180
2181static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
2182{
2183        if (nic_id->id < 0x8000)
2184                return FIRMWARE_TYPE_AGERE;
2185        else if (nic_id->id == 0x8000 && nic_id->major == 0)
2186                return FIRMWARE_TYPE_SYMBOL;
2187        else
2188                return FIRMWARE_TYPE_INTERSIL;
2189}
2190
2191/* Set priv->firmware type, determine firmware properties */
2192static int determine_firmware(struct net_device *dev)
2193{
2194        struct orinoco_private *priv = netdev_priv(dev);
2195        hermes_t *hw = &priv->hw;
2196        int err;
2197        struct comp_id nic_id, sta_id;
2198        unsigned int firmver;
2199        char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
2200
2201        /* Get the hardware version */
2202        err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
2203        if (err) {
2204                printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
2205                       dev->name, err);
2206                return err;
2207        }
2208
2209        le16_to_cpus(&nic_id.id);
2210        le16_to_cpus(&nic_id.variant);
2211        le16_to_cpus(&nic_id.major);
2212        le16_to_cpus(&nic_id.minor);
2213        printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
2214               dev->name, nic_id.id, nic_id.variant,
2215               nic_id.major, nic_id.minor);
2216
2217        priv->firmware_type = determine_firmware_type(&nic_id);
2218
2219        /* Get the firmware version */
2220        err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
2221        if (err) {
2222                printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
2223                       dev->name, err);
2224                return err;
2225        }
2226
2227        le16_to_cpus(&sta_id.id);
2228        le16_to_cpus(&sta_id.variant);
2229        le16_to_cpus(&sta_id.major);
2230        le16_to_cpus(&sta_id.minor);
2231        printk(KERN_DEBUG "%s: Station identity  %04x:%04x:%04x:%04x\n",
2232               dev->name, sta_id.id, sta_id.variant,
2233               sta_id.major, sta_id.minor);
2234
2235        switch (sta_id.id) {
2236        case 0x15:
2237                printk(KERN_ERR "%s: Primary firmware is active\n",
2238                       dev->name);
2239                return -ENODEV;
2240        case 0x14b:
2241                printk(KERN_ERR "%s: Tertiary firmware is active\n",
2242                       dev->name);
2243                return -ENODEV;
2244        case 0x1f:      /* Intersil, Agere, Symbol Spectrum24 */
2245        case 0x21:      /* Symbol Spectrum24 Trilogy */
2246                break;
2247        default:
2248                printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
2249                       dev->name);
2250                break;
2251        }
2252
2253        /* Default capabilities */
2254        priv->has_sensitivity = 1;
2255        priv->has_mwo = 0;
2256        priv->has_preamble = 0;
2257        priv->has_port3 = 1;
2258        priv->has_ibss = 1;
2259        priv->has_wep = 0;
2260        priv->has_big_wep = 0;
2261
2262        /* Determine capabilities from the firmware version */
2263        switch (priv->firmware_type) {
2264        case FIRMWARE_TYPE_AGERE:
2265                /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
2266                   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
2267                snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2268                         "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
2269
2270                firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
2271
2272                priv->has_ibss = (firmver >= 0x60006);
2273                priv->has_wep = (firmver >= 0x40020);
2274                priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
2275                                          Gold cards from the others? */
2276                priv->has_mwo = (firmver >= 0x60000);
2277                priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
2278                priv->ibss_port = 1;
2279                priv->has_hostscan = (firmver >= 0x8000a);
2280                priv->broken_monitor = (firmver >= 0x80000);
2281
2282                /* Tested with Agere firmware :
2283                 *      1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
2284                 * Tested CableTron firmware : 4.32 => Anton */
2285                break;
2286        case FIRMWARE_TYPE_SYMBOL:
2287                /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
2288                /* Intel MAC : 00:02:B3:* */
2289                /* 3Com MAC : 00:50:DA:* */
2290                memset(tmp, 0, sizeof(tmp));
2291                /* Get the Symbol firmware version */
2292                err = hermes_read_ltv(hw, USER_BAP,
2293                                      HERMES_RID_SECONDARYVERSION_SYMBOL,
2294                                      SYMBOL_MAX_VER_LEN, NULL, &tmp);
2295                if (err) {
2296                        printk(KERN_WARNING
2297                               "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
2298                               dev->name, err);
2299                        firmver = 0;
2300                        tmp[0] = '\0';
2301                } else {
2302                        /* The firmware revision is a string, the format is
2303                         * something like : "V2.20-01".
2304                         * Quick and dirty parsing... - Jean II
2305                         */
2306                        firmver = ((tmp[1] - '0') << 16) | ((tmp[3] - '0') << 12)
2307                                | ((tmp[4] - '0') << 8) | ((tmp[6] - '0') << 4)
2308                                | (tmp[7] - '0');
2309
2310                        tmp[SYMBOL_MAX_VER_LEN] = '\0';
2311                }
2312
2313                snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2314                         "Symbol %s", tmp);
2315
2316                priv->has_ibss = (firmver >= 0x20000);
2317                priv->has_wep = (firmver >= 0x15012);
2318                priv->has_big_wep = (firmver >= 0x20000);
2319                priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) || 
2320                               (firmver >= 0x29000 && firmver < 0x30000) ||
2321                               firmver >= 0x31000;
2322                priv->has_preamble = (firmver >= 0x20000);
2323                priv->ibss_port = 4;
2324                priv->broken_disableport = (firmver == 0x25013) ||
2325                                           (firmver >= 0x30000 && firmver <= 0x31000);
2326                priv->has_hostscan = (firmver >= 0x31001) ||
2327                                     (firmver >= 0x29057 && firmver < 0x30000);
2328                /* Tested with Intel firmware : 0x20015 => Jean II */
2329                /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
2330                break;
2331        case FIRMWARE_TYPE_INTERSIL:
2332                /* D-Link, Linksys, Adtron, ZoomAir, and many others...
2333                 * Samsung, Compaq 100/200 and Proxim are slightly
2334                 * different and less well tested */
2335                /* D-Link MAC : 00:40:05:* */
2336                /* Addtron MAC : 00:90:D1:* */
2337                snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
2338                         "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
2339                         sta_id.variant);
2340
2341                firmver = ((unsigned long)sta_id.major << 16) |
2342                        ((unsigned long)sta_id.minor << 8) | sta_id.variant;
2343
2344                priv->has_ibss = (firmver >= 0x000700); /* FIXME */
2345                priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
2346                priv->has_pm = (firmver >= 0x000700);
2347                priv->has_hostscan = (firmver >= 0x010301);
2348
2349                if (firmver >= 0x000800)
2350                        priv->ibss_port = 0;
2351                else {
2352                        printk(KERN_NOTICE "%s: Intersil firmware earlier "
2353                               "than v0.8.x - several features not supported\n",
2354                               dev->name);
2355                        priv->ibss_port = 1;
2356                }
2357                break;
2358        }
2359        printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
2360               priv->fw_name);
2361
2362        return 0;
2363}
2364
2365static int orinoco_init(struct net_device *dev)
2366{
2367        struct orinoco_private *priv = netdev_priv(dev);
2368        hermes_t *hw = &priv->hw;
2369        int err = 0;
2370        struct hermes_idstring nickbuf;
2371        u16 reclen;
2372        int len;
2373        DECLARE_MAC_BUF(mac);
2374
2375        /* No need to lock, the hw_unavailable flag is already set in
2376         * alloc_orinocodev() */
2377        priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
2378
2379        /* Initialize the firmware */
2380        err = hermes_init(hw);
2381        if (err != 0) {
2382                printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
2383                       dev->name, err);
2384                goto out;
2385        }
2386
2387        err = determine_firmware(dev);
2388        if (err != 0) {
2389                printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
2390                       dev->name);
2391                goto out;
2392        }
2393
2394        if (priv->has_port3)
2395                printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
2396        if (priv->has_ibss)
2397                printk(KERN_DEBUG "%s: IEEE standard IBSS ad-hoc mode supported\n",
2398                       dev->name);
2399        if (priv->has_wep) {
2400                printk(KERN_DEBUG "%s: WEP supported, ", dev->name);
2401                if (priv->has_big_wep)
2402                        printk("104-bit key\n");
2403                else
2404                        printk("40-bit key\n");
2405        }
2406
2407        /* Get the MAC address */
2408        err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
2409                              ETH_ALEN, NULL, dev->dev_addr);
2410        if (err) {
2411                printk(KERN_WARNING "%s: failed to read MAC address!\n",
2412                       dev->name);
2413                goto out;
2414        }
2415
2416        printk(KERN_DEBUG "%s: MAC address %s\n",
2417               dev->name, print_mac(mac, dev->dev_addr));
2418
2419        /* Get the station name */
2420        err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
2421                              sizeof(nickbuf), &reclen, &nickbuf);
2422        if (err) {
2423                printk(KERN_ERR "%s: failed to read station name\n",
2424                       dev->name);
2425                goto out;
2426        }
2427        if (nickbuf.len)
2428                len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
2429        else
2430                len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
2431        memcpy(priv->nick, &nickbuf.val, len);
2432        priv->nick[len] = '\0';
2433
2434        printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
2435
2436        err = orinoco_allocate_fid(dev);
2437        if (err) {
2438                printk(KERN_ERR "%s: failed to allocate NIC buffer!\n",
2439                       dev->name);
2440                goto out;
2441        }
2442
2443        /* Get allowed channels */
2444        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
2445                                  &priv->channel_mask);
2446        if (err) {
2447                printk(KERN_ERR "%s: failed to read channel list!\n",
2448                       dev->name);
2449                goto out;
2450        }
2451
2452        /* Get initial AP density */
2453        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
2454                                  &priv->ap_density);
2455        if (err || priv->ap_density < 1 || priv->ap_density > 3) {
2456                priv->has_sensitivity = 0;
2457        }
2458
2459        /* Get initial RTS threshold */
2460        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
2461                                  &priv->rts_thresh);
2462        if (err) {
2463                printk(KERN_ERR "%s: failed to read RTS threshold!\n",
2464                       dev->name);
2465                goto out;
2466        }
2467
2468        /* Get initial fragmentation settings */
2469        if (priv->has_mwo)
2470                err = hermes_read_wordrec(hw, USER_BAP,
2471                                          HERMES_RID_CNFMWOROBUST_AGERE,
2472                                          &priv->mwo_robust);
2473        else
2474                err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
2475                                          &priv->frag_thresh);
2476        if (err) {
2477                printk(KERN_ERR "%s: failed to read fragmentation settings!\n",
2478                       dev->name);
2479                goto out;
2480        }
2481
2482        /* Power management setup */
2483        if (priv->has_pm) {
2484                priv->pm_on = 0;
2485                priv->pm_mcast = 1;
2486                err = hermes_read_wordrec(hw, USER_BAP,
2487                                          HERMES_RID_CNFMAXSLEEPDURATION,
2488                                          &priv->pm_period);
2489                if (err) {
2490                        printk(KERN_ERR "%s: failed to read power management period!\n",
2491                               dev->name);
2492                        goto out;
2493                }
2494                err = hermes_read_wordrec(hw, USER_BAP,
2495                                          HERMES_RID_CNFPMHOLDOVERDURATION,
2496                                          &priv->pm_timeout);
2497                if (err) {
2498                        printk(KERN_ERR "%s: failed to read power management timeout!\n",
2499                               dev->name);
2500                        goto out;
2501                }
2502        }
2503
2504        /* Preamble setup */
2505        if (priv->has_preamble) {
2506                err = hermes_read_wordrec(hw, USER_BAP,
2507                                          HERMES_RID_CNFPREAMBLE_SYMBOL,
2508                                          &priv->preamble);
2509                if (err)
2510                        goto out;
2511        }
2512                
2513        /* Set up the default configuration */
2514        priv->iw_mode = IW_MODE_INFRA;
2515        /* By default use IEEE/IBSS ad-hoc mode if we have it */
2516        priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
2517        set_port_type(priv);
2518        priv->channel = 0; /* use firmware default */
2519
2520        priv->promiscuous = 0;
2521        priv->wep_on = 0;
2522        priv->tx_key = 0;
2523
2524        /* Make the hardware available, as long as it hasn't been
2525         * removed elsewhere (e.g. by PCMCIA hot unplug) */
2526        spin_lock_irq(&priv->lock);
2527        priv->hw_unavailable--;
2528        spin_unlock_irq(&priv->lock);
2529
2530        printk(KERN_DEBUG "%s: ready\n", dev->name);
2531
2532 out:
2533        return err;
2534}
2535
2536struct net_device *alloc_orinocodev(int sizeof_card,
2537                                    int (*hard_reset)(struct orinoco_private *))
2538{
2539        struct net_device *dev;
2540        struct orinoco_private *priv;
2541
2542        dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
2543        if (! dev)
2544                return NULL;
2545        priv = netdev_priv(dev);
2546        priv->ndev = dev;
2547        if (sizeof_card)
2548                priv->card = (void *)((unsigned long)priv
2549                                      + sizeof(struct orinoco_private));
2550        else
2551                priv->card = NULL;
2552
2553        if (orinoco_bss_data_allocate(priv))
2554                goto err_out_free;
2555        orinoco_bss_data_init(priv);
2556
2557        /* Setup / override net_device fields */
2558        dev->init = orinoco_init;
2559        dev->hard_start_xmit = orinoco_xmit;
2560        dev->tx_timeout = orinoco_tx_timeout;
2561        dev->watchdog_timeo = HZ; /* 1 second timeout */
2562        dev->get_stats = orinoco_get_stats;
2563        dev->ethtool_ops = &orinoco_ethtool_ops;
2564        dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
2565#ifdef WIRELESS_SPY
2566        priv->wireless_data.spy_data = &priv->spy_data;
2567        dev->wireless_data = &priv->wireless_data;
2568#endif
2569        dev->change_mtu = orinoco_change_mtu;
2570        dev->set_multicast_list = orinoco_set_multicast_list;
2571        /* we use the default eth_mac_addr for setting the MAC addr */
2572
2573        /* Set up default callbacks */
2574        dev->open = orinoco_open;
2575        dev->stop = orinoco_stop;
2576        priv->hard_reset = hard_reset;
2577
2578        spin_lock_init(&priv->lock);
2579        priv->open = 0;
2580        priv->hw_unavailable = 1; /* orinoco_init() must clear this
2581                                   * before anything else touches the
2582                                   * hardware */
2583        INIT_WORK(&priv->reset_work, orinoco_reset);
2584        INIT_WORK(&priv->join_work, orinoco_join_ap);
2585        INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
2586
2587        netif_carrier_off(dev);
2588        priv->last_linkstatus = 0xffff;
2589
2590        return dev;
2591
2592err_out_free:
2593        free_netdev(dev);
2594        return NULL;
2595}
2596
2597void free_orinocodev(struct net_device *dev)
2598{
2599        struct orinoco_private *priv = netdev_priv(dev);
2600
2601        orinoco_bss_data_free(priv);
2602        free_netdev(dev);
2603}
2604
2605/********************************************************************/
2606/* Wireless extensions                                              */
2607/********************************************************************/
2608
2609/* Return : < 0 -> error code ; >= 0 -> length */
2610static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
2611                                char buf[IW_ESSID_MAX_SIZE+1])
2612{
2613        hermes_t *hw = &priv->hw;
2614        int err = 0;
2615        struct hermes_idstring essidbuf;
2616        char *p = (char *)(&essidbuf.val);
2617        int len;
2618        unsigned long flags;
2619
2620        if (orinoco_lock(priv, &flags) != 0)
2621                return -EBUSY;
2622
2623        if (strlen(priv->desired_essid) > 0) {
2624                /* We read the desired SSID from the hardware rather
2625                   than from priv->desired_essid, just in case the
2626                   firmware is allowed to change it on us. I'm not
2627                   sure about this */
2628                /* My guess is that the OWNSSID should always be whatever
2629                 * we set to the card, whereas CURRENT_SSID is the one that
2630                 * may change... - Jean II */
2631                u16 rid;
2632
2633                *active = 1;
2634
2635                rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
2636                        HERMES_RID_CNFDESIREDSSID;
2637                
2638                err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
2639                                      NULL, &essidbuf);
2640                if (err)
2641                        goto fail_unlock;
2642        } else {
2643                *active = 0;
2644
2645                err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
2646                                      sizeof(essidbuf), NULL, &essidbuf);
2647                if (err)
2648                        goto fail_unlock;
2649        }
2650
2651        len = le16_to_cpu(essidbuf.len);
2652        BUG_ON(len > IW_ESSID_MAX_SIZE);
2653
2654        memset(buf, 0, IW_ESSID_MAX_SIZE);
2655        memcpy(buf, p, len);
2656        err = len;
2657
2658 fail_unlock:
2659        orinoco_unlock(priv, &flags);
2660
2661        return err;       
2662}
2663
2664static long orinoco_hw_get_freq(struct orinoco_private *priv)
2665{
2666        
2667        hermes_t *hw = &priv->hw;
2668        int err = 0;
2669        u16 channel;
2670        long freq = 0;
2671        unsigned long flags;
2672
2673        if (orinoco_lock(priv, &flags) != 0)
2674                return -EBUSY;
2675        
2676        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
2677        if (err)
2678                goto out;
2679
2680        /* Intersil firmware 1.3.5 returns 0 when the interface is down */
2681        if (channel == 0) {
2682                err = -EBUSY;
2683                goto out;
2684        }
2685
2686        if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
2687                printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
2688                       priv->ndev->name, channel);
2689                err = -EBUSY;
2690                goto out;
2691
2692        }
2693        freq = channel_frequency[channel-1] * 100000;
2694
2695 out:
2696        orinoco_unlock(priv, &flags);
2697
2698        if (err > 0)
2699                err = -EBUSY;
2700        return err ? err : freq;
2701}
2702
2703static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
2704                                      int *numrates, s32 *rates, int max)
2705{
2706        hermes_t *hw = &priv->hw;
2707        struct hermes_idstring list;
2708        unsigned char *p = (unsigned char *)&list.val;
2709        int err = 0;
2710        int num;
2711        int i;
2712        unsigned long flags;
2713
2714        if (orinoco_lock(priv, &flags) != 0)
2715                return -EBUSY;
2716
2717        err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
2718                              sizeof(list), NULL, &list);
2719        orinoco_unlock(priv, &flags);
2720
2721        if (err)
2722                return err;
2723        
2724        num = le16_to_cpu(list.len);
2725        *numrates = num;
2726        num = min(num, max);
2727
2728        for (i = 0; i < num; i++) {
2729                rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
2730        }
2731
2732        return 0;
2733}
2734
2735static int orinoco_ioctl_getname(struct net_device *dev,
2736                                 struct iw_request_info *info,
2737                                 char *name,
2738                                 char *extra)
2739{
2740        struct orinoco_private *priv = netdev_priv(dev);
2741        int numrates;
2742        int err;
2743
2744        err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
2745
2746        if (!err && (numrates > 2))
2747                strcpy(name, "IEEE 802.11b");
2748        else
2749                strcpy(name, "IEEE 802.11-DS");
2750
2751        return 0;
2752}
2753
2754static int orinoco_ioctl_setwap(struct net_device *dev,
2755                                struct iw_request_info *info,
2756                                struct sockaddr *ap_addr,
2757                                char *extra)
2758{
2759        struct orinoco_private *priv = netdev_priv(dev);
2760        int err = -EINPROGRESS;         /* Call commit handler */
2761        unsigned long flags;
2762        static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2763        static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2764
2765        if (orinoco_lock(priv, &flags) != 0)
2766                return -EBUSY;
2767
2768        /* Enable automatic roaming - no sanity checks are needed */
2769        if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
2770            memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
2771                priv->bssid_fixed = 0;
2772                memset(priv->desired_bssid, 0, ETH_ALEN);
2773
2774                /* "off" means keep existing connection */
2775                if (ap_addr->sa_data[0] == 0) {
2776                        __orinoco_hw_set_wap(priv);
2777                        err = 0;
2778                }
2779                goto out;
2780        }
2781
2782        if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
2783                printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
2784                       "support manual roaming\n",
2785                       dev->name);
2786                err = -EOPNOTSUPP;
2787                goto out;
2788        }
2789
2790        if (priv->iw_mode != IW_MODE_INFRA) {
2791                printk(KERN_WARNING "%s: Manual roaming supported only in "
2792                       "managed mode\n", dev->name);
2793                err = -EOPNOTSUPP;
2794                goto out;
2795        }
2796
2797        /* Intersil firmware hangs without Desired ESSID */
2798        if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
2799            strlen(priv->desired_essid) == 0) {
2800                printk(KERN_WARNING "%s: Desired ESSID must be set for "
2801                       "manual roaming\n", dev->name);
2802                err = -EOPNOTSUPP;
2803                goto out;
2804        }
2805
2806        /* Finally, enable manual roaming */
2807        priv->bssid_fixed = 1;
2808        memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
2809
2810 out:
2811        orinoco_unlock(priv, &flags);
2812        return err;
2813}
2814
2815static int orinoco_ioctl_getwap(struct net_device *dev,
2816                                struct iw_request_info *info,
2817                                struct sockaddr *ap_addr,
2818                                char *extra)
2819{
2820        struct orinoco_private *priv = netdev_priv(dev);
2821
2822        hermes_t *hw = &priv->hw;
2823        int err = 0;
2824        unsigned long flags;
2825
2826        if (orinoco_lock(priv, &flags) != 0)
2827                return -EBUSY;
2828
2829        ap_addr->sa_family = ARPHRD_ETHER;
2830        err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2831                              ETH_ALEN, NULL, ap_addr->sa_data);
2832
2833        orinoco_unlock(priv, &flags);
2834
2835        return err;
2836}
2837
2838static int orinoco_ioctl_setmode(struct net_device *dev,
2839                                 struct iw_request_info *info,
2840                                 u32 *mode,
2841                                 char *extra)
2842{
2843        struct orinoco_private *priv = netdev_priv(dev);
2844        int err = -EINPROGRESS;         /* Call commit handler */
2845        unsigned long flags;
2846
2847        if (priv->iw_mode == *mode)
2848                return 0;
2849
2850        if (orinoco_lock(priv, &flags) != 0)
2851                return -EBUSY;
2852
2853        switch (*mode) {
2854        case IW_MODE_ADHOC:
2855                if (!priv->has_ibss && !priv->has_port3)
2856                        err = -EOPNOTSUPP;
2857                break;
2858
2859        case IW_MODE_INFRA:
2860                break;
2861
2862        case IW_MODE_MONITOR:
2863                if (priv->broken_monitor && !force_monitor) {
2864                        printk(KERN_WARNING "%s: Monitor mode support is "
2865                               "buggy in this firmware, not enabling\n",
2866                               dev->name);
2867                        err = -EOPNOTSUPP;
2868                }
2869                break;
2870
2871        default:
2872                err = -EOPNOTSUPP;
2873                break;
2874        }
2875
2876        if (err == -EINPROGRESS) {
2877                priv->iw_mode = *mode;
2878                set_port_type(priv);
2879        }
2880
2881        orinoco_unlock(priv, &flags);
2882
2883        return err;
2884}
2885
2886static int orinoco_ioctl_getmode(struct net_device *dev,
2887                                 struct iw_request_info *info,
2888                                 u32 *mode,
2889                                 char *extra)
2890{
2891        struct orinoco_private *priv = netdev_priv(dev);
2892
2893        *mode = priv->iw_mode;
2894        return 0;
2895}
2896
2897static int orinoco_ioctl_getiwrange(struct net_device *dev,
2898                                    struct iw_request_info *info,
2899                                    struct iw_point *rrq,
2900                                    char *extra)
2901{
2902        struct orinoco_private *priv = netdev_priv(dev);
2903        int err = 0;
2904        struct iw_range *range = (struct iw_range *) extra;
2905        int numrates;
2906        int i, k;
2907
2908        rrq->length = sizeof(struct iw_range);
2909        memset(range, 0, sizeof(struct iw_range));
2910
2911        range->we_version_compiled = WIRELESS_EXT;
2912        range->we_version_source = 14;
2913
2914        /* Set available channels/frequencies */
2915        range->num_channels = NUM_CHANNELS;
2916        k = 0;
2917        for (i = 0; i < NUM_CHANNELS; i++) {
2918                if (priv->channel_mask & (1 << i)) {
2919                        range->freq[k].i = i + 1;
2920                        range->freq[k].m = channel_frequency[i] * 100000;
2921                        range->freq[k].e = 1;
2922                        k++;
2923                }
2924                
2925                if (k >= IW_MAX_FREQUENCIES)
2926                        break;
2927        }
2928        range->num_frequency = k;
2929        range->sensitivity = 3;
2930
2931        if (priv->has_wep) {
2932                range->max_encoding_tokens = ORINOCO_MAX_KEYS;
2933                range->encoding_size[0] = SMALL_KEY_SIZE;
2934                range->num_encoding_sizes = 1;
2935
2936                if (priv->has_big_wep) {
2937                        range->encoding_size[1] = LARGE_KEY_SIZE;
2938                        range->num_encoding_sizes = 2;
2939                }
2940        }
2941
2942        if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
2943                /* Quality stats meaningless in ad-hoc mode */
2944        } else {
2945                range->max_qual.qual = 0x8b - 0x2f;
2946                range->max_qual.level = 0x2f - 0x95 - 1;
2947                range->max_qual.noise = 0x2f - 0x95 - 1;
2948                /* Need to get better values */
2949                range->avg_qual.qual = 0x24;
2950                range->avg_qual.level = 0xC2;
2951                range->avg_qual.noise = 0x9E;
2952        }
2953
2954        err = orinoco_hw_get_bitratelist(priv, &numrates,
2955                                         range->bitrate, IW_MAX_BITRATES);
2956        if (err)
2957                return err;
2958        range->num_bitrates = numrates;
2959
2960        /* Set an indication of the max TCP throughput in bit/s that we can
2961         * expect using this interface. May be use for QoS stuff...
2962         * Jean II */
2963        if (numrates > 2)
2964                range->throughput = 5 * 1000 * 1000;    /* ~5 Mb/s */
2965        else
2966                range->throughput = 1.5 * 1000 * 1000;  /* ~1.5 Mb/s */
2967
2968        range->min_rts = 0;
2969        range->max_rts = 2347;
2970        range->min_frag = 256;
2971        range->max_frag = 2346;
2972
2973        range->min_pmp = 0;
2974        range->max_pmp = 65535000;
2975        range->min_pmt = 0;
2976        range->max_pmt = 65535 * 1000;  /* ??? */
2977        range->pmp_flags = IW_POWER_PERIOD;
2978        range->pmt_flags = IW_POWER_TIMEOUT;
2979        range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2980
2981        range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2982        range->retry_flags = IW_RETRY_LIMIT;
2983        range->r_time_flags = IW_RETRY_LIFETIME;
2984        range->min_retry = 0;
2985        range->max_retry = 65535;       /* ??? */
2986        range->min_r_time = 0;
2987        range->max_r_time = 65535 * 1000;       /* ??? */
2988
2989        /* Event capability (kernel) */
2990        IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
2991        /* Event capability (driver) */
2992        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
2993        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
2994        IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
2995        IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
2996
2997        return 0;
2998}
2999
3000static int orinoco_ioctl_setiwencode(struct net_device *dev,
3001                                     struct iw_request_info *info,
3002                                     struct iw_point *erq,
3003                                     char *keybuf)
3004{
3005        struct orinoco_private *priv = netdev_priv(dev);
3006        int index = (erq->flags & IW_ENCODE_INDEX) - 1;
3007        int setindex = priv->tx_key;
3008        int enable = priv->wep_on;
3009        int restricted = priv->wep_restrict;
3010        u16 xlen = 0;
3011        int err = -EINPROGRESS;         /* Call commit handler */
3012        unsigned long flags;
3013
3014        if (! priv->has_wep)
3015                return -EOPNOTSUPP;
3016
3017        if (erq->pointer) {
3018                /* We actually have a key to set - check its length */
3019                if (erq->length > LARGE_KEY_SIZE)
3020                        return -E2BIG;
3021
3022                if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
3023                        return -E2BIG;
3024        }
3025
3026        if (orinoco_lock(priv, &flags) != 0)
3027                return -EBUSY;
3028
3029        if (erq->length > 0) {
3030                if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
3031                        index = priv->tx_key;
3032
3033                /* Adjust key length to a supported value */
3034                if (erq->length > SMALL_KEY_SIZE) {
3035                        xlen = LARGE_KEY_SIZE;
3036                } else if (erq->length > 0) {
3037                        xlen = SMALL_KEY_SIZE;
3038                } else
3039                        xlen = 0;
3040
3041                /* Switch on WEP if off */
3042                if ((!enable) && (xlen > 0)) {
3043                        setindex = index;
3044                        enable = 1;
3045                }
3046        } else {
3047                /* Important note : if the user do "iwconfig eth0 enc off",
3048                 * we will arrive there with an index of -1. This is valid
3049                 * but need to be taken care off... Jean II */
3050                if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
3051                        if((index != -1) || (erq->flags == 0)) {
3052                                err = -EINVAL;
3053                                goto out;
3054                        }
3055                } else {
3056                        /* Set the index : Check that the key is valid */
3057                        if(priv->keys[index].len == 0) {
3058                                err = -EINVAL;
3059                                goto out;
3060                        }
3061                        setindex = index;
3062                }
3063        }
3064
3065        if (erq->flags & IW_ENCODE_DISABLED)
3066                enable = 0;
3067        if (erq->flags & IW_ENCODE_OPEN)
3068                restricted = 0;
3069        if (erq->flags & IW_ENCODE_RESTRICTED)
3070                restricted = 1;
3071
3072        if (erq->pointer && erq->length > 0) {
3073                priv->keys[index].len = cpu_to_le16(xlen);
3074                memset(priv->keys[index].data, 0,
3075                       sizeof(priv->keys[index].data));
3076                memcpy(priv->keys[index].data, keybuf, erq->length);
3077        }
3078        priv->tx_key = setindex;
3079
3080        /* Try fast key change if connected and only keys are changed */
3081        if (priv->wep_on && enable && (priv->wep_restrict == restricted) &&
3082            netif_carrier_ok(dev)) {
3083                err = __orinoco_hw_setup_wepkeys(priv);
3084                /* No need to commit if successful */
3085                goto out;
3086        }
3087
3088        priv->wep_on = enable;
3089        priv->wep_restrict = restricted;
3090
3091 out:
3092        orinoco_unlock(priv, &flags);
3093
3094        return err;
3095}
3096
3097static int orinoco_ioctl_getiwencode(struct net_device *dev,
3098                                     struct iw_request_info *info,
3099                                     struct iw_point *erq,
3100                                     char *keybuf)
3101{
3102        struct orinoco_private *priv = netdev_priv(dev);
3103        int index = (erq->flags & IW_ENCODE_INDEX) - 1;
3104        u16 xlen = 0;
3105        unsigned long flags;
3106
3107        if (! priv->has_wep)
3108                return -EOPNOTSUPP;
3109
3110        if (orinoco_lock(priv, &flags) != 0)
3111                return -EBUSY;
3112
3113        if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
3114                index = priv->tx_key;
3115
3116        erq->flags = 0;
3117        if (! priv->wep_on)
3118                erq->flags |= IW_ENCODE_DISABLED;
3119        erq->flags |= index + 1;
3120
3121        if (priv->wep_restrict)
3122                erq->flags |= IW_ENCODE_RESTRICTED;
3123        else
3124                erq->flags |= IW_ENCODE_OPEN;
3125
3126        xlen = le16_to_cpu(priv->keys[index].len);
3127
3128        erq->length = xlen;
3129
3130        memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
3131
3132        orinoco_unlock(priv, &flags);
3133        return 0;
3134}
3135
3136static int orinoco_ioctl_setessid(struct net_device *dev,
3137                                  struct iw_request_info *info,
3138                                  struct iw_point *erq,
3139                                  char *essidbuf)
3140{
3141        struct orinoco_private *priv = netdev_priv(dev);
3142        unsigned long flags;
3143
3144        /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
3145         * anyway... - Jean II */
3146
3147        /* Hum... Should not use Wireless Extension constant (may change),
3148         * should use our own... - Jean II */
3149        if (erq->length > IW_ESSID_MAX_SIZE)
3150                return -E2BIG;
3151
3152        if (orinoco_lock(priv, &flags) != 0)
3153                return -EBUSY;
3154
3155        /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
3156        memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
3157
3158        /* If not ANY, get the new ESSID */
3159        if (erq->flags) {
3160                memcpy(priv->desired_essid, essidbuf, erq->length);
3161        }
3162
3163        orinoco_unlock(priv, &flags);
3164
3165        return -EINPROGRESS;            /* Call commit handler */
3166}
3167
3168static int orinoco_ioctl_getessid(struct net_device *dev,
3169                                  struct iw_request_info *info,
3170                                  struct iw_point *erq,
3171                                  char *essidbuf)
3172{
3173        struct orinoco_private *priv = netdev_priv(dev);
3174        int active;
3175        int err = 0;
3176        unsigned long flags;
3177
3178        if (netif_running(dev)) {
3179                err = orinoco_hw_get_essid(priv, &active, essidbuf);
3180                if (err < 0)
3181                        return err;
3182                erq->length = err;
3183        } else {
3184                if (orinoco_lock(priv, &flags) != 0)
3185                        return -EBUSY;
3186                memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
3187                erq->length = strlen(priv->desired_essid);
3188                orinoco_unlock(priv, &flags);
3189        }
3190
3191        erq->flags = 1;
3192
3193        return 0;
3194}
3195
3196static int orinoco_ioctl_setnick(struct net_device *dev,
3197                                 struct iw_request_info *info,
3198                                 struct iw_point *nrq,
3199                                 char *nickbuf)
3200{
3201        struct orinoco_private *priv = netdev_priv(dev);
3202        unsigned long flags;
3203
3204        if (nrq->length > IW_ESSID_MAX_SIZE)
3205                return -E2BIG;
3206
3207        if (orinoco_lock(priv, &flags) != 0)
3208                return -EBUSY;
3209
3210        memset(priv->nick, 0, sizeof(priv->nick));
3211        memcpy(priv->nick, nickbuf, nrq->length);
3212
3213        orinoco_unlock(priv, &flags);
3214
3215        return -EINPROGRESS;            /* Call commit handler */
3216}
3217
3218static int orinoco_ioctl_getnick(struct net_device *dev,
3219                                 struct iw_request_info *info,
3220                                 struct iw_point *nrq,
3221                                 char *nickbuf)
3222{
3223        struct orinoco_private *priv = netdev_priv(dev);
3224        unsigned long flags;
3225
3226        if (orinoco_lock(priv, &flags) != 0)
3227                return -EBUSY;
3228
3229        memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE);
3230        orinoco_unlock(priv, &flags);
3231
3232        nrq->length = strlen(priv->nick);
3233
3234        return 0;
3235}
3236
3237static int orinoco_ioctl_setfreq(struct net_device *dev,
3238                                 struct iw_request_info *info,
3239                                 struct iw_freq *frq,
3240                                 char *extra)
3241{
3242        struct orinoco_private *priv = netdev_priv(dev);
3243        int chan = -1;
3244        unsigned long flags;
3245        int err = -EINPROGRESS;         /* Call commit handler */
3246
3247        /* In infrastructure mode the AP sets the channel */
3248        if (priv->iw_mode == IW_MODE_INFRA)
3249                return -EBUSY;
3250
3251        if ( (frq->e == 0) && (frq->m <= 1000) ) {
3252                /* Setting by channel number */
3253                chan = frq->m;
3254        } else {
3255                /* Setting by frequency - search the table */
3256                int mult = 1;
3257                int i;
3258
3259                for (i = 0; i < (6 - frq->e); i++)
3260                        mult *= 10;
3261
3262                for (i = 0; i < NUM_CHANNELS; i++)
3263                        if (frq->m == (channel_frequency[i] * mult))
3264                                chan = i+1;
3265        }
3266
3267        if ( (chan < 1) || (chan > NUM_CHANNELS) ||
3268             ! (priv->channel_mask & (1 << (chan-1)) ) )
3269                return -EINVAL;
3270
3271        if (orinoco_lock(priv, &flags) != 0)
3272                return -EBUSY;
3273
3274        priv->channel = chan;
3275        if (priv->iw_mode == IW_MODE_MONITOR) {
3276                /* Fast channel change - no commit if successful */
3277                hermes_t *hw = &priv->hw;
3278                err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
3279                                            HERMES_TEST_SET_CHANNEL,
3280                                        chan, NULL);
3281        }
3282        orinoco_unlock(priv, &flags);
3283
3284        return err;
3285}
3286
3287static int orinoco_ioctl_getfreq(struct net_device *dev,
3288                                 struct iw_request_info *info,
3289                                 struct iw_freq *frq,
3290                                 char *extra)
3291{
3292        struct orinoco_private *priv = netdev_priv(dev);
3293        int tmp;
3294
3295        /* Locking done in there */
3296        tmp = orinoco_hw_get_freq(priv);
3297        if (tmp < 0) {
3298                return tmp;
3299        }
3300
3301        frq->m = tmp;
3302        frq->e = 1;
3303
3304        return 0;
3305}
3306
3307static int orinoco_ioctl_getsens(struct net_device *dev,
3308                                 struct iw_request_info *info,
3309                                 struct iw_param *srq,
3310                                 char *extra)
3311{
3312        struct orinoco_private *priv = netdev_priv(dev);
3313        hermes_t *hw = &priv->hw;
3314        u16 val;
3315        int err;
3316        unsigned long flags;
3317
3318        if (!priv->has_sensitivity)
3319                return -EOPNOTSUPP;
3320
3321        if (orinoco_lock(priv, &flags) != 0)
3322                return -EBUSY;
3323        err = hermes_read_wordrec(hw, USER_BAP,
3324                                  HERMES_RID_CNFSYSTEMSCALE, &val);
3325        orinoco_unlock(priv, &flags);
3326
3327        if (err)
3328                return err;
3329
3330        srq->value = val;
3331        srq->fixed = 0; /* auto */
3332
3333        return 0;
3334}
3335
3336static int orinoco_ioctl_setsens(struct net_device *dev,
3337                                 struct iw_request_info *info,
3338                                 struct iw_param *srq,
3339                                 char *extra)
3340{
3341        struct orinoco_private *priv = netdev_priv(dev);
3342        int val = srq->value;
3343        unsigned long flags;
3344
3345        if (!priv->has_sensitivity)
3346                return -EOPNOTSUPP;
3347
3348        if ((val < 1) || (val > 3))
3349                return -EINVAL;
3350        
3351        if (orinoco_lock(priv, &flags) != 0)
3352                return -EBUSY;
3353        priv->ap_density = val;
3354        orinoco_unlock(priv, &flags);
3355
3356        return -EINPROGRESS;            /* Call commit handler */
3357}
3358
3359static int orinoco_ioctl_setrts(struct net_device *dev,
3360                                struct iw_request_info *info,
3361                                struct iw_param *rrq,
3362                                char *extra)
3363{
3364        struct orinoco_private *priv = netdev_priv(dev);
3365        int val = rrq->value;
3366        unsigned long flags;
3367
3368        if (rrq->disabled)
3369                val = 2347;
3370
3371        if ( (val < 0) || (val > 2347) )
3372                return -EINVAL;
3373
3374        if (orinoco_lock(priv, &flags) != 0)
3375                return -EBUSY;
3376
3377        priv->rts_thresh = val;
3378        orinoco_unlock(priv, &flags);
3379
3380        return -EINPROGRESS;            /* Call commit handler */
3381}
3382
3383static int orinoco_ioctl_getrts(struct net_device *dev,
3384                                struct iw_request_info *info,
3385                                struct iw_param *rrq,
3386                                char *extra)
3387{
3388        struct orinoco_private *priv = netdev_priv(dev);
3389
3390        rrq->value = priv->rts_thresh;
3391        rrq->disabled = (rrq->value == 2347);
3392        rrq->fixed = 1;
3393
3394        return 0;
3395}
3396
3397static int orinoco_ioctl_setfrag(struct net_device *dev,
3398                                 struct iw_request_info *info,
3399                                 struct iw_param *frq,
3400                                 char *extra)
3401{
3402        struct orinoco_private *priv = netdev_priv(dev);
3403        int err = -EINPROGRESS;         /* Call commit handler */
3404        unsigned long flags;
3405
3406        if (orinoco_lock(priv, &flags) != 0)
3407                return -EBUSY;
3408
3409        if (priv->has_mwo) {
3410                if (frq->disabled)
3411                        priv->mwo_robust = 0;
3412                else {
3413                        if (frq->fixed)
3414                                printk(KERN_WARNING "%s: Fixed fragmentation is "
3415                                       "not supported on this firmware. "
3416                                       "Using MWO robust instead.\n", dev->name);
3417                        priv->mwo_robust = 1;
3418                }
3419        } else {
3420                if (frq->disabled)
3421                        priv->frag_thresh = 2346;
3422                else {
3423                        if ( (frq->value < 256) || (frq->value > 2346) )
3424                                err = -EINVAL;
3425                        else
3426                                priv->frag_thresh = frq->value & ~0x1; /* must be even */
3427                }
3428        }
3429
3430        orinoco_unlock(priv, &flags);
3431
3432        return err;
3433}
3434
3435static int orinoco_ioctl_getfrag(struct net_device *dev,
3436                                 struct iw_request_info *info,
3437                                 struct iw_param *frq,
3438                                 char *extra)
3439{
3440        struct orinoco_private *priv = netdev_priv(dev);
3441        hermes_t *hw = &priv->hw;
3442        int err;
3443        u16 val;
3444        unsigned long flags;
3445
3446        if (orinoco_lock(priv, &flags) != 0)
3447                return -EBUSY;
3448        
3449        if (priv->has_mwo) {
3450                err = hermes_read_wordrec(hw, USER_BAP,
3451                                          HERMES_RID_CNFMWOROBUST_AGERE,
3452                                          &val);
3453                if (err)
3454                        val = 0;
3455
3456                frq->value = val ? 2347 : 0;
3457                frq->disabled = ! val;
3458                frq->fixed = 0;
3459        } else {
3460                err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
3461                                          &val);
3462                if (err)
3463                        val = 0;
3464
3465                frq->value = val;
3466                frq->disabled = (val >= 2346);
3467                frq->fixed = 1;
3468        }
3469
3470        orinoco_unlock(priv, &flags);
3471        
3472        return err;
3473}
3474
3475static int orinoco_ioctl_setrate(struct net_device *dev,
3476                                 struct iw_request_info *info,
3477                                 struct iw_param *rrq,
3478                                 char *extra)
3479{
3480        struct orinoco_private *priv = netdev_priv(dev);
3481        int ratemode = -1;
3482        int bitrate; /* 100s of kilobits */
3483        int i;
3484        unsigned long flags;
3485        
3486        /* As the user space doesn't know our highest rate, it uses -1
3487         * to ask us to set the highest rate.  Test it using "iwconfig
3488         * ethX rate auto" - Jean II */
3489        if (rrq->value == -1)
3490                bitrate = 110;
3491        else {
3492                if (rrq->value % 100000)
3493                        return -EINVAL;
3494                bitrate = rrq->value / 100000;
3495        }
3496
3497        if ( (bitrate != 10) && (bitrate != 20) &&
3498             (bitrate != 55) && (bitrate != 110) )
3499                return -EINVAL;
3500
3501        for (i = 0; i < BITRATE_TABLE_SIZE; i++)
3502                if ( (bitrate_table[i].bitrate == bitrate) &&
3503                     (bitrate_table[i].automatic == ! rrq->fixed) ) {
3504                        ratemode = i;
3505                        break;
3506                }
3507        
3508        if (ratemode == -1)
3509                return -EINVAL;
3510
3511        if (orinoco_lock(priv, &flags) != 0)
3512                return -EBUSY;
3513        priv->bitratemode = ratemode;
3514        orinoco_unlock(priv, &flags);
3515
3516        return -EINPROGRESS;
3517}
3518
3519static int orinoco_ioctl_getrate(struct net_device *dev,
3520                                 struct iw_request_info *info,
3521                                 struct iw_param *rrq,
3522                                 char *extra)
3523{
3524        struct orinoco_private *priv = netdev_priv(dev);
3525        hermes_t *hw = &priv->hw;
3526        int err = 0;
3527        int ratemode;
3528        int i;
3529        u16 val;
3530        unsigned long flags;
3531
3532        if (orinoco_lock(priv, &flags) != 0)
3533                return -EBUSY;
3534
3535        ratemode = priv->bitratemode;
3536
3537        BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
3538
3539        rrq->value = bitrate_table[ratemode].bitrate * 100000;
3540        rrq->fixed = ! bitrate_table[ratemode].automatic;
3541        rrq->disabled = 0;
3542
3543        /* If the interface is running we try to find more about the
3544           current mode */
3545        if (netif_running(dev)) {
3546                err = hermes_read_wordrec(hw, USER_BAP,
3547                                          HERMES_RID_CURRENTTXRATE, &val);
3548                if (err)
3549                        goto out;
3550                
3551                switch (priv->firmware_type) {
3552                case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
3553                        /* Note : in Lucent firmware, the return value of
3554                         * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
3555                         * and therefore is totally different from the
3556                         * encoding of HERMES_RID_CNFTXRATECONTROL.
3557                         * Don't forget that 6Mb/s is really 5.5Mb/s */
3558                        if (val == 6)
3559                                rrq->value = 5500000;
3560                        else
3561                                rrq->value = val * 1000000;
3562                        break;
3563                case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
3564                case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
3565                        for (i = 0; i < BITRATE_TABLE_SIZE; i++)
3566                                if (bitrate_table[i].intersil_txratectrl == val) {
3567                                        ratemode = i;
3568                                        break;
3569                                }
3570                        if (i >= BITRATE_TABLE_SIZE)
3571                                printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
3572                                       dev->name, val);
3573
3574                        rrq->value = bitrate_table[ratemode].bitrate * 100000;
3575                        break;
3576                default:
3577                        BUG();
3578                }
3579        }
3580
3581 out:
3582        orinoco_unlock(priv, &flags);
3583
3584        return err;
3585}
3586
3587static int orinoco_ioctl_setpower(struct net_device *dev,
3588                                  struct iw_request_info *info,
3589                                  struct iw_param *prq,
3590                                  char *extra)
3591{
3592        struct orinoco_private *priv = netdev_priv(dev);
3593        int err = -EINPROGRESS;         /* Call commit handler */
3594        unsigned long flags;
3595
3596        if (orinoco_lock(priv, &flags) != 0)
3597                return -EBUSY;
3598
3599        if (prq->disabled) {
3600                priv->pm_on = 0;
3601        } else {
3602                switch (prq->flags & IW_POWER_MODE) {
3603                case IW_POWER_UNICAST_R:
3604                        priv->pm_mcast = 0;
3605                        priv->pm_on = 1;
3606                        break;
3607                case IW_POWER_ALL_R:
3608                        priv->pm_mcast = 1;
3609                        priv->pm_on = 1;
3610                        break;
3611                case IW_POWER_ON:
3612                        /* No flags : but we may have a value - Jean II */
3613                        break;
3614                default:
3615                        err = -EINVAL;
3616                        goto out;
3617                }
3618                
3619                if (prq->flags & IW_POWER_TIMEOUT) {
3620                        priv->pm_on = 1;
3621                        priv->pm_timeout = prq->value / 1000;
3622                }
3623                if (prq->flags & IW_POWER_PERIOD) {
3624                        priv->pm_on = 1;
3625                        priv->pm_period = prq->value / 1000;
3626                }
3627                /* It's valid to not have a value if we are just toggling
3628                 * the flags... Jean II */
3629                if(!priv->pm_on) {
3630                        err = -EINVAL;
3631                        goto out;
3632                }                       
3633        }
3634
3635 out:
3636        orinoco_unlock(priv, &flags);
3637
3638        return err;
3639}
3640
3641static int orinoco_ioctl_getpower(struct net_device *dev,
3642                                  struct iw_request_info *info,
3643                                  struct iw_param *prq,
3644                                  char *extra)
3645{
3646        struct orinoco_private *priv = netdev_priv(dev);
3647        hermes_t *hw = &priv->hw;
3648        int err = 0;
3649        u16 enable, period, timeout, mcast;
3650        unsigned long flags;
3651
3652        if (orinoco_lock(priv, &flags) != 0)
3653                return -EBUSY;
3654        
3655        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
3656        if (err)
3657                goto out;
3658
3659        err = hermes_read_wordrec(hw, USER_BAP,
3660                                  HERMES_RID_CNFMAXSLEEPDURATION, &period);
3661        if (err)
3662                goto out;
3663
3664        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
3665        if (err)
3666                goto out;
3667
3668        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
3669        if (err)
3670                goto out;
3671
3672        prq->disabled = !enable;
3673        /* Note : by default, display the period */
3674        if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
3675                prq->flags = IW_POWER_TIMEOUT;
3676                prq->value = timeout * 1000;
3677        } else {
3678                prq->flags = IW_POWER_PERIOD;
3679                prq->value = period * 1000;
3680        }
3681        if (mcast)
3682                prq->flags |= IW_POWER_ALL_R;
3683        else
3684                prq->flags |= IW_POWER_UNICAST_R;
3685
3686 out:
3687        orinoco_unlock(priv, &flags);
3688
3689        return err;
3690}
3691
3692static int orinoco_ioctl_getretry(struct net_device *dev,
3693                                  struct iw_request_info *info,
3694                                  struct iw_param *rrq,
3695                                  char *extra)
3696{
3697        struct orinoco_private *priv = netdev_priv(dev);
3698        hermes_t *hw = &priv->hw;
3699        int err = 0;
3700        u16 short_limit, long_limit, lifetime;
3701        unsigned long flags;
3702
3703        if (orinoco_lock(priv, &flags) != 0)
3704                return -EBUSY;
3705        
3706        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
3707                                  &short_limit);
3708        if (err)
3709                goto out;
3710
3711        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
3712                                  &long_limit);
3713        if (err)
3714                goto out;
3715
3716        err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
3717                                  &lifetime);
3718        if (err)
3719                goto out;
3720
3721        rrq->disabled = 0;              /* Can't be disabled */
3722
3723        /* Note : by default, display the retry number */
3724        if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
3725                rrq->flags = IW_RETRY_LIFETIME;
3726                rrq->value = lifetime * 1000;   /* ??? */
3727        } else {
3728                /* By default, display the min number */
3729                if ((rrq->flags & IW_RETRY_LONG)) {
3730                        rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
3731                        rrq->value = long_limit;
3732                } else {
3733                        rrq->flags = IW_RETRY_LIMIT;
3734                        rrq->value = short_limit;
3735                        if(short_limit != long_limit)
3736                                rrq->flags |= IW_RETRY_SHORT;
3737                }
3738        }
3739
3740 out:
3741        orinoco_unlock(priv, &flags);
3742
3743        return err;
3744}
3745
3746static int orinoco_ioctl_reset(struct net_device *dev,
3747                               struct iw_request_info *info,
3748                               void *wrqu,
3749                               char *extra)
3750{
3751        struct orinoco_private *priv = netdev_priv(dev);
3752
3753        if (! capable(CAP_NET_ADMIN))
3754                return -EPERM;
3755
3756        if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
3757                printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
3758
3759                /* Firmware reset */
3760                orinoco_reset(&priv->reset_work);
3761        } else {
3762                printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3763
3764                schedule_work(&priv->reset_work);
3765        }
3766
3767        return 0;
3768}
3769
3770static int orinoco_ioctl_setibssport(struct net_device *dev,
3771                                     struct iw_request_info *info,
3772                                     void *wrqu,
3773                                     char *extra)
3774
3775{
3776        struct orinoco_private *priv = netdev_priv(dev);
3777        int val = *( (int *) extra );
3778        unsigned long flags;
3779
3780        if (orinoco_lock(priv, &flags) != 0)
3781                return -EBUSY;
3782
3783        priv->ibss_port = val ;
3784
3785        /* Actually update the mode we are using */
3786        set_port_type(priv);
3787
3788        orinoco_unlock(priv, &flags);
3789        return -EINPROGRESS;            /* Call commit handler */
3790}
3791
3792static int orinoco_ioctl_getibssport(struct net_device *dev,
3793                                     struct iw_request_info *info,
3794                                     void *wrqu,
3795                                     char *extra)
3796{
3797        struct orinoco_private *priv = netdev_priv(dev);
3798        int *val = (int *) extra;
3799
3800        *val = priv->ibss_port;
3801        return 0;
3802}
3803
3804static int orinoco_ioctl_setport3(struct net_device *dev,
3805                                  struct iw_request_info *info,
3806                                  void *wrqu,
3807                                  char *extra)
3808{
3809        struct orinoco_private *priv = netdev_priv(dev);
3810        int val = *( (int *) extra );
3811        int err = 0;
3812        unsigned long flags;
3813
3814        if (orinoco_lock(priv, &flags) != 0)
3815                return -EBUSY;
3816
3817        switch (val) {
3818        case 0: /* Try to do IEEE ad-hoc mode */
3819                if (! priv->has_ibss) {
3820                        err = -EINVAL;
3821                        break;
3822                }
3823                priv->prefer_port3 = 0;
3824                        
3825                break;
3826
3827        case 1: /* Try to do Lucent proprietary ad-hoc mode */
3828                if (! priv->has_port3) {
3829                        err = -EINVAL;
3830                        break;
3831                }
3832                priv->prefer_port3 = 1;
3833                break;
3834
3835        default:
3836                err = -EINVAL;
3837        }
3838
3839        if (! err) {
3840                /* Actually update the mode we are using */
3841                set_port_type(priv);
3842                err = -EINPROGRESS;
3843        }
3844
3845        orinoco_unlock(priv, &flags);
3846
3847        return err;
3848}
3849
3850static int orinoco_ioctl_getport3(struct net_device *dev,
3851                                  struct iw_request_info *info,
3852                                  void *wrqu,
3853                                  char *extra)
3854{
3855        struct orinoco_private *priv = netdev_priv(dev);
3856        int *val = (int *) extra;
3857
3858        *val = priv->prefer_port3;
3859        return 0;
3860}
3861
3862static int orinoco_ioctl_setpreamble(struct net_device *dev,
3863                                     struct iw_request_info *info,
3864                                     void *wrqu,
3865                                     char *extra)
3866{
3867        struct orinoco_private *priv = netdev_priv(dev);
3868        unsigned long flags;
3869        int val;
3870
3871        if (! priv->has_preamble)
3872                return -EOPNOTSUPP;
3873
3874        /* 802.11b has recently defined some short preamble.
3875         * Basically, the Phy header has been reduced in size.
3876         * This increase performance, especially at high rates
3877         * (the preamble is transmitted at 1Mb/s), unfortunately
3878         * this give compatibility troubles... - Jean II */
3879        val = *( (int *) extra );
3880
3881        if (orinoco_lock(priv, &flags) != 0)
3882                return -EBUSY;
3883
3884        if (val)
3885                priv->preamble = 1;
3886        else
3887                priv->preamble = 0;
3888
3889        orinoco_unlock(priv, &flags);
3890
3891        return -EINPROGRESS;            /* Call commit handler */
3892}
3893
3894static int orinoco_ioctl_getpreamble(struct net_device *dev,
3895                                     struct iw_request_info *info,
3896                                     void *wrqu,
3897                                     char *extra)
3898{
3899        struct orinoco_private *priv = netdev_priv(dev);
3900        int *val = (int *) extra;
3901
3902        if (! priv->has_preamble)
3903                return -EOPNOTSUPP;
3904
3905        *val = priv->preamble;
3906        return 0;
3907}
3908
3909/* ioctl interface to hermes_read_ltv()
3910 * To use with iwpriv, pass the RID as the token argument, e.g.
3911 * iwpriv get_rid [0xfc00]
3912 * At least Wireless Tools 25 is required to use iwpriv.
3913 * For Wireless Tools 25 and 26 append "dummy" are the end. */
3914static int orinoco_ioctl_getrid(struct net_device *dev,
3915                                struct iw_request_info *info,
3916                                struct iw_point *data,
3917                                char *extra)
3918{
3919        struct orinoco_private *priv = netdev_priv(dev);
3920        hermes_t *hw = &priv->hw;
3921        int rid = data->flags;
3922        u16 length;
3923        int err;
3924        unsigned long flags;
3925
3926        /* It's a "get" function, but we don't want users to access the
3927         * WEP key and other raw firmware data */
3928        if (! capable(CAP_NET_ADMIN))
3929                return -EPERM;
3930
3931        if (rid < 0xfc00 || rid > 0xffff)
3932                return -EINVAL;
3933
3934        if (orinoco_lock(priv, &flags) != 0)
3935                return -EBUSY;
3936
3937        err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
3938                              extra);
3939        if (err)
3940                goto out;
3941
3942        data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
3943                             MAX_RID_LEN);
3944
3945 out:
3946        orinoco_unlock(priv, &flags);
3947        return err;
3948}
3949
3950/* Trigger a scan (look for other cells in the vicinity */
3951static int orinoco_ioctl_setscan(struct net_device *dev,
3952                                 struct iw_request_info *info,
3953                                 struct iw_param *srq,
3954                                 char *extra)
3955{
3956        struct orinoco_private *priv = netdev_priv(dev);
3957        hermes_t *hw = &priv->hw;
3958        int err = 0;
3959        unsigned long flags;
3960
3961        /* Note : you may have realised that, as this is a SET operation,
3962         * this is privileged and therefore a normal user can't
3963         * perform scanning.
3964         * This is not an error, while the device perform scanning,
3965         * traffic doesn't flow, so it's a perfect DoS...
3966         * Jean II */
3967
3968        if (orinoco_lock(priv, &flags) != 0)
3969                return -EBUSY;
3970
3971        /* Scanning with port 0 disabled would fail */
3972        if (!netif_running(dev)) {
3973                err = -ENETDOWN;
3974                goto out;
3975        }
3976
3977        /* In monitor mode, the scan results are always empty.
3978         * Probe responses are passed to the driver as received
3979         * frames and could be processed in software. */
3980        if (priv->iw_mode == IW_MODE_MONITOR) {
3981                err = -EOPNOTSUPP;
3982                goto out;
3983        }
3984
3985        /* Note : because we don't lock out the irq handler, the way
3986         * we access scan variables in priv is critical.
3987         *      o scan_inprogress : not touched by irq handler
3988         *      o scan_mode : not touched by irq handler
3989         *      o scan_len : synchronised with scan_result
3990         * Before modifying anything on those variables, please think hard !
3991         * Jean II */
3992
3993        /* Save flags */
3994        priv->scan_mode = srq->flags;
3995
3996        /* Always trigger scanning, even if it's in progress.
3997         * This way, if the info frame get lost, we will recover somewhat
3998         * gracefully  - Jean II */
3999
4000        if (priv->has_hostscan) {
4001                switch (priv->firmware_type) {
4002                case FIRMWARE_TYPE_SYMBOL:
4003                        err = hermes_write_wordrec(hw, USER_BAP,
4004                                                   HERMES_RID_CNFHOSTSCAN_SYMBOL,
4005                                                   HERMES_HOSTSCAN_SYMBOL_ONCE |
4006                                                   HERMES_HOSTSCAN_SYMBOL_BCAST);
4007                        break;
4008                case FIRMWARE_TYPE_INTERSIL: {
4009                        __le16 req[3];
4010
4011                        req[0] = cpu_to_le16(0x3fff);   /* All channels */
4012                        req[1] = cpu_to_le16(0x0001);   /* rate 1 Mbps */
4013                        req[2] = 0;                     /* Any ESSID */
4014                        err = HERMES_WRITE_RECORD(hw, USER_BAP,
4015                                                  HERMES_RID_CNFHOSTSCAN, &req);
4016                }
4017                break;
4018                case FIRMWARE_TYPE_AGERE:
4019                        err = hermes_write_wordrec(hw, USER_BAP,
4020                                                   HERMES_RID_CNFSCANSSID_AGERE,
4021                                                   0);  /* Any ESSID */
4022                        if (err)
4023                                break;
4024
4025                        err = hermes_inquire(hw, HERMES_INQ_SCAN);
4026                        break;
4027                }
4028        } else
4029                err = hermes_inquire(hw, HERMES_INQ_SCAN);
4030
4031        /* One more client */
4032        if (! err)
4033                priv->scan_inprogress = 1;
4034
4035 out:
4036        orinoco_unlock(priv, &flags);
4037        return err;
4038}
4039
4040#define MAX_CUSTOM_LEN 64
4041
4042/* Translate scan data returned from the card to a card independant
4043 * format that the Wireless Tools will understand - Jean II
4044 * Return message length or -errno for fatal errors */
4045static inline char *orinoco_translate_scan(struct net_device *dev,
4046                                           struct iw_request_info *info,
4047                                           char *current_ev,
4048                                           char *end_buf,
4049                                           union hermes_scan_info *bss,
4050                                           unsigned int last_scanned)
4051{
4052        struct orinoco_private *priv = netdev_priv(dev);
4053        u16                     capabilities;
4054        u16                     channel;
4055        struct iw_event         iwe;            /* Temporary buffer */
4056        char                   *p;
4057        char custom[MAX_CUSTOM_LEN];
4058
4059        /* First entry *MUST* be the AP MAC address */
4060        iwe.cmd = SIOCGIWAP;
4061        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
4062        memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN);
4063        current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4064                                          &iwe, IW_EV_ADDR_LEN);
4065
4066        /* Other entries will be displayed in the order we give them */
4067
4068        /* Add the ESSID */
4069        iwe.u.data.length = le16_to_cpu(bss->a.essid_len);
4070        if (iwe.u.data.length > 32)
4071                iwe.u.data.length = 32;
4072        iwe.cmd = SIOCGIWESSID;
4073        iwe.u.data.flags = 1;
4074        current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4075                                          &iwe, bss->a.essid);
4076
4077        /* Add mode */
4078        iwe.cmd = SIOCGIWMODE;
4079        capabilities = le16_to_cpu(bss->a.capabilities);
4080        if (capabilities & 0x3) {
4081                if (capabilities & 0x1)
4082                        iwe.u.mode = IW_MODE_MASTER;
4083                else
4084                        iwe.u.mode = IW_MODE_ADHOC;
4085                current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4086                                                  &iwe, IW_EV_UINT_LEN);
4087        }
4088
4089        channel = bss->s.channel;
4090        if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
4091                /* Add frequency */
4092                iwe.cmd = SIOCGIWFREQ;
4093                iwe.u.freq.m = channel_frequency[channel-1] * 100000;
4094                iwe.u.freq.e = 1;
4095                current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4096                                                  &iwe, IW_EV_FREQ_LEN);
4097        }
4098
4099        /* Add quality statistics */
4100        iwe.cmd = IWEVQUAL;
4101        iwe.u.qual.updated = 0x10;      /* no link quality */
4102        iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
4103        iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
4104        /* Wireless tools prior to 27.pre22 will show link quality
4105         * anyway, so we provide a reasonable value. */
4106        if (iwe.u.qual.level > iwe.u.qual.noise)
4107                iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
4108        else
4109                iwe.u.qual.qual = 0;
4110        current_ev = iwe_stream_add_event(info, current_ev, end_buf,
4111                                          &iwe, IW_EV_QUAL_LEN);
4112
4113        /* Add encryption capability */
4114        iwe.cmd = SIOCGIWENCODE;
4115        if (capabilities & 0x10)
4116                iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
4117        else
4118                iwe.u.data.flags = IW_ENCODE_DISABLED;
4119        iwe.u.data.length = 0;
4120        current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4121                                          &iwe, bss->a.essid);
4122
4123        /* Add EXTRA: Age to display seconds since last beacon/probe response
4124         * for given network. */
4125        iwe.cmd = IWEVCUSTOM;
4126        p = custom;
4127        p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
4128                      " Last beacon: %dms ago",
4129                      jiffies_to_msecs(jiffies - last_scanned));
4130        iwe.u.data.length = p - custom;
4131        if (iwe.u.data.length)
4132                current_ev = iwe_stream_add_point(info, current_ev, end_buf,
4133                                                  &iwe, custom);
4134
4135        /* Bit rate is not available in Lucent/Agere firmwares */
4136        if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
4137                char *current_val = current_ev + iwe_stream_lcp_len(info);
4138                int i;
4139                int step;
4140
4141                if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
4142                        step = 2;
4143                else
4144                        step = 1;
4145
4146                iwe.cmd = SIOCGIWRATE;
4147                /* Those two flags are ignored... */
4148                iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
4149                /* Max 10 values */
4150                for (i = 0; i < 10; i += step) {
4151                        /* NULL terminated */
4152                        if (bss->p.rates[i] == 0x0)
4153                                break;
4154                        /* Bit rate given in 500 kb/s units (+ 0x80) */
4155                        iwe.u.bitrate.value = ((bss->p.rates[i] & 0x7f) * 500000);
4156                        current_val = iwe_stream_add_value(info, current_ev,
4157                                                           current_val,
4158                                                           end_buf, &iwe,
4159                                                           IW_EV_PARAM_LEN);
4160                }
4161                /* Check if we added any event */
4162                if ((current_val - current_ev) > iwe_stream_lcp_len(info))
4163                        current_ev = current_val;
4164        }
4165
4166        return current_ev;
4167}
4168
4169/* Return results of a scan */
4170static int orinoco_ioctl_getscan(struct net_device *dev,
4171                                 struct iw_request_info *info,
4172                                 struct iw_point *srq,
4173                                 char *extra)
4174{
4175        struct orinoco_private *priv = netdev_priv(dev);
4176        bss_element *bss;
4177        int err = 0;
4178        unsigned long flags;
4179        char *current_ev = extra;
4180
4181        if (orinoco_lock(priv, &flags) != 0)
4182                return -EBUSY;
4183
4184        if (priv->scan_inprogress) {
4185                /* Important note : we don't want to block the caller
4186                 * until results are ready for various reasons.
4187                 * First, managing wait queues is complex and racy.
4188                 * Second, we grab some rtnetlink lock before comming
4189                 * here (in dev_ioctl()).
4190                 * Third, we generate an Wireless Event, so the
4191                 * caller can wait itself on that - Jean II */
4192                err = -EAGAIN;
4193                goto out;
4194        }
4195
4196        list_for_each_entry(bss, &priv->bss_list, list) {
4197                /* Translate to WE format this entry */
4198                current_ev = orinoco_translate_scan(dev, info, current_ev,
4199                                                    extra + srq->length,
4200                                                    &bss->bss,
4201                                                    bss->last_scanned);
4202
4203                /* Check if there is space for one more entry */
4204                if ((extra + srq->length - current_ev) <= IW_EV_ADDR_LEN) {
4205                        /* Ask user space to try again with a bigger buffer */
4206                        err = -E2BIG;
4207                        goto out;
4208                }
4209        }
4210
4211        srq->length = (current_ev - extra);
4212        srq->flags = (__u16) priv->scan_mode;
4213
4214out:
4215        orinoco_unlock(priv, &flags);
4216        return err;
4217}
4218
4219/* Commit handler, called after set operations */
4220static int orinoco_ioctl_commit(struct net_device *dev,
4221                                struct iw_request_info *info,
4222                                void *wrqu,
4223                                char *extra)
4224{
4225        struct orinoco_private *priv = netdev_priv(dev);
4226        struct hermes *hw = &priv->hw;
4227        unsigned long flags;
4228        int err = 0;
4229
4230        if (!priv->open)
4231                return 0;
4232
4233        if (priv->broken_disableport) {
4234                orinoco_reset(&priv->reset_work);
4235                return 0;
4236        }
4237
4238        if (orinoco_lock(priv, &flags) != 0)
4239                return err;
4240
4241        err = hermes_disable_port(hw, 0);
4242        if (err) {
4243                printk(KERN_WARNING "%s: Unable to disable port "
4244                       "while reconfiguring card\n", dev->name);
4245                priv->broken_disableport = 1;
4246                goto out;
4247        }
4248
4249        err = __orinoco_program_rids(dev);
4250        if (err) {
4251                printk(KERN_WARNING "%s: Unable to reconfigure card\n",
4252                       dev->name);
4253                goto out;
4254        }
4255
4256        err = hermes_enable_port(hw, 0);
4257        if (err) {
4258                printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
4259                       dev->name);
4260                goto out;
4261        }
4262
4263 out:
4264        if (err) {
4265                printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
4266                schedule_work(&priv->reset_work);
4267                err = 0;
4268        }
4269
4270        orinoco_unlock(priv, &flags);
4271        return err;
4272}
4273
4274static const struct iw_priv_args orinoco_privtab[] = {
4275        { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
4276        { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
4277        { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4278          0, "set_port3" },
4279        { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4280          "get_port3" },
4281        { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4282          0, "set_preamble" },
4283        { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4284          "get_preamble" },
4285        { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4286          0, "set_ibssport" },
4287        { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
4288          "get_ibssport" },
4289        { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
4290          "get_rid" },
4291};
4292
4293
4294/*
4295 * Structures to export the Wireless Handlers
4296 */
4297
4298static const iw_handler orinoco_handler[] = {
4299        [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_commit,
4300        [SIOCGIWNAME  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getname,
4301        [SIOCSIWFREQ  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfreq,
4302        [SIOCGIWFREQ  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfreq,
4303        [SIOCSIWMODE  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setmode,
4304        [SIOCGIWMODE  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getmode,
4305        [SIOCSIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setsens,
4306        [SIOCGIWSENS  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getsens,
4307        [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwrange,
4308        [SIOCSIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
4309        [SIOCGIWSPY   -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
4310        [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
4311        [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
4312        [SIOCSIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setwap,
4313        [SIOCGIWAP    -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getwap,
4314        [SIOCSIWSCAN  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setscan,
4315        [SIOCGIWSCAN  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getscan,
4316        [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setessid,
4317        [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getessid,
4318        [SIOCSIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setnick,
4319        [SIOCGIWNICKN -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getnick,
4320        [SIOCSIWRATE  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrate,
4321        [SIOCGIWRATE  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrate,
4322        [SIOCSIWRTS   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setrts,
4323        [SIOCGIWRTS   -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getrts,
4324        [SIOCSIWFRAG  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setfrag,
4325        [SIOCGIWFRAG  -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getfrag,
4326        [SIOCGIWRETRY -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getretry,
4327        [SIOCSIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setiwencode,
4328        [SIOCGIWENCODE-SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getiwencode,
4329        [SIOCSIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_setpower,
4330        [SIOCGIWPOWER -SIOCIWFIRST] = (iw_handler) orinoco_ioctl_getpower,
4331};
4332
4333
4334/*
4335  Added typecasting since we no longer use iwreq_data -- Moustafa
4336 */
4337static const iw_handler orinoco_private_handler[] = {
4338        [0] = (iw_handler) orinoco_ioctl_reset,
4339        [1] = (iw_handler) orinoco_ioctl_reset,
4340        [2] = (iw_handler) orinoco_ioctl_setport3,
4341        [3] = (iw_handler) orinoco_ioctl_getport3,
4342        [4] = (iw_handler) orinoco_ioctl_setpreamble,
4343        [5] = (iw_handler) orinoco_ioctl_getpreamble,
4344        [6] = (iw_handler) orinoco_ioctl_setibssport,
4345        [7] = (iw_handler) orinoco_ioctl_getibssport,
4346        [9] = (iw_handler) orinoco_ioctl_getrid,
4347};
4348
4349static const struct iw_handler_def orinoco_handler_def = {
4350        .num_standard = ARRAY_SIZE(orinoco_handler),
4351        .num_private = ARRAY_SIZE(orinoco_private_handler),
4352        .num_private_args = ARRAY_SIZE(orinoco_privtab),
4353        .standard = orinoco_handler,
4354        .private = orinoco_private_handler,
4355        .private_args = orinoco_privtab,
4356        .get_wireless_stats = orinoco_get_wireless_stats,
4357};
4358
4359static void orinoco_get_drvinfo(struct net_device *dev,
4360                                struct ethtool_drvinfo *info)
4361{
4362        struct orinoco_private *priv = netdev_priv(dev);
4363
4364        strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
4365        strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
4366        strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
4367        if (dev->dev.parent)
4368                strncpy(info->bus_info, dev->dev.parent->bus_id,
4369                        sizeof(info->bus_info) - 1);
4370        else
4371                snprintf(info->bus_info, sizeof(info->bus_info) - 1,
4372                         "PCMCIA %p", priv->hw.iobase);
4373}
4374
4375static const struct ethtool_ops orinoco_ethtool_ops = {
4376        .get_drvinfo = orinoco_get_drvinfo,
4377        .get_link = ethtool_op_get_link,
4378};
4379
4380/********************************************************************/
4381/* Module initialization                                            */
4382/********************************************************************/
4383
4384EXPORT_SYMBOL(alloc_orinocodev);
4385EXPORT_SYMBOL(free_orinocodev);
4386
4387EXPORT_SYMBOL(__orinoco_up);
4388EXPORT_SYMBOL(__orinoco_down);
4389EXPORT_SYMBOL(orinoco_reinit_firmware);
4390
4391EXPORT_SYMBOL(orinoco_interrupt);
4392
4393/* Can't be declared "const" or the whole __initdata section will
4394 * become const */
4395static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
4396        " (David Gibson <hermes@gibson.dropbear.id.au>, "
4397        "Pavel Roskin <proski@gnu.org>, et al)";
4398
4399static int __init init_orinoco(void)
4400{
4401        printk(KERN_DEBUG "%s\n", version);
4402        return 0;
4403}
4404
4405static void __exit exit_orinoco(void)
4406{
4407}
4408
4409module_init(init_orinoco);
4410module_exit(exit_orinoco);
4411
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.