linux/drivers/net/wireless/airo.c
<<
>>
Prefs
   1/*======================================================================
   2
   3    Aironet driver for 4500 and 4800 series cards
   4
   5    This code is released under both the GPL version 2 and BSD licenses.
   6    Either license may be used.  The respective licenses are found at
   7    the end of this file.
   8
   9    This code was developed by Benjamin Reed <breed@users.sourceforge.net>
  10    including portions of which come from the Aironet PC4500
  11    Developer's Reference Manual and used with permission.  Copyright
  12    (C) 1999 Benjamin Reed.  All Rights Reserved.  Permission to use
  13    code in the Developer's manual was granted for this driver by
  14    Aironet.  Major code contributions were received from Javier Achirica
  15    <achirica@users.sourceforge.net> and Jean Tourrilhes <jt@hpl.hp.com>.
  16    Code was also integrated from the Cisco Aironet driver for Linux.
  17    Support for MPI350 cards was added by Fabrice Bellet
  18    <fabrice@bellet.info>.
  19
  20======================================================================*/
  21
  22#include <linux/err.h>
  23#include <linux/init.h>
  24
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/proc_fs.h>
  28
  29#include <linux/sched.h>
  30#include <linux/ptrace.h>
  31#include <linux/slab.h>
  32#include <linux/string.h>
  33#include <linux/timer.h>
  34#include <linux/interrupt.h>
  35#include <linux/in.h>
  36#include <linux/bitops.h>
  37#include <linux/scatterlist.h>
  38#include <linux/crypto.h>
  39#include <asm/io.h>
  40#include <asm/system.h>
  41
  42#include <linux/netdevice.h>
  43#include <linux/etherdevice.h>
  44#include <linux/skbuff.h>
  45#include <linux/if_arp.h>
  46#include <linux/ioport.h>
  47#include <linux/pci.h>
  48#include <asm/uaccess.h>
  49#include <net/ieee80211.h>
  50#include <linux/kthread.h>
  51#include <linux/freezer.h>
  52
  53#include "airo.h"
  54
  55#define DRV_NAME "airo"
  56
  57#ifdef CONFIG_PCI
  58static struct pci_device_id card_ids[] = {
  59        { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
  60        { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID },
  61        { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, },
  62        { 0x14b9, 0x0340, PCI_ANY_ID, PCI_ANY_ID, },
  63        { 0x14b9, 0x0350, PCI_ANY_ID, PCI_ANY_ID, },
  64        { 0x14b9, 0x5000, PCI_ANY_ID, PCI_ANY_ID, },
  65        { 0x14b9, 0xa504, PCI_ANY_ID, PCI_ANY_ID, },
  66        { 0, }
  67};
  68MODULE_DEVICE_TABLE(pci, card_ids);
  69
  70static int airo_pci_probe(struct pci_dev *, const struct pci_device_id *);
  71static void airo_pci_remove(struct pci_dev *);
  72static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state);
  73static int airo_pci_resume(struct pci_dev *pdev);
  74
  75static struct pci_driver airo_driver = {
  76        .name     = DRV_NAME,
  77        .id_table = card_ids,
  78        .probe    = airo_pci_probe,
  79        .remove   = __devexit_p(airo_pci_remove),
  80        .suspend  = airo_pci_suspend,
  81        .resume   = airo_pci_resume,
  82};
  83#endif /* CONFIG_PCI */
  84
  85/* Include Wireless Extension definition and check version - Jean II */
  86#include <linux/wireless.h>
  87#define WIRELESS_SPY            // enable iwspy support
  88#include <net/iw_handler.h>     // New driver API
  89
  90#define CISCO_EXT               // enable Cisco extensions
  91#ifdef CISCO_EXT
  92#include <linux/delay.h>
  93#endif
  94
  95/* Hack to do some power saving */
  96#define POWER_ON_DOWN
  97
  98/* As you can see this list is HUGH!
  99   I really don't know what a lot of these counts are about, but they
 100   are all here for completeness.  If the IGNLABEL macro is put in
 101   infront of the label, that statistic will not be included in the list
 102   of statistics in the /proc filesystem */
 103
 104#define IGNLABEL(comment) NULL
 105static char *statsLabels[] = {
 106        "RxOverrun",
 107        IGNLABEL("RxPlcpCrcErr"),
 108        IGNLABEL("RxPlcpFormatErr"),
 109        IGNLABEL("RxPlcpLengthErr"),
 110        "RxMacCrcErr",
 111        "RxMacCrcOk",
 112        "RxWepErr",
 113        "RxWepOk",
 114        "RetryLong",
 115        "RetryShort",
 116        "MaxRetries",
 117        "NoAck",
 118        "NoCts",
 119        "RxAck",
 120        "RxCts",
 121        "TxAck",
 122        "TxRts",
 123        "TxCts",
 124        "TxMc",
 125        "TxBc",
 126        "TxUcFrags",
 127        "TxUcPackets",
 128        "TxBeacon",
 129        "RxBeacon",
 130        "TxSinColl",
 131        "TxMulColl",
 132        "DefersNo",
 133        "DefersProt",
 134        "DefersEngy",
 135        "DupFram",
 136        "RxFragDisc",
 137        "TxAged",
 138        "RxAged",
 139        "LostSync-MaxRetry",
 140        "LostSync-MissedBeacons",
 141        "LostSync-ArlExceeded",
 142        "LostSync-Deauth",
 143        "LostSync-Disassoced",
 144        "LostSync-TsfTiming",
 145        "HostTxMc",
 146        "HostTxBc",
 147        "HostTxUc",
 148        "HostTxFail",
 149        "HostRxMc",
 150        "HostRxBc",
 151        "HostRxUc",
 152        "HostRxDiscard",
 153        IGNLABEL("HmacTxMc"),
 154        IGNLABEL("HmacTxBc"),
 155        IGNLABEL("HmacTxUc"),
 156        IGNLABEL("HmacTxFail"),
 157        IGNLABEL("HmacRxMc"),
 158        IGNLABEL("HmacRxBc"),
 159        IGNLABEL("HmacRxUc"),
 160        IGNLABEL("HmacRxDiscard"),
 161        IGNLABEL("HmacRxAccepted"),
 162        "SsidMismatch",
 163        "ApMismatch",
 164        "RatesMismatch",
 165        "AuthReject",
 166        "AuthTimeout",
 167        "AssocReject",
 168        "AssocTimeout",
 169        IGNLABEL("ReasonOutsideTable"),
 170        IGNLABEL("ReasonStatus1"),
 171        IGNLABEL("ReasonStatus2"),
 172        IGNLABEL("ReasonStatus3"),
 173        IGNLABEL("ReasonStatus4"),
 174        IGNLABEL("ReasonStatus5"),
 175        IGNLABEL("ReasonStatus6"),
 176        IGNLABEL("ReasonStatus7"),
 177        IGNLABEL("ReasonStatus8"),
 178        IGNLABEL("ReasonStatus9"),
 179        IGNLABEL("ReasonStatus10"),
 180        IGNLABEL("ReasonStatus11"),
 181        IGNLABEL("ReasonStatus12"),
 182        IGNLABEL("ReasonStatus13"),
 183        IGNLABEL("ReasonStatus14"),
 184        IGNLABEL("ReasonStatus15"),
 185        IGNLABEL("ReasonStatus16"),
 186        IGNLABEL("ReasonStatus17"),
 187        IGNLABEL("ReasonStatus18"),
 188        IGNLABEL("ReasonStatus19"),
 189        "RxMan",
 190        "TxMan",
 191        "RxRefresh",
 192        "TxRefresh",
 193        "RxPoll",
 194        "TxPoll",
 195        "HostRetries",
 196        "LostSync-HostReq",
 197        "HostTxBytes",
 198        "HostRxBytes",
 199        "ElapsedUsec",
 200        "ElapsedSec",
 201        "LostSyncBetterAP",
 202        "PrivacyMismatch",
 203        "Jammed",
 204        "DiscRxNotWepped",
 205        "PhyEleMismatch",
 206        (char*)-1 };
 207#ifndef RUN_AT
 208#define RUN_AT(x) (jiffies+(x))
 209#endif
 210
 211
 212/* These variables are for insmod, since it seems that the rates
 213   can only be set in setup_card.  Rates should be a comma separated
 214   (no spaces) list of rates (up to 8). */
 215
 216static int rates[8];
 217static int basic_rate;
 218static char *ssids[3];
 219
 220static int io[4];
 221static int irq[4];
 222
 223static
 224int maxencrypt /* = 0 */; /* The highest rate that the card can encrypt at.
 225                       0 means no limit.  For old cards this was 4 */
 226
 227static int auto_wep /* = 0 */; /* If set, it tries to figure out the wep mode */
 228static int aux_bap /* = 0 */; /* Checks to see if the aux ports are needed to read
 229                    the bap, needed on some older cards and buses. */
 230static int adhoc;
 231
 232static int probe = 1;
 233
 234static int proc_uid /* = 0 */;
 235
 236static int proc_gid /* = 0 */;
 237
 238static int airo_perm = 0555;
 239
 240static int proc_perm = 0644;
 241
 242MODULE_AUTHOR("Benjamin Reed");
 243MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \
 244cards.  Direct support for ISA/PCI/MPI cards and support \
 245for PCMCIA when used with airo_cs.");
 246MODULE_LICENSE("Dual BSD/GPL");
 247MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
 248module_param_array(io, int, NULL, 0);
 249module_param_array(irq, int, NULL, 0);
 250module_param(basic_rate, int, 0);
 251module_param_array(rates, int, NULL, 0);
 252module_param_array(ssids, charp, NULL, 0);
 253module_param(auto_wep, int, 0);
 254MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \
 255the authentication options until an association is made.  The value of \
 256auto_wep is number of the wep keys to check.  A value of 2 will try using \
 257the key at index 0 and index 1.");
 258module_param(aux_bap, int, 0);
 259MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \
 260than seems to work better for older cards with some older buses.  Before \
 261switching it checks that the switch is needed.");
 262module_param(maxencrypt, int, 0);
 263MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \
 264encryption.  Units are in 512kbs.  Zero (default) means there is no limit. \
 265Older cards used to be limited to 2mbs (4).");
 266module_param(adhoc, int, 0);
 267MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode.");
 268module_param(probe, int, 0);
 269MODULE_PARM_DESC(probe, "If zero, the driver won't start the card.");
 270
 271module_param(proc_uid, int, 0);
 272MODULE_PARM_DESC(proc_uid, "The uid that the /proc files will belong to.");
 273module_param(proc_gid, int, 0);
 274MODULE_PARM_DESC(proc_gid, "The gid that the /proc files will belong to.");
 275module_param(airo_perm, int, 0);
 276MODULE_PARM_DESC(airo_perm, "The permission bits of /proc/[driver/]aironet.");
 277module_param(proc_perm, int, 0);
 278MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc");
 279
 280/* This is a kind of sloppy hack to get this information to OUT4500 and
 281   IN4500.  I would be extremely interested in the situation where this
 282   doesn't work though!!! */
 283static int do8bitIO = 0;
 284
 285/* Return codes */
 286#define SUCCESS 0
 287#define ERROR -1
 288#define NO_PACKET -2
 289
 290/* Commands */
 291#define NOP2            0x0000
 292#define MAC_ENABLE      0x0001
 293#define MAC_DISABLE     0x0002
 294#define CMD_LOSE_SYNC   0x0003 /* Not sure what this does... */
 295#define CMD_SOFTRESET   0x0004
 296#define HOSTSLEEP       0x0005
 297#define CMD_MAGIC_PKT   0x0006
 298#define CMD_SETWAKEMASK 0x0007
 299#define CMD_READCFG     0x0008
 300#define CMD_SETMODE     0x0009
 301#define CMD_ALLOCATETX  0x000a
 302#define CMD_TRANSMIT    0x000b
 303#define CMD_DEALLOCATETX 0x000c
 304#define NOP             0x0010
 305#define CMD_WORKAROUND  0x0011
 306#define CMD_ALLOCATEAUX 0x0020
 307#define CMD_ACCESS      0x0021
 308#define CMD_PCIBAP      0x0022
 309#define CMD_PCIAUX      0x0023
 310#define CMD_ALLOCBUF    0x0028
 311#define CMD_GETTLV      0x0029
 312#define CMD_PUTTLV      0x002a
 313#define CMD_DELTLV      0x002b
 314#define CMD_FINDNEXTTLV 0x002c
 315#define CMD_PSPNODES    0x0030
 316#define CMD_SETCW       0x0031    
 317#define CMD_SETPCF      0x0032    
 318#define CMD_SETPHYREG   0x003e
 319#define CMD_TXTEST      0x003f
 320#define MAC_ENABLETX    0x0101
 321#define CMD_LISTBSS     0x0103
 322#define CMD_SAVECFG     0x0108
 323#define CMD_ENABLEAUX   0x0111
 324#define CMD_WRITERID    0x0121
 325#define CMD_USEPSPNODES 0x0130
 326#define MAC_ENABLERX    0x0201
 327
 328/* Command errors */
 329#define ERROR_QUALIF 0x00
 330#define ERROR_ILLCMD 0x01
 331#define ERROR_ILLFMT 0x02
 332#define ERROR_INVFID 0x03
 333#define ERROR_INVRID 0x04
 334#define ERROR_LARGE 0x05
 335#define ERROR_NDISABL 0x06
 336#define ERROR_ALLOCBSY 0x07
 337#define ERROR_NORD 0x0B
 338#define ERROR_NOWR 0x0C
 339#define ERROR_INVFIDTX 0x0D
 340#define ERROR_TESTACT 0x0E
 341#define ERROR_TAGNFND 0x12
 342#define ERROR_DECODE 0x20
 343#define ERROR_DESCUNAV 0x21
 344#define ERROR_BADLEN 0x22
 345#define ERROR_MODE 0x80
 346#define ERROR_HOP 0x81
 347#define ERROR_BINTER 0x82
 348#define ERROR_RXMODE 0x83
 349#define ERROR_MACADDR 0x84
 350#define ERROR_RATES 0x85
 351#define ERROR_ORDER 0x86
 352#define ERROR_SCAN 0x87
 353#define ERROR_AUTH 0x88
 354#define ERROR_PSMODE 0x89
 355#define ERROR_RTYPE 0x8A
 356#define ERROR_DIVER 0x8B
 357#define ERROR_SSID 0x8C
 358#define ERROR_APLIST 0x8D
 359#define ERROR_AUTOWAKE 0x8E
 360#define ERROR_LEAP 0x8F
 361
 362/* Registers */
 363#define COMMAND 0x00
 364#define PARAM0 0x02
 365#define PARAM1 0x04
 366#define PARAM2 0x06
 367#define STATUS 0x08
 368#define RESP0 0x0a
 369#define RESP1 0x0c
 370#define RESP2 0x0e
 371#define LINKSTAT 0x10
 372#define SELECT0 0x18
 373#define OFFSET0 0x1c
 374#define RXFID 0x20
 375#define TXALLOCFID 0x22
 376#define TXCOMPLFID 0x24
 377#define DATA0 0x36
 378#define EVSTAT 0x30
 379#define EVINTEN 0x32
 380#define EVACK 0x34
 381#define SWS0 0x28
 382#define SWS1 0x2a
 383#define SWS2 0x2c
 384#define SWS3 0x2e
 385#define AUXPAGE 0x3A
 386#define AUXOFF 0x3C
 387#define AUXDATA 0x3E
 388
 389#define FID_TX 1
 390#define FID_RX 2
 391/* Offset into aux memory for descriptors */
 392#define AUX_OFFSET 0x800
 393/* Size of allocated packets */
 394#define PKTSIZE 1840
 395#define RIDSIZE 2048
 396/* Size of the transmit queue */
 397#define MAXTXQ 64
 398
 399/* BAP selectors */
 400#define BAP0 0 // Used for receiving packets
 401#define BAP1 2 // Used for xmiting packets and working with RIDS
 402
 403/* Flags */
 404#define COMMAND_BUSY 0x8000
 405
 406#define BAP_BUSY 0x8000
 407#define BAP_ERR 0x4000
 408#define BAP_DONE 0x2000
 409
 410#define PROMISC 0xffff
 411#define NOPROMISC 0x0000
 412
 413#define EV_CMD 0x10
 414#define EV_CLEARCOMMANDBUSY 0x4000
 415#define EV_RX 0x01
 416#define EV_TX 0x02
 417#define EV_TXEXC 0x04
 418#define EV_ALLOC 0x08
 419#define EV_LINK 0x80
 420#define EV_AWAKE 0x100
 421#define EV_TXCPY 0x400
 422#define EV_UNKNOWN 0x800
 423#define EV_MIC 0x1000 /* Message Integrity Check Interrupt */
 424#define EV_AWAKEN 0x2000
 425#define STATUS_INTS (EV_AWAKE|EV_LINK|EV_TXEXC|EV_TX|EV_TXCPY|EV_RX|EV_MIC)
 426
 427#ifdef CHECK_UNKNOWN_INTS
 428#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN)
 429#else
 430#define IGNORE_INTS (~STATUS_INTS)
 431#endif
 432
 433/* RID TYPES */
 434#define RID_RW 0x20
 435
 436/* The RIDs */
 437#define RID_CAPABILITIES 0xFF00
 438#define RID_APINFO     0xFF01
 439#define RID_RADIOINFO  0xFF02
 440#define RID_UNKNOWN3   0xFF03
 441#define RID_RSSI       0xFF04
 442#define RID_CONFIG     0xFF10
 443#define RID_SSID       0xFF11
 444#define RID_APLIST     0xFF12
 445#define RID_DRVNAME    0xFF13
 446#define RID_ETHERENCAP 0xFF14
 447#define RID_WEP_TEMP   0xFF15
 448#define RID_WEP_PERM   0xFF16
 449#define RID_MODULATION 0xFF17
 450#define RID_OPTIONS    0xFF18
 451#define RID_ACTUALCONFIG 0xFF20 /*readonly*/
 452#define RID_FACTORYCONFIG 0xFF21
 453#define RID_UNKNOWN22  0xFF22
 454#define RID_LEAPUSERNAME 0xFF23
 455#define RID_LEAPPASSWORD 0xFF24
 456#define RID_STATUS     0xFF50
 457#define RID_BEACON_HST 0xFF51
 458#define RID_BUSY_HST   0xFF52
 459#define RID_RETRIES_HST 0xFF53
 460#define RID_UNKNOWN54  0xFF54
 461#define RID_UNKNOWN55  0xFF55
 462#define RID_UNKNOWN56  0xFF56
 463#define RID_MIC        0xFF57
 464#define RID_STATS16    0xFF60
 465#define RID_STATS16DELTA 0xFF61
 466#define RID_STATS16DELTACLEAR 0xFF62
 467#define RID_STATS      0xFF68
 468#define RID_STATSDELTA 0xFF69
 469#define RID_STATSDELTACLEAR 0xFF6A
 470#define RID_ECHOTEST_RID 0xFF70
 471#define RID_ECHOTEST_RESULTS 0xFF71
 472#define RID_BSSLISTFIRST 0xFF72
 473#define RID_BSSLISTNEXT  0xFF73
 474#define RID_WPA_BSSLISTFIRST 0xFF74
 475#define RID_WPA_BSSLISTNEXT  0xFF75
 476
 477typedef struct {
 478        u16 cmd;
 479        u16 parm0;
 480        u16 parm1;
 481        u16 parm2;
 482} Cmd;
 483
 484typedef struct {
 485        u16 status;
 486        u16 rsp0;
 487        u16 rsp1;
 488        u16 rsp2;
 489} Resp;
 490
 491/*
 492 * Rids and endian-ness:  The Rids will always be in cpu endian, since
 493 * this all the patches from the big-endian guys end up doing that.
 494 * so all rid access should use the read/writeXXXRid routines.
 495 */
 496
 497/* This is redundant for x86 archs, but it seems necessary for ARM */
 498#pragma pack(1)
 499
 500/* This structure came from an email sent to me from an engineer at
 501   aironet for inclusion into this driver */
 502typedef struct {
 503        u16 len;
 504        u16 kindex;
 505        u8 mac[ETH_ALEN];
 506        u16 klen;
 507        u8 key[16];
 508} WepKeyRid;
 509
 510/* These structures are from the Aironet's PC4500 Developers Manual */
 511typedef struct {
 512        u16 len;
 513        u8 ssid[32];
 514} Ssid;
 515
 516typedef struct {
 517        u16 len;
 518        Ssid ssids[3];
 519} SsidRid;
 520
 521typedef struct {
 522        u16 len;
 523        u16 modulation;
 524#define MOD_DEFAULT 0
 525#define MOD_CCK 1
 526#define MOD_MOK 2
 527} ModulationRid;
 528
 529typedef struct {
 530        u16 len; /* sizeof(ConfigRid) */
 531        u16 opmode; /* operating mode */
 532#define MODE_STA_IBSS 0
 533#define MODE_STA_ESS 1
 534#define MODE_AP 2
 535#define MODE_AP_RPTR 3
 536#define MODE_ETHERNET_HOST (0<<8) /* rx payloads converted */
 537#define MODE_LLC_HOST (1<<8) /* rx payloads left as is */
 538#define MODE_AIRONET_EXTEND (1<<9) /* enable Aironet extenstions */
 539#define MODE_AP_INTERFACE (1<<10) /* enable ap interface extensions */
 540#define MODE_ANTENNA_ALIGN (1<<11) /* enable antenna alignment */
 541#define MODE_ETHER_LLC (1<<12) /* enable ethernet LLC */
 542#define MODE_LEAF_NODE (1<<13) /* enable leaf node bridge */
 543#define MODE_CF_POLLABLE (1<<14) /* enable CF pollable */
 544#define MODE_MIC (1<<15) /* enable MIC */
 545        u16 rmode; /* receive mode */
 546#define RXMODE_BC_MC_ADDR 0
 547#define RXMODE_BC_ADDR 1 /* ignore multicasts */
 548#define RXMODE_ADDR 2 /* ignore multicast and broadcast */
 549#define RXMODE_RFMON 3 /* wireless monitor mode */
 550#define RXMODE_RFMON_ANYBSS 4
 551#define RXMODE_LANMON 5 /* lan style monitor -- data packets only */
 552#define RXMODE_DISABLE_802_3_HEADER (1<<8) /* disables 802.3 header on rx */
 553#define RXMODE_NORMALIZED_RSSI (1<<9) /* return normalized RSSI */
 554        u16 fragThresh;
 555        u16 rtsThres;
 556        u8 macAddr[ETH_ALEN];
 557        u8 rates[8];
 558        u16 shortRetryLimit;
 559        u16 longRetryLimit;
 560        u16 txLifetime; /* in kusec */
 561        u16 rxLifetime; /* in kusec */
 562        u16 stationary;
 563        u16 ordering;
 564        u16 u16deviceType; /* for overriding device type */
 565        u16 cfpRate;
 566        u16 cfpDuration;
 567        u16 _reserved1[3];
 568        /*---------- Scanning/Associating ----------*/
 569        u16 scanMode;
 570#define SCANMODE_ACTIVE 0
 571#define SCANMODE_PASSIVE 1
 572#define SCANMODE_AIROSCAN 2
 573        u16 probeDelay; /* in kusec */
 574        u16 probeEnergyTimeout; /* in kusec */
 575        u16 probeResponseTimeout;
 576        u16 beaconListenTimeout;
 577        u16 joinNetTimeout;
 578        u16 authTimeout;
 579        u16 authType;
 580#define AUTH_OPEN 0x1
 581#define AUTH_ENCRYPT 0x101
 582#define AUTH_SHAREDKEY 0x102
 583#define AUTH_ALLOW_UNENCRYPTED 0x200
 584        u16 associationTimeout;
 585        u16 specifiedApTimeout;
 586        u16 offlineScanInterval;
 587        u16 offlineScanDuration;
 588        u16 linkLossDelay;
 589        u16 maxBeaconLostTime;
 590        u16 refreshInterval;
 591#define DISABLE_REFRESH 0xFFFF
 592        u16 _reserved1a[1];
 593        /*---------- Power save operation ----------*/
 594        u16 powerSaveMode;
 595#define POWERSAVE_CAM 0
 596#define POWERSAVE_PSP 1
 597#define POWERSAVE_PSPCAM 2
 598        u16 sleepForDtims;
 599        u16 listenInterval;
 600        u16 fastListenInterval;
 601        u16 listenDecay;
 602        u16 fastListenDelay;
 603        u16 _reserved2[2];
 604        /*---------- Ap/Ibss config items ----------*/
 605        u16 beaconPeriod;
 606        u16 atimDuration;
 607        u16 hopPeriod;
 608        u16 channelSet;
 609        u16 channel;
 610        u16 dtimPeriod;
 611        u16 bridgeDistance;
 612        u16 radioID;
 613        /*---------- Radio configuration ----------*/
 614        u16 radioType;
 615#define RADIOTYPE_DEFAULT 0
 616#define RADIOTYPE_802_11 1
 617#define RADIOTYPE_LEGACY 2
 618        u8 rxDiversity;
 619        u8 txDiversity;
 620        u16 txPower;
 621#define TXPOWER_DEFAULT 0
 622        u16 rssiThreshold;
 623#define RSSI_DEFAULT 0
 624        u16 modulation;
 625#define PREAMBLE_AUTO 0
 626#define PREAMBLE_LONG 1
 627#define PREAMBLE_SHORT 2
 628        u16 preamble;
 629        u16 homeProduct;
 630        u16 radioSpecific;
 631        /*---------- Aironet Extensions ----------*/
 632        u8 nodeName[16];
 633        u16 arlThreshold;
 634        u16 arlDecay;
 635        u16 arlDelay;
 636        u16 _reserved4[1];
 637        /*---------- Aironet Extensions ----------*/
 638        u8 magicAction;
 639#define MAGIC_ACTION_STSCHG 1
 640#define MAGIC_ACTION_RESUME 2
 641#define MAGIC_IGNORE_MCAST (1<<8)
 642#define MAGIC_IGNORE_BCAST (1<<9)
 643#define MAGIC_SWITCH_TO_PSP (0<<10)
 644#define MAGIC_STAY_IN_CAM (1<<10)
 645        u8 magicControl;
 646        u16 autoWake;
 647} ConfigRid;
 648
 649typedef struct {
 650        u16 len;
 651        u8 mac[ETH_ALEN];
 652        u16 mode;
 653        u16 errorCode;
 654        u16 sigQuality;
 655        u16 SSIDlen;
 656        char SSID[32];
 657        char apName[16];
 658        u8 bssid[4][ETH_ALEN];
 659        u16 beaconPeriod;
 660        u16 dimPeriod;
 661        u16 atimDuration;
 662        u16 hopPeriod;
 663        u16 channelSet;
 664        u16 channel;
 665        u16 hopsToBackbone;
 666        u16 apTotalLoad;
 667        u16 generatedLoad;
 668        u16 accumulatedArl;
 669        u16 signalQuality;
 670        u16 currentXmitRate;
 671        u16 apDevExtensions;
 672        u16 normalizedSignalStrength;
 673        u16 shortPreamble;
 674        u8 apIP[4];
 675        u8 noisePercent; /* Noise percent in last second */
 676        u8 noisedBm; /* Noise dBm in last second */
 677        u8 noiseAvePercent; /* Noise percent in last minute */
 678        u8 noiseAvedBm; /* Noise dBm in last minute */
 679        u8 noiseMaxPercent; /* Highest noise percent in last minute */
 680        u8 noiseMaxdBm; /* Highest noise dbm in last minute */
 681        u16 load;
 682        u8 carrier[4];
 683        u16 assocStatus;
 684#define STAT_NOPACKETS 0
 685#define STAT_NOCARRIERSET 10
 686#define STAT_GOTCARRIERSET 11
 687#define STAT_WRONGSSID 20
 688#define STAT_BADCHANNEL 25
 689#define STAT_BADBITRATES 30
 690#define STAT_BADPRIVACY 35
 691#define STAT_APFOUND 40
 692#define STAT_APREJECTED 50
 693#define STAT_AUTHENTICATING 60
 694#define STAT_DEAUTHENTICATED 61
 695#define STAT_AUTHTIMEOUT 62
 696#define STAT_ASSOCIATING 70
 697#define STAT_DEASSOCIATED 71
 698#define STAT_ASSOCTIMEOUT 72
 699#define STAT_NOTAIROAP 73
 700#define STAT_ASSOCIATED 80
 701#define STAT_LEAPING 90
 702#define STAT_LEAPFAILED 91
 703#define STAT_LEAPTIMEDOUT 92
 704#define STAT_LEAPCOMPLETE 93
 705} StatusRid;
 706
 707typedef struct {
 708        u16 len;
 709        u16 spacer;
 710        u32 vals[100];
 711} StatsRid;
 712
 713
 714typedef struct {
 715        u16 len;
 716        u8 ap[4][ETH_ALEN];
 717} APListRid;
 718
 719typedef struct {
 720        u16 len;
 721        char oui[3];
 722        char zero;
 723        u16 prodNum;
 724        char manName[32];
 725        char prodName[16];
 726        char prodVer[8];
 727        char factoryAddr[ETH_ALEN];
 728        char aironetAddr[ETH_ALEN];
 729        u16 radioType;
 730        u16 country;
 731        char callid[ETH_ALEN];
 732        char supportedRates[8];
 733        char rxDiversity;
 734        char txDiversity;
 735        u16 txPowerLevels[8];
 736        u16 hardVer;
 737        u16 hardCap;
 738        u16 tempRange;
 739        u16 softVer;
 740        u16 softSubVer;
 741        u16 interfaceVer;
 742        u16 softCap;
 743        u16 bootBlockVer;
 744        u16 requiredHard;
 745        u16 extSoftCap;
 746} CapabilityRid;
 747
 748
 749/* Only present on firmware >= 5.30.17 */
 750typedef struct {
 751  u16 unknown[4];
 752  u8 fixed[12]; /* WLAN management frame */
 753  u8 iep[624];
 754} BSSListRidExtra;
 755
 756typedef struct {
 757  u16 len;
 758  u16 index; /* First is 0 and 0xffff means end of list */
 759#define RADIO_FH 1 /* Frequency hopping radio type */
 760#define RADIO_DS 2 /* Direct sequence radio type */
 761#define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */
 762  u16 radioType;
 763  u8 bssid[ETH_ALEN]; /* Mac address of the BSS */
 764  u8 zero;
 765  u8 ssidLen;
 766  u8 ssid[32];
 767  u16 dBm;
 768#define CAP_ESS (1<<0)
 769#define CAP_IBSS (1<<1)
 770#define CAP_PRIVACY (1<<4)
 771#define CAP_SHORTHDR (1<<5)
 772  u16 cap;
 773  u16 beaconInterval;
 774  u8 rates[8]; /* Same as rates for config rid */
 775  struct { /* For frequency hopping only */
 776    u16 dwell;
 777    u8 hopSet;
 778    u8 hopPattern;
 779    u8 hopIndex;
 780    u8 fill;
 781  } fh;
 782  u16 dsChannel;
 783  u16 atimWindow;
 784
 785  /* Only present on firmware >= 5.30.17 */
 786  BSSListRidExtra extra;
 787} BSSListRid;
 788
 789typedef struct {
 790  BSSListRid bss;
 791  struct list_head list;
 792} BSSListElement;
 793
 794typedef struct {
 795  u8 rssipct;
 796  u8 rssidBm;
 797} tdsRssiEntry;
 798
 799typedef struct {
 800  u16 len;
 801  tdsRssiEntry x[256];
 802} tdsRssiRid;
 803
 804typedef struct {
 805        u16 len;
 806        u16 state;
 807        u16 multicastValid;
 808        u8  multicast[16];
 809        u16 unicastValid;
 810        u8  unicast[16];
 811} MICRid;
 812
 813typedef struct {
 814        u16 typelen;
 815
 816        union {
 817            u8 snap[8];
 818            struct {
 819                u8 dsap;
 820                u8 ssap;
 821                u8 control;
 822                u8 orgcode[3];
 823                u8 fieldtype[2];
 824            } llc;
 825        } u;
 826        u32 mic;
 827        u32 seq;
 828} MICBuffer;
 829
 830typedef struct {
 831        u8 da[ETH_ALEN];
 832        u8 sa[ETH_ALEN];
 833} etherHead;
 834
 835#pragma pack()
 836
 837#define TXCTL_TXOK (1<<1) /* report if tx is ok */
 838#define TXCTL_TXEX (1<<2) /* report if tx fails */
 839#define TXCTL_802_3 (0<<3) /* 802.3 packet */
 840#define TXCTL_802_11 (1<<3) /* 802.11 mac packet */
 841#define TXCTL_ETHERNET (0<<4) /* payload has ethertype */
 842#define TXCTL_LLC (1<<4) /* payload is llc */
 843#define TXCTL_RELEASE (0<<5) /* release after completion */
 844#define TXCTL_NORELEASE (1<<5) /* on completion returns to host */
 845
 846#define BUSY_FID 0x10000
 847
 848#ifdef CISCO_EXT
 849#define AIROMAGIC       0xa55a
 850/* Warning : SIOCDEVPRIVATE may disapear during 2.5.X - Jean II */
 851#ifdef SIOCIWFIRSTPRIV
 852#ifdef SIOCDEVPRIVATE
 853#define AIROOLDIOCTL    SIOCDEVPRIVATE
 854#define AIROOLDIDIFC    AIROOLDIOCTL + 1
 855#endif /* SIOCDEVPRIVATE */
 856#else /* SIOCIWFIRSTPRIV */
 857#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
 858#endif /* SIOCIWFIRSTPRIV */
 859/* This may be wrong. When using the new SIOCIWFIRSTPRIV range, we probably
 860 * should use only "GET" ioctls (last bit set to 1). "SET" ioctls are root
 861 * only and don't return the modified struct ifreq to the application which
 862 * is usually a problem. - Jean II */
 863#define AIROIOCTL       SIOCIWFIRSTPRIV
 864#define AIROIDIFC       AIROIOCTL + 1
 865
 866/* Ioctl constants to be used in airo_ioctl.command */
 867
 868#define AIROGCAP                0       // Capability rid
 869#define AIROGCFG                1       // USED A LOT
 870#define AIROGSLIST              2       // System ID list
 871#define AIROGVLIST              3       // List of specified AP's
 872#define AIROGDRVNAM             4       //  NOTUSED
 873#define AIROGEHTENC             5       // NOTUSED
 874#define AIROGWEPKTMP            6
 875#define AIROGWEPKNV             7
 876#define AIROGSTAT               8
 877#define AIROGSTATSC32           9
 878#define AIROGSTATSD32           10
 879#define AIROGMICRID             11
 880#define AIROGMICSTATS           12
 881#define AIROGFLAGS              13
 882#define AIROGID                 14
 883#define AIRORRID                15
 884#define AIRORSWVERSION          17
 885
 886/* Leave gap of 40 commands after AIROGSTATSD32 for future */
 887
 888#define AIROPCAP                AIROGSTATSD32 + 40
 889#define AIROPVLIST              AIROPCAP      + 1
 890#define AIROPSLIST              AIROPVLIST    + 1
 891#define AIROPCFG                AIROPSLIST    + 1
 892#define AIROPSIDS               AIROPCFG      + 1
 893#define AIROPAPLIST             AIROPSIDS     + 1
 894#define AIROPMACON              AIROPAPLIST   + 1       /* Enable mac  */
 895#define AIROPMACOFF             AIROPMACON    + 1       /* Disable mac */
 896#define AIROPSTCLR              AIROPMACOFF   + 1
 897#define AIROPWEPKEY             AIROPSTCLR    + 1
 898#define AIROPWEPKEYNV           AIROPWEPKEY   + 1
 899#define AIROPLEAPPWD            AIROPWEPKEYNV + 1
 900#define AIROPLEAPUSR            AIROPLEAPPWD  + 1
 901
 902/* Flash codes */
 903
 904#define AIROFLSHRST            AIROPWEPKEYNV  + 40
 905#define AIROFLSHGCHR           AIROFLSHRST    + 1
 906#define AIROFLSHSTFL           AIROFLSHGCHR   + 1
 907#define AIROFLSHPCHR           AIROFLSHSTFL   + 1
 908#define AIROFLPUTBUF           AIROFLSHPCHR   + 1
 909#define AIRORESTART            AIROFLPUTBUF   + 1
 910
 911#define FLASHSIZE       32768
 912#define AUXMEMSIZE      (256 * 1024)
 913
 914typedef struct aironet_ioctl {
 915        unsigned short command;         // What to do
 916        unsigned short len;             // Len of data
 917        unsigned short ridnum;          // rid number
 918        unsigned char __user *data;     // d-data
 919} aironet_ioctl;
 920
 921static char swversion[] = "2.1";
 922#endif /* CISCO_EXT */
 923
 924#define NUM_MODULES       2
 925#define MIC_MSGLEN_MAX    2400
 926#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
 927#define AIRO_DEF_MTU      2312
 928
 929typedef struct {
 930        u32   size;            // size
 931        u8    enabled;         // MIC enabled or not
 932        u32   rxSuccess;       // successful packets received
 933        u32   rxIncorrectMIC;  // pkts dropped due to incorrect MIC comparison
 934        u32   rxNotMICed;      // pkts dropped due to not being MIC'd
 935        u32   rxMICPlummed;    // pkts dropped due to not having a MIC plummed
 936        u32   rxWrongSequence; // pkts dropped due to sequence number violation
 937        u32   reserve[32];
 938} mic_statistics;
 939
 940typedef struct {
 941        u32 coeff[((EMMH32_MSGLEN_MAX)+3)>>2];
 942        u64 accum;      // accumulated mic, reduced to u32 in final()
 943        int position;   // current position (byte offset) in message
 944        union {
 945                u8  d8[4];
 946                u32 d32;
 947        } part; // saves partial message word across update() calls
 948} emmh32_context;
 949
 950typedef struct {
 951        emmh32_context seed;        // Context - the seed
 952        u32              rx;        // Received sequence number
 953        u32              tx;        // Tx sequence number
 954        u32              window;    // Start of window
 955        u8               valid;     // Flag to say if context is valid or not
 956        u8               key[16];
 957} miccntx;
 958
 959typedef struct {
 960        miccntx mCtx;           // Multicast context
 961        miccntx uCtx;           // Unicast context
 962} mic_module;
 963
 964typedef struct {
 965        unsigned int  rid: 16;
 966        unsigned int  len: 15;
 967        unsigned int  valid: 1;
 968        dma_addr_t host_addr;
 969} Rid;
 970
 971typedef struct {
 972        unsigned int  offset: 15;
 973        unsigned int  eoc: 1;
 974        unsigned int  len: 15;
 975        unsigned int  valid: 1;
 976        dma_addr_t host_addr;
 977} TxFid;
 978
 979typedef struct {
 980        unsigned int  ctl: 15;
 981        unsigned int  rdy: 1;
 982        unsigned int  len: 15;
 983        unsigned int  valid: 1;
 984        dma_addr_t host_addr;
 985} RxFid;
 986
 987/*
 988 * Host receive descriptor
 989 */
 990typedef struct {
 991        unsigned char __iomem *card_ram_off; /* offset into card memory of the
 992                                                desc */
 993        RxFid         rx_desc;               /* card receive descriptor */
 994        char          *virtual_host_addr;    /* virtual address of host receive
 995                                                buffer */
 996        int           pending;
 997} HostRxDesc;
 998
 999/*
1000 * Host transmit descriptor
1001 */
1002typedef struct {
1003        unsigned char __iomem *card_ram_off;         /* offset into card memory of the
1004                                                desc */
1005        TxFid         tx_desc;               /* card transmit descriptor */
1006        char          *virtual_host_addr;    /* virtual address of host receive
1007                                                buffer */
1008        int           pending;
1009} HostTxDesc;
1010
1011/*
1012 * Host RID descriptor
1013 */
1014typedef struct {
1015        unsigned char __iomem *card_ram_off;      /* offset into card memory of the
1016                                             descriptor */
1017        Rid           rid_desc;           /* card RID descriptor */
1018        char          *virtual_host_addr; /* virtual address of host receive
1019                                             buffer */
1020} HostRidDesc;
1021
1022typedef struct {
1023        u16 sw0;
1024        u16 sw1;
1025        u16 status;
1026        u16 len;
1027#define HOST_SET (1 << 0)
1028#define HOST_INT_TX (1 << 1) /* Interrupt on successful TX */
1029#define HOST_INT_TXERR (1 << 2) /* Interrupt on unseccessful TX */
1030#define HOST_LCC_PAYLOAD (1 << 4) /* LLC payload, 0 = Ethertype */
1031#define HOST_DONT_RLSE (1 << 5) /* Don't release buffer when done */
1032#define HOST_DONT_RETRY (1 << 6) /* Don't retry trasmit */
1033#define HOST_CLR_AID (1 << 7) /* clear AID failure */
1034#define HOST_RTS (1 << 9) /* Force RTS use */
1035#define HOST_SHORT (1 << 10) /* Do short preamble */
1036        u16 ctl;
1037        u16 aid;
1038        u16 retries;
1039        u16 fill;
1040} TxCtlHdr;
1041
1042typedef struct {
1043        u16 ctl;
1044        u16 duration;
1045        char addr1[6];
1046        char addr2[6];
1047        char addr3[6];
1048        u16 seq;
1049        char addr4[6];
1050} WifiHdr;
1051
1052
1053typedef struct {
1054        TxCtlHdr ctlhdr;
1055        u16 fill1;
1056        u16 fill2;
1057        WifiHdr wifihdr;
1058        u16 gaplen;
1059        u16 status;
1060} WifiCtlHdr;
1061
1062static WifiCtlHdr wifictlhdr8023 = {
1063        .ctlhdr = {
1064                .ctl    = HOST_DONT_RLSE,
1065        }
1066};
1067
1068// Frequency list (map channels to frequencies)
1069static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
1070                                2447, 2452, 2457, 2462, 2467, 2472, 2484 };
1071
1072// A few details needed for WEP (Wireless Equivalent Privacy)
1073#define MAX_KEY_SIZE 13                 // 128 (?) bits
1074#define MIN_KEY_SIZE  5                 // 40 bits RC4 - WEP
1075typedef struct wep_key_t {
1076        u16     len;
1077        u8      key[16];        /* 40-bit and 104-bit keys */
1078} wep_key_t;
1079
1080/* Backward compatibility */
1081#ifndef IW_ENCODE_NOKEY
1082#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
1083#define IW_ENCODE_MODE  (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)
1084#endif /* IW_ENCODE_NOKEY */
1085
1086/* List of Wireless Handlers (new API) */
1087static const struct iw_handler_def      airo_handler_def;
1088
1089static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
1090
1091struct airo_info;
1092
1093static int get_dec_u16( char *buffer, int *start, int limit );
1094static void OUT4500( struct airo_info *, u16 register, u16 value );
1095static unsigned short IN4500( struct airo_info *, u16 register );
1096static u16 setup_card(struct airo_info*, u8 *mac, int lock);
1097static int enable_MAC(struct airo_info *ai, int lock);
1098static void disable_MAC(struct airo_info *ai, int lock);
1099static void enable_interrupts(struct airo_info*);
1100static void disable_interrupts(struct airo_info*);
1101static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
1102static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);
1103static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
1104                        int whichbap);
1105static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
1106                         int whichbap);
1107static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen,
1108                     int whichbap);
1109static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);
1110static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock);
1111static int PC4500_writerid(struct airo_info*, u16 rid, const void
1112                           *pBuf, int len, int lock);
1113static int do_writerid( struct airo_info*, u16 rid, const void *rid_data,
1114                        int len, int dummy );
1115static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw);
1116static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);
1117static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);
1118
1119static int mpi_send_packet (struct net_device *dev);
1120static void mpi_unmap_card(struct pci_dev *pci);
1121static void mpi_receive_802_3(struct airo_info *ai);
1122static void mpi_receive_802_11(struct airo_info *ai);
1123static int waitbusy (struct airo_info *ai);
1124
1125static irqreturn_t airo_interrupt( int irq, void* dev_id);
1126static int airo_thread(void *data);
1127static void timer_func( struct net_device *dev );
1128static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
1129static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
1130static void airo_read_wireless_stats (struct airo_info *local);
1131#ifdef CISCO_EXT
1132static int readrids(struct net_device *dev, aironet_ioctl *comp);
1133static int writerids(struct net_device *dev, aironet_ioctl *comp);
1134static int flashcard(struct net_device *dev, aironet_ioctl *comp);
1135#endif /* CISCO_EXT */
1136static void micinit(struct airo_info *ai);
1137static int micsetup(struct airo_info *ai);
1138static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
1139static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
1140
1141static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
1142static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
1143
1144static void airo_networks_free(struct airo_info *ai);
1145
1146struct airo_info {
1147        struct net_device_stats stats;
1148        struct net_device             *dev;
1149        struct list_head              dev_list;
1150        /* Note, we can have MAX_FIDS outstanding.  FIDs are 16-bits, so we
1151           use the high bit to mark whether it is in use. */
1152#define MAX_FIDS 6
1153#define MPI_MAX_FIDS 1
1154        int                           fids[MAX_FIDS];
1155        ConfigRid config;
1156        char keyindex; // Used with auto wep
1157        char defindex; // Used with auto wep
1158        struct proc_dir_entry *proc_entry;
1159        spinlock_t aux_lock;
1160#define FLAG_RADIO_OFF  0       /* User disabling of MAC */
1161#define FLAG_RADIO_DOWN 1       /* ifup/ifdown disabling of MAC */
1162#define FLAG_RADIO_MASK 0x03
1163#define FLAG_ENABLED    2
1164#define FLAG_ADHOC      3       /* Needed by MIC */
1165#define FLAG_MIC_CAPABLE 4
1166#define FLAG_UPDATE_MULTI 5
1167#define FLAG_UPDATE_UNI 6
1168#define FLAG_802_11     7
1169#define FLAG_PROMISC    8       /* IFF_PROMISC 0x100 - include/linux/if.h */
1170#define FLAG_PENDING_XMIT 9
1171#define FLAG_PENDING_XMIT11 10
1172#define FLAG_MPI        11
1173#define FLAG_REGISTERED 12
1174#define FLAG_COMMIT     13
1175#define FLAG_RESET      14
1176#define FLAG_FLASHING   15
1177#define FLAG_WPA_CAPABLE        16
1178        unsigned long flags;
1179#define JOB_DIE 0
1180#define JOB_XMIT        1
1181#define JOB_XMIT11      2
1182#define JOB_STATS       3
1183#define JOB_PROMISC     4
1184#define JOB_MIC 5
1185#define JOB_EVENT       6
1186#define JOB_AUTOWEP     7
1187#define JOB_WSTATS      8
1188#define JOB_SCAN_RESULTS  9
1189        unsigned long jobs;
1190        int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
1191                        int whichbap);
1192        unsigned short *flash;
1193        tdsRssiEntry *rssi;
1194        struct task_struct *list_bss_task;
1195        struct task_struct *airo_thread_task;
1196        struct semaphore sem;
1197        wait_queue_head_t thr_wait;
1198        unsigned long expires;
1199        struct {
1200                struct sk_buff *skb;
1201                int fid;
1202        } xmit, xmit11;
1203        struct net_device *wifidev;
1204        struct iw_statistics    wstats;         // wireless stats
1205        unsigned long           scan_timeout;   /* Time scan should be read */
1206        struct iw_spy_data      spy_data;
1207        struct iw_public_data   wireless_data;
1208        /* MIC stuff */
1209        struct crypto_cipher    *tfm;
1210        mic_module              mod[2];
1211        mic_statistics          micstats;
1212        HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
1213        HostTxDesc txfids[MPI_MAX_FIDS];
1214        HostRidDesc config_desc;
1215        unsigned long ridbus; // phys addr of config_desc
1216        struct sk_buff_head txq;// tx queue used by mpi350 code
1217        struct pci_dev          *pci;
1218        unsigned char           __iomem *pcimem;
1219        unsigned char           __iomem *pciaux;
1220        unsigned char           *shared;
1221        dma_addr_t              shared_dma;
1222        pm_message_t            power;
1223        SsidRid                 *SSID;
1224        APListRid               *APList;
1225#define PCI_SHARED_LEN          2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
1226        char                    proc_name[IFNAMSIZ];
1227
1228        /* WPA-related stuff */
1229        unsigned int bssListFirst;
1230        unsigned int bssListNext;
1231        unsigned int bssListRidLen;
1232
1233        struct list_head network_list;
1234        struct list_head network_free_list;
1235        BSSListElement *networks;
1236};
1237
1238static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
1239                           int whichbap) {
1240        return ai->bap_read(ai, pu16Dst, bytelen, whichbap);
1241}
1242
1243static int setup_proc_entry( struct net_device *dev,
1244                             struct airo_info *apriv );
1245static int takedown_proc_entry( struct net_device *dev,
1246                                struct airo_info *apriv );
1247
1248static int cmdreset(struct airo_info *ai);
1249static int setflashmode (struct airo_info *ai);
1250static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
1251static int flashputbuf(struct airo_info *ai);
1252static int flashrestart(struct airo_info *ai,struct net_device *dev);
1253
1254#define airo_print(type, name, fmt, args...) \
1255        printk(type DRV_NAME "(%s): " fmt "\n", name, ##args)
1256
1257#define airo_print_info(name, fmt, args...) \
1258        airo_print(KERN_INFO, name, fmt, ##args)
1259
1260#define airo_print_dbg(name, fmt, args...) \
1261        airo_print(KERN_DEBUG, name, fmt, ##args)
1262
1263#define airo_print_warn(name, fmt, args...) \
1264        airo_print(KERN_WARNING, name, fmt, ##args)
1265
1266#define airo_print_err(name, fmt, args...) \
1267        airo_print(KERN_ERR, name, fmt, ##args)
1268
1269
1270/***********************************************************************
1271 *                              MIC ROUTINES                           *
1272 ***********************************************************************
1273 */
1274
1275static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
1276static void MoveWindow(miccntx *context, u32 micSeq);
1277static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
1278                           struct crypto_cipher *tfm);
1279static void emmh32_init(emmh32_context *context);
1280static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
1281static void emmh32_final(emmh32_context *context, u8 digest[4]);
1282static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
1283
1284/* micinit - Initialize mic seed */
1285
1286static void micinit(struct airo_info *ai)
1287{
1288        MICRid mic_rid;
1289
1290        clear_bit(JOB_MIC, &ai->jobs);
1291        PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
1292        up(&ai->sem);
1293
1294        ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0;
1295
1296        if (ai->micstats.enabled) {
1297                /* Key must be valid and different */
1298                if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid ||
1299                    (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast,
1300                             sizeof(ai->mod[0].mCtx.key)) != 0))) {
1301                        /* Age current mic Context */
1302                        memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx));
1303                        /* Initialize new context */
1304                        memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast));
1305                        ai->mod[0].mCtx.window  = 33; //Window always points to the middle
1306                        ai->mod[0].mCtx.rx      = 0;  //Rx Sequence numbers
1307                        ai->mod[0].mCtx.tx      = 0;  //Tx sequence numbers
1308                        ai->mod[0].mCtx.valid   = 1;  //Key is now valid
1309  
1310                        /* Give key to mic seed */
1311                        emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm);
1312                }
1313
1314                /* Key must be valid and different */
1315                if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || 
1316                    (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast,
1317                            sizeof(ai->mod[0].uCtx.key)) != 0))) {
1318                        /* Age current mic Context */
1319                        memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx));
1320                        /* Initialize new context */
1321                        memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast));
1322        
1323                        ai->mod[0].uCtx.window  = 33; //Window always points to the middle
1324                        ai->mod[0].uCtx.rx      = 0;  //Rx Sequence numbers
1325                        ai->mod[0].uCtx.tx      = 0;  //Tx sequence numbers
1326                        ai->mod[0].uCtx.valid   = 1;  //Key is now valid
1327        
1328                        //Give key to mic seed
1329                        emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm);
1330                }
1331        } else {
1332      /* So next time we have a valid key and mic is enabled, we will update
1333       * the sequence number if the key is the same as before.
1334       */
1335                ai->mod[0].uCtx.valid = 0;
1336                ai->mod[0].mCtx.valid = 0;
1337        }
1338}
1339
1340/* micsetup - Get ready for business */
1341
1342static int micsetup(struct airo_info *ai) {
1343        int i;
1344
1345        if (ai->tfm == NULL)
1346                ai->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
1347
1348        if (IS_ERR(ai->tfm)) {
1349                airo_print_err(ai->dev->name, "failed to load transform for AES");
1350                ai->tfm = NULL;
1351                return ERROR;
1352        }
1353
1354        for (i=0; i < NUM_MODULES; i++) {
1355                memset(&ai->mod[i].mCtx,0,sizeof(miccntx));
1356                memset(&ai->mod[i].uCtx,0,sizeof(miccntx));
1357        }
1358        return SUCCESS;
1359}
1360
1361static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
1362
1363/*===========================================================================
1364 * Description: Mic a packet
1365 *    
1366 *      Inputs: etherHead * pointer to an 802.3 frame
1367 *    
1368 *     Returns: BOOLEAN if successful, otherwise false.
1369 *             PacketTxLen will be updated with the mic'd packets size.
1370 *
1371 *    Caveats: It is assumed that the frame buffer will already
1372 *             be big enough to hold the largets mic message possible.
1373 *            (No memory allocation is done here).
1374 *  
1375 *    Author: sbraneky (10/15/01)
1376 *    Merciless hacks by rwilcher (1/14/02)
1377 */
1378
1379static int encapsulate(struct airo_info *ai ,etherHead *frame, MICBuffer *mic, int payLen)
1380{
1381        miccntx   *context;
1382
1383        // Determine correct context
1384        // If not adhoc, always use unicast key
1385
1386        if (test_bit(FLAG_ADHOC, &ai->flags) && (frame->da[0] & 0x1))
1387                context = &ai->mod[0].mCtx;
1388        else
1389                context = &ai->mod[0].uCtx;
1390  
1391        if (!context->valid)
1392                return ERROR;
1393
1394        mic->typelen = htons(payLen + 16); //Length of Mic'd packet
1395
1396        memcpy(&mic->u.snap, micsnap, sizeof(micsnap)); // Add Snap
1397
1398        // Add Tx sequence
1399        mic->seq = htonl(context->tx);
1400        context->tx += 2;
1401
1402        emmh32_init(&context->seed); // Mic the packet
1403        emmh32_update(&context->seed,frame->da,ETH_ALEN * 2); // DA,SA
1404        emmh32_update(&context->seed,(u8*)&mic->typelen,10); // Type/Length and Snap
1405        emmh32_update(&context->seed,(u8*)&mic->seq,sizeof(mic->seq)); //SEQ
1406        emmh32_update(&context->seed,frame->da + ETH_ALEN * 2,payLen); //payload
1407        emmh32_final(&context->seed, (u8*)&mic->mic);
1408
1409        /*    New Type/length ?????????? */
1410        mic->typelen = 0; //Let NIC know it could be an oversized packet
1411        return SUCCESS;
1412}
1413
1414typedef enum {
1415    NONE,
1416    NOMIC,
1417    NOMICPLUMMED,
1418    SEQUENCE,
1419    INCORRECTMIC,
1420} mic_error;
1421
1422/*===========================================================================
1423 *  Description: Decapsulates a MIC'd packet and returns the 802.3 packet
1424 *               (removes the MIC stuff) if packet is a valid packet.
1425 *      
1426 *       Inputs: etherHead  pointer to the 802.3 packet             
1427 *     
1428 *      Returns: BOOLEAN - TRUE if packet should be dropped otherwise FALSE
1429 *     
1430 *      Author: sbraneky (10/15/01)
1431 *    Merciless hacks by rwilcher (1/14/02)
1432 *---------------------------------------------------------------------------
1433 */
1434
1435static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *eth, u16 payLen)
1436{
1437        int      i;
1438        u32      micSEQ;
1439        miccntx  *context;
1440        u8       digest[4];
1441        mic_error micError = NONE;
1442
1443        // Check if the packet is a Mic'd packet
1444
1445        if (!ai->micstats.enabled) {
1446                //No Mic set or Mic OFF but we received a MIC'd packet.
1447                if (memcmp ((u8*)eth + 14, micsnap, sizeof(micsnap)) == 0) {
1448                        ai->micstats.rxMICPlummed++;
1449                        return ERROR;
1450                }
1451                return SUCCESS;
1452        }
1453
1454        if (ntohs(mic->typelen) == 0x888E)
1455                return SUCCESS;
1456
1457        if (memcmp (mic->u.snap, micsnap, sizeof(micsnap)) != 0) {
1458            // Mic enabled but packet isn't Mic'd
1459                ai->micstats.rxMICPlummed++;
1460                return ERROR;
1461        }
1462
1463        micSEQ = ntohl(mic->seq);            //store SEQ as CPU order
1464
1465        //At this point we a have a mic'd packet and mic is enabled
1466        //Now do the mic error checking.
1467
1468        //Receive seq must be odd
1469        if ( (micSEQ & 1) == 0 ) {
1470                ai->micstats.rxWrongSequence++;
1471                return ERROR;
1472        }
1473
1474        for (i = 0; i < NUM_MODULES; i++) {
1475                int mcast = eth->da[0] & 1;
1476                //Determine proper context 
1477                context = mcast ? &ai->mod[i].mCtx : &ai->mod[i].uCtx;
1478        
1479                //Make sure context is valid
1480                if (!context->valid) {
1481                        if (i == 0)
1482                                micError = NOMICPLUMMED;
1483                        continue;                
1484                }
1485                //DeMic it 
1486
1487                if (!mic->typelen)
1488                        mic->typelen = htons(payLen + sizeof(MICBuffer) - 2);
1489        
1490                emmh32_init(&context->seed);
1491                emmh32_update(&context->seed, eth->da, ETH_ALEN*2); 
1492                emmh32_update(&context->seed, (u8 *)&mic->typelen, sizeof(mic->typelen)+sizeof(mic->u.snap)); 
1493                emmh32_update(&context->seed, (u8 *)&mic->seq,sizeof(mic->seq));        
1494                emmh32_update(&context->seed, eth->da + ETH_ALEN*2,payLen);     
1495                //Calculate MIC
1496                emmh32_final(&context->seed, digest);
1497        
1498                if (memcmp(digest, &mic->mic, 4)) { //Make sure the mics match
1499                  //Invalid Mic
1500                        if (i == 0)
1501                                micError = INCORRECTMIC;
1502                        continue;
1503                }
1504
1505                //Check Sequence number if mics pass
1506                if (RxSeqValid(ai, context, mcast, micSEQ) == SUCCESS) {
1507                        ai->micstats.rxSuccess++;
1508                        return SUCCESS;
1509                }
1510                if (i == 0)
1511                        micError = SEQUENCE;
1512        }
1513
1514        // Update statistics
1515        switch (micError) {
1516                case NOMICPLUMMED: ai->micstats.rxMICPlummed++;   break;
1517                case SEQUENCE:    ai->micstats.rxWrongSequence++; break;
1518                case INCORRECTMIC: ai->micstats.rxIncorrectMIC++; break;
1519                case NONE:  break;
1520                case NOMIC: break;
1521        }
1522        return ERROR;
1523}
1524
1525/*===========================================================================
1526 * Description:  Checks the Rx Seq number to make sure it is valid
1527 *               and hasn't already been received
1528 *   
1529 *     Inputs: miccntx - mic context to check seq against
1530 *             micSeq  - the Mic seq number
1531 *   
1532 *    Returns: TRUE if valid otherwise FALSE. 
1533 *
1534 *    Author: sbraneky (10/15/01)
1535 *    Merciless hacks by rwilcher (1/14/02)
1536 *---------------------------------------------------------------------------
1537 */
1538
1539static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq)
1540{
1541        u32 seq,index;
1542
1543        //Allow for the ap being rebooted - if it is then use the next 
1544        //sequence number of the current sequence number - might go backwards
1545
1546        if (mcast) {
1547                if (test_bit(FLAG_UPDATE_MULTI, &ai->flags)) {
1548                        clear_bit (FLAG_UPDATE_MULTI, &ai->flags);
1549                        context->window = (micSeq > 33) ? micSeq : 33;
1550                        context->rx     = 0;        // Reset rx
1551                }
1552        } else if (test_bit(FLAG_UPDATE_UNI, &ai->flags)) {
1553                clear_bit (FLAG_UPDATE_UNI, &ai->flags);
1554                context->window = (micSeq > 33) ? micSeq : 33; // Move window
1555                context->rx     = 0;        // Reset rx
1556        }
1557
1558        //Make sequence number relative to START of window
1559        seq = micSeq - (context->window - 33);
1560
1561        //Too old of a SEQ number to check.
1562        if ((s32)seq < 0)
1563                return ERROR;
1564    
1565        if ( seq > 64 ) {
1566                //Window is infinite forward
1567                MoveWindow(context,micSeq);
1568                return SUCCESS;
1569        }
1570
1571        // We are in the window. Now check the context rx bit to see if it was already sent
1572        seq >>= 1;         //divide by 2 because we only have odd numbers
1573        index = 1 << seq;  //Get an index number
1574
1575        if (!(context->rx & index)) {
1576                //micSEQ falls inside the window.
1577                //Add seqence number to the list of received numbers.
1578                context->rx |= index;
1579
1580                MoveWindow(context,micSeq);
1581
1582                return SUCCESS;
1583        }
1584        return ERROR;
1585}
1586
1587static void MoveWindow(miccntx *context, u32 micSeq)
1588{
1589        u32 shift;
1590
1591        //Move window if seq greater than the middle of the window
1592        if (micSeq > context->window) {
1593                shift = (micSeq - context->window) >> 1;
1594    
1595                    //Shift out old
1596                if (shift < 32)
1597                        context->rx >>= shift;
1598                else
1599                        context->rx = 0;
1600
1601                context->window = micSeq;      //Move window
1602        }
1603}
1604
1605/*==============================================*/
1606/*========== EMMH ROUTINES  ====================*/
1607/*==============================================*/
1608
1609/* mic accumulate */
1610#define MIC_ACCUM(val)  \
1611        context->accum += (u64)(val) * context->coeff[coeff_position++];
1612
1613static unsigned char aes_counter[16];
1614
1615/* expand the key to fill the MMH coefficient array */
1616static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
1617                           struct crypto_cipher *tfm)
1618{
1619  /* take the keying material, expand if necessary, truncate at 16-bytes */
1620  /* run through AES counter mode to generate context->coeff[] */
1621  
1622        int i,j;
1623        u32 counter;
1624        u8 *cipher, plain[16];
1625
1626        crypto_cipher_setkey(tfm, pkey, 16);
1627        counter = 0;
1628        for (i = 0; i < ARRAY_SIZE(context->coeff); ) {
1629                aes_counter[15] = (u8)(counter >> 0);
1630                aes_counter[14] = (u8)(counter >> 8);
1631                aes_counter[13] = (u8)(counter >> 16);
1632                aes_counter[12] = (u8)(counter >> 24);
1633                counter++;
1634                memcpy (plain, aes_counter, 16);
1635                crypto_cipher_encrypt_one(tfm, plain, plain);
1636                cipher = plain;
1637                for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) {
1638                        context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
1639                        j += 4;
1640                }
1641        }
1642}
1643
1644/* prepare for calculation of a new mic */
1645static void emmh32_init(emmh32_context *context)
1646{
1647        /* prepare for new mic calculation */
1648        context->accum = 0;
1649        context->position = 0;
1650}
1651
1652/* add some bytes to the mic calculation */
1653static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
1654{
1655        int     coeff_position, byte_position;
1656  
1657        if (len == 0) return;
1658  
1659        coeff_position = context->position >> 2;
1660  
1661        /* deal with partial 32-bit word left over from last update */
1662        byte_position = context->position & 3;
1663        if (byte_position) {
1664                /* have a partial word in part to deal with */
1665                do {
1666                        if (len == 0) return;
1667                        context->part.d8[byte_position++] = *pOctets++;
1668                        context->position++;
1669                        len--;
1670                } while (byte_position < 4);
1671                MIC_ACCUM(htonl(context->part.d32));
1672        }
1673
1674        /* deal with full 32-bit words */
1675        while (len >= 4) {
1676                MIC_ACCUM(htonl(*(u32 *)pOctets));
1677                context->position += 4;
1678                pOctets += 4;
1679                len -= 4;
1680        }
1681
1682        /* deal with partial 32-bit word that will be left over from this update */
1683        byte_position = 0;
1684        while (len > 0) {
1685                context->part.d8[byte_position++] = *pOctets++;
1686                context->position++;
1687                len--;
1688        }
1689}
1690
1691/* mask used to zero empty bytes for final partial word */
1692static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
1693
1694/* calculate the mic */
1695static void emmh32_final(emmh32_context *context, u8 digest[4])
1696{
1697        int     coeff_position, byte_position;
1698        u32     val;
1699  
1700        u64 sum, utmp;
1701        s64 stmp;
1702
1703        coeff_position = context->position >> 2;
1704  
1705        /* deal with partial 32-bit word left over from last update */
1706        byte_position = context->position & 3;
1707        if (byte_position) {
1708                /* have a partial word in part to deal with */
1709                val = htonl(context->part.d32);
1710                MIC_ACCUM(val & mask32[byte_position]); /* zero empty bytes */
1711        }
1712
1713        /* reduce the accumulated u64 to a 32-bit MIC */
1714        sum = context->accum;
1715        stmp = (sum  & 0xffffffffLL) - ((sum >> 32)  * 15);
1716        utmp = (stmp & 0xffffffffLL) - ((stmp >> 32) * 15);
1717        sum = utmp & 0xffffffffLL;
1718        if (utmp > 0x10000000fLL)
1719                sum -= 15;
1720
1721        val = (u32)sum;
1722        digest[0] = (val>>24) & 0xFF;
1723        digest[1] = (val>>16) & 0xFF;
1724        digest[2] = (val>>8) & 0xFF;
1725        digest[3] = val & 0xFF;
1726}
1727
1728static int readBSSListRid(struct airo_info *ai, int first,
1729                      BSSListRid *list) {
1730        int rc;
1731        Cmd cmd;
1732        Resp rsp;
1733
1734        if (first == 1) {
1735                if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
1736                memset(&cmd, 0, sizeof(cmd));
1737                cmd.cmd=CMD_LISTBSS;
1738                if (down_interruptible(&ai->sem))
1739                        return -ERESTARTSYS;
1740                ai->list_bss_task = current;
1741                issuecommand(ai, &cmd, &rsp);
1742                up(&ai->sem);
1743                /* Let the command take effect */
1744                schedule_timeout_uninterruptible(3 * HZ);
1745                ai->list_bss_task = NULL;
1746        }
1747        rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
1748                            list, ai->bssListRidLen, 1);
1749
1750        list->len = le16_to_cpu(list->len);
1751        list->index = le16_to_cpu(list->index);
1752        list->radioType = le16_to_cpu(list->radioType);
1753        list->cap = le16_to_cpu(list->cap);
1754        list->beaconInterval = le16_to_cpu(list->beaconInterval);
1755        list->fh.dwell = le16_to_cpu(list->fh.dwell);
1756        list->dsChannel = le16_to_cpu(list->dsChannel);
1757        list->atimWindow = le16_to_cpu(list->atimWindow);
1758        list->dBm = le16_to_cpu(list->dBm);
1759        return rc;
1760}
1761
1762static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp, int lock) {
1763        int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM,
1764                                wkr, sizeof(*wkr), lock);
1765
1766        wkr->len = le16_to_cpu(wkr->len);
1767        wkr->kindex = le16_to_cpu(wkr->kindex);
1768        wkr->klen = le16_to_cpu(wkr->klen);
1769        return rc;
1770}
1771/* In the writeXXXRid routines we copy the rids so that we don't screwup
1772 * the originals when we endian them... */
1773static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lock) {
1774        int rc;
1775        WepKeyRid wkr = *pwkr;
1776
1777        wkr.len = cpu_to_le16(wkr.len);
1778        wkr.kindex = cpu_to_le16(wkr.kindex);
1779        wkr.klen = cpu_to_le16(wkr.klen);
1780        rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);
1781        if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
1782        if (perm) {
1783                rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);
1784                if (rc!=SUCCESS) {
1785                        airo_print_err(ai->dev->name, "WEP_PERM set %x", rc);
1786                }
1787        }
1788        return rc;
1789}
1790
1791static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) {
1792        int i;
1793        int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
1794
1795        ssidr->len = le16_to_cpu(ssidr->len);
1796        for(i = 0; i < 3; i++) {
1797                ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len);
1798        }
1799        return rc;
1800}
1801static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) {
1802        int rc;
1803        int i;
1804        SsidRid ssidr = *pssidr;
1805
1806        ssidr.len = cpu_to_le16(ssidr.len);
1807        for(i = 0; i < 3; i++) {
1808                ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len);
1809        }
1810        rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), lock);
1811        return rc;
1812}
1813static int readConfigRid(struct airo_info*ai, int lock) {
1814        int rc;
1815        u16 *s;
1816        ConfigRid cfg;
1817
1818        if (ai->config.len)
1819                return SUCCESS;
1820
1821        rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock);
1822        if (rc != SUCCESS)
1823                return rc;
1824
1825        for(s = &cfg.len; s <= &cfg.rtsThres; s++) *s = le16_to_cpu(*s);
1826
1827        for(s = &cfg.shortRetryLimit; s <= &cfg.radioType; s++)
1828                *s = le16_to_cpu(*s);
1829
1830        for(s = &cfg.txPower; s <= &cfg.radioSpecific; s++)
1831                *s = le16_to_cpu(*s);
1832
1833        for(s = &cfg.arlThreshold; s <= &cfg._reserved4[0]; s++)
1834                *s = cpu_to_le16(*s);
1835
1836        for(s = &cfg.autoWake; s <= &cfg.autoWake; s++)
1837                *s = cpu_to_le16(*s);
1838
1839        ai->config = cfg;
1840        return SUCCESS;
1841}
1842static inline void checkThrottle(struct airo_info *ai) {
1843        int i;
1844/* Old hardware had a limit on encryption speed */
1845        if (ai->config.authType != AUTH_OPEN && maxencrypt) {
1846                for(i=0; i<8; i++) {
1847                        if (ai->config.rates[i] > maxencrypt) {
1848                                ai->config.rates[i] = 0;
1849                        }
1850                }
1851        }
1852}
1853static int writeConfigRid(struct airo_info*ai, int lock) {
1854        u16 *s;
1855        ConfigRid cfgr;
1856
1857        if (!test_bit (FLAG_COMMIT, &ai->flags))
1858                return SUCCESS;
1859
1860        clear_bit (FLAG_COMMIT, &ai->flags);
1861        clear_bit (FLAG_RESET, &ai->flags);
1862        checkThrottle(ai);
1863        cfgr = ai->config;
1864
1865        if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS)
1866                set_bit(FLAG_ADHOC, &ai->flags);
1867        else
1868                clear_bit(FLAG_ADHOC, &ai->flags);
1869
1870        for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s);
1871
1872        for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++)
1873                *s = cpu_to_le16(*s);
1874
1875        for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++)
1876                *s = cpu_to_le16(*s);
1877
1878        for(s = &cfgr.arlThreshold; s <= &cfgr._reserved4[0]; s++)
1879                *s = cpu_to_le16(*s);
1880
1881        for(s = &cfgr.autoWake; s <= &cfgr.autoWake; s++)
1882                *s = cpu_to_le16(*s);
1883
1884        return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock);
1885}
1886static int readStatusRid(struct airo_info*ai, StatusRid *statr, int lock) {
1887        int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);
1888        u16 *s;
1889
1890        statr->len = le16_to_cpu(statr->len);
1891        for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s);
1892
1893        for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++)
1894                *s = le16_to_cpu(*s);
1895        statr->load = le16_to_cpu(statr->load);
1896        statr->assocStatus = le16_to_cpu(statr->assocStatus);
1897        return rc;
1898}
1899static int readAPListRid(struct airo_info*ai, APListRid *aplr) {
1900        int rc =  PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
1901        aplr->len = le16_to_cpu(aplr->len);
1902        return rc;
1903}
1904static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) {
1905        int rc;
1906        aplr->len = cpu_to_le16(aplr->len);
1907        rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
1908        return rc;
1909}
1910static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) {
1911        int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
1912        u16 *s;
1913
1914        capr->len = le16_to_cpu(capr->len);
1915        capr->prodNum = le16_to_cpu(capr->prodNum);
1916        capr->radioType = le16_to_cpu(capr->radioType);
1917        capr->country = le16_to_cpu(capr->country);
1918        for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)
1919                *s = le16_to_cpu(*s);
1920        return rc;
1921}
1922static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) {
1923        int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock);
1924        u32 *i;
1925
1926        sr->len = le16_to_cpu(sr->len);
1927        for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i);
1928        return rc;
1929}
1930
1931static void try_auto_wep(struct airo_info *ai)
1932{
1933        if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
1934                ai->expires = RUN_AT(3*HZ);
1935                wake_up_interruptible(&ai->thr_wait);
1936        }
1937}
1938
1939static int airo_open(struct net_device *dev) {
1940        struct airo_info *ai = dev->priv;
1941        int rc = 0;
1942
1943        if (test_bit(FLAG_FLASHING, &ai->flags))
1944                return -EIO;
1945
1946        /* Make sure the card is configured.
1947         * Wireless Extensions may postpone config changes until the card
1948         * is open (to pipeline changes and speed-up card setup). If
1949         * those changes are not yet commited, do it now - Jean II */
1950        if (test_bit(FLAG_COMMIT, &ai->flags)) {
1951                disable_MAC(ai, 1);
1952                writeConfigRid(ai, 1);
1953        }
1954
1955        if (ai->wifidev != dev) {
1956                clear_bit(JOB_DIE, &ai->jobs);
1957                ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
1958                if (IS_ERR(ai->airo_thread_task))
1959                        return (int)PTR_ERR(ai->airo_thread_task);
1960
1961                rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED,
1962                        dev->name, dev);
1963                if (rc) {
1964                        airo_print_err(dev->name,
1965                                "register interrupt %d failed, rc %d",
1966                                dev->irq, rc);
1967                        set_bit(JOB_DIE, &ai->jobs);
1968                        kthread_stop(ai->airo_thread_task);
1969                        return rc;
1970                }
1971
1972                /* Power on the MAC controller (which may have been disabled) */
1973                clear_bit(FLAG_RADIO_DOWN, &ai->flags);
1974                enable_interrupts(ai);
1975
1976                try_auto_wep(ai);
1977        }
1978        enable_MAC(ai, 1);
1979
1980        netif_start_queue(dev);
1981        return 0;
1982}
1983
1984static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
1985        int npacks, pending;
1986        unsigned long flags;
1987        struct airo_info *ai = dev->priv;
1988
1989        if (!skb) {
1990                airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
1991                return 0;
1992        }
1993        npacks = skb_queue_len (&ai->txq);
1994
1995        if (npacks >= MAXTXQ - 1) {
1996                netif_stop_queue (dev);
1997                if (npacks > MAXTXQ) {
1998                        ai->stats.tx_fifo_errors++;
1999                        return 1;
2000                }
2001                skb_queue_tail (&ai->txq, skb);
2002                return 0;
2003        }
2004
2005        spin_lock_irqsave(&ai->aux_lock, flags);
2006        skb_queue_tail (&ai->txq, skb);
2007        pending = test_bit(FLAG_PENDING_XMIT, &ai->flags);
2008        spin_unlock_irqrestore(&ai->aux_lock,flags);
2009        netif_wake_queue (dev);
2010
2011        if (pending == 0) {
2012                set_bit(FLAG_PENDING_XMIT, &ai->flags);
2013                mpi_send_packet (dev);
2014        }
2015        return 0;
2016}
2017
2018/*
2019 * @mpi_send_packet
2020 *
2021 * Attempt to transmit a packet. Can be called from interrupt
2022 * or transmit . return number of packets we tried to send
2023 */
2024
2025static int mpi_send_packet (struct net_device *dev)
2026{
2027        struct sk_buff *skb;
2028        unsigned char *buffer;
2029        s16 len, *payloadLen;
2030        struct airo_info *ai = dev->priv;
2031        u8 *sendbuf;
2032
2033        /* get a packet to send */
2034
2035        if ((skb = skb_dequeue(&ai->txq)) == 0) {
2036                airo_print_err(dev->name,
2037                        "%s: Dequeue'd zero in send_packet()",
2038                        __FUNCTION__);
2039                return 0;
2040        }
2041
2042        /* check min length*/
2043        len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
2044        buffer = skb->data;
2045
2046        ai->txfids[0].tx_desc.offset = 0;
2047        ai->txfids[0].tx_desc.valid = 1;
2048        ai->txfids[0].tx_desc.eoc = 1;
2049        ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);
2050
2051/*
2052 * Magic, the cards firmware needs a length count (2 bytes) in the host buffer
2053 * right after  TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
2054 * is immediatly after it. ------------------------------------------------
2055 *                         |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA|
2056 *                         ------------------------------------------------
2057 */
2058
2059        memcpy((char *)ai->txfids[0].virtual_host_addr,
2060                (char *)&wifictlhdr8023, sizeof(wifictlhdr8023));
2061
2062        payloadLen = (s16 *)(ai->txfids[0].virtual_host_addr +
2063                sizeof(wifictlhdr8023));
2064        sendbuf = ai->txfids[0].virtual_host_addr +
2065                sizeof(wifictlhdr8023) + 2 ;
2066
2067        /*
2068         * Firmware automaticly puts 802 header on so
2069         * we don't need to account for it in the length
2070         */
2071        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
2072                (ntohs(((u16 *)buffer)[6]) != 0x888E)) {
2073                MICBuffer pMic;
2074
2075                if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS)
2076                        return ERROR;
2077
2078                *payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic));
2079                ai->txfids[0].tx_desc.len += sizeof(pMic);
2080                /* copy data into airo dma buffer */
2081                memcpy (sendbuf, buffer, sizeof(etherHead));
2082                buffer += sizeof(etherHead);
2083                sendbuf += sizeof(etherHead);
2084                memcpy (sendbuf, &pMic, sizeof(pMic));
2085                sendbuf += sizeof(pMic);
2086                memcpy (sendbuf, buffer, len - sizeof(etherHead));
2087        } else {
2088                *payloadLen = cpu_to_le16(len - sizeof(etherHead));
2089
2090                dev->trans_start = jiffies;
2091
2092                /* copy data into airo dma buffer */
2093                memcpy(sendbuf, buffer, len);
2094        }
2095
2096        memcpy_toio(ai->txfids[0].card_ram_off,
2097                &ai->txfids[0].tx_desc, sizeof(TxFid));
2098
2099        OUT4500(ai, EVACK, 8);
2100
2101        dev_kfree_skb_any(skb);
2102        return 1;
2103}
2104
2105static void get_tx_error(struct airo_info *ai, s32 fid)
2106{
2107        u16 status;
2108
2109        if (fid < 0)
2110                status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status;
2111        else {
2112                if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) != SUCCESS)
2113                        return;
2114                bap_read(ai, &status, 2, BAP0);
2115        }
2116        if (le16_to_cpu(status) & 2) /* Too many retries */
2117                ai->stats.tx_aborted_errors++;
2118        if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */
2119                ai->stats.tx_heartbeat_errors++;
2120        if (le16_to_cpu(status) & 8) /* Aid fail */
2121                { }
2122        if (le16_to_cpu(status) & 0x10) /* MAC disabled */
2123                ai->stats.tx_carrier_errors++;
2124        if (le16_to_cpu(status) & 0x20) /* Association lost */
2125                { }
2126        /* We produce a TXDROP event only for retry or lifetime
2127         * exceeded, because that's the only status that really mean
2128         * that this particular node went away.
2129         * Other errors means that *we* screwed up. - Jean II */
2130        if ((le16_to_cpu(status) & 2) ||
2131             (le16_to_cpu(status) & 4)) {
2132                union iwreq_data        wrqu;
2133                char junk[0x18];
2134
2135                /* Faster to skip over useless data than to do
2136                 * another bap_setup(). We are at offset 0x6 and
2137                 * need to go to 0x18 and read 6 bytes - Jean II */
2138                bap_read(ai, (u16 *) junk, 0x18, BAP0);
2139
2140                /* Copy 802.11 dest address.
2141                 * We use the 802.11 header because the frame may
2142                 * not be 802.3 or may be mangled...
2143                 * In Ad-Hoc mode, it will be the node address.
2144                 * In managed mode, it will be most likely the AP addr
2145                 * User space will figure out how to convert it to
2146                 * whatever it needs (IP address or else).
2147                 * - Jean II */
2148                memcpy(wrqu.addr.sa_data, junk + 0x12, ETH_ALEN);
2149                wrqu.addr.sa_family = ARPHRD_ETHER;
2150
2151                /* Send event to user space */
2152                wireless_send_event(ai->dev, IWEVTXDROP, &wrqu, NULL);
2153        }
2154}
2155
2156static void airo_end_xmit(struct net_device *dev) {
2157        u16 status;
2158        int i;
2159        struct airo_info *priv = dev->priv;
2160        struct sk_buff *skb = priv->xmit.skb;
2161        int fid = priv->xmit.fid;
2162        u32 *fids = priv->fids;
2163
2164        clear_bit(JOB_XMIT, &priv->jobs);
2165        clear_bit(FLAG_PENDING_XMIT, &priv->flags);
2166        status = transmit_802_3_packet (priv, fids[fid], skb->data);
2167        up(&priv->sem);
2168
2169        i = 0;
2170        if ( status == SUCCESS ) {
2171                dev->trans_start = jiffies;
2172                for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++);
2173        } else {
2174                priv->fids[fid] &= 0xffff;
2175                priv->stats.tx_window_errors++;
2176        }
2177        if (i < MAX_FIDS / 2)
2178                netif_wake_queue(dev);
2179        dev_kfree_skb(skb);
2180}
2181
2182static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
2183        s16 len;
2184        int i, j;
2185        struct airo_info *priv = dev->priv;
2186        u32 *fids = priv->fids;
2187
2188        if ( skb == NULL ) {
2189                airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
2190                return 0;
2191        }
2192
2193        /* Find a vacant FID */
2194        for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );
2195        for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ );
2196
2197        if ( j >= MAX_FIDS / 2 ) {
2198                netif_stop_queue(dev);
2199
2200                if (i == MAX_FIDS / 2) {
2201                        priv->stats.tx_fifo_errors++;
2202                        return 1;
2203                }
2204        }
2205        /* check min length*/
2206        len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
2207        /* Mark fid as used & save length for later */
2208        fids[i] |= (len << 16);
2209        priv->xmit.skb = skb;
2210        priv->xmit.fid = i;
2211        if (down_trylock(&priv->sem) != 0) {
2212                set_bit(FLAG_PENDING_XMIT, &priv->flags);
2213                netif_stop_queue(dev);
2214                set_bit(JOB_XMIT, &priv->jobs);
2215                wake_up_interruptible(&priv->thr_wait);
2216        } else
2217                airo_end_xmit(dev);
2218        return 0;
2219}
2220
2221static void airo_end_xmit11(struct net_device *dev) {
2222        u16 status;
2223        int i;
2224        struct airo_info *priv = dev->priv;
2225        struct sk_buff *skb = priv->xmit11.skb;
2226        int fid = priv->xmit11.fid;
2227        u32 *fids = priv->fids;
2228
2229        clear_bit(JOB_XMIT11, &priv->jobs);
2230        clear_bit(FLAG_PENDING_XMIT11, &priv->flags);
2231        status = transmit_802_11_packet (priv, fids[fid], skb->data);
2232        up(&priv->sem);
2233
2234        i = MAX_FIDS / 2;
2235        if ( status == SUCCESS ) {
2236                dev->trans_start = jiffies;
2237                for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++);
2238        } else {
2239                priv->fids[fid] &= 0xffff;
2240                priv->stats.tx_window_errors++;
2241        }
2242        if (i < MAX_FIDS)
2243                netif_wake_queue(dev);
2244        dev_kfree_skb(skb);
2245}
2246
2247static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
2248        s16 len;
2249        int i, j;
2250        struct airo_info *priv = dev->priv;
2251        u32 *fids = priv->fids;
2252
2253        if (test_bit(FLAG_MPI, &priv->flags)) {
2254                /* Not implemented yet for MPI350 */
2255                netif_stop_queue(dev);
2256                return -ENETDOWN;
2257        }
2258
2259        if ( skb == NULL ) {
2260                airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
2261                return 0;
2262        }
2263
2264        /* Find a vacant FID */
2265        for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );
2266        for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ );
2267
2268        if ( j >= MAX_FIDS ) {
2269                netif_stop_queue(dev);
2270
2271                if (i == MAX_FIDS) {
2272                        priv->stats.tx_fifo_errors++;
2273                        return 1;
2274                }
2275        }
2276        /* check min length*/
2277        len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
2278        /* Mark fid as used & save length for later */
2279        fids[i] |= (len << 16);
2280        priv->xmit11.skb = skb;
2281        priv->xmit11.fid = i;
2282        if (down_trylock(&priv->sem) != 0) {
2283                set_bit(FLAG_PENDING_XMIT11, &priv->flags);
2284                netif_stop_queue(dev);
2285                set_bit(JOB_XMIT11, &priv->jobs);
2286                wake_up_interruptible(&priv->thr_wait);
2287        } else
2288                airo_end_xmit11(dev);
2289        return 0;
2290}
2291
2292static void airo_read_stats(struct airo_info *ai) {
2293        StatsRid stats_rid;
2294        u32 *vals = stats_rid.vals;
2295
2296        clear_bit(JOB_STATS, &ai->jobs);
2297        if (ai->power.event) {
2298                up(&ai->sem);
2299                return;
2300        }
2301        readStatsRid(ai, &stats_rid, RID_STATS, 0);
2302        up(&ai->sem);
2303
2304        ai->stats.rx_packets = vals[43] + vals[44] + vals[45];
2305        ai->stats.tx_packets = vals[39] + vals[40] + vals[41];
2306        ai->stats.rx_bytes = vals[92];
2307        ai->stats.tx_bytes = vals[91];
2308        ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4];
2309        ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors;
2310        ai->stats.multicast = vals[43];
2311        ai->stats.collisions = vals[89];
2312
2313        /* detailed rx_errors: */
2314        ai->stats.rx_length_errors = vals[3];
2315        ai->stats.rx_crc_errors = vals[4];
2316        ai->stats.rx_frame_errors = vals[2];
2317        ai->stats.rx_fifo_errors = vals[0];
2318}
2319
2320static struct net_device_stats *airo_get_stats(struct net_device *dev)
2321{
2322        struct airo_info *local =  dev->priv;
2323
2324        if (!test_bit(JOB_STATS, &local->jobs)) {
2325                /* Get stats out of the card if available */
2326                if (down_trylock(&local->sem) != 0) {
2327                        set_bit(JOB_STATS, &local->jobs);
2328                        wake_up_interruptible(&local->thr_wait);
2329                } else
2330                        airo_read_stats(local);
2331        }
2332
2333        return &local->stats;
2334}
2335
2336static void airo_set_promisc(struct airo_info *ai) {
2337        Cmd cmd;
2338        Resp rsp;
2339
2340        memset(&cmd, 0, sizeof(cmd));
2341        cmd.cmd=CMD_SETMODE;
2342        clear_bit(JOB_PROMISC, &ai->jobs);
2343        cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
2344        issuecommand(ai, &cmd, &rsp);
2345        up(&ai->sem);
2346}
2347
2348static void airo_set_multicast_list(struct net_device *dev) {
2349        struct airo_info *ai = dev->priv;
2350
2351        if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
2352                change_bit(FLAG_PROMISC, &ai->flags);
2353                if (down_trylock(&ai->sem) != 0) {
2354                        set_bit(JOB_PROMISC, &ai->jobs);
2355                        wake_up_interruptible(&ai->thr_wait);
2356                } else
2357                        airo_set_promisc(ai);
2358        }
2359
2360        if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
2361                /* Turn on multicast.  (Should be already setup...) */
2362        }
2363}
2364
2365static int airo_set_mac_address(struct net_device *dev, void *p)
2366{
2367        struct airo_info *ai = dev->priv;
2368        struct sockaddr *addr = p;
2369
2370        readConfigRid(ai, 1);
2371        memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);
2372        set_bit (FLAG_COMMIT, &ai->flags);
2373        disable_MAC(ai, 1);
2374        writeConfigRid (ai, 1);
2375        enable_MAC(ai, 1);
2376        memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);
2377        if (ai->wifidev)
2378                memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);
2379        return 0;
2380}
2381
2382static int airo_change_mtu(struct net_device *dev, int new_mtu)
2383{
2384        if ((new_mtu < 68) || (new_mtu > 2400))
2385                return -EINVAL;
2386        dev->mtu = new_mtu;
2387        return 0;
2388}
2389
2390static LIST_HEAD(airo_devices);
2391
2392static void add_airo_dev(struct airo_info *ai)
2393{
2394        /* Upper layers already keep track of PCI devices,
2395         * so we only need to remember our non-PCI cards. */
2396        if (!ai->pci)
2397                list_add_tail(&ai->dev_list, &airo_devices);
2398}
2399
2400static void del_airo_dev(struct airo_info *ai)
2401{
2402        if (!ai->pci)
2403                list_del(&ai->dev_list);
2404}
2405
2406static int airo_close(struct net_device *dev) {
2407        struct airo_info *ai = dev->priv;
2408
2409        netif_stop_queue(dev);
2410
2411        if (ai->wifidev != dev) {
2412#ifdef POWER_ON_DOWN
2413                /* Shut power to the card. The idea is that the user can save
2414                 * power when he doesn't need the card with "ifconfig down".
2415                 * That's the method that is most friendly towards the network
2416                 * stack (i.e. the network stack won't try to broadcast
2417                 * anything on the interface and routes are gone. Jean II */
2418                set_bit(FLAG_RADIO_DOWN, &ai->flags);
2419                disable_MAC(ai, 1);
2420#endif
2421                disable_interrupts( ai );
2422
2423                free_irq(dev->irq, dev);
2424
2425                set_bit(JOB_DIE, &ai->jobs);
2426                kthread_stop(ai->airo_thread_task);
2427        }
2428        return 0;
2429}
2430
2431void stop_airo_card( struct net_device *dev, int freeres )
2432{
2433        struct airo_info *ai = dev->priv;
2434
2435        set_bit(FLAG_RADIO_DOWN, &ai->flags);
2436        disable_MAC(ai, 1);
2437        disable_interrupts(ai);
2438        takedown_proc_entry( dev, ai );
2439        if (test_bit(FLAG_REGISTERED, &ai->flags)) {
2440                unregister_netdev( dev );
2441                if (ai->wifidev) {
2442                        unregister_netdev(ai->wifidev);
2443                        free_netdev(ai->wifidev);
2444                        ai->wifidev = NULL;
2445                }
2446                clear_bit(FLAG_REGISTERED, &ai->flags);
2447        }
2448        /*
2449         * Clean out tx queue
2450         */
2451        if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) {
2452                struct sk_buff *skb = NULL;
2453                for (;(skb = skb_dequeue(&ai->txq));)
2454                        dev_kfree_skb(skb);
2455        }
2456
2457        airo_networks_free (ai);
2458
2459        kfree(ai->flash);
2460        kfree(ai->rssi);
2461        kfree(ai->APList);
2462        kfree(ai->SSID);
2463        if (freeres) {
2464                /* PCMCIA frees this stuff, so only for PCI and ISA */
2465                release_region( dev->base_addr, 64 );
2466                if (test_bit(FLAG_MPI, &ai->flags)) {
2467                        if (ai->pci)
2468                                mpi_unmap_card(ai->pci);
2469                        if (ai->pcimem)
2470                                iounmap(ai->pcimem);
2471                        if (ai->pciaux)
2472                                iounmap(ai->pciaux);
2473                        pci_free_consistent(ai->pci, PCI_SHARED_LEN,
2474                                ai->shared, ai->shared_dma);
2475                }
2476        }
2477        crypto_free_cipher(ai->tfm);
2478        del_airo_dev(ai);
2479        free_netdev( dev );
2480}
2481
2482EXPORT_SYMBOL(stop_airo_card);
2483
2484static int wll_header_parse(const struct sk_buff *skb, unsigned char *haddr)
2485{
2486        memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN);
2487        return ETH_ALEN;
2488}
2489
2490static void mpi_unmap_card(struct pci_dev *pci)
2491{
2492        unsigned long mem_start = pci_resource_start(pci, 1);
2493        unsigned long mem_len = pci_resource_len(pci, 1);
2494        unsigned long aux_start = pci_resource_start(pci, 2);
2495        unsigned long aux_len = AUXMEMSIZE;
2496
2497        release_mem_region(aux_start, aux_len);
2498        release_mem_region(mem_start, mem_len);
2499}
2500
2501/*************************************************************
2502 *  This routine assumes that descriptors have been setup .
2503 *  Run at insmod time or after reset  when the decriptors
2504 *  have been initialized . Returns 0 if all is well nz
2505 *  otherwise . Does not allocate memory but sets up card
2506 *  using previously allocated descriptors.
2507 */
2508static int mpi_init_descriptors (struct airo_info *ai)
2509{
2510        Cmd cmd;
2511        Resp rsp;
2512        int i;
2513        int rc = SUCCESS;
2514
2515        /* Alloc  card RX descriptors */
2516        netif_stop_queue(ai->dev);
2517
2518        memset(&rsp,0,sizeof(rsp));
2519        memset(&cmd,0,sizeof(cmd));
2520
2521        cmd.cmd = CMD_ALLOCATEAUX;
2522        cmd.parm0 = FID_RX;
2523        cmd.parm1 = (ai->rxfids[0].card_ram_off - ai->pciaux);
2524        cmd.parm2 = MPI_MAX_FIDS;
2525        rc=issuecommand(ai, &cmd, &rsp);
2526        if (rc != SUCCESS) {
2527                airo_print_err(ai->dev->name, "Couldn't allocate RX FID");
2528                return rc;
2529        }
2530
2531        for (i=0; i<MPI_MAX_FIDS; i++) {
2532                memcpy_toio(ai->rxfids[i].card_ram_off,
2533                        &ai->rxfids[i].rx_desc, sizeof(RxFid));
2534        }
2535
2536        /* Alloc card TX descriptors */
2537
2538        memset(&rsp,0,sizeof(rsp));
2539        memset(&cmd,0,sizeof(cmd));
2540
2541        cmd.cmd = CMD_ALLOCATEAUX;
2542        cmd.parm0 = FID_TX;
2543        cmd.parm1 = (ai->txfids[0].card_ram_off - ai->pciaux);
2544        cmd.parm2 = MPI_MAX_FIDS;
2545
2546        for (i=0; i<MPI_MAX_FIDS; i++) {
2547                ai->txfids[i].tx_desc.valid = 1;
2548                memcpy_toio(ai->txfids[i].card_ram_off,
2549                        &ai->txfids[i].tx_desc, sizeof(TxFid));
2550        }
2551        ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */
2552
2553        rc=issuecommand(ai, &cmd, &rsp);
2554        if (rc != SUCCESS) {
2555                airo_print_err(ai->dev->name, "Couldn't allocate TX FID");
2556                return rc;
2557        }
2558
2559        /* Alloc card Rid descriptor */
2560        memset(&rsp,0,sizeof(rsp));
2561        memset(&cmd,0,sizeof(cmd));
2562
2563        cmd.cmd = CMD_ALLOCATEAUX;
2564        cmd.parm0 = RID_RW;
2565        cmd.parm1 = (ai->config_desc.card_ram_off - ai->pciaux);
2566        cmd.parm2 = 1; /* Magic number... */
2567        rc=issuecommand(ai, &cmd, &rsp);
2568        if (rc != SUCCESS) {
2569                airo_print_err(ai->dev->name, "Couldn't allocate RID");
2570                return rc;
2571        }
2572
2573        memcpy_toio(ai->config_desc.card_ram_off,
2574                &ai->config_desc.rid_desc, sizeof(Rid));
2575
2576        return rc;
2577}
2578
2579/*
2580 * We are setting up three things here:
2581 * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid.
2582 * 2) Map PCI memory for issueing commands.
2583 * 3) Allocate memory (shared) to send and receive ethernet frames.
2584 */
2585static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
2586{
2587        unsigned long mem_start, mem_len, aux_start, aux_len;
2588        int rc = -1;
2589        int i;
2590        dma_addr_t busaddroff;
2591        unsigned char *vpackoff;
2592        unsigned char __iomem *pciaddroff;
2593
2594        mem_start = pci_resource_start(pci, 1);
2595        mem_len = pci_resource_len(pci, 1);
2596        aux_start = pci_resource_start(pci, 2);
2597        aux_len = AUXMEMSIZE;
2598
2599        if (!request_mem_region(mem_start, mem_len, DRV_NAME)) {
2600                airo_print_err("", "Couldn't get region %x[%x]",
2601                        (int)mem_start, (int)mem_len);
2602                goto out;
2603        }
2604        if (!request_mem_region(aux_start, aux_len, DRV_NAME)) {
2605                airo_print_err("", "Couldn't get region %x[%x]",
2606                        (int)aux_start, (int)aux_len);
2607                goto free_region1;
2608        }
2609
2610        ai->pcimem = ioremap(mem_start, mem_len);
2611        if (!ai->pcimem) {
2612                airo_print_err("", "Couldn't map region %x[%x]",
2613                        (int)mem_start, (int)mem_len);
2614                goto free_region2;
2615        }
2616        ai->pciaux = ioremap(aux_start, aux_len);
2617        if (!ai->pciaux) {
2618                airo_print_err("", "Couldn't map region %x[%x]",
2619                        (int)aux_start, (int)aux_len);
2620                goto free_memmap;
2621        }
2622
2623        /* Reserve PKTSIZE for each fid and 2K for the Rids */
2624        ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
2625        if (!ai->shared) {
2626                airo_print_err("", "Couldn't alloc_consistent %d",
2627                        PCI_SHARED_LEN);
2628                goto free_auxmap;
2629        }
2630
2631        /*
2632         * Setup descriptor RX, TX, CONFIG
2633         */
2634        busaddroff = ai->shared_dma;
2635        pciaddroff = ai->pciaux + AUX_OFFSET;
2636        vpackoff   = ai->shared;
2637
2638        /* RX descriptor setup */
2639        for(i = 0; i < MPI_MAX_FIDS; i++) {
2640                ai->rxfids[i].pending = 0;
2641                ai->rxfids[i].card_ram_off = pciaddroff;
2642                ai->rxfids[i].virtual_host_addr = vpackoff;
2643                ai->rxfids[i].rx_desc.host_addr = busaddroff;
2644                ai->rxfids[i].rx_desc.valid = 1;
2645                ai->rxfids[i].rx_desc.len = PKTSIZE;
2646                ai->rxfids[i].rx_desc.rdy = 0;
2647
2648                pciaddroff += sizeof(RxFid);
2649                busaddroff += PKTSIZE;
2650                vpackoff   += PKTSIZE;
2651        }
2652
2653        /* TX descriptor setup */
2654        for(i = 0; i < MPI_MAX_FIDS; i++) {
2655                ai->txfids[i].card_ram_off = pciaddroff;
2656                ai->txfids[i].virtual_host_addr = vpackoff;
2657                ai->txfids[i].tx_desc.valid = 1;
2658                ai->txfids[i].tx_desc.host_addr = busaddroff;
2659                memcpy(ai->txfids[i].virtual_host_addr,
2660                        &wifictlhdr8023, sizeof(wifictlhdr8023));
2661
2662                pciaddroff += sizeof(TxFid);
2663                busaddroff += PKTSIZE;
2664                vpackoff   += PKTSIZE;
2665        }
2666        ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */
2667
2668        /* Rid descriptor setup */
2669        ai->config_desc.card_ram_off = pciaddroff;
2670        ai->config_desc.virtual_host_addr = vpackoff;
2671        ai->config_desc.rid_desc.host_addr = busaddroff;
2672        ai->ridbus = busaddroff;
2673        ai->config_desc.rid_desc.rid = 0;
2674        ai->config_desc.rid_desc.len = RIDSIZE;
2675        ai->config_desc.rid_desc.valid = 1;
2676        pciaddroff += sizeof(Rid);
2677        busaddroff += RIDSIZE;
2678        vpackoff   += RIDSIZE;
2679
2680        /* Tell card about descriptors */
2681        if (mpi_init_descriptors (ai) != SUCCESS)
2682                goto free_shared;
2683
2684        return 0;
2685 free_shared:
2686        pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
2687 free_auxmap:
2688        iounmap(ai->pciaux);
2689 free_memmap:
2690        iounmap(ai->pcimem);
2691 free_region2:
2692        release_mem_region(aux_start, aux_len);
2693 free_region1:
2694        release_mem_region(mem_start, mem_len);
2695 out:
2696        return rc;
2697}
2698
2699static const struct header_ops airo_header_ops = {
2700        .parse = wll_header_parse,
2701};
2702
2703static void wifi_setup(struct net_device *dev)
2704{
2705        dev->header_ops = &airo_header_ops;
2706        dev->hard_start_xmit = &airo_start_xmit11;
2707        dev->get_stats = &airo_get_stats;
2708        dev->set_mac_address = &airo_set_mac_address;
2709        dev->do_ioctl = &airo_ioctl;
2710        dev->wireless_handlers = &airo_handler_def;
2711        dev->change_mtu = &airo_change_mtu;
2712        dev->open = &airo_open;
2713        dev->stop = &airo_close;
2714
2715        dev->type               = ARPHRD_IEEE80211;
2716        dev->hard_header_len    = ETH_HLEN;
2717        dev->mtu                = AIRO_DEF_MTU;
2718        dev->addr_len           = ETH_ALEN;
2719        dev->tx_queue_len       = 100; 
2720
2721        memset(dev->broadcast,0xFF, ETH_ALEN);
2722
2723        dev->flags              = IFF_BROADCAST|IFF_MULTICAST;
2724}
2725
2726static struct net_device *init_wifidev(struct airo_info *ai,
2727                                        struct net_device *ethdev)
2728{
2729        int err;
2730        struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
2731        if (!dev)
2732                return NULL;
2733        dev->priv = ethdev->priv;
2734        dev->irq = ethdev->irq;
2735        dev->base_addr = ethdev->base_addr;
2736        dev->wireless_data = ethdev->wireless_data;
2737        memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
2738        err = register_netdev(dev);
2739        if (err<0) {
2740                free_netdev(dev);
2741                return NULL;
2742        }
2743        return dev;
2744}
2745
2746static int reset_card( struct net_device *dev , int lock) {
2747        struct airo_info *ai = dev->priv;
2748
2749        if (lock && down_interruptible(&ai->sem))
2750                return -1;
2751        waitbusy (ai);
2752        OUT4500(ai,COMMAND,CMD_SOFTRESET);
2753        msleep(200);
2754        waitbusy (ai);
2755        msleep(200);
2756        if (lock)
2757                up(&ai->sem);
2758        return 0;
2759}
2760
2761#define AIRO_MAX_NETWORK_COUNT  64
2762static int airo_networks_allocate(struct airo_info *ai)
2763{
2764        if (ai->networks)
2765                return 0;
2766
2767        ai->networks =
2768            kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
2769                    GFP_KERNEL);
2770        if (!ai->networks) {
2771                airo_print_warn("", "Out of memory allocating beacons");
2772                return -ENOMEM;
2773        }
2774
2775        return 0;
2776}
2777
2778static void airo_networks_free(struct airo_info *ai)
2779{
2780        kfree(ai->networks);
2781        ai->networks = NULL;
2782}
2783
2784static void airo_networks_initialize(struct airo_info *ai)
2785{
2786        int i;
2787
2788        INIT_LIST_HEAD(&ai->network_free_list);
2789        INIT_LIST_HEAD(&ai->network_list);
2790        for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++)
2791                list_add_tail(&ai->networks[i].list,
2792                              &ai->network_free_list);
2793}
2794
2795static int airo_test_wpa_capable(struct airo_info *ai)
2796{
2797        int status;
2798        CapabilityRid cap_rid;
2799
2800        status = readCapabilityRid(ai, &cap_rid, 1);
2801        if (status != SUCCESS) return 0;
2802
2803        /* Only firmware versions 5.30.17 or better can do WPA */
2804        if ((cap_rid.softVer > 0x530)
2805          || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
2806                airo_print_info("", "WPA is supported.");
2807                return 1;
2808        }
2809
2810        /* No WPA support */
2811        airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
2812                " and greater support WPA.  Detected %s)", cap_rid.prodVer);
2813        return 0;
2814}
2815
2816static struct net_device *_init_airo_card( unsigned short irq, int port,
2817                                           int is_pcmcia, struct pci_dev *pci,
2818                                           struct device *dmdev )
2819{
2820        struct net_device *dev;
2821        struct airo_info *ai;
2822        int i, rc;
2823        DECLARE_MAC_BUF(mac);
2824
2825        /* Create the network device object. */
2826        dev = alloc_netdev(sizeof(*ai), "", ether_setup);
2827        if (!dev) {
2828                airo_print_err("", "Couldn't alloc_etherdev");
2829                return NULL;
2830        }
2831
2832        ai = dev->priv;
2833        ai->wifidev = NULL;
2834        ai->flags = 1 << FLAG_RADIO_DOWN;
2835        ai->jobs = 0;
2836        ai->dev = dev;
2837        if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
2838                airo_print_dbg("", "Found an MPI350 card");
2839                set_bit(FLAG_MPI, &ai->flags);
2840        }
2841        spin_lock_init(&ai->aux_lock);
2842        sema_init(&ai->sem, 1);
2843        ai->config.len = 0;
2844        ai->pci = pci;
2845        init_waitqueue_head (&ai->thr_wait);
2846        ai->tfm = NULL;
2847        add_airo_dev(ai);
2848
2849        if (airo_networks_allocate (ai))
2850                goto err_out_free;
2851        airo_networks_initialize (ai);
2852
2853        /* The Airo-specific entries in the device structure. */
2854        if (test_bit(FLAG_MPI,&ai->flags)) {
2855                skb_queue_head_init (&ai->txq);
2856                dev->hard_start_xmit = &mpi_start_xmit;
2857        } else
2858                dev->hard_start_xmit = &airo_start_xmit;
2859        dev->get_stats = &airo_get_stats;
2860        dev->set_multicast_list = &airo_set_multicast_list;
2861        dev->set_mac_address = &airo_set_mac_address;
2862        dev->do_ioctl = &airo_ioctl;
2863        dev->wireless_handlers = &airo_handler_def;
2864        ai->wireless_data.spy_data = &ai->spy_data;
2865        dev->wireless_data = &ai->wireless_data;
2866        dev->change_mtu = &airo_change_mtu;
2867        dev->open = &airo_open;
2868        dev->stop = &airo_close;
2869        dev->irq = irq;
2870        dev->base_addr = port;
2871
2872        SET_NETDEV_DEV(dev, dmdev);
2873
2874        reset_card (dev, 1);
2875        msleep(400);
2876
2877        if (!is_pcmcia) {
2878                if (!request_region(dev->base_addr, 64, DRV_NAME)) {
2879                        rc = -EBUSY;
2880                        airo_print_err(dev->name, "Couldn't request region");
2881                        goto err_out_nets;
2882                }
2883        }
2884
2885        if (test_bit(FLAG_MPI,&ai->flags)) {
2886                if (mpi_map_card(ai, pci)) {
2887                        airo_print_err("", "Could not map memory");
2888                        goto err_out_res;
2889                }
2890        }
2891
2892        if (probe) {
2893                if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
2894                        airo_print_err(dev->name, "MAC could not be enabled" );
2895                        rc = -EIO;
2896                        goto err_out_map;
2897                }
2898        } else if (!test_bit(FLAG_MPI,&ai->flags)) {
2899                ai->bap_read = fast_bap_read;
2900                set_bit(FLAG_FLASHING, &ai->flags);
2901        }
2902
2903        /* Test for WPA support */
2904        if (airo_test_wpa_capable(ai)) {
2905                set_bit(FLAG_WPA_CAPABLE, &ai->flags);
2906                ai->bssListFirst = RID_WPA_BSSLISTFIRST;
2907                ai->bssListNext = RID_WPA_BSSLISTNEXT;
2908                ai->bssListRidLen = sizeof(BSSListRid);
2909        } else {
2910                ai->bssListFirst = RID_BSSLISTFIRST;
2911                ai->bssListNext = RID_BSSLISTNEXT;
2912                ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
2913        }
2914
2915        strcpy(dev->name, "eth%d");
2916        rc = register_netdev(dev);
2917        if (rc) {
2918                airo_print_err(dev->name, "Couldn't register_netdev");
2919                goto err_out_map;
2920        }
2921        ai->wifidev = init_wifidev(ai, dev);
2922        if (!ai->wifidev)
2923                goto err_out_reg;
2924
2925        set_bit(FLAG_REGISTERED,&ai->flags);
2926        airo_print_info(dev->name, "MAC enabled %s",
2927                        print_mac(mac, dev->dev_addr));
2928
2929        /* Allocate the transmit buffers */
2930        if (probe && !test_bit(FLAG_MPI,&ai->flags))
2931                for( i = 0; i < MAX_FIDS; i++ )
2932                        ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
2933
2934        if (setup_proc_entry(dev, dev->priv) < 0)
2935                goto err_out_wifi;
2936
2937        return dev;
2938
2939err_out_wifi:
2940        unregister_netdev(ai->wifidev);
2941        free_netdev(ai->wifidev);
2942err_out_reg:
2943        unregister_netdev(dev);
2944err_out_map:
2945        if (test_bit(FLAG_MPI,&ai->flags) && pci) {
2946                pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma);
2947                iounmap(ai->pciaux);
2948                iounmap(ai->pcimem);
2949                mpi_unmap_card(ai->pci);
2950        }
2951err_out_res:
2952        if (!is_pcmcia)
2953                release_region( dev->base_addr, 64 );
2954err_out_nets:
2955        airo_networks_free(ai);
2956        del_airo_dev(ai);
2957err_out_free:
2958        free_netdev(dev);
2959        return NULL;
2960}
2961
2962struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia,
2963                                  struct device *dmdev)
2964{
2965        return _init_airo_card ( irq, port, is_pcmcia, NULL, dmdev);
2966}
2967
2968EXPORT_SYMBOL(init_airo_card);
2969
2970static int waitbusy (struct airo_info *ai) {
2971        int delay = 0;
2972        while ((IN4500 (ai, COMMAND) & COMMAND_BUSY) & (delay < 10000)) {
2973                udelay (10);
2974                if ((++delay % 20) == 0)
2975                        OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
2976        }
2977        return delay < 10000;
2978}
2979
2980int reset_airo_card( struct net_device *dev )
2981{
2982        int i;
2983        struct airo_info *ai = dev->priv;
2984        DECLARE_MAC_BUF(mac);
2985
2986        if (reset_card (dev, 1))
2987                return -1;
2988
2989        if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) {
2990                airo_print_err(dev->name, "MAC could not be enabled");
2991                return -1;
2992        }
2993        airo_print_info(dev->name, "MAC enabled %s",
2994                        print_mac(mac, dev->dev_addr));
2995        /* Allocate the transmit buffers if needed */
2996        if (!test_bit(FLAG_MPI,&ai->flags))
2997                for( i = 0; i < MAX_FIDS; i++ )
2998                        ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
2999
3000        enable_interrupts( ai );
3001        netif_wake_queue(dev);
3002        return 0;
3003}
3004
3005EXPORT_SYMBOL(reset_airo_card);
3006
3007static void airo_send_event(struct net_device *dev) {
3008        struct airo_info *ai = dev->priv;
3009        union iwreq_data wrqu;
3010        StatusRid status_rid;
3011
3012        clear_bit(JOB_EVENT, &ai->jobs);
3013        PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0);
3014        up(&ai->sem);
3015        wrqu.data.length = 0;
3016        wrqu.data.flags = 0;
3017        memcpy(wrqu.ap_addr.sa_data, status_rid.bssid[0], ETH_ALEN);
3018        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3019
3020        /* Send event to user space */
3021        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
3022}
3023
3024static void airo_process_scan_results (struct airo_info *ai) {
3025        union iwreq_data        wrqu;
3026        BSSListRid bss;
3027        int rc;
3028        BSSListElement * loop_net;
3029        BSSListElement * tmp_net;
3030
3031        /* Blow away current list of scan results */
3032        list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) {
3033                list_move_tail (&loop_net->list, &ai->network_free_list);
3034                /* Don't blow away ->list, just BSS data */
3035                memset (loop_net, 0, sizeof (loop_net->bss));
3036        }
3037
3038        /* Try to read the first entry of the scan result */
3039        rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0);
3040        if((rc) || (bss.index == 0xffff)) {
3041                /* No scan results */
3042                goto out;
3043        }
3044
3045        /* Read and parse all entries */
3046        tmp_net = NULL;
3047        while((!rc) && (bss.index != 0xffff)) {
3048                /* Grab a network off the free list */
3049                if (!list_empty(&ai->network_free_list)) {
3050                        tmp_net = list_entry(ai->network_free_list.next,
3051                                            BSSListElement, list);
3052                        list_del(ai->network_free_list.next);
3053                }
3054
3055                if (tmp_net != NULL) {
3056                        memcpy(tmp_net, &bss, sizeof(tmp_net->bss));
3057                        list_add_tail(&tmp_net->list, &ai->network_list);
3058                        tmp_net = NULL;
3059                }
3060
3061                /* Read next entry */
3062                rc = PC4500_readrid(ai, ai->bssListNext,
3063                                    &bss, ai->bssListRidLen, 0);
3064        }
3065
3066out:
3067        ai->scan_timeout = 0;
3068        clear_bit(JOB_SCAN_RESULTS, &ai->jobs);
3069        up(&ai->sem);
3070
3071        /* Send an empty event to user space.
3072         * We don't send the received data on
3073         * the event because it would require
3074         * us to do complex transcoding, and
3075         * we want to minimise the work done in
3076         * the irq handler. Use a request to
3077         * extract the data - Jean II */
3078        wrqu.data.length = 0;
3079        wrqu.data.flags = 0;
3080        wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL);
3081}
3082
3083static int airo_thread(void *data) {
3084        struct net_device *dev = data;
3085        struct airo_info *ai = dev->priv;
3086        int locked;
3087
3088        set_freezable();
3089        while(1) {
3090                /* make swsusp happy with our thread */
3091                try_to_freeze();
3092
3093                if (test_bit(JOB_DIE, &ai->jobs))
3094                        break;
3095
3096                if (ai->jobs) {
3097                        locked = down_interruptible(&ai->sem);
3098                } else {
3099                        wait_queue_t wait;
3100
3101                        init_waitqueue_entry(&wait, current);
3102                        add_wait_queue(&ai->thr_wait, &wait);
3103                        for (;;) {
3104                                set_current_state(TASK_INTERRUPTIBLE);
3105                                if (ai->jobs)
3106                                        break;
3107                                if (ai->expires || ai->scan_timeout) {
3108                                        if (ai->scan_timeout &&
3109                                                        time_after_eq(jiffies,ai->scan_timeout)){
3110                                                set_bit(JOB_SCAN_RESULTS, &ai->jobs);
3111                                                break;
3112                                        } else if (ai->expires &&
3113                                                        time_after_eq(jiffies,ai->expires)){
3114                                                set_bit(JOB_AUTOWEP, &ai->jobs);
3115                                                break;
3116                                        }
3117                                        if (!kthread_should_stop() &&
3118                                            !freezing(current)) {
3119                                                unsigned long wake_at;
3120                                                if (!ai->expires || !ai->scan_timeout) {
3121                                                        wake_at = max(ai->expires,
3122                                                                ai->scan_timeout);
3123                                                } else {
3124                                                        wake_at = min(ai->expires,
3125                                                                ai->scan_timeout);
3126                                                }
3127                                                schedule_timeout(wake_at - jiffies);
3128                                                continue;
3129                                        }
3130                                } else if (!kthread_should_stop() &&
3131                                           !freezing(current)) {
3132                                        schedule();
3133                                        continue;
3134                                }
3135                                break;
3136                        }
3137                        current->state = TASK_RUNNING;
3138                        remove_wait_queue(&ai->thr_wait, &wait);
3139                        locked = 1;
3140                }
3141
3142                if (locked)
3143                        continue;
3144
3145                if (test_bit(JOB_DIE, &ai->jobs)) {
3146                        up(&ai->sem);
3147                        break;
3148                }
3149
3150                if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) {
3151                        up(&ai->sem);
3152                        continue;
3153                }
3154
3155                if (test_bit(JOB_XMIT, &ai->jobs))
3156                        airo_end_xmit(dev);
3157                else if (test_bit(JOB_XMIT11, &ai->jobs))
3158                        airo_end_xmit11(dev);
3159                else if (test_bit(JOB_STATS, &ai->jobs))
3160                        airo_read_stats(ai);
3161                else if (test_bit(JOB_WSTATS, &ai->jobs))
3162                        airo_read_wireless_stats(ai);
3163                else if (test_bit(JOB_PROMISC, &ai->jobs))
3164                        airo_set_promisc(ai);
3165                else if (test_bit(JOB_MIC, &ai->jobs))
3166                        micinit(ai);
3167                else if (test_bit(JOB_EVENT, &ai->jobs))
3168                        airo_send_event(dev);
3169                else if (test_bit(JOB_AUTOWEP, &ai->jobs))
3170                        timer_func(dev);
3171                else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs))
3172                        airo_process_scan_results(ai);
3173                else  /* Shouldn't get here, but we make sure to unlock */
3174                        up(&ai->sem);
3175        }
3176
3177        return 0;
3178}
3179
3180static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
3181        struct net_device *dev = (struct net_device *)dev_id;
3182        u16 status;
3183        u16 fid;
3184        struct airo_info *apriv = dev->priv;
3185        u16 savedInterrupts = 0;
3186        int handled = 0;
3187
3188        if (!netif_device_present(dev))
3189                return IRQ_NONE;
3190
3191        for (;;) {
3192                status = IN4500( apriv, EVSTAT );
3193                if ( !(status & STATUS_INTS) || status == 0xffff ) break;
3194
3195                handled = 1;
3196
3197                if ( status & EV_AWAKE ) {
3198                        OUT4500( apriv, EVACK, EV_AWAKE );
3199                        OUT4500( apriv, EVACK, EV_AWAKE );
3200                }
3201
3202                if (!savedInterrupts) {
3203                        savedInterrupts = IN4500( apriv, EVINTEN );
3204                        OUT4500( apriv, EVINTEN, 0 );
3205                }
3206
3207                if ( status & EV_MIC ) {
3208                        OUT4500( apriv, EVACK, EV_MIC );
3209                        if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
3210                                set_bit(JOB_MIC, &apriv->jobs);
3211                                wake_up_interruptible(&apriv->thr_wait);
3212                        }
3213                }
3214                if ( status & EV_LINK ) {
3215                        union iwreq_data        wrqu;
3216                        int scan_forceloss = 0;
3217                        /* The link status has changed, if you want to put a
3218                           monitor hook in, do it here.  (Remember that
3219                           interrupts are still disabled!)
3220                        */
3221                        u16 newStatus = IN4500(apriv, LINKSTAT);
3222                        OUT4500( apriv, EVACK, EV_LINK);
3223                        /* Here is what newStatus means: */
3224#define NOBEACON 0x8000 /* Loss of sync - missed beacons */
3225#define MAXRETRIES 0x8001 /* Loss of sync - max retries */
3226#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
3227#define FORCELOSS 0x8003 /* Loss of sync - host request */
3228#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
3229#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */
3230#define DISASS 0x8200 /* Disassociation (low byte is reason code) */
3231#define ASSFAIL 0x8400 /* Association failure (low byte is reason
3232                          code) */
3233#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
3234                           code) */
3235#define ASSOCIATED 0x0400 /* Associated */
3236#define REASSOCIATED 0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
3237#define RC_RESERVED 0 /* Reserved return code */
3238#define RC_NOREASON 1 /* Unspecified reason */
3239#define RC_AUTHINV 2 /* Previous authentication invalid */
3240#define RC_DEAUTH 3 /* Deauthenticated because sending station is
3241                       leaving */
3242#define RC_NOACT 4 /* Disassociated due to inactivity */
3243#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle
3244                        all currently associated stations */
3245#define RC_BADCLASS2 6 /* Class 2 frame received from
3246                          non-Authenticated station */
3247#define RC_BADCLASS3 7 /* Class 3 frame received from
3248                          non-Associated station */
3249#define RC_STATLEAVE 8 /* Disassociated because sending station is
3250                          leaving BSS */
3251#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
3252                       Authenticated with the responding station */
3253                        if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
3254                                scan_forceloss = 1;
3255                        if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
3256                                if (auto_wep)
3257                                        apriv->expires = 0;
3258                                if (apriv->list_bss_task)
3259                                        wake_up_process(apriv->list_bss_task);
3260                                set_bit(FLAG_UPDATE_UNI, &apriv->flags);
3261                                set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
3262
3263                                if (down_trylock(&apriv->sem) != 0) {
3264                                        set_bit(JOB_EVENT, &apriv->jobs);
3265                                        wake_up_interruptible(&apriv->thr_wait);
3266                                } else
3267                                        airo_send_event(dev);
3268                        } else if (!scan_forceloss) {
3269                                if (auto_wep && !apriv->expires) {
3270                                        apriv->expires = RUN_AT(3*HZ);
3271                                        wake_up_interruptible(&apriv->thr_wait);
3272                                }
3273
3274                                /* Send event to user space */
3275                                memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
3276                                wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3277                                wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
3278                        }
3279                }
3280
3281                /* Check to see if there is something to receive */
3282                if ( status & EV_RX  ) {
3283                        struct sk_buff *skb = NULL;
3284                        u16 fc, len, hdrlen = 0;
3285#pragma pack(1)
3286                        struct {
3287                                u16 status, len;
3288                                u8 rssi[2];
3289                                u8 rate;
3290                                u8 freq;
3291                                u16 tmp[4];
3292                        } hdr;
3293#pragma pack()
3294                        u16 gap;
3295                        u16 tmpbuf[4];
3296                        u16 *buffer;
3297
3298                        if (test_bit(FLAG_MPI,&apriv->flags)) {
3299                                if (test_bit(FLAG_802_11, &apriv->flags))
3300                                        mpi_receive_802_11(apriv);
3301                                else
3302                                        mpi_receive_802_3(apriv);
3303                                OUT4500(apriv, EVACK, EV_RX);
3304                                goto exitrx;
3305                        }
3306
3307                        fid = IN4500( apriv, RXFID );
3308
3309                        /* Get the packet length */
3310                        if (test_bit(FLAG_802_11, &apriv->flags)) {
3311                                bap_setup (apriv, fid, 4, BAP0);
3312                                bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0);
3313                                /* Bad CRC. Ignore packet */
3314                                if (le16_to_cpu(hdr.status) & 2)
3315                                        hdr.len = 0;
3316                                if (apriv->wifidev == NULL)
3317                                        hdr.len = 0;
3318                        } else {
3319                                bap_setup (apriv, fid, 0x36, BAP0);
3320                                bap_read (apriv, (u16*)&hdr.len, 2, BAP0);
3321                        }
3322                        len = le16_to_cpu(hdr.len);
3323
3324                        if (len > AIRO_DEF_MTU) {
3325                                airo_print_err(apriv->dev->name, "Bad size %d", len);
3326                                goto badrx;
3327                        }
3328                        if (len == 0)
3329                                goto badrx;
3330
3331                        if (test_bit(FLAG_802_11, &apriv->flags)) {
3332                                bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);
3333                                fc = le16_to_cpu(fc);
3334                                switch (fc & 0xc) {
3335                                        case 4:
3336                                                if ((fc & 0xe0) == 0xc0)
3337                                                        hdrlen = 10;
3338                                                else
3339                                                        hdrlen = 16;
3340                                                break;
3341                                        case 8:
3342                                                if ((fc&0x300)==0x300){
3343                                                        hdrlen = 30;
3344                                                        break;
3345                                                }
3346                                        default:
3347                                                hdrlen = 24;
3348                                }
3349                        } else
3350                                hdrlen = ETH_ALEN * 2;
3351
3352                        skb = dev_alloc_skb( len + hdrlen + 2 + 2 );
3353                        if ( !skb ) {
3354                                apriv->stats.rx_dropped++;
3355                                goto badrx;
3356                        }
3357                        skb_reserve(skb, 2); /* This way the IP header is aligned */
3358                        buffer = (u16*)skb_put (skb, len + hdrlen);
3359                        if (test_bit(FLAG_802_11, &apriv->flags)) {
3360                                buffer[0] = fc;
3361                                bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
3362                                if (hdrlen == 24)
3363                                        bap_read (apriv, tmpbuf, 6, BAP0);
3364
3365                                bap_read (apriv, &gap, sizeof(gap), BAP0);
3366                                gap = le16_to_cpu(gap);
3367                                if (gap) {
3368                                        if (gap <= 8) {
3369                                                bap_read (apriv, tmpbuf, gap, BAP0);
3370                                        } else {
3371                                                airo_print_err(apriv->dev->name, "gaplen too "
3372                                                        "big. Problems will follow...");
3373                                        }
3374                                }
3375                                bap_read (apriv, buffer + hdrlen/2, len, BAP0);
3376                        } else {
3377                                MICBuffer micbuf;
3378                                bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
3379                                if (apriv->micstats.enabled) {
3380                                        bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
3381                                        if (ntohs(micbuf.typelen) > 0x05DC)
3382                                                bap_setup (apriv, fid, 0x44, BAP0);
3383                                        else {
3384                                                if (len <= sizeof(micbuf))
3385                                                        goto badmic;
3386
3387                                                len -= sizeof(micbuf);
3388                                                skb_trim (skb, len + hdrlen);
3389                                        }
3390                                }
3391                                bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
3392                                if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
3393badmic:
3394                                        dev_kfree_skb_irq (skb);
3395badrx:
3396                                        OUT4500( apriv, EVACK, EV_RX);
3397                                        goto exitrx;
3398                                }
3399                        }
3400#ifdef WIRELESS_SPY
3401                        if (apriv->spy_data.spy_number > 0) {
3402                                char *sa;
3403                                struct iw_quality wstats;
3404                                /* Prepare spy data : addr + qual */
3405                                if (!test_bit(FLAG_802_11, &apriv->flags)) {
3406                                        sa = (char*)buffer + 6;
3407                                        bap_setup (apriv, fid, 8, BAP0);
3408                                        bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);
3409                                } else
3410                                        sa = (char*)buffer + 10;
3411                                wstats.qual = hdr.rssi[0];
3412                                if (apriv->rssi)
3413                                        wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
3414                                else
3415                                        wstats.level = (hdr.rssi[1] + 321) / 2;
3416                                wstats.noise = apriv->wstats.qual.noise;
3417                                wstats.updated = IW_QUAL_LEVEL_UPDATED
3418                                        | IW_QUAL_QUAL_UPDATED
3419                                        | IW_QUAL_DBM;
3420                                /* Update spy records */
3421                                wireless_spy_update(dev, sa, &wstats);
3422                        }
3423#endif /* WIRELESS_SPY */
3424                        OUT4500( apriv, EVACK, EV_RX);
3425
3426                        if (test_bit(FLAG_802_11, &apriv->flags)) {
3427                                skb_reset_mac_header(skb);
3428                                skb->pkt_type = PACKET_OTHERHOST;
3429                                skb->dev = apriv->wifidev;
3430                                skb->protocol = htons(ETH_P_802_2);
3431                        } else
3432                                skb->protocol = eth_type_trans(skb,dev);
3433                        skb->dev->last_rx = jiffies;
3434                        skb->ip_summed = CHECKSUM_NONE;
3435
3436                        netif_rx( skb );
3437                }
3438exitrx:
3439
3440                /* Check to see if a packet has been transmitted */
3441                if (  status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) {
3442                        int i;
3443                        int len = 0;
3444                        int index = -1;
3445
3446                        if (test_bit(FLAG_MPI,&apriv->flags)) {
3447                                unsigned long flags;
3448
3449                                if (status & EV_TXEXC)
3450                                        get_tx_error(apriv, -1);
3451                                spin_lock_irqsave(&apriv->aux_lock, flags);
3452                                if (!skb_queue_empty(&apriv->txq)) {
3453                                        spin_unlock_irqrestore(&apriv->aux_lock,flags);
3454                                        mpi_send_packet (dev);
3455                                } else {
3456                                        clear_bit(FLAG_PENDING_XMIT, &apriv->flags);
3457                                        spin_unlock_irqrestore(&apriv->aux_lock,flags);
3458                                        netif_wake_queue (dev);
3459                                }
3460                                OUT4500( apriv, EVACK,
3461                                        status & (EV_TX|EV_TXCPY|EV_TXEXC));
3462                                goto exittx;
3463                        }
3464
3465                        fid = IN4500(apriv, TXCOMPLFID);
3466
3467                        for( i = 0; i < MAX_FIDS; i++ ) {
3468                                if ( ( apriv->fids[i] & 0xffff ) == fid ) {
3469                                        len = apriv->fids[i] >> 16;
3470                                        index = i;
3471                                }
3472                        }
3473                        if (index != -1) {
3474                                if (status & EV_TXEXC)
3475                                        get_tx_error(apriv, index);
3476                                OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
3477                                /* Set up to be used again */
3478                                apriv->fids[index] &= 0xffff;
3479                                if (index < MAX_FIDS / 2) {
3480                                        if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags))
3481                                                netif_wake_queue(dev);
3482                                } else {
3483                                        if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags))
3484                                                netif_wake_queue(apriv->wifidev);
3485                                }
3486                        } else {
3487                                OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
3488                                airo_print_err(apriv->dev->name, "Unallocated FID was "
3489                                        "used to xmit" );
3490                        }
3491                }
3492exittx:
3493                if ( status & ~STATUS_INTS & ~IGNORE_INTS )
3494                        airo_print_warn(apriv->dev->name, "Got weird status %x",
3495                                status & ~STATUS_INTS & ~IGNORE_INTS );
3496        }
3497
3498        if (savedInterrupts)
3499                OUT4500( apriv, EVINTEN, savedInterrupts );
3500
3501        /* done.. */
3502        return IRQ_RETVAL(handled);
3503}
3504
3505/*
3506 *  Routines to talk to the card
3507 */
3508
3509/*
3510 *  This was originally written for the 4500, hence the name
3511 *  NOTE:  If use with 8bit mode and SMP bad things will happen!
3512 *         Why would some one do 8 bit IO in an SMP machine?!?
3513 */
3514static void OUT4500( struct airo_info *ai, u16 reg, u16 val ) {
3515        if (test_bit(FLAG_MPI,&ai->flags))
3516                reg <<= 1;
3517        if ( !do8bitIO )
3518                outw( val, ai->dev->base_addr + reg );
3519        else {
3520                outb( val & 0xff, ai->dev->base_addr + reg );
3521                outb( val >> 8, ai->dev->base_addr + reg + 1 );
3522        }
3523}
3524
3525static u16 IN4500( struct airo_info *ai, u16 reg ) {
3526        unsigned short rc;
3527
3528        if (test_bit(FLAG_MPI,&ai->flags))
3529                reg <<= 1;
3530        if ( !do8bitIO )
3531                rc = inw( ai->dev->base_addr + reg );
3532        else {
3533                rc = inb( ai->dev->base_addr + reg );
3534                rc += ((int)inb( ai->dev->base_addr + reg + 1 )) << 8;
3535        }
3536        return rc;
3537}
3538
3539static int enable_MAC(struct airo_info *ai, int lock)
3540{
3541        int rc;
3542        Cmd cmd;
3543        Resp rsp;
3544
3545        /* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions
3546         * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down"
3547         * Note : we could try to use !netif_running(dev) in enable_MAC()
3548         * instead of this flag, but I don't trust it *within* the
3549         * open/close functions, and testing both flags together is
3550         * "cheaper" - Jean II */
3551        if (ai->flags & FLAG_RADIO_MASK) return SUCCESS;
3552
3553        if (lock && down_interruptible(&ai->sem))
3554                return -ERESTARTSYS;
3555
3556        if (!test_bit(FLAG_ENABLED, &ai->flags)) {
3557                memset(&cmd, 0, sizeof(cmd));
3558                cmd.cmd = MAC_ENABLE;
3559                rc = issuecommand(ai, &cmd, &rsp);
3560                if (rc == SUCCESS)
3561                        set_bit(FLAG_ENABLED, &ai->flags);
3562        } else
3563                rc = SUCCESS;
3564
3565        if (lock)
3566            up(&ai->sem);
3567
3568        if (rc)
3569                airo_print_err(ai->dev->name, "Cannot enable MAC");
3570        else if ((rsp.status & 0xFF00) != 0) {
3571                airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, "
3572                        "rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2);
3573                rc = ERROR;
3574        }
3575        return rc;
3576}
3577
3578static void disable_MAC( struct airo_info *ai, int lock ) {
3579        Cmd cmd;
3580        Resp rsp;
3581
3582        if (lock && down_interruptible(&ai->sem))
3583                return;
3584
3585        if (test_bit(FLAG_ENABLED, &ai->flags)) {
3586                memset(&cmd, 0, sizeof(cmd));
3587                cmd.cmd = MAC_DISABLE; // disable in case already enabled
3588                issuecommand(ai, &cmd, &rsp);
3589                clear_bit(FLAG_ENABLED, &ai->flags);
3590        }
3591        if (lock)
3592                up(&ai->sem);
3593}
3594
3595static void enable_interrupts( struct airo_info *ai ) {
3596        /* Enable the interrupts */
3597        OUT4500( ai, EVINTEN, STATUS_INTS );
3598}
3599
3600static void disable_interrupts( struct airo_info *ai ) {
3601        OUT4500( ai, EVINTEN, 0 );
3602}
3603
3604static void mpi_receive_802_3(struct airo_info *ai)
3605{
3606        RxFid rxd;
3607        int len = 0;
3608        struct sk_buff *skb;
3609        char *buffer;
3610        int off = 0;
3611        MICBuffer micbuf;
3612
3613        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
3614        /* Make sure we got something */
3615        if (rxd.rdy && rxd.valid == 0) {
3616                len = rxd.len + 12;
3617                if (len < 12 || len > 2048)
3618                        goto badrx;
3619
3620                skb = dev_alloc_skb(len);
3621                if (!skb) {
3622                        ai->stats.rx_dropped++;
3623                        goto badrx;
3624                }
3625                buffer = skb_put(skb,len);
3626                memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2);
3627                if (ai->micstats.enabled) {
3628                        memcpy(&micbuf,
3629                                ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2,
3630                                sizeof(micbuf));
3631                        if (ntohs(micbuf.typelen) <= 0x05DC) {
3632                                if (len <= sizeof(micbuf) + ETH_ALEN * 2)
3633                                        goto badmic;
3634
3635                                off = sizeof(micbuf);
3636                                skb_trim (skb, len - off);
3637                        }
3638                }
3639                memcpy(buffer + ETH_ALEN * 2,
3640                        ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off,
3641                        len - ETH_ALEN * 2 - off);
3642                if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) {
3643badmic:
3644                        dev_kfree_skb_irq (skb);
3645                        goto badrx;
3646                }
3647#ifdef WIRELESS_SPY
3648                if (ai->spy_data.spy_number > 0) {
3649                        char *sa;
3650                        struct iw_quality wstats;
3651                        /* Prepare spy data : addr + qual */
3652                        sa = buffer + ETH_ALEN;
3653                        wstats.qual = 0; /* XXX Where do I get that info from ??? */
3654                        wstats.level = 0;
3655                        wstats.updated = 0;
3656                        /* Update spy records */
3657                        wireless_spy_update(ai->dev, sa, &wstats);
3658                }
3659#endif /* WIRELESS_SPY */
3660
3661                skb->ip_summed = CHECKSUM_NONE;
3662                skb->protocol = eth_type_trans(skb, ai->dev);
3663                skb->dev->last_rx = jiffies;
3664                netif_rx(skb);
3665        }
3666badrx:
3667        if (rxd.valid == 0) {
3668                rxd.valid = 1;
3669                rxd.rdy = 0;
3670                rxd.len = PKTSIZE;
3671                memcpy_toio(ai->rxfids[0].card_ram_off, &rxd, sizeof(rxd));
3672        }
3673}
3674
3675void mpi_receive_802_11 (struct airo_info *ai)
3676{
3677        RxFid rxd;
3678        struct sk_buff *skb = NULL;
3679        u16 fc, len, hdrlen = 0;
3680#pragma pack(1)
3681        struct {
3682                u16 status, len;
3683                u8 rssi[2];
3684                u8 rate;
3685                u8 freq;
3686                u16 tmp[4];
3687        } hdr;
3688#pragma pack()
3689        u16 gap;
3690        u16 *buffer;
3691        char *ptr = ai->rxfids[0].virtual_host_addr+4;
3692
3693        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
3694        memcpy ((char *)&hdr, ptr, sizeof(hdr));
3695        ptr += sizeof(hdr);
3696        /* Bad CRC. Ignore packet */
3697        if (le16_to_cpu(hdr.status) & 2)
3698                hdr.len = 0;
3699        if (ai->wifidev == NULL)
3700                hdr.len = 0;
3701        len = le16_to_cpu(hdr.len);
3702        if (len > AIRO_DEF_MTU) {
3703                airo_print_err(ai->dev->name, "Bad size %d", len);
3704                goto badrx;
3705        }
3706        if (len == 0)
3707                goto badrx;
3708
3709        memcpy ((char *)&fc, ptr, sizeof(fc));
3710        fc = le16_to_cpu(fc);
3711        switch (fc & 0xc) {
3712                case 4:
3713                        if ((fc & 0xe0) == 0xc0)
3714                                hdrlen = 10;
3715                        else
3716                                hdrlen = 16;
3717                        break;
3718                case 8:
3719                        if ((fc&0x300)==0x300){
3720                                hdrlen = 30;
3721                                break;
3722                        }
3723                default:
3724                        hdrlen = 24;
3725        }
3726
3727        skb = dev_alloc_skb( len + hdrlen + 2 );
3728        if ( !skb ) {
3729                ai->stats.rx_dropped++;
3730                goto badrx;
3731        }
3732        buffer = (u16*)skb_put (skb, len + hdrlen);
3733        memcpy ((char *)buffer, ptr, hdrlen);
3734        ptr += hdrlen;
3735        if (hdrlen == 24)
3736                ptr += 6;
3737        memcpy ((char *)&gap, ptr, sizeof(gap));
3738        ptr += sizeof(gap);
3739        gap = le16_to_cpu(gap);
3740        if (gap) {
3741                if (gap <= 8)
3742                        ptr += gap;
3743                else
3744                        airo_print_err(ai->dev->name,
3745                            "gaplen too big. Problems will follow...");
3746        }
3747        memcpy ((char *)buffer + hdrlen, ptr, len);
3748        ptr += len;
3749#ifdef IW_WIRELESS_SPY    /* defined in iw_handler.h */
3750        if (ai->spy_data.spy_number > 0) {
3751                char *sa;
3752                struct iw_quality wstats;
3753                /* Prepare spy data : addr + qual */
3754                sa = (char*)buffer + 10;
3755                wstats.qual = hdr.rssi[0];
3756                if (ai->rssi)
3757                        wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
3758                else
3759                        wstats.level = (hdr.rssi[1] + 321) / 2;
3760                wstats.noise = ai->wstats.qual.noise;
3761                wstats.updated = IW_QUAL_QUAL_UPDATED
3762                        | IW_QUAL_LEVEL_UPDATED
3763                        | IW_QUAL_DBM;
3764                /* Update spy records */
3765                wireless_spy_update(ai->dev, sa, &wstats);
3766        }
3767#endif /* IW_WIRELESS_SPY */
3768        skb_reset_mac_header(skb);
3769        skb->pkt_type = PACKET_OTHERHOST;
3770        skb->dev = ai->wifidev;
3771        skb->protocol = htons(ETH_P_802_2);
3772        skb->dev->last_rx = jiffies;
3773        skb->ip_summed = CHECKSUM_NONE;
3774        netif_rx( skb );
3775badrx:
3776        if (rxd.valid == 0) {
3777                rxd.valid = 1;
3778                rxd.rdy = 0;
3779                rxd.len = PKTSIZE;
3780                memcpy_toio(ai->rxfids[0].card_ram_off, &rxd, sizeof(rxd));
3781        }
3782}
3783
3784static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
3785{
3786        Cmd cmd;
3787        Resp rsp;
3788        int status;
3789        int i;
3790        SsidRid mySsid;
3791        u16 lastindex;
3792        WepKeyRid wkr;
3793        int rc;
3794
3795        memset( &mySsid, 0, sizeof( mySsid ) );
3796        kfree (ai->flash);
3797        ai->flash = NULL;
3798
3799        /* The NOP is the first step in getting the card going */
3800        cmd.cmd = NOP;
3801        cmd.parm0 = cmd.parm1 = cmd.parm2 = 0;
3802        if (lock && down_interruptible(&ai->sem))
3803                return ERROR;
3804        if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) {
3805                if (lock)
3806                        up(&ai->sem);
3807                return ERROR;
3808        }
3809        disable_MAC( ai, 0);
3810
3811        // Let's figure out if we need to use the AUX port
3812        if (!test_bit(FLAG_MPI,&ai->flags)) {
3813                cmd.cmd = CMD_ENABLEAUX;
3814                if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
3815                        if (lock)
3816                                up(&ai->sem);
3817                        airo_print_err(ai->dev->name, "Error checking for AUX port");
3818                        return ERROR;
3819                }
3820                if (!aux_bap || rsp.status & 0xff00) {
3821                        ai->bap_read = fast_bap_read;
3822                        airo_print_dbg(ai->dev->name, "Doing fast bap_reads");
3823                } else {
3824                        ai->bap_read = aux_bap_read;
3825                        airo_print_dbg(ai->dev->name, "Doing AUX bap_reads");
3826                }
3827        }
3828        if (lock)
3829                up(&ai->sem);
3830        if (ai->config.len == 0) {
3831                tdsRssiRid rssi_rid;
3832                CapabilityRid cap_rid;
3833
3834                kfree(ai->APList);
3835                ai->APList = NULL;
3836                kfree(ai->SSID);
3837                ai->SSID = NULL;
3838                // general configuration (read/modify/write)
3839                status = readConfigRid(ai, lock);
3840                if ( status != SUCCESS ) return ERROR;
3841
3842                status = readCapabilityRid(ai, &cap_rid, lock);
3843                if ( status != SUCCESS ) return ERROR;
3844
3845                status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
3846                if ( status == SUCCESS ) {
3847                        if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
3848                                memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
3849                }
3850                else {
3851                        kfree(ai->rssi);
3852                        ai->rssi = NULL;
3853                        if (cap_rid.softCap & 8)
3854                                ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
3855                        else
3856                                airo_print_warn(ai->dev->name, "unknown received signal "
3857                                                "level scale");
3858                }
3859                ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
3860                ai->config.authType = AUTH_OPEN;
3861                ai->config.modulation = MOD_CCK;
3862
3863                if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
3864                    (micsetup(ai) == SUCCESS)) {
3865                        ai->config.opmode |= MODE_MIC;
3866                        set_bit(FLAG_MIC_CAPABLE, &ai->flags);
3867                }
3868
3869                /* Save off the MAC */
3870                for( i = 0; i < ETH_ALEN; i++ ) {
3871                        mac[i] = ai->config.macAddr[i];
3872                }
3873
3874                /* Check to see if there are any insmod configured
3875                   rates to add */
3876                if ( rates[0] ) {
3877                        int i = 0;
3878                        memset(ai->config.rates,0,sizeof(ai->config.rates));
3879                        for( i = 0; i < 8 && rates[i]; i++ ) {
3880                                ai->config.rates[i] = rates[i];
3881                        }
3882                }
3883                if ( basic_rate > 0 ) {
3884                        int i;
3885                        for( i = 0; i < 8; i++ ) {
3886                                if ( ai->config.rates[i] == basic_rate ||
3887                                     !ai->config.rates ) {
3888                                        ai->config.rates[i] = basic_rate | 0x80;
3889                                        break;
3890                                }
3891                        }
3892                }
3893                set_bit (FLAG_COMMIT, &ai->flags);
3894        }
3895
3896        /* Setup the SSIDs if present */
3897        if ( ssids[0] ) {
3898                int i;
3899                for( i = 0; i < 3 && ssids[i]; i++ ) {
3900                        mySsid.ssids[i].len = strlen(ssids[i]);
3901                        if ( mySsid.ssids[i].len > 32 )
3902                                mySsid.ssids[i].len = 32;
3903                        memcpy(mySsid.ssids[i].ssid, ssids[i],
3904                               mySsid.ssids[i].len);
3905                }
3906                mySsid.len = sizeof(mySsid);
3907        }
3908
3909        status = writeConfigRid(ai, lock);
3910        if ( status != SUCCESS ) return ERROR;
3911
3912        /* Set up the SSID list */
3913        if ( ssids[0] ) {
3914                status = writeSsidRid(ai, &mySsid, lock);
3915                if ( status != SUCCESS ) return ERROR;
3916        }
3917
3918        status = enable_MAC(ai, lock);
3919        if (status != SUCCESS)
3920                return ERROR;
3921
3922        /* Grab the initial wep key, we gotta save it for auto_wep */
3923        rc = readWepKeyRid(ai, &wkr, 1, lock);
3924        if (rc == SUCCESS) do {
3925                lastindex = wkr.kindex;
3926                if (wkr.kindex == 0xffff) {
3927                        ai->defindex = wkr.mac[0];
3928                }
3929                rc = readWepKeyRid(ai, &wkr, 0, lock);
3930        } while(lastindex != wkr.kindex);
3931
3932        try_auto_wep(ai);
3933
3934        return SUCCESS;
3935}
3936
3937static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
3938        // Im really paranoid about letting it run forever!
3939        int max_tries = 600000;
3940
3941        if (IN4500(ai, EVSTAT) & EV_CMD)
3942                OUT4500(ai, EVACK, EV_CMD);
3943
3944        OUT4500(ai, PARAM0, pCmd->parm0);
3945        OUT4500(ai, PARAM1, pCmd->parm1);
3946        OUT4500(ai, PARAM2, pCmd->parm2);
3947        OUT4500(ai, COMMAND, pCmd->cmd);
3948
3949        while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
3950                if ((IN4500(ai, COMMAND)) == pCmd->cmd)
3951                        // PC4500 didn't notice command, try again
3952                        OUT4500(ai, COMMAND, pCmd->cmd);
3953                if (!in_atomic() && (max_tries & 255) == 0)
3954                        schedule();
3955        }
3956
3957        if ( max_tries == -1 ) {
3958                airo_print_err(ai->dev->name,
3959                        "Max tries exceeded when issueing command");
3960                if (IN4500(ai, COMMAND) & COMMAND_BUSY)
3961                        OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
3962                return ERROR;
3963        }
3964
3965        // command completed
3966        pRsp->status = IN4500(ai, STATUS);
3967        pRsp->rsp0 = IN4500(ai, RESP0);
3968        pRsp->rsp1 = IN4500(ai, RESP1);
3969        pRsp->rsp2 = IN4500(ai, RESP2);
3970        if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET)
3971                airo_print_err(ai->dev->name,
3972                        "cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x",
3973                        pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1,
3974                        pRsp->rsp2);
3975
3976        // clear stuck command busy if necessary
3977        if (IN4500(ai, COMMAND) & COMMAND_BUSY) {
3978                OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
3979        }
3980        // acknowledge processing the status/response
3981        OUT4500(ai, EVACK, EV_CMD);
3982
3983        return SUCCESS;
3984}
3985
3986/* Sets up the bap to start exchange data.  whichbap should
3987 * be one of the BAP0 or BAP1 defines.  Locks should be held before
3988 * calling! */
3989static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
3990{
3991        int timeout = 50;
3992        int max_tries = 3;
3993
3994        OUT4500(ai, SELECT0+whichbap, rid);
3995        OUT4500(ai, OFFSET0+whichbap, offset);
3996        while (1) {
3997                int status = IN4500(ai, OFFSET0+whichbap);
3998                if (status & BAP_BUSY) {
3999                        /* This isn't really a timeout, but its kinda
4000                           close */
4001                        if (timeout--) {
4002                                continue;
4003                        }
4004                } else if ( status & BAP_ERR ) {
4005                        /* invalid rid or offset */
4006                        airo_print_err(ai->dev->name, "BAP error %x %d",
4007                                status, whichbap );
4008                        return ERROR;
4009                } else if (status & BAP_DONE) { // success
4010                        return SUCCESS;
4011                }
4012                if ( !(max_tries--) ) {
4013                        airo_print_err(ai->dev->name,
4014                                "BAP setup error too many retries\n");
4015                        return ERROR;
4016                }
4017                // -- PC4500 missed it, try again
4018                OUT4500(ai, SELECT0+whichbap, rid);
4019                OUT4500(ai, OFFSET0+whichbap, offset);
4020                timeout = 50;
4021        }
4022}
4023
4024/* should only be called by aux_bap_read.  This aux function and the
4025   following use concepts not documented in the developers guide.  I
4026   got them from a patch given to my by Aironet */
4027static u16 aux_setup(struct airo_info *ai, u16 page,
4028                     u16 offset, u16 *len)
4029{
4030        u16 next;
4031
4032        OUT4500(ai, AUXPAGE, page);
4033        OUT4500(ai, AUXOFF, 0);
4034        next = IN4500(ai, AUXDATA);
4035        *len = IN4500(ai, AUXDATA)&0xff;
4036        if (offset != 4) OUT4500(ai, AUXOFF, offset);
4037        return next;
4038}
4039
4040/* requires call to bap_setup() first */
4041static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst,
4042                        int bytelen, int whichbap)
4043{
4044        u16 len;
4045        u16 page;
4046        u16 offset;
4047        u16 next;
4048        int words;
4049        int i;
4050        unsigned long flags;
4051
4052        spin_lock_irqsave(&ai->aux_lock, flags);
4053        page = IN4500(ai, SWS0+whichbap);
4054        offset = IN4500(ai, SWS2+whichbap);
4055        next = aux_setup(ai, page, offset, &len);
4056        words = (bytelen+1)>>1;
4057
4058        for (i=0; i<words;) {
4059                int count;
4060                count = (len>>1) < (words-i) ? (len>>1) : (words-i);
4061                if ( !do8bitIO )
4062                        insw( ai->dev->base_addr+DATA0+whichbap,
4063                              pu16Dst+i,count );
4064                else
4065                        insb( ai->dev->base_addr+DATA0+whichbap,
4066                              pu16Dst+i, count << 1 );
4067                i += count;
4068                if (i<words) {
4069                        next = aux_setup(ai, next, 4, &len);
4070                }
4071        }
4072        spin_unlock_irqrestore(&ai->aux_lock, flags);
4073        return SUCCESS;
4074}
4075
4076
4077/* requires call to bap_setup() first */
4078static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst,
4079                         int bytelen, int whichbap)
4080{
4081        bytelen = (bytelen + 1) & (~1); // round up to even value
4082        if ( !do8bitIO )
4083                insw( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen>>1 );
4084        else
4085                insb( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen );
4086        return SUCCESS;
4087}
4088
4089/* requires call to bap_setup() first */
4090static int bap_write(struct airo_info *ai, const u16 *pu16Src,
4091                     int bytelen, int whichbap)
4092{
4093        bytelen = (bytelen + 1) & (~1); // round up to even value
4094        if ( !do8bitIO )
4095                outsw( ai->dev->base_addr+DATA0+whichbap,
4096                       pu16Src, bytelen>>1 );
4097        else
4098                outsb( ai->dev->base_addr+DATA0+whichbap, pu16Src, bytelen );
4099        return SUCCESS;
4100}
4101
4102static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd)
4103{
4104        Cmd cmd; /* for issuing commands */
4105        Resp rsp; /* response from commands */
4106        u16 status;
4107
4108        memset(&cmd, 0, sizeof(cmd));
4109        cmd.cmd = accmd;
4110        cmd.parm0 = rid;
4111        status = issuecommand(ai, &cmd, &rsp);
4112        if (status != 0) return status;
4113        if ( (rsp.status & 0x7F00) != 0) {
4114                return (accmd << 8) + (rsp.rsp0 & 0xFF);
4115        }
4116        return 0;
4117}
4118
4119/*  Note, that we are using BAP1 which is also used by transmit, so
4120 *  we must get a lock. */
4121static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, int lock)
4122{
4123        u16 status;
4124        int rc = SUCCESS;
4125
4126        if (lock) {
4127                if (down_interruptible(&ai->sem))
4128                        return ERROR;
4129        }
4130        if (test_bit(FLAG_MPI,&ai->flags)) {
4131                Cmd cmd;
4132                Resp rsp;
4133
4134                memset(&cmd, 0, sizeof(cmd));
4135                memset(&rsp, 0, sizeof(rsp));
4136                ai->config_desc.rid_desc.valid = 1;
4137                ai->config_desc.rid_desc.len = RIDSIZE;
4138                ai->config_desc.rid_desc.rid = 0;
4139                ai->config_desc.rid_desc.host_addr = ai->ridbus;
4140
4141                cmd.cmd = CMD_ACCESS;
4142                cmd.parm0 = rid;
4143
4144                memcpy_toio(ai->config_desc.card_ram_off,
4145                        &ai->config_desc.rid_desc, sizeof(Rid));
4146
4147                rc = issuecommand(ai, &cmd, &rsp);
4148
4149                if (rsp.status & 0x7f00)
4150                        rc = rsp.rsp0;
4151                if (!rc)
4152                        memcpy(pBuf, ai->config_desc.virtual_host_addr, len);
4153                goto done;
4154        } else {
4155                if ((status = PC4500_accessrid(ai, rid, CMD_ACCESS))!=SUCCESS) {
4156                        rc = status;
4157                        goto done;
4158                }
4159                if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {
4160                        rc = ERROR;
4161                        goto done;
4162                }
4163                // read the rid length field
4164                bap_read(ai, pBuf, 2, BAP1);
4165                // length for remaining part of rid
4166                len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2;
4167
4168                if ( len <= 2 ) {
4169                        airo_print_err(ai->dev->name,
4170                                "Rid %x has a length of %d which is too short",
4171                                (int)rid, (int)len );
4172                        rc = ERROR;
4173                        goto done;
4174                }
4175                // read remainder of the rid
4176                rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1);
4177        }
4178done:
4179        if (lock)
4180                up(&ai->sem);
4181        return rc;
4182}
4183
4184/*  Note, that we are using BAP1 which is also used by transmit, so
4185 *  make sure this isnt called when a transmit is happening */
4186static int PC4500_writerid(struct airo_info *ai, u16 rid,
4187                           const void *pBuf, int len, int lock)
4188{
4189        u16 status;
4190        int rc = SUCCESS;
4191
4192        *(u16*)pBuf = cpu_to_le16((u16)len);
4193
4194        if (lock) {
4195                if (down_interruptible(&ai->sem))
4196                        return ERROR;
4197        }
4198        if (test_bit(FLAG_MPI,&ai->flags)) {
4199                Cmd cmd;
4200                Resp rsp;
4201
4202                if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
4203                        airo_print_err(ai->dev->name,
4204                                "%s: MAC should be disabled (rid=%04x)",
4205                                __FUNCTION__, rid);
4206                memset(&cmd, 0, sizeof(cmd));
4207                memset(&rsp, 0, sizeof(rsp));
4208
4209                ai->config_desc.rid_desc.valid = 1;
4210                ai->config_desc.rid_desc.len = *((u16 *)pBuf);
4211                ai->config_desc.rid_desc.rid = 0;
4212
4213                cmd.cmd = CMD_WRITERID;
4214                cmd.parm0 = rid;
4215
4216                memcpy_toio(ai->config_desc.card_ram_off,
4217                        &ai->config_desc.rid_desc, sizeof(Rid));
4218
4219                if (len < 4 || len > 2047) {
4220                        airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
4221                        rc = -1;
4222                } else {
4223                        memcpy((char *)ai->config_desc.virtual_host_addr,
4224                                pBuf, len);
4225
4226                        rc = issuecommand(ai, &cmd, &rsp);
4227                        if ((rc & 0xff00) != 0) {
4228                                airo_print_err(ai->dev->name, "%s: Write rid Error %d",
4229                                                __FUNCTION__, rc);
4230                                airo_print_err(ai->dev->name, "%s: Cmd=%04x",
4231                                                __FUNCTION__, cmd.cmd);
4232                        }
4233
4234                        if ((rsp.status & 0x7f00))
4235                                rc = rsp.rsp0;
4236                }
4237        } else {
4238                // --- first access so that we can write the rid data
4239                if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) {
4240                        rc = status;
4241                        goto done;
4242                }
4243                // --- now write the rid data
4244                if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) {
4245                        rc = ERROR;
4246                        goto done;
4247                }
4248                bap_write(ai, pBuf, len, BAP1);
4249                // ---now commit the rid data
4250                rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS);
4251        }
4252done:
4253        if (lock)
4254                up(&ai->sem);
4255        return rc;
4256}
4257
4258/* Allocates a FID to be used for transmitting packets.  We only use
4259   one for now. */
4260static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
4261{
4262        unsigned int loop = 3000;
4263        Cmd cmd;
4264        Resp rsp;
4265        u16 txFid;
4266        u16 txControl;
4267
4268        cmd.cmd = CMD_ALLOCATETX;
4269        cmd.parm0 = lenPayload;
4270        if (down_interruptible(&ai->sem))
4271                return ERROR;
4272        if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
4273                txFid = ERROR;
4274                goto done;
4275        }
4276        if ( (rsp.status & 0xFF00) != 0) {
4277                txFid = ERROR;
4278                goto done;
4279        }
4280        /* wait for the allocate event/indication
4281         * It makes me kind of nervous that this can just sit here and spin,
4282         * but in practice it only loops like four times. */
4283        while (((IN4500(ai, EVSTAT) & EV_ALLOC) == 0) && --loop);
4284        if (!loop) {
4285                txFid = ERROR;
4286                goto done;
4287        }
4288
4289        // get the allocated fid and acknowledge
4290        txFid = IN4500(ai, TXALLOCFID);
4291        OUT4500(ai, EVACK, EV_ALLOC);
4292
4293        /*  The CARD is pretty cool since it converts the ethernet packet
4294         *  into 802.11.  Also note that we don't release the FID since we
4295         *  will be using the same one over and over again. */
4296        /*  We only have to setup the control once since we are not
4297         *  releasing the fid. */
4298        if (raw)
4299                txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_11
4300                        | TXCTL_ETHERNET | TXCTL_NORELEASE);
4301        else
4302                txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3
4303                        | TXCTL_ETHERNET | TXCTL_NORELEASE);
4304        if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS)
4305                txFid = ERROR;
4306        else
4307                bap_write(ai, &txControl, sizeof(txControl), BAP1);
4308
4309done:
4310        up(&ai->sem);
4311
4312        return txFid;
4313}
4314
4315/* In general BAP1 is dedicated to transmiting packets.  However,
4316   since we need a BAP when accessing RIDs, we also use BAP1 for that.
4317   Make sure the BAP1 spinlock is held when this is called. */
4318static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
4319{
4320        u16 payloadLen;
4321        Cmd cmd;
4322        Resp rsp;
4323        int miclen = 0;
4324        u16 txFid = len;
4325        MICBuffer pMic;
4326
4327        len >>= 16;
4328
4329        if (len <= ETH_ALEN * 2) {
4330                airo_print_warn(ai->dev->name, "Short packet %d", len);
4331                return ERROR;
4332        }
4333        len -= ETH_ALEN * 2;
4334
4335        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && 
4336            (ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
4337                if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
4338                        return ERROR;
4339                miclen = sizeof(pMic);
4340        }
4341        // packet is destination[6], source[6], payload[len-12]
4342        // write the payload length and dst/src/payload
4343        if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
4344        /* The hardware addresses aren't counted as part of the payload, so
4345         * we have to subtract the 12 bytes for the addresses off */
4346        payloadLen = cpu_to_le16(len + miclen);
4347        bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
4348        bap_write(ai, (const u16*)pPacket, sizeof(etherHead), BAP1);
4349        if (miclen)
4350                bap_write(ai, (const u16*)&pMic, miclen, BAP1);
4351        bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len, BAP1);
4352        // issue the transmit command
4353        memset( &cmd, 0, sizeof( cmd ) );
4354        cmd.cmd = CMD_TRANSMIT;
4355        cmd.parm0 = txFid;
4356        if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
4357        if ( (rsp.status & 0xFF00) != 0) return ERROR;
4358        return SUCCESS;
4359}
4360
4361static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
4362{
4363        u16 fc, payloadLen;
4364        Cmd cmd;
4365        Resp rsp;
4366        int hdrlen;
4367        struct {
4368                u8 addr4[ETH_ALEN];
4369                u16 gaplen;
4370                u8 gap[6];
4371        } gap;
4372        u16 txFid = len;
4373        len >>= 16;
4374        gap.gaplen = 6;
4375
4376        fc = le16_to_cpu(*(const u16*)pPacket);
4377        switch (fc & 0xc) {
4378                case 4:
4379                        if ((fc & 0xe0) == 0xc0)
4380                                hdrlen = 10;
4381                        else
4382                                hdrlen = 16;
4383                        break;
4384                case 8:
4385                        if ((fc&0x300)==0x300){
4386                                hdrlen = 30;
4387                                break;
4388                        }
4389                default:
4390                        hdrlen = 24;
4391        }
4392
4393        if (len < hdrlen) {
4394                airo_print_warn(ai->dev->name, "Short packet %d", len);
4395                return ERROR;
4396        }
4397
4398        /* packet is 802.11 header +  payload
4399         * write the payload length and dst/src/payload */
4400        if (bap_setup(ai, txFid, 6, BAP1) != SUCCESS) return ERROR;
4401        /* The 802.11 header aren't counted as part of the payload, so
4402         * we have to subtract the header bytes off */
4403        payloadLen = cpu_to_le16(len-hdrlen);
4404        bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
4405        if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR;
4406        bap_write(ai, (const u16*)pPacket, hdrlen, BAP1);
4407        bap_write(ai, hdrlen == 30 ?
4408                (const u16*)&gap.gaplen : (const u16*)&gap, 38 - hdrlen, BAP1);
4409
4410        bap_write(ai, (const u16*)(pPacket + hdrlen), len - hdrlen, BAP1);
4411        // issue the transmit command
4412        memset( &cmd, 0, sizeof( cmd ) );
4413        cmd.cmd = CMD_TRANSMIT;
4414        cmd.parm0 = txFid;
4415        if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR;
4416        if ( (rsp.status & 0xFF00) != 0) return ERROR;
4417        return SUCCESS;
4418}
4419
4420/*
4421 *  This is the proc_fs routines.  It is a bit messier than I would
4422 *  like!  Feel free to clean it up!
4423 */
4424
4425static ssize_t proc_read( struct file *file,
4426                          char __user *buffer,
4427                          size_t len,
4428                          loff_t *offset);
4429
4430static ssize_t proc_write( struct file *file,
4431                           const char __user *buffer,
4432                           size_t len,
4433                           loff_t *offset );
4434static int proc_close( struct inode *inode, struct file *file );
4435
4436static int proc_stats_open( struct inode *inode, struct file *file );
4437static int proc_statsdelta_open( struct inode *inode, struct file *file );
4438static int proc_status_open( struct inode *inode, struct file *file );
4439static int proc_SSID_open( struct inode *inode, struct file *file );
4440static int proc_APList_open( struct inode *inode, struct file *file );
4441static int proc_BSSList_open( struct inode *inode, struct file *file );
4442static int proc_config_open( struct inode *inode, struct file *file );
4443static int proc_wepkey_open( struct inode *inode, struct file *file );
4444
4445static const struct file_operations proc_statsdelta_ops = {
4446        .read           = proc_read,
4447        .open           = proc_statsdelta_open,
4448        .release        = proc_close
4449};
4450
4451static const struct file_operations proc_stats_ops = {
4452        .read           = proc_read,
4453        .open           = proc_stats_open,
4454        .release        = proc_close
4455};
4456
4457static const struct file_operations proc_status_ops = {
4458        .read           = proc_read,
4459        .open           = proc_status_open,
4460        .release        = proc_close
4461};
4462
4463static const struct file_operations proc_SSID_ops = {
4464        .read           = proc_read,
4465        .write          = proc_write,
4466        .open           = proc_SSID_open,
4467        .release        = proc_close
4468};
4469
4470static const struct file_operations proc_BSSList_ops = {
4471        .read           = proc_read,
4472        .write          = proc_write,
4473        .open           = proc_BSSList_open,
4474        .release        = proc_close
4475};
4476
4477static const struct file_operations proc_APList_ops = {
4478        .read           = proc_read,
4479        .write          = proc_write,
4480        .open           = proc_APList_open,
4481        .release        = proc_close
4482};
4483
4484static const struct file_operations proc_config_ops = {
4485        .read           = proc_read,
4486        .write          = proc_write,
4487        .open           = proc_config_open,
4488        .release        = proc_close
4489};
4490
4491static const struct file_operations proc_wepkey_ops = {
4492        .read           = proc_read,
4493        .write          = proc_write,
4494        .open           = proc_wepkey_open,
4495        .release        = proc_close
4496};
4497
4498static struct proc_dir_entry *airo_entry;
4499
4500struct proc_data {
4501        int release_buffer;
4502        int readlen;
4503        char *rbuffer;
4504        int writelen;
4505        int maxwritelen;
4506        char *wbuffer;
4507        void (*on_close) (struct inode *, struct file *);
4508};
4509
4510#ifndef SETPROC_OPS
4511#define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops)
4512#endif
4513
4514static int setup_proc_entry( struct net_device *dev,
4515                             struct airo_info *apriv ) {
4516        struct proc_dir_entry *entry;
4517        /* First setup the device directory */
4518        strcpy(apriv->proc_name,dev->name);
4519        apriv->proc_entry = create_proc_entry(apriv->proc_name,
4520                                              S_IFDIR|airo_perm,
4521                                              airo_entry);
4522        if (!apriv->proc_entry)
4523                goto fail;
4524        apriv->proc_entry->uid = proc_uid;
4525        apriv->proc_entry->gid = proc_gid;
4526        apriv->proc_entry->owner = THIS_MODULE;
4527
4528        /* Setup the StatsDelta */
4529        entry = create_proc_entry("StatsDelta",
4530                                  S_IFREG | (S_IRUGO&proc_perm),
4531                                  apriv->proc_entry);
4532        if (!entry)
4533                goto fail_stats_delta;
4534        entry->uid = proc_uid;
4535        entry->gid = proc_gid;
4536        entry->data = dev;
4537        entry->owner = THIS_MODULE;
4538        SETPROC_OPS(entry, proc_statsdelta_ops);
4539
4540        /* Setup the Stats */
4541        entry = create_proc_entry("Stats",
4542                                  S_IFREG | (S_IRUGO&proc_perm),
4543                                  apriv->proc_entry);
4544        if (!entry)
4545                goto fail_stats;
4546        entry->uid = proc_uid;
4547        entry->gid = proc_gid;
4548        entry->data = dev;
4549        entry->owner = THIS_MODULE;
4550        SETPROC_OPS(entry, proc_stats_ops);
4551
4552        /* Setup the Status */
4553        entry = create_proc_entry("Status",
4554                                  S_IFREG | (S_IRUGO&proc_perm),
4555                                  apriv->proc_entry);
4556        if (!entry)
4557                goto fail_status;
4558        entry->uid = proc_uid;
4559        entry->gid = proc_gid;
4560        entry->data = dev;
4561        entry->owner = THIS_MODULE;
4562        SETPROC_OPS(entry, proc_status_ops);
4563
4564        /* Setup the Config */
4565        entry = create_proc_entry("Config",
4566                                  S_IFREG | proc_perm,
4567                                  apriv->proc_entry);
4568        if (!entry)
4569                goto fail_config;
4570        entry->uid = proc_uid;
4571        entry->gid = proc_gid;
4572        entry->data = dev;
4573        entry->owner = THIS_MODULE;
4574        SETPROC_OPS(entry, proc_config_ops);
4575
4576        /* Setup the SSID */
4577        entry = create_proc_entry("SSID",
4578                                  S_IFREG | proc_perm,
4579                                  apriv->proc_entry);
4580        if (!entry)
4581                goto fail_ssid;
4582        entry->uid = proc_uid;
4583        entry->gid = proc_gid;
4584        entry->data = dev;
4585        entry->owner = THIS_MODULE;
4586        SETPROC_OPS(entry, proc_SSID_ops);
4587
4588        /* Setup the APList */
4589        entry = create_proc_entry("APList",
4590                                  S_IFREG | proc_perm,
4591                                  apriv->proc_entry);
4592        if (!entry)
4593                goto fail_aplist;
4594        entry->uid = proc_uid;
4595        entry->gid = proc_gid;
4596        entry->data = dev;
4597        entry->owner = THIS_MODULE;
4598        SETPROC_OPS(entry, proc_APList_ops);
4599
4600        /* Setup the BSSList */
4601        entry = create_proc_entry("BSSList",
4602                                  S_IFREG | proc_perm,
4603                                  apriv->proc_entry);
4604        if (!entry)
4605                goto fail_bsslist;
4606        entry->uid = proc_uid;
4607        entry->gid = proc_gid;
4608        entry->data = dev;
4609        entry->owner = THIS_MODULE;
4610        SETPROC_OPS(entry, proc_BSSList_ops);
4611
4612        /* Setup the WepKey */
4613        entry = create_proc_entry("WepKey",
4614                                  S_IFREG | proc_perm,
4615                                  apriv->proc_entry);
4616        if (!entry)
4617                goto fail_wepkey;
4618        entry->uid = proc_uid;
4619        entry->gid = proc_gid;
4620        entry->data = dev;
4621        entry->owner = THIS_MODULE;
4622        SETPROC_OPS(entry, proc_wepkey_ops);
4623
4624        return 0;
4625
4626fail_wepkey:
4627        remove_proc_entry("BSSList", apriv->proc_entry);
4628fail_bsslist:
4629        remove_proc_entry("APList", apriv->proc_entry);
4630fail_aplist:
4631        remove_proc_entry("SSID", apriv->proc_entry);
4632fail_ssid:
4633        remove_proc_entry("Config", apriv->proc_entry);
4634fail_config:
4635        remove_proc_entry("Status", apriv->proc_entry);
4636fail_status:
4637        remove_proc_entry("Stats", apriv->proc_entry);
4638fail_stats:
4639        remove_proc_entry("StatsDelta", apriv->proc_entry);
4640fail_stats_delta:
4641        remove_proc_entry(apriv->proc_name, airo_entry);
4642fail:
4643        return -ENOMEM;
4644}
4645
4646static int takedown_proc_entry( struct net_device *dev,
4647                                struct airo_info *apriv ) {
4648        if ( !apriv->proc_entry->namelen ) return 0;
4649        remove_proc_entry("Stats",apriv->proc_entry);
4650        remove_proc_entry("StatsDelta",apriv->proc_entry);
4651        remove_proc_entry("Status",apriv->proc_entry);
4652        remove_proc_entry("Config",apriv->proc_entry);
4653        remove_proc_entry("SSID",apriv->proc_entry);
4654        remove_proc_entry("APList",apriv->proc_entry);
4655        remove_proc_entry("BSSList",apriv->proc_entry);
4656        remove_proc_entry("WepKey",apriv->proc_entry);
4657        remove_proc_entry(apriv->proc_name,airo_entry);
4658        return 0;
4659}
4660
4661/*
4662 *  What we want from the proc_fs is to be able to efficiently read
4663 *  and write the configuration.  To do this, we want to read the
4664 *  configuration when the file is opened and write it when the file is
4665 *  closed.  So basically we allocate a read buffer at open and fill it
4666 *  with data, and allocate a write buffer and read it at close.
4667 */
4668
4669/*
4670 *  The read routine is generic, it relies on the preallocated rbuffer
4671 *  to supply the data.
4672 */
4673static ssize_t proc_read( struct file *file,
4674                          char __user *buffer,
4675                          size_t len,
4676                          loff_t *offset )
4677{
4678        loff_t pos = *offset;
4679        struct proc_data *priv = (struct proc_data*)file->private_data;
4680
4681        if (!priv->rbuffer)
4682                return -EINVAL;
4683
4684        if (pos < 0)
4685                return -EINVAL;
4686        if (pos >= priv->readlen)
4687                return 0;
4688        if (len > priv->readlen - pos)
4689                len = priv->readlen - pos;
4690        if (copy_to_user(buffer, priv->rbuffer + pos, len))
4691                return -EFAULT;
4692        *offset = pos + len;
4693        return len;
4694}
4695
4696/*
4697 *  The write routine is generic, it fills in a preallocated rbuffer
4698 *  to supply the data.
4699 */
4700static ssize_t proc_write( struct file *file,
4701                           const char __user *buffer,
4702                           size_t len,
4703                           loff_t *offset )
4704{
4705        loff_t pos = *offset;
4706        struct proc_data *priv = (struct proc_data*)file->private_data;
4707
4708        if (!priv->wbuffer)
4709                return -EINVAL;
4710
4711        if (pos < 0)
4712                return -EINVAL;
4713        if (pos >= priv->maxwritelen)
4714                return 0;
4715        if (len > priv->maxwritelen - pos)
4716                len = priv->maxwritelen - pos;
4717        if (copy_from_user(priv->wbuffer + pos, buffer, len))
4718                return -EFAULT;
4719        if ( pos + len > priv->writelen )
4720                priv->writelen = len + file->f_pos;
4721        *offset = pos + len;
4722        return len;
4723}
4724
4725static int proc_status_open( struct inode *inode, struct file *file ) {
4726        struct proc_data *data;
4727        struct proc_dir_entry *dp = PDE(inode);
4728        struct net_device *dev = dp->data;
4729        struct airo_info *apriv = dev->priv;
4730        CapabilityRid cap_rid;
4731        StatusRid status_rid;
4732        int i;
4733
4734        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
4735                return -ENOMEM;
4736        data = (struct proc_data *)file->private_data;
4737        if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
4738                kfree (file->private_data);
4739                return -ENOMEM;
4740        }
4741
4742        readStatusRid(apriv, &status_rid, 1);
4743        readCapabilityRid(apriv, &cap_rid, 1);
4744
4745        i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n",
4746                    status_rid.mode & 1 ? "CFG ": "",
4747                    status_rid.mode & 2 ? "ACT ": "",
4748                    status_rid.mode & 0x10 ? "SYN ": "",
4749                    status_rid.mode & 0x20 ? "LNK ": "",
4750                    status_rid.mode & 0x40 ? "LEAP ": "",
4751                    status_rid.mode & 0x80 ? "PRIV ": "",
4752                    status_rid.mode & 0x100 ? "KEY ": "",
4753                    status_rid.mode & 0x200 ? "WEP ": "",
4754                    status_rid.mode & 0x8000 ? "ERR ": "");
4755        sprintf( data->rbuffer+i, "Mode: %x\n"
4756                 "Signal Strength: %d\n"
4757                 "Signal Quality: %d\n"
4758                 "SSID: %-.*s\n"
4759                 "AP: %-.16s\n"
4760                 "Freq: %d\n"
4761                 "BitRate: %dmbs\n"
4762                 "Driver Version: %s\n"
4763                 "Device: %s\nManufacturer: %s\nFirmware Version: %s\n"
4764                 "Radio type: %x\nCountry: %x\nHardware Version: %x\n"
4765                 "Software Version: %x\nSoftware Subversion: %x\n"
4766                 "Boot block version: %x\n",
4767                 (int)status_rid.mode,
4768                 (int)status_rid.normalizedSignalStrength,
4769                 (int)status_rid.signalQuality,
4770                 (int)status_rid.SSIDlen,
4771                 status_rid.SSID,
4772                 status_rid.apName,
4773                 (int)status_rid.channel,
4774                 (int)status_rid.currentXmitRate/2,
4775                 version,
4776                 cap_rid.prodName,
4777                 cap_rid.manName,
4778                 cap_rid.prodVer,
4779                 cap_rid.radioType,
4780                 cap_rid.country,
4781                 cap_rid.hardVer,
4782                 (int)cap_rid.softVer,
4783                 (int)cap_rid.softSubVer,
4784                 (int)cap_rid.bootBlockVer );
4785        data->readlen = strlen( data->rbuffer );
4786        return 0;
4787}
4788
4789static int proc_stats_rid_open(struct inode*, struct file*, u16);
4790static int proc_statsdelta_open( struct inode *inode,
4791                                 struct file *file ) {
4792        if (file->f_mode&FMODE_WRITE) {
4793                return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR);
4794        }
4795        return proc_stats_rid_open(inode, file, RID_STATSDELTA);
4796}
4797
4798static int proc_stats_open( struct inode *inode, struct file *file ) {
4799        return proc_stats_rid_open(inode, file, RID_STATS);
4800}
4801
4802static int proc_stats_rid_open( struct inode *inode,
4803                                struct file *file,
4804                                u16 rid ) {
4805        struct proc_data *data;
4806        struct proc_dir_entry *dp = PDE(inode);
4807        struct net_device *dev = dp->data;
4808        struct airo_info *apriv = dev->priv;
4809        StatsRid stats;
4810        int i, j;
4811        u32 *vals = stats.vals;
4812
4813        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
4814                return -ENOMEM;
4815        data = (struct proc_data *)file->private_data;
4816        if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
4817                kfree (file->private_data);
4818                return -ENOMEM;
4819        }
4820
4821        readStatsRid(apriv, &stats, rid, 1);
4822
4823        j = 0;
4824        for(i=0; statsLabels[i]!=(char *)-1 &&
4825                    i*4<stats.len; i++){
4826                if (!statsLabels[i]) continue;
4827                if (j+strlen(statsLabels[i])+16>4096) {
4828                        airo_print_warn(apriv->dev->name,
4829                               "Potentially disasterous buffer overflow averted!");
4830                        break;
4831                }
4832                j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]);
4833        }
4834        if (i*4>=stats.len){
4835                airo_print_warn(apriv->dev->name, "Got a short rid");
4836        }
4837        data->readlen = j;
4838        return 0;
4839}
4840
4841static int get_dec_u16( char *buffer, int *start, int limit ) {
4842        u16 value;
4843        int valid = 0;
4844        for( value = 0; buffer[*start] >= '0' &&
4845                     buffer[*start] <= '9' &&
4846                     *start < limit; (*start)++ ) {
4847                valid = 1;
4848                value *= 10;
4849                value += buffer[*start] - '0';
4850        }
4851        if ( !valid ) return -1;
4852        return value;
4853}
4854
4855static int airo_config_commit(struct net_device *dev,
4856                              struct iw_request_info *info, void *zwrq,
4857                              char *extra);
4858
4859static void proc_config_on_close( struct inode *inode, struct file *file ) {
4860        struct proc_data *data = file->private_data;
4861        struct proc_dir_entry *dp = PDE(inode);
4862        struct net_device *dev = dp->data;
4863        struct airo_info *ai = dev->priv;
4864        char *line;
4865
4866        if ( !data->writelen ) return;
4867
4868        readConfigRid(ai, 1);
4869        set_bit (FLAG_COMMIT, &ai->flags);
4870
4871        line = data->wbuffer;
4872        while( line[0] ) {
4873/*** Mode processing */
4874                if ( !strncmp( line, "Mode: ", 6 ) ) {
4875                        line += 6;
4876                        if ((ai->config.rmode & 0xff) >= RXMODE_RFMON)
4877                                        set_bit (FLAG_RESET, &ai->flags);
4878                        ai->config.rmode &= 0xfe00;
4879                        clear_bit (FLAG_802_11, &ai->flags);
4880                        ai->config.opmode &= 0xFF00;
4881                        ai->config.scanMode = SCANMODE_ACTIVE;
4882                        if ( line[0] == 'a' ) {
4883                                ai->config.opmode |= 0;
4884                        } else {
4885                                ai->config.opmode |= 1;
4886                                if ( line[0] == 'r' ) {
4887                                        ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
4888                                        ai->config.scanMode = SCANMODE_PASSIVE;
4889                                        set_bit (FLAG_802_11, &ai->flags);
4890                                } else if ( line[0] == 'y' ) {
4891                                        ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER;
4892                                        ai->config.scanMode = SCANMODE_PASSIVE;
4893                                        set_bit (FLAG_802_11, &ai->flags);
4894                                } else if ( line[0] == 'l' )
4895                                        ai->config.rmode |= RXMODE_LANMON;
4896                        }
4897                        set_bit (FLAG_COMMIT, &ai->flags);
4898                }
4899
4900/*** Radio status */
4901                else if (!strncmp(line,"Radio: ", 7)) {
4902                        line += 7;
4903                        if (!strncmp(line,"off",3)) {
4904                                set_bit (FLAG_RADIO_OFF, &ai->flags);
4905                        } else {
4906                                clear_bit (FLAG_RADIO_OFF, &ai->flags);
4907                        }
4908                }
4909/*** NodeName processing */
4910                else if ( !strncmp( line, "NodeName: ", 10 ) ) {
4911                        int j;
4912
4913                        line += 10;
4914                        memset( ai->config.nodeName, 0, 16 );
4915/* Do the name, assume a space between the mode and node name */
4916                        for( j = 0; j < 16 && line[j] != '\n'; j++ ) {
4917                                ai->config.nodeName[j] = line[j];
4918                        }
4919                        set_bit (FLAG_COMMIT, &ai->flags);
4920                }
4921
4922/*** PowerMode processing */
4923                else if ( !strncmp( line, "PowerMode: ", 11 ) ) {
4924                        line += 11;
4925                        if ( !strncmp( line, "PSPCAM", 6 ) ) {
4926                                ai->config.powerSaveMode = POWERSAVE_PSPCAM;
4927                                set_bit (FLAG_COMMIT, &ai->flags);
4928                        } else if ( !strncmp( line, "PSP", 3 ) ) {
4929                                ai->config.powerSaveMode = POWERSAVE_PSP;
4930                                set_bit (FLAG_COMMIT, &ai->flags);
4931                        } else {
4932                                ai->config.powerSaveMode = POWERSAVE_CAM;
4933                                set_bit (FLAG_COMMIT, &ai->flags);
4934                        }
4935                } else if ( !strncmp( line, "DataRates: ", 11 ) ) {
4936                        int v, i = 0, k = 0; /* i is index into line,
4937                                                k is index to rates */
4938
4939                        line += 11;
4940                        while((v = get_dec_u16(line, &i, 3))!=-1) {
4941                                ai->config.rates[k++] = (u8)v;
4942                                line += i + 1;
4943                                i = 0;
4944                        }
4945                        set_bit (FLAG_COMMIT, &ai->flags);
4946                } else if ( !strncmp( line, "Channel: ", 9 ) ) {
4947                        int v, i = 0;
4948                        line += 9;
4949                        v = get_dec_u16(line, &i, i+3);
4950                        if ( v != -1 ) {
4951                                ai->config.channelSet = (u16)v;
4952                                set_bit (FLAG_COMMIT, &ai->flags);
4953                        }
4954                } else if ( !strncmp( line, "XmitPower: ", 11 ) ) {
4955                        int v, i = 0;
4956                        line += 11;
4957                        v = get_dec_u16(line, &i, i+3);
4958                        if ( v != -1 ) {
4959                                ai->config.txPower = (u16)v;
4960                                set_bit (FLAG_COMMIT, &ai->flags);
4961                        }
4962                } else if ( !strncmp( line, "WEP: ", 5 ) ) {
4963                        line += 5;
4964                        switch( line[0] ) {
4965                        case 's':
4966                                ai->config.authType = (u16)AUTH_SHAREDKEY;
4967                                break;
4968                        case 'e':
4969                                ai->config.authType = (u16)AUTH_ENCRYPT;
4970                                break;
4971                        default:
4972                                ai->config.authType = (u16)AUTH_OPEN;
4973                                break;
4974                        }
4975                        set_bit (FLAG_COMMIT, &ai->flags);
4976                } else if ( !strncmp( line, "LongRetryLimit: ", 16 ) ) {
4977                        int v, i = 0;
4978
4979                        line += 16;
4980                        v = get_dec_u16(line, &i, 3);
4981                        v = (v<0) ? 0 : ((v>255) ? 255 : v);
4982                        ai->config.longRetryLimit = (u16)v;
4983                        set_bit (FLAG_COMMIT, &ai->flags);
4984                } else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) {
4985                        int v, i = 0;
4986
4987                        line += 17;
4988                        v = get_dec_u16(line, &i, 3);
4989                        v = (v<0) ? 0 : ((v>255) ? 255 : v);
4990                        ai->config.shortRetryLimit = (u16)v;
4991                        set_bit (FLAG_COMMIT, &ai->flags);
4992                } else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) {
4993                        int v, i = 0;
4994
4995                        line += 14;
4996                        v = get_dec_u16(line, &i, 4);
4997                        v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
4998                        ai->config.rtsThres = (u16)v;
4999                        set_bit (FLAG_COMMIT, &ai->flags);
5000                } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
5001                        int v, i = 0;
5002
5003                        line += 16;
5004                        v = get_dec_u16(line, &i, 5);
5005                        v = (v<0) ? 0 : v;
5006                        ai->config.txLifetime = (u16)v;
5007                        set_bit (FLAG_COMMIT, &ai->flags);
5008                } else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) {
5009                        int v, i = 0;
5010
5011                        line += 16;
5012                        v = get_dec_u16(line, &i, 5);
5013                        v = (v<0) ? 0 : v;
5014                        ai->config.rxLifetime = (u16)v;
5015                        set_bit (FLAG_COMMIT, &ai->flags);
5016                } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) {
5017                        ai->config.txDiversity =
5018                                (line[13]=='l') ? 1 :
5019                                ((line[13]=='r')? 2: 3);
5020                        set_bit (FLAG_COMMIT, &ai->flags);
5021                } else if ( !strncmp( line, "RXDiversity: ", 13 ) ) {
5022                        ai->config.rxDiversity =
5023                                (line[13]=='l') ? 1 :
5024                                ((line[13]=='r')? 2: 3);
5025                        set_bit (FLAG_COMMIT, &ai->flags);
5026                } else if ( !strncmp( line, "FragThreshold: ", 15 ) ) {
5027                        int v, i = 0;
5028
5029                        line += 15;
5030                        v = get_dec_u16(line, &i, 4);
5031                        v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
5032                        v = v & 0xfffe; /* Make sure its even */
5033                        ai->config.fragThresh = (u16)v;
5034                        set_bit (FLAG_COMMIT, &ai->flags);
5035                } else if (!strncmp(line, "Modulation: ", 12)) {
5036                        line += 12;
5037                        switch(*line) {
5038                        case 'd':  ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break;
5039                        case 'c':  ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break;
5040                        case 'm':  ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break;
5041                        default: airo_print_warn(ai->dev->name, "Unknown modulation");
5042                        }
5043                } else if (!strncmp(line, "Preamble: ", 10)) {
5044                        line += 10;
5045                        switch(*line) {
5046                        case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break;
5047                        case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break;
5048                        case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break;
5049                        default: airo_print_warn(ai->dev->name, "Unknown preamble");
5050                        }
5051                } else {
5052                        airo_print_warn(ai->dev->name, "Couldn't figure out %s", line);
5053                }
5054                while( line[0] && line[0] != '\n' ) line++;
5055                if ( line[0] ) line++;
5056        }
5057        airo_config_commit(dev, NULL, NULL, NULL);
5058}
5059
5060static char *get_rmode(u16 mode) {
5061        switch(mode&0xff) {
5062        case RXMODE_RFMON:  return "rfmon";
5063        case RXMODE_RFMON_ANYBSS:  return "yna (any) bss rfmon";
5064        case RXMODE_LANMON:  return "lanmon";
5065        }
5066        return "ESS";
5067}
5068
5069static int proc_config_open( struct inode *inode, struct file *file ) {
5070        struct proc_data *data;
5071        struct proc_dir_entry *dp = PDE(inode);
5072        struct net_device *dev = dp->data;
5073        struct airo_info *ai = dev->priv;
5074        int i;
5075
5076        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
5077                return -ENOMEM;
5078        data = (struct proc_data *)file->private_data;
5079        if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
5080                kfree (file->private_data);
5081                return -ENOMEM;
5082        }
5083        if ((data->wbuffer = kzalloc( 2048, GFP_KERNEL )) == NULL) {
5084                kfree (data->rbuffer);
5085                kfree (file->private_data);
5086                return -ENOMEM;
5087        }
5088        data->maxwritelen = 2048;
5089        data->on_close = proc_config_on_close;
5090
5091        readConfigRid(ai, 1);
5092
5093        i = sprintf( data->rbuffer,
5094                     "Mode: %s\n"
5095                     "Radio: %s\n"
5096                     "NodeName: %-16s\n"
5097                     "PowerMode: %s\n"
5098                     "DataRates: %d %d %d %d %d %d %d %d\n"
5099                     "Channel: %d\n"
5100                     "XmitPower: %d\n",
5101                     (ai->config.opmode & 0xFF) == 0 ? "adhoc" :
5102                     (ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode):
5103                     (ai->config.opmode & 0xFF) == 2 ? "AP" :
5104                     (ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error",
5105                     test_bit(FLAG_RADIO_OFF, &ai->flags) ? "off" : "on",
5106                     ai->config.nodeName,
5107                     ai->config.powerSaveMode == 0 ? "CAM" :
5108                     ai->config.powerSaveMode == 1 ? "PSP" :
5109                     ai->config.powerSaveMode == 2 ? "PSPCAM" : "Error",
5110                     (int)ai->config.rates[0],
5111                     (int)ai->config.rates[1],
5112                     (int)ai->config.rates[2],
5113                     (int)ai->config.rates[3],
5114                     (int)ai->config.rates[4],
5115                     (int)ai->config.rates[5],
5116                     (int)ai->config.rates[6],
5117                     (int)ai->config.rates[7],
5118                     (int)ai->config.channelSet,
5119                     (int)ai->config.txPower
5120                );
5121        sprintf( data->rbuffer + i,
5122                 "LongRetryLimit: %d\n"
5123                 "ShortRetryLimit: %d\n"
5124                 "RTSThreshold: %d\n"
5125                 "TXMSDULifetime: %d\n"
5126                 "RXMSDULifetime: %d\n"
5127                 "TXDiversity: %s\n"
5128                 "RXDiversity: %s\n"
5129                 "FragThreshold: %d\n"
5130                 "WEP: %s\n"
5131                 "Modulation: %s\n"
5132                 "Preamble: %s\n",
5133                 (int)ai->config.longRetryLimit,
5134                 (int)ai->config.shortRetryLimit,
5135                 (int)ai->config.rtsThres,
5136                 (int)ai->config.txLifetime,
5137                 (int)ai->config.rxLifetime,
5138                 ai->config.txDiversity == 1 ? "left" :
5139                 ai->config.txDiversity == 2 ? "right" : "both",
5140                 ai->config.rxDiversity == 1 ? "left" :
5141                 ai->config.rxDiversity == 2 ? "right" : "both",
5142                 (int)ai->config.fragThresh,
5143                 ai->config.authType == AUTH_ENCRYPT ? "encrypt" :
5144                 ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open",
5145                 ai->config.modulation == 0 ? "default" :
5146                 ai->config.modulation == MOD_CCK ? "cck" :
5147                 ai->config.modulation == MOD_MOK ? "mok" : "error",
5148                 ai->config.preamble == PREAMBLE_AUTO ? "auto" :
5149                 ai->config.preamble == PREAMBLE_LONG ? "long" :
5150                 ai->config.preamble == PREAMBLE_SHORT ? "short" : "error"
5151                );
5152        data->readlen = strlen( data->rbuffer );
5153        return 0;
5154}
5155
5156static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
5157        struct proc_data *data = (struct proc_data *)file->private_data;
5158        struct proc_dir_entry *dp = PDE(inode);
5159        struct net_device *dev = dp->data;
5160        struct airo_info *ai = dev->priv;
5161        SsidRid SSID_rid;
5162        int i;
5163        int offset = 0;
5164
5165        if ( !data->writelen ) return;
5166
5167        memset( &SSID_rid, 0, sizeof( SSID_rid ) );
5168
5169        for( i = 0; i < 3; i++ ) {
5170                int j;
5171                for( j = 0; j+offset < data->writelen && j < 32 &&
5172                             data->wbuffer[offset+j] != '\n'; j++ ) {
5173                        SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j];
5174                }
5175                if ( j == 0 ) break;
5176                SSID_rid.ssids[i].len = j;
5177                offset += j;
5178                while( data->wbuffer[offset] != '\n' &&
5179                       offset < data->writelen ) offset++;
5180                offset++;
5181        }
5182        if (i)
5183                SSID_rid.len = sizeof(SSID_rid);
5184        disable_MAC(ai, 1);
5185        writeSsidRid(ai, &SSID_rid, 1);
5186        enable_MAC(ai, 1);
5187}
5188
5189static inline u8 hexVal(char c) {
5190        if (c>='0' && c<='9') return c -= '0';
5191        if (c>='a' && c<='f') return c -= 'a'-10;
5192        if (c>='A' && c<='F') return c -= 'A'-10;
5193        return 0;
5194}
5195
5196static void proc_APList_on_close( struct inode *inode, struct file *file ) {
5197        struct proc_data *data = (struct proc_data *)file->private_data;
5198        struct proc_dir_entry *dp = PDE(inode);
5199        struct net_device *dev = dp->data;
5200        struct airo_info *ai = dev->priv;
5201        APListRid APList_rid;
5202        int i;
5203
5204        if ( !data->writelen ) return;
5205
5206        memset( &APList_rid, 0, sizeof(APList_rid) );
5207        APList_rid.len = sizeof(APList_rid);
5208
5209        for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
5210                int j;
5211                for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
5212                        switch(j%3) {
5213                        case 0:
5214                                APList_rid.ap[i][j/3]=
5215                                        hexVal(data->wbuffer[j+i*6*3])<<4;
5216                                break;
5217                        case 1:
5218                                APList_rid.ap[i][j/3]|=
5219                                        hexVal(data->wbuffer[j+i*6*3]);
5220                                break;
5221                        }
5222                }
5223        }
5224        disable_MAC(ai, 1);
5225        writeAPListRid(ai, &APList_rid, 1);
5226        enable_MAC(ai, 1);
5227}
5228
5229/* This function wraps PC4500_writerid with a MAC disable */
5230static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
5231                        int len, int dummy ) {
5232        int rc;
5233
5234        disable_MAC(ai, 1);
5235        rc = PC4500_writerid(ai, rid, rid_data, len, 1);
5236        enable_MAC(ai, 1);
5237        return rc;
5238}
5239
5240/* Returns the length of the key at the index.  If index == 0xffff
5241 * the index of the transmit key is returned.  If the key doesn't exist,
5242 * -1 will be returned.
5243 */
5244static int get_wep_key(struct airo_info *ai, u16 index) {
5245        WepKeyRid wkr;
5246        int rc;
5247        u16 lastindex;
5248
5249        rc = readWepKeyRid(ai, &wkr, 1, 1);
5250        if (rc == SUCCESS) do {
5251                lastindex = wkr.kindex;
5252                if (wkr.kindex == index) {
5253                        if (index == 0xffff) {
5254                                return wkr.mac[0];
5255                        }
5256                        return wkr.klen;
5257                }
5258                readWepKeyRid(ai, &wkr, 0, 1);
5259        } while(lastindex != wkr.kindex);
5260        return -1;
5261}
5262
5263static int set_wep_key(struct airo_info *ai, u16 index,
5264                       const char *key, u16 keylen, int perm, int lock ) {
5265        static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
5266        WepKeyRid wkr;
5267
5268        memset(&wkr, 0, sizeof(wkr));
5269        if (keylen == 0) {
5270// We are selecting which key to use
5271                wkr.len = sizeof(wkr);
5272                wkr.kindex = 0xffff;
5273                wkr.mac[0] = (char)index;
5274                if (perm) ai->defindex = (char)index;
5275        } else {
5276// We are actually setting the key
5277                wkr.len = sizeof(wkr);
5278                wkr.kindex = index;
5279                wkr.klen = keylen;
5280                memcpy( wkr.key, key, keylen );
5281                memcpy( wkr.mac, macaddr, ETH_ALEN );
5282        }
5283
5284        if (perm) disable_MAC(ai, lock);
5285        writeWepKeyRid(ai, &wkr, perm, lock);
5286        if (perm) enable_MAC(ai, lock);
5287        return 0;
5288}
5289
5290static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
5291        struct proc_data *data;
5292        struct proc_dir_entry *dp = PDE(inode);
5293        struct net_device *dev = dp->data;
5294        struct airo_info *ai = dev->priv;
5295        int i;
5296        char key[16];
5297        u16 index = 0;
5298        int j = 0;
5299
5300        memset(key, 0, sizeof(key));
5301
5302        data = (struct proc_data *)file->private_data;
5303        if ( !data->writelen ) return;
5304
5305        if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' &&
5306            (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
5307                index = data->wbuffer[0] - '0';
5308                if (data->wbuffer[1] == '\n') {
5309                        set_wep_key(ai, index, NULL, 0, 1, 1);
5310                        return;
5311                }
5312                j = 2;
5313        } else {
5314                airo_print_err(ai->dev->name, "WepKey passed invalid key index");
5315                return;
5316        }
5317
5318        for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) {
5319                switch(i%3) {
5320                case 0:
5321                        key[i/3] = hexVal(data->wbuffer[i+j])<<4;
5322                        break;
5323                case 1:
5324                        key[i/3] |= hexVal(data->wbuffer[i+j]);
5325                        break;
5326                }
5327        }
5328        set_wep_key(ai, index, key, i/3, 1, 1);
5329}
5330
5331static int proc_wepkey_open( struct inode *inode, struct file *file ) {
5332        struct proc_data *data;
5333        struct proc_dir_entry *dp = PDE(inode);
5334        struct net_device *dev = dp->data;
5335        struct airo_info *ai = dev->priv;
5336        char *ptr;
5337        WepKeyRid wkr;
5338        u16 lastindex;
5339        int j=0;
5340        int rc;
5341
5342        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
5343                return -ENOMEM;
5344        memset(&wkr, 0, sizeof(wkr));
5345        data = (struct proc_data *)file->private_data;
5346        if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) {
5347                kfree (file->private_data);
5348                return -ENOMEM;
5349        }
5350        data->writelen = 0;
5351        data->maxwritelen = 80;
5352        if ((data->wbuffer = kzalloc( 80, GFP_KERNEL )) == NULL) {
5353                kfree (data->rbuffer);
5354                kfree (file->private_data);
5355                return -ENOMEM;
5356        }
5357        data->on_close = proc_wepkey_on_close;
5358
5359        ptr = data->rbuffer;
5360        strcpy(ptr, "No wep keys\n");
5361        rc = readWepKeyRid(ai, &wkr, 1, 1);
5362        if (rc == SUCCESS) do {
5363                lastindex = wkr.kindex;
5364                if (wkr.kindex == 0xffff) {
5365                        j += sprintf(ptr+j, "Tx key = %d\n",
5366                                     (int)wkr.mac[0]);
5367                } else {
5368                        j += sprintf(ptr+j, "Key %d set with length = %d\n",
5369                                     (int)wkr.kindex, (int)wkr.klen);
5370                }
5371                readWepKeyRid(ai, &wkr, 0, 1);
5372        } while((lastindex != wkr.kindex) && (j < 180-30));
5373
5374        data->readlen = strlen( data->rbuffer );
5375        return 0;
5376}
5377
5378static int proc_SSID_open( struct inode *inode, struct file *file ) {
5379        struct proc_data *data;
5380        struct proc_dir_entry *dp = PDE(inode);
5381        struct net_device *dev = dp->data;
5382        struct airo_info *ai = dev->priv;
5383        int i;
5384        char *ptr;
5385        SsidRid SSID_rid;
5386
5387        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
5388                return -ENOMEM;
5389        data = (struct proc_data *)file->private_data;
5390        if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
5391                kfree (file->private_data);
5392                return -ENOMEM;
5393        }
5394        data->writelen = 0;
5395        data->maxwritelen = 33*3;
5396        if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) {
5397                kfree (data->rbuffer);
5398                kfree (file->private_data);
5399                return -ENOMEM;
5400        }
5401        data->on_close = proc_SSID_on_close;
5402
5403        readSsidRid(ai, &SSID_rid);
5404        ptr = data->rbuffer;
5405        for( i = 0; i < 3; i++ ) {
5406                int j;
5407                if ( !SSID_rid.ssids[i].len ) break;
5408                for( j = 0; j < 32 &&
5409                             j < SSID_rid.ssids[i].len &&
5410                             SSID_rid.ssids[i].ssid[j]; j++ ) {
5411                        *ptr++ = SSID_rid.ssids[i].ssid[j];
5412                }
5413                *ptr++ = '\n';
5414        }
5415        *ptr = '\0';
5416        data->readlen = strlen( data->rbuffer );
5417        return 0;
5418}
5419
5420static int proc_APList_open( struct inode *inode, struct file *file ) {
5421        struct proc_data *data;
5422        struct proc_dir_entry *dp = PDE(inode);
5423        struct net_device *dev = dp->data;
5424        struct airo_info *ai = dev->priv;
5425        int i;
5426        char *ptr;
5427        APListRid APList_rid;
5428        DECLARE_MAC_BUF(mac);
5429
5430        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
5431                return -ENOMEM;
5432        data = (struct proc_data *)file->private_data;
5433        if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
5434                kfree (file->private_data);
5435                return -ENOMEM;
5436        }
5437        data->writelen = 0;
5438        data->maxwritelen = 4*6*3;
5439        if ((data->wbuffer = kzalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
5440                kfree (data->rbuffer);
5441                kfree (file->private_data);
5442                return -ENOMEM;
5443        }
5444        data->on_close = proc_APList_on_close;
5445
5446        readAPListRid(ai, &APList_rid);
5447        ptr = data->rbuffer;
5448        for( i = 0; i < 4; i++ ) {
5449// We end when we find a zero MAC
5450                if ( !*(int*)APList_rid.ap[i] &&
5451                     !*(int*)&APList_rid.ap[i][2]) break;
5452                ptr += sprintf(ptr, "%s\n",
5453                               print_mac(mac, APList_rid.ap[i]));
5454        }
5455        if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
5456
5457        *ptr = '\0';
5458        data->readlen = strlen( data->rbuffer );
5459        return 0;
5460}
5461
5462static int proc_BSSList_open( struct inode *inode, struct file *file ) {
5463        struct proc_data *data;
5464        struct proc_dir_entry *dp = PDE(inode);
5465        struct net_device *dev = dp->data;
5466        struct airo_info *ai = dev->priv;
5467        char *ptr;
5468        BSSListRid BSSList_rid;
5469        int rc;
5470        /* If doLoseSync is not 1, we won't do a Lose Sync */
5471        int doLoseSync = -1;
5472        DECLARE_MAC_BUF(mac);
5473
5474        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
5475                return -ENOMEM;
5476        data = (struct proc_data *)file->private_data;
5477        if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
5478                kfree (file->private_data);
5479                return -ENOMEM;
5480        }
5481        data->writelen = 0;
5482        data->maxwritelen = 0;
5483        data->wbuffer = NULL;
5484        data->on_close = NULL;
5485
5486        if (file->f_mode & FMODE_WRITE) {
5487                if (!(file->f_mode & FMODE_READ)) {
5488                        Cmd cmd;
5489                        Resp rsp;
5490
5491                        if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
5492                        memset(&cmd, 0, sizeof(cmd));
5493                        cmd.cmd=CMD_LISTBSS;
5494                        if (down_interruptible(&ai->sem))
5495                                return -ERESTARTSYS;
5496                        issuecommand(ai, &cmd, &rsp);
5497                        up(&ai->sem);
5498                        data->readlen = 0;
5499                        return 0;
5500                }
5501                doLoseSync = 1;
5502        }
5503        ptr = data->rbuffer;
5504        /* There is a race condition here if there are concurrent opens.
5505           Since it is a rare condition, we'll just live with it, otherwise
5506           we have to add a spin lock... */
5507        rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
5508        while(rc == 0 && BSSList_rid.index != 0xffff) {
5509                ptr += sprintf(ptr, "%s %*s rssi = %d",
5510                               print_mac(mac, BSSList_rid.bssid),
5511                                (int)BSSList_rid.ssidLen,
5512                                BSSList_rid.ssid,
5513                                (int)BSSList_rid.dBm);
5514                ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
5515                                (int)BSSList_rid.dsChannel,
5516                                BSSList_rid.cap & CAP_ESS ? "ESS" : "",
5517                                BSSList_rid.cap & CAP_IBSS ? "adhoc" : "",
5518                                BSSList_rid.cap & CAP_PRIVACY ? "wep" : "",
5519                                BSSList_rid.cap & CAP_SHORTHDR ? "shorthdr" : "");
5520                rc = readBSSListRid(ai, 0, &BSSList_rid);
5521        }
5522        *ptr = '\0';
5523        data->readlen = strlen( data->rbuffer );
5524        return 0;
5525}
5526
5527static int proc_close( struct inode *inode, struct file *file )
5528{
5529        struct proc_data *data = file->private_data;
5530
5531        if (data->on_close != NULL)
5532                data->on_close(inode, file);
5533        kfree(data->rbuffer);
5534        kfree(data->wbuffer);
5535        kfree(data);
5536        return 0;
5537}
5538
5539/* Since the card doesn't automatically switch to the right WEP mode,
5540   we will make it do it.  If the card isn't associated, every secs we
5541   will switch WEP modes to see if that will help.  If the card is
5542   associated we will check every minute to see if anything has
5543   changed. */
5544static void timer_func( struct net_device *dev ) {
5545        struct airo_info *apriv = dev->priv;
5546
5547/* We don't have a link so try changing the authtype */
5548        readConfigRid(apriv, 0);
5549        disable_MAC(apriv, 0);
5550        switch(apriv->config.authType) {
5551                case AUTH_ENCRYPT:
5552/* So drop to OPEN */
5553                        apriv->config.authType = AUTH_OPEN;
5554                        break;
5555                case AUTH_SHAREDKEY:
5556                        if (apriv->keyindex < auto_wep) {
5557                                set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0);
5558                                apriv->config.authType = AUTH_SHAREDKEY;
5559                                apriv->keyindex++;
5560                        } else {
5561                                /* Drop to ENCRYPT */
5562                                apriv->keyindex = 0;
5563                                set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0);
5564                                apriv->config.authType = AUTH_ENCRYPT;
5565                        }
5566                        break;
5567                default:  /* We'll escalate to SHAREDKEY */
5568                        apriv->config.authType = AUTH_SHAREDKEY;
5569        }
5570        set_bit (FLAG_COMMIT, &apriv->flags);
5571        writeConfigRid(apriv, 0);
5572        enable_MAC(apriv, 0);
5573        up(&apriv->sem);
5574
5575/* Schedule check to see if the change worked */
5576        clear_bit(JOB_AUTOWEP, &apriv->jobs);
5577        apriv->expires = RUN_AT(HZ*3);
5578}
5579
5580#ifdef CONFIG_PCI
5581static int __devinit airo_pci_probe(struct pci_dev *pdev,
5582                                    const struct pci_device_id *pent)
5583{
5584        struct net_device *dev;
5585
5586        if (pci_enable_device(pdev))
5587                return -ENODEV;
5588        pci_set_master(pdev);
5589
5590        if (pdev->device == 0x5000 || pdev->device == 0xa504)
5591                        dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev);
5592        else
5593                        dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev);
5594        if (!dev) {
5595                pci_disable_device(pdev);
5596                return -ENODEV;
5597        }
5598
5599        pci_set_drvdata(pdev, dev);
5600        return 0;
5601}
5602
5603static void __devexit airo_pci_remove(struct pci_dev *pdev)
5604{
5605        struct net_device *dev = pci_get_drvdata(pdev);
5606
5607        airo_print_info(dev->name, "Unregistering...");
5608        stop_airo_card(dev, 1);
5609        pci_disable_device(pdev);
5610        pci_set_drvdata(pdev, NULL);
5611}
5612
5613static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
5614{
5615        struct net_device *dev = pci_get_drvdata(pdev);
5616        struct airo_info *ai = dev->priv;
5617        Cmd cmd;
5618        Resp rsp;
5619
5620        if ((ai->APList == NULL) &&
5621                (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL)
5622                return -ENOMEM;
5623        if ((ai->SSID == NULL) &&
5624                (ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL)) == NULL)
5625                return -ENOMEM;
5626        readAPListRid(ai, ai->APList);
5627        readSsidRid(ai, ai->SSID);
5628        memset(&cmd, 0, sizeof(cmd));
5629        /* the lock will be released at the end of the resume callback */
5630        if (down_interruptible(&ai->sem))
5631                return -EAGAIN;
5632        disable_MAC(ai, 0);
5633        netif_device_detach(dev);
5634        ai->power = state;
5635        cmd.cmd=HOSTSLEEP;
5636        issuecommand(ai, &cmd, &rsp);
5637
5638        pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
5639        pci_save_state(pdev);
5640        return pci_set_power_state(pdev, pci_choose_state(pdev, state));
5641}
5642
5643static int airo_pci_resume(struct pci_dev *pdev)
5644{
5645        struct net_device *dev = pci_get_drvdata(pdev);
5646        struct airo_info *ai = dev->priv;
5647        pci_power_t prev_state = pdev->current_state;
5648
5649        pci_set_power_state(pdev, PCI_D0);
5650        pci_restore_state(pdev);
5651        pci_enable_wake(pdev, PCI_D0, 0);
5652
5653        if (prev_state != PCI_D1) {
5654                reset_card(dev, 0);
5655                mpi_init_descriptors(ai);
5656                setup_card(ai, dev->dev_addr, 0);
5657                clear_bit(FLAG_RADIO_OFF, &ai->flags);
5658                clear_bit(FLAG_PENDING_XMIT, &ai->flags);
5659        } else {
5660                OUT4500(ai, EVACK, EV_AWAKEN);
5661                OUT4500(ai, EVACK, EV_AWAKEN);
5662                msleep(100);
5663        }
5664
5665        set_bit (FLAG_COMMIT, &ai->flags);
5666        disable_MAC(ai, 0);
5667        msleep(200);
5668        if (ai->SSID) {
5669                writeSsidRid(ai, ai->SSID, 0);
5670                kfree(ai->SSID);
5671                ai->SSID = NULL;
5672        }
5673        if (ai->APList) {
5674                writeAPListRid(ai, ai->APList, 0);
5675                kfree(ai->APList);
5676                ai->APList = NULL;
5677        }
5678        writeConfigRid(ai, 0);
5679        enable_MAC(ai, 0);
5680        ai->power = PMSG_ON;
5681        netif_device_attach(dev);
5682        netif_wake_queue(dev);
5683        enable_interrupts(ai);
5684        up(&ai->sem);
5685        return 0;
5686}
5687#endif
5688
5689static int __init airo_init_module( void )
5690{
5691        int i;
5692#if 0
5693        int have_isa_dev = 0;
5694#endif
5695
5696        airo_entry = create_proc_entry("aironet",
5697                                       S_IFDIR | airo_perm,
5698                                       proc_root_driver);
5699
5700        if (airo_entry) {
5701                airo_entry->uid = proc_uid;
5702                airo_entry->gid = proc_gid;
5703        }
5704
5705        for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
5706                airo_print_info("", "Trying to configure ISA adapter at irq=%d "
5707                        "io=0x%x", irq[i], io[i] );
5708                if (init_airo_card( irq[i], io[i], 0, NULL ))
5709#if 0
5710                        have_isa_dev = 1;
5711#else
5712                        /* do nothing */ ;
5713#endif
5714        }
5715
5716#ifdef CONFIG_PCI
5717        airo_print_info("", "Probing for PCI adapters");
5718        i = pci_register_driver(&airo_driver);
5719        airo_print_info("", "Finished probing for PCI adapters");
5720
5721        if (i) {
5722                remove_proc_entry("aironet", proc_root_driver);
5723                return i;
5724        }
5725#endif
5726
5727        /* Always exit with success, as we are a library module
5728         * as well as a driver module
5729         */
5730        return 0;
5731}
5732
5733static void __exit airo_cleanup_module( void )
5734{
5735        struct airo_info *ai;
5736        while(!list_empty(&airo_devices)) {
5737                ai = list_entry(airo_devices.next, struct airo_info, dev_list);
5738                airo_print_info(ai->dev->name, "Unregistering...");
5739                stop_airo_card(ai->dev, 1);
5740        }
5741#ifdef CONFIG_PCI
5742        pci_unregister_driver(&airo_driver);
5743#endif
5744        remove_proc_entry("aironet", proc_root_driver);
5745}
5746
5747/*
5748 * Initial Wireless Extension code for Aironet driver by :
5749 *      Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
5750 * Conversion to new driver API by :
5751 *      Jean Tourrilhes <jt@hpl.hp.com> - HPL - 26 March 02
5752 * Javier also did a good amount of work here, adding some new extensions
5753 * and fixing my code. Let's just say that without him this code just
5754 * would not work at all... - Jean II
5755 */
5756
5757static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi)
5758{
5759        if( !rssi_rid )
5760                return 0;
5761
5762        return (0x100 - rssi_rid[rssi].rssidBm);
5763}
5764
5765static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
5766{
5767        int i;
5768
5769        if( !rssi_rid )
5770                return 0;
5771
5772        for( i = 0; i < 256; i++ )
5773                if (rssi_rid[i].rssidBm == dbm)
5774                        return rssi_rid[i].rssipct;
5775
5776        return 0;
5777}
5778
5779
5780static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
5781{
5782        int quality = 0;
5783
5784        if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
5785                if (memcmp(cap_rid->prodName, "350", 3))
5786                        if (status_rid->signalQuality > 0x20)
5787                                quality = 0;
5788                        else
5789                                quality = 0x20 - status_rid->signalQuality;
5790                else
5791                        if (status_rid->signalQuality > 0xb0)
5792                                quality = 0;
5793                        else if (status_rid->signalQuality < 0x10)
5794                                quality = 0xa0;
5795                        else
5796                                quality = 0xb0 - status_rid->signalQuality;
5797        }
5798        return quality;
5799}
5800
5801#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0)
5802#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50);
5803
5804/*------------------------------------------------------------------*/
5805/*
5806 * Wireless Handler : get protocol name
5807 */
5808static int airo_get_name(struct net_device *dev,
5809                         struct iw_request_info *info,
5810                         char *cwrq,
5811                         char *extra)
5812{
5813        strcpy(cwrq, "IEEE 802.11-DS");
5814        return 0;
5815}
5816
5817/*------------------------------------------------------------------*/
5818/*
5819 * Wireless Handler : set frequency
5820 */
5821static int airo_set_freq(struct net_device *dev,
5822                         struct iw_request_info *info,
5823                         struct iw_freq *fwrq,
5824                         char *extra)
5825{
5826        struct airo_info *local = dev->priv;
5827        int rc = -EINPROGRESS;          /* Call commit handler */
5828
5829        /* If setting by frequency, convert to a channel */
5830        if((fwrq->e == 1) &&
5831           (fwrq->m >= (int) 2.412e8) &&
5832           (fwrq->m <= (int) 2.487e8)) {
5833                int f = fwrq->m / 100000;
5834                int c = 0;
5835                while((c < 14) && (f != frequency_list[c]))
5836                        c++;
5837                /* Hack to fall through... */
5838                fwrq->e = 0;
5839                fwrq->m = c + 1;
5840        }
5841        /* Setting by channel number */
5842        if((fwrq->m > 1000) || (fwrq->e > 0))
5843                rc = -EOPNOTSUPP;
5844        else {
5845                int channel = fwrq->m;
5846                /* We should do a better check than that,
5847                 * based on the card capability !!! */
5848                if((channel < 1) || (channel > 14)) {
5849                        airo_print_dbg(dev->name, "New channel value of %d is invalid!",
5850                                fwrq->m);
5851                        rc = -EINVAL;
5852                } else {
5853                        readConfigRid(local, 1);
5854                        /* Yes ! We can set it !!! */
5855                        local->config.channelSet = (u16) channel;
5856                        set_bit (FLAG_COMMIT, &local->flags);
5857                }
5858        }
5859        return rc;
5860}
5861
5862/*------------------------------------------------------------------*/
5863/*
5864 * Wireless Handler : get frequency
5865 */
5866static int airo_get_freq(struct net_device *dev,
5867                         struct iw_request_info *info,
5868                         struct iw_freq *fwrq,
5869                         char *extra)
5870{
5871        struct airo_info *local = dev->priv;
5872        StatusRid status_rid;           /* Card status info */
5873        int ch;
5874
5875        readConfigRid(local, 1);
5876        if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
5877                status_rid.channel = local->config.channelSet;
5878        else
5879                readStatusRid(local, &status_rid, 1);
5880
5881        ch = (int)status_rid.channel;
5882        if((ch > 0) && (ch < 15)) {
5883                fwrq->m = frequency_list[ch - 1] * 100000;
5884                fwrq->e = 1;
5885        } else {
5886                fwrq->m = ch;
5887                fwrq->e = 0;
5888        }
5889
5890        return 0;
5891}
5892
5893/*------------------------------------------------------------------*/
5894/*
5895 * Wireless Handler : set ESSID
5896 */
5897static int airo_set_essid(struct net_device *dev,
5898                          struct iw_request_info *info,
5899                          struct iw_point *dwrq,
5900                          char *extra)
5901{
5902        struct airo_info *local = dev->priv;
5903        SsidRid SSID_rid;               /* SSIDs */
5904
5905        /* Reload the list of current SSID */
5906        readSsidRid(local, &SSID_rid);
5907
5908        /* Check if we asked for `any' */
5909        if(dwrq->flags == 0) {
5910                /* Just send an empty SSID list */
5911                memset(&SSID_rid, 0, sizeof(SSID_rid));
5912        } else {
5913                int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
5914
5915                /* Check the size of the string */
5916                if(dwrq->length > IW_ESSID_MAX_SIZE) {
5917                        return -E2BIG ;
5918                }
5919                /* Check if index is valid */
5920                if((index < 0) || (index >= 4)) {
5921                        return -EINVAL;
5922                }
5923
5924                /* Set the SSID */
5925                memset(SSID_rid.ssids[index].ssid, 0,
5926                       sizeof(SSID_rid.ssids[index].ssid));
5927                memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
5928                SSID_rid.ssids[index].len = dwrq->length;
5929        }
5930        SSID_rid.len = sizeof(SSID_rid);
5931        /* Write it to the card */
5932        disable_MAC(local, 1);
5933        writeSsidRid(local, &SSID_rid, 1);
5934        enable_MAC(local, 1);
5935
5936        return 0;
5937}
5938
5939/*------------------------------------------------------------------*/
5940/*
5941 * Wireless Handler : get ESSID
5942 */
5943static int airo_get_essid(struct net_device *dev,
5944                          struct iw_request_info *info,
5945                          struct iw_point *dwrq,
5946                          char *extra)
5947{
5948        struct airo_info *local = dev->priv;
5949        StatusRid status_rid;           /* Card status info */
5950
5951        readStatusRid(local, &status_rid, 1);
5952
5953        /* Note : if dwrq->flags != 0, we should
5954         * get the relevant SSID from the SSID list... */
5955
5956        /* Get the current SSID */
5957        memcpy(extra, status_rid.SSID, status_rid.SSIDlen);
5958        /* If none, we may want to get the one that was set */
5959
5960        /* Push it out ! */
5961        dwrq->length = status_rid.SSIDlen;
5962        dwrq->flags = 1; /* active */
5963
5964        return 0;
5965}
5966
5967/*------------------------------------------------------------------*/
5968/*
5969 * Wireless Handler : set AP address
5970 */
5971static int airo_set_wap(struct net_device *dev,
5972                        struct iw_request_info *info,
5973                        struct sockaddr *awrq,
5974                        char *extra)
5975{
5976        struct airo_info *local = dev->priv;
5977        Cmd cmd;
5978        Resp rsp;
5979        APListRid APList_rid;
5980        static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5981        static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
5982
5983        if (awrq->sa_family != ARPHRD_ETHER)
5984                return -EINVAL;
5985        else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
5986                 !memcmp(off, awrq->sa_data, ETH_ALEN)) {
5987                memset(&cmd, 0, sizeof(cmd));
5988                cmd.cmd=CMD_LOSE_SYNC;
5989                if (down_interruptible(&local->sem))
5990                        return -ERESTARTSYS;
5991                issuecommand(local, &cmd, &rsp);
5992                up(&local->sem);
5993        } else {
5994                memset(&APList_rid, 0, sizeof(APList_rid));
5995                APList_rid.len = sizeof(APList_rid);
5996                memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
5997                disable_MAC(local, 1);
5998                writeAPListRid(local, &APList_rid, 1);
5999                enable_MAC(local, 1);
6000        }
6001        return 0;
6002}
6003
6004/*------------------------------------------------------------------*/
6005/*
6006 * Wireless Handler : get AP address
6007 */
6008static int airo_get_wap(struct net_device *dev,
6009                        struct iw_request_info *info,
6010                        struct sockaddr *awrq,
6011                        char *extra)
6012{
6013        struct airo_info *local = dev->priv;
6014        StatusRid status_rid;           /* Card status info */
6015
6016        readStatusRid(local, &status_rid, 1);
6017
6018        /* Tentative. This seems to work, wow, I'm lucky !!! */
6019        memcpy(awrq->sa_data, status_rid.bssid[0], ETH_ALEN);
6020        awrq->sa_family = ARPHRD_ETHER;
6021
6022        return 0;
6023}
6024
6025/*------------------------------------------------------------------*/
6026/*
6027 * Wireless Handler : set Nickname
6028 */
6029static int airo_set_nick(struct net_device *dev,
6030                         struct iw_request_info *info,
6031                         struct iw_point *dwrq,
6032                         char *extra)
6033{
6034        struct airo_info *local = dev->priv;
6035
6036        /* Check the size of the string */
6037        if(dwrq->length > 16) {
6038                return -E2BIG;
6039        }
6040        readConfigRid(local, 1);
6041        memset(local->config.nodeName, 0, sizeof(local->config.nodeName));
6042        memcpy(local->config.nodeName, extra, dwrq->length);
6043        set_bit (FLAG_COMMIT, &local->flags);
6044
6045        return -EINPROGRESS;            /* Call commit handler */
6046}
6047
6048/*------------------------------------------------------------------*/
6049/*
6050 * Wireless Handler : get Nickname
6051 */
6052static int airo_get_nick(struct net_device *dev,
6053                         struct iw_request_info *info,
6054                         struct iw_point *dwrq,
6055                         char *extra)
6056{
6057        struct airo_info *local = dev->priv;
6058
6059        readConfigRid(local, 1);
6060        strncpy(extra, local->config.nodeName, 16);
6061        extra[16] = '\0';
6062        dwrq->length = strlen(extra);
6063
6064        return 0;
6065}
6066
6067/*------------------------------------------------------------------*/
6068/*
6069 * Wireless Handler : set Bit-Rate
6070 */
6071static int airo_set_rate(struct net_device *dev,
6072                         struct iw_request_info *info,
6073                         struct iw_param *vwrq,
6074                         char *extra)
6075{
6076        struct airo_info *local = dev->priv;
6077        CapabilityRid cap_rid;          /* Card capability info */
6078        u8      brate = 0;
6079        int     i;
6080
6081        /* First : get a valid bit rate value */
6082        readCapabilityRid(local, &cap_rid, 1);
6083
6084        /* Which type of value ? */
6085        if((vwrq->value < 8) && (vwrq->value >= 0)) {
6086                /* Setting by rate index */
6087                /* Find value in the magic rate table */
6088                brate = cap_rid.supportedRates[vwrq->value];
6089        } else {
6090                /* Setting by frequency value */
6091                u8      normvalue = (u8) (vwrq->value/500000);
6092
6093                /* Check if rate is valid */
6094                for(i = 0 ; i < 8 ; i++) {
6095                        if(normvalue == cap_rid.supportedRates[i]) {
6096                                brate = normvalue;
6097                                break;
6098                        }
6099                }
6100        }
6101        /* -1 designed the max rate (mostly auto mode) */
6102        if(vwrq->value == -1) {
6103                /* Get the highest available rate */
6104                for(i = 0 ; i < 8 ; i++) {
6105                        if(cap_rid.supportedRates[i] == 0)
6106                                break;
6107                }
6108                if(i != 0)
6109                        brate = cap_rid.supportedRates[i - 1];
6110        }
6111        /* Check that it is valid */
6112        if(brate == 0) {
6113                return -EINVAL;
6114        }
6115
6116        readConfigRid(local, 1);
6117        /* Now, check if we want a fixed or auto value */
6118        if(vwrq->fixed == 0) {
6119                /* Fill all the rates up to this max rate */
6120                memset(local->config.rates, 0, 8);
6121                for(i = 0 ; i < 8 ; i++) {
6122                        local->config.rates[i] = cap_rid.supportedRates[i];
6123                        if(local->config.rates[i] == brate)
6124                                break;
6125                }
6126        } else {
6127                /* Fixed mode */
6128                /* One rate, fixed */
6129                memset(local->config.rates, 0, 8);
6130                local->config.rates[0] = brate;
6131        }
6132        set_bit (FLAG_COMMIT, &local->flags);
6133
6134        return -EINPROGRESS;            /* Call commit handler */
6135}
6136
6137/*------------------------------------------------------------------*/
6138/*
6139 * Wireless Handler : get Bit-Rate
6140 */
6141static int airo_get_rate(struct net_device *dev,
6142                         struct iw_request_info *info,
6143                         struct iw_param *vwrq,
6144                         char *extra)
6145{
6146        struct airo_info *local = dev->priv;
6147        StatusRid status_rid;           /* Card status info */
6148
6149        readStatusRid(local, &status_rid, 1);
6150
6151        vwrq->value = status_rid.currentXmitRate * 500000;
6152        /* If more than one rate, set auto */
6153        readConfigRid(local, 1);
6154        vwrq->fixed = (local->config.rates[1] == 0);
6155
6156        return 0;
6157}
6158
6159/*------------------------------------------------------------------*/
6160/*
6161 * Wireless Handler : set RTS threshold
6162 */
6163static int airo_set_rts(struct net_device *dev,
6164                        struct iw_request_info *info,
6165                        struct iw_param *vwrq,
6166                        char *extra)
6167{
6168        struct airo_info *local = dev->priv;
6169        int rthr = vwrq->value;
6170
6171        if(vwrq->disabled)
6172                rthr = AIRO_DEF_MTU;
6173        if((rthr < 0) || (rthr > AIRO_DEF_MTU)) {
6174                return -EINVAL;
6175        }
6176        readConfigRid(local, 1);
6177        local->config.rtsThres = rthr;
6178        set_bit (FLAG_COMMIT, &local->flags);
6179
6180        return -EINPROGRESS;            /* Call commit handler */
6181}
6182
6183/*------------------------------------------------------------------*/
6184/*
6185 * Wireless Handler : get RTS threshold
6186 */
6187static int airo_get_rts(struct net_device *dev,
6188                        struct iw_request_info *info,
6189                        struct iw_param *vwrq,
6190                        char *extra)
6191{
6192        struct airo_info *local = dev->priv;
6193
6194        readConfigRid(local, 1);
6195        vwrq->value = local->config.rtsThres;
6196        vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
6197        vwrq->fixed = 1;
6198
6199        return 0;
6200}
6201
6202/*------------------------------------------------------------------*/
6203/*
6204 * Wireless Handler : set Fragmentation threshold
6205 */
6206static int airo_set_frag(struct net_device *dev,
6207                         struct iw_request_info *info,
6208                         struct iw_param *vwrq,
6209                         char *extra)
6210{
6211        struct airo_info *local = dev->priv;
6212        int fthr = vwrq->value;
6213
6214        if(vwrq->disabled)
6215                fthr = AIRO_DEF_MTU;
6216        if((fthr < 256) || (fthr > AIRO_DEF_MTU)) {
6217                return -EINVAL;
6218        }
6219        fthr &= ~0x1;   /* Get an even value - is it really needed ??? */
6220        readConfigRid(local, 1);
6221        local->config.fragThresh = (u16)fthr;
6222        set_bit (FLAG_COMMIT, &local->flags);
6223
6224        return -EINPROGRESS;            /* Call commit handler */
6225}
6226
6227/*------------------------------------------------------------------*/
6228/*
6229 * Wireless Handler : get Fragmentation threshold
6230 */
6231static int airo_get_frag(struct net_device *dev,
6232                         struct iw_request_info *info,
6233                         struct iw_param *vwrq,
6234                         char *extra)
6235{
6236        struct airo_info *local = dev->priv;
6237
6238        readConfigRid(local, 1);
6239        vwrq->value = local->config.fragThresh;
6240        vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
6241        vwrq->fixed = 1;
6242
6243        return 0;
6244}
6245
6246/*------------------------------------------------------------------*/
6247/*
6248 * Wireless Handler : set Mode of Operation
6249 */
6250static int airo_set_mode(struct net_device *dev,
6251                         struct iw_request_info *info,
6252                         __u32 *uwrq,
6253                         char *extra)
6254{
6255        struct airo_info *local = dev->priv;
6256        int reset = 0;
6257
6258        readConfigRid(local, 1);
6259        if ((local->config.rmode & 0xff) >= RXMODE_RFMON)
6260                reset = 1;
6261
6262        switch(*uwrq) {
6263                case IW_MODE_ADHOC:
6264                        local->config.opmode &= 0xFF00;
6265                        local->config.opmode |= MODE_STA_IBSS;
6266                        local->config.rmode &= 0xfe00;
6267                        local->config.scanMode = SCANMODE_ACTIVE;
6268                        clear_bit (FLAG_802_11, &local->flags);
6269                        break;
6270                case IW_MODE_INFRA:
6271                        local->config.opmode &= 0xFF00;
6272                        local->config.opmode |= MODE_STA_ESS;
6273                        local->config.rmode &= 0xfe00;
6274                        local->config.scanMode = SCANMODE_ACTIVE;
6275                        clear_bit (FLAG_802_11, &local->flags);
6276                        break;
6277                case IW_MODE_MASTER:
6278                        local->config.opmode &= 0xFF00;
6279                        local->config.opmode |= MODE_AP;
6280                        local->config.rmode &= 0xfe00;
6281                        local->config.scanMode = SCANMODE_ACTIVE;
6282                        clear_bit (FLAG_802_11, &local->flags);
6283                        break;
6284                case IW_MODE_REPEAT:
6285                        local->config.opmode &= 0xFF00;
6286                        local->config.opmode |= MODE_AP_RPTR;
6287                        local->config.rmode &= 0xfe00;
6288                        local->config.scanMode = SCANMODE_ACTIVE;
6289                        clear_bit (FLAG_802_11, &local->flags);
6290                        break;
6291                case IW_MODE_MONITOR:
6292                        local->config.opmode &= 0xFF00;
6293                        local->config.opmode |= MODE_STA_ESS;
6294                        local->config.rmode &= 0xfe00;
6295                        local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
6296                        local->config.scanMode = SCANMODE_PASSIVE;
6297                        set_bit (FLAG_802_11, &local->flags);
6298                        break;
6299                default:
6300                        return -EINVAL;
6301        }
6302        if (reset)
6303                set_bit (FLAG_RESET, &local->flags);
6304        set_bit (FLAG_COMMIT, &local->flags);
6305
6306        return -EINPROGRESS;            /* Call commit handler */
6307}
6308
6309/*------------------------------------------------------------------*/
6310/*
6311 * Wireless Handler : get Mode of Operation
6312 */
6313static int airo_get_mode(struct net_device *dev,
6314                         struct iw_request_info *info,
6315                         __u32 *uwrq,
6316                         char *extra)
6317{
6318        struct airo_info *local = dev->priv;
6319
6320        readConfigRid(local, 1);
6321        /* If not managed, assume it's ad-hoc */
6322        switch (local->config.opmode & 0xFF) {
6323                case MODE_STA_ESS:
6324                        *uwrq = IW_MODE_INFRA;
6325                        break;
6326                case MODE_AP:
6327                        *uwrq = IW_MODE_MASTER;
6328                        break;
6329                case MODE_AP_RPTR:
6330                        *uwrq = IW_MODE_REPEAT;
6331                        break;
6332                default:
6333                        *uwrq = IW_MODE_ADHOC;
6334        }
6335
6336        return 0;
6337}
6338
6339/*------------------------------------------------------------------*/
6340/*
6341 * Wireless Handler : set Encryption Key
6342 */
6343static int airo_set_encode(struct net_device *dev,
6344                           struct iw_request_info *info,
6345                           struct iw_point *dwrq,
6346                           char *extra)
6347{
6348        struct airo_info *local = dev->priv;
6349        CapabilityRid cap_rid;          /* Card capability info */
6350        int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
6351        u16 currentAuthType = local->config.authType;
6352
6353        /* Is WEP supported ? */
6354        readCapabilityRid(local, &cap_rid, 1);
6355        /* Older firmware doesn't support this...
6356        if(!(cap_rid.softCap & 2)) {
6357                return -EOPNOTSUPP;
6358        } */
6359        readConfigRid(local, 1);
6360
6361        /* Basic checking: do we have a key to set ?
6362         * Note : with the new API, it's impossible to get a NULL pointer.
6363         * Therefore, we need to check a key size == 0 instead.
6364         * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
6365         * when no key is present (only change flags), but older versions
6366         * don't do it. - Jean II */
6367        if (dwrq->length > 0) {
6368                wep_key_t key;
6369                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6370                int current_index = get_wep_key(local, 0xffff);
6371                /* Check the size of the key */
6372                if (dwrq->length > MAX_KEY_SIZE) {
6373                        return -EINVAL;
6374                }
6375                /* Check the index (none -> use current) */
6376                if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4:1)))
6377                        index = current_index;
6378                /* Set the length */
6379                if (dwrq->length > MIN_KEY_SIZE)
6380                        key.len = MAX_KEY_SIZE;
6381                else
6382                        if (dwrq->length > 0)
6383                                key.len = MIN_KEY_SIZE;
6384                        else
6385                                /* Disable the key */
6386                                key.len = 0;
6387                /* Check if the key is not marked as invalid */
6388                if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
6389                        /* Cleanup */
6390                        memset(key.key, 0, MAX_KEY_SIZE);
6391                        /* Copy the key in the driver */
6392                        memcpy(key.key, extra, dwrq->length);
6393                        /* Send the key to the card */
6394                        set_wep_key(local, index, key.key, key.len, perm, 1);
6395                }
6396                /* WE specify that if a valid key is set, encryption
6397                 * should be enabled (user may turn it off later)
6398                 * This is also how "iwconfig ethX key on" works */
6399                if((index == current_index) && (key.len > 0) &&
6400                   (local->config.authType == AUTH_OPEN)) {
6401                        local->config.authType = AUTH_ENCRYPT;
6402                }
6403        } else {
6404                /* Do we want to just set the transmit key index ? */
6405                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6406                if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
6407                        set_wep_key(local, index, NULL, 0, perm, 1);
6408                } else
6409                        /* Don't complain if only change the mode */
6410                        if(!dwrq->flags & IW_ENCODE_MODE) {
6411                                return -EINVAL;
6412                        }
6413        }
6414        /* Read the flags */
6415        if(dwrq->flags & IW_ENCODE_DISABLED)
6416                local->config.authType = AUTH_OPEN;     // disable encryption
6417        if(dwrq->flags & IW_ENCODE_RESTRICTED)
6418                local->config.authType = AUTH_SHAREDKEY;        // Only Both
6419        if(dwrq->flags & IW_ENCODE_OPEN)
6420                local->config.authType = AUTH_ENCRYPT;  // Only Wep
6421        /* Commit the changes to flags if needed */
6422        if (local->config.authType != currentAuthType)
6423                set_bit (FLAG_COMMIT, &local->flags);
6424        return -EINPROGRESS;            /* Call commit handler */
6425}
6426
6427/*------------------------------------------------------------------*/
6428/*
6429 * Wireless Handler : get Encryption Key
6430 */
6431static int airo_get_encode(struct net_device *dev,
6432                           struct iw_request_info *info,
6433                           struct iw_point *dwrq,
6434                           char *extra)
6435{
6436        struct airo_info *local = dev->priv;
6437        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
6438        CapabilityRid cap_rid;          /* Card capability info */
6439
6440        /* Is it supported ? */
6441        readCapabilityRid(local, &cap_rid, 1);
6442        if(!(cap_rid.softCap & 2)) {
6443                return -EOPNOTSUPP;
6444        }
6445        readConfigRid(local, 1);
6446        /* Check encryption mode */
6447        switch(local->config.authType)  {
6448                case AUTH_ENCRYPT:
6449                        dwrq->flags = IW_ENCODE_OPEN;
6450                        break;
6451                case AUTH_SHAREDKEY:
6452                        dwrq->flags = IW_ENCODE_RESTRICTED;
6453                        break;
6454                default:
6455                case AUTH_OPEN:
6456                        dwrq->flags = IW_ENCODE_DISABLED;
6457                        break;
6458        }
6459        /* We can't return the key, so set the proper flag and return zero */
6460        dwrq->flags |= IW_ENCODE_NOKEY;
6461        memset(extra, 0, 16);
6462
6463        /* Which key do we want ? -1 -> tx index */
6464        if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4 : 1)))
6465                index = get_wep_key(local, 0xffff);
6466        dwrq->flags |= index + 1;
6467        /* Copy the key to the user buffer */
6468        dwrq->length = get_wep_key(local, index);
6469        if (dwrq->length > 16) {
6470                dwrq->length=0;
6471        }
6472        return 0;
6473}
6474
6475/*------------------------------------------------------------------*/
6476/*
6477 * Wireless Handler : set extended Encryption parameters
6478 */
6479static int airo_set_encodeext(struct net_device *dev,
6480                           struct iw_request_info *info,
6481                            union iwreq_data *wrqu,
6482                            char *extra)
6483{
6484        struct airo_info *local = dev->priv;
6485        struct iw_point *encoding = &wrqu->encoding;
6486        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
6487        CapabilityRid cap_rid;          /* Card capability info */
6488        int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
6489        u16 currentAuthType = local->config.authType;
6490        int idx, key_len, alg = ext->alg, set_key = 1;
6491        wep_key_t key;
6492
6493        /* Is WEP supported ? */
6494        readCapabilityRid(local, &cap_rid, 1);
6495        /* Older firmware doesn't support this...
6496        if(!(cap_rid.softCap & 2)) {
6497                return -EOPNOTSUPP;
6498        } */
6499        readConfigRid(local, 1);
6500
6501        /* Determine and validate the key index */
6502        idx = encoding->flags & IW_ENCODE_INDEX;
6503        if (idx) {
6504                if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
6505                        return -EINVAL;
6506                idx--;
6507        } else
6508                idx = get_wep_key(local, 0xffff);
6509
6510        if (encoding->flags & IW_ENCODE_DISABLED)
6511                alg = IW_ENCODE_ALG_NONE;
6512
6513        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
6514                /* Only set transmit key index here, actual
6515                 * key is set below if needed.
6516                 */
6517                set_wep_key(local, idx, NULL, 0, perm, 1);
6518                set_key = ext->key_len > 0 ? 1 : 0;
6519        }
6520
6521        if (set_key) {
6522                /* Set the requested key first */
6523                memset(key.key, 0, MAX_KEY_SIZE);
6524                switch (alg) {
6525                case IW_ENCODE_ALG_NONE:
6526                        key.len = 0;
6527                        break;
6528                case IW_ENCODE_ALG_WEP:
6529                        if (ext->key_len > MIN_KEY_SIZE) {
6530                                key.len = MAX_KEY_SIZE;
6531                        } else if (ext->key_len > 0) {
6532                                key.len = MIN_KEY_SIZE;
6533                        } else {
6534                                return -EINVAL;
6535                        }
6536                        key_len = min (ext->key_len, key.len);
6537                        memcpy(key.key, ext->key, key_len);
6538                        break;
6539                default:
6540                        return -EINVAL;
6541                }
6542                /* Send the key to the card */
6543                set_wep_key(local, idx, key.key, key.len, perm, 1);
6544        }
6545
6546        /* Read the flags */
6547        if(encoding->flags & IW_ENCODE_DISABLED)
6548                local->config.authType = AUTH_OPEN;     // disable encryption
6549        if(encoding->flags & IW_ENCODE_RESTRICTED)
6550                local->config.authType = AUTH_SHAREDKEY;        // Only Both
6551        if(encoding->flags & IW_ENCODE_OPEN)
6552                local->config.authType = AUTH_ENCRYPT;  // Only Wep
6553        /* Commit the changes to flags if needed */
6554        if (local->config.authType != currentAuthType)
6555                set_bit (FLAG_COMMIT, &local->flags);
6556
6557        return -EINPROGRESS;
6558}
6559
6560
6561/*------------------------------------------------------------------*/
6562/*
6563 * Wireless Handler : get extended Encryption parameters
6564 */
6565static int airo_get_encodeext(struct net_device *dev,
6566                            struct iw_request_info *info,
6567                            union iwreq_data *wrqu,
6568                            char *extra)
6569{
6570        struct airo_info *local = dev->priv;
6571        struct iw_point *encoding = &wrqu->encoding;
6572        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
6573        CapabilityRid cap_rid;          /* Card capability info */
6574        int idx, max_key_len;
6575
6576        /* Is it supported ? */
6577        readCapabilityRid(local, &cap_rid, 1);
6578        if(!(cap_rid.softCap & 2)) {
6579                return -EOPNOTSUPP;
6580        }
6581        readConfigRid(local, 1);
6582
6583        max_key_len = encoding->length - sizeof(*ext);
6584        if (max_key_len < 0)
6585                return -EINVAL;
6586
6587        idx = encoding->flags & IW_ENCODE_INDEX;
6588        if (idx) {
6589                if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
6590                        return -EINVAL;
6591                idx--;
6592        } else
6593                idx = get_wep_key(local, 0xffff);
6594
6595        encoding->flags = idx + 1;
6596        memset(ext, 0, sizeof(*ext));
6597
6598        /* Check encryption mode */
6599        switch(local->config.authType) {
6600                case AUTH_ENCRYPT:
6601                        encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
6602                        break;
6603                case AUTH_SHAREDKEY:
6604                        encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
6605                        break;
6606                default:
6607                case AUTH_OPEN:
6608                        encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED;
6609                        break;
6610        }
6611        /* We can't return the key, so set the proper flag and return zero */
6612        encoding->flags |= IW_ENCODE_NOKEY;
6613        memset(extra, 0, 16);
6614        
6615        /* Copy the key to the user buffer */
6616        ext->key_len = get_wep_key(local, idx);
6617        if (ext->key_len > 16) {
6618                ext->key_len=0;
6619        }
6620
6621        return 0;
6622}
6623
6624
6625/*------------------------------------------------------------------*/
6626/*
6627 * Wireless Handler : set extended authentication parameters
6628 */
6629static int airo_set_auth(struct net_device *dev,
6630                               struct iw_request_info *info,
6631                               union iwreq_data *wrqu, char *extra)
6632{
6633        struct airo_info *local = dev->priv;
6634        struct iw_param *param = &wrqu->param;
6635        u16 currentAuthType = local->config.authType;
6636
6637        switch (param->flags & IW_AUTH_INDEX) {
6638        case IW_AUTH_WPA_VERSION:
6639        case IW_AUTH_CIPHER_PAIRWISE:
6640        case IW_AUTH_CIPHER_GROUP:
6641        case IW_AUTH_KEY_MGMT:
6642        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
6643        case IW_AUTH_PRIVACY_INVOKED:
6644                /*
6645                 * airo does not use these parameters
6646                 */
6647                break;
6648
6649        case IW_AUTH_DROP_UNENCRYPTED:
6650                if (param->value) {
6651                        /* Only change auth type if unencrypted */
6652                        if (currentAuthType == AUTH_OPEN)
6653                                local->config.authType = AUTH_ENCRYPT;
6654                } else {
6655                        local->config.authType = AUTH_OPEN;
6656                }
6657
6658                /* Commit the changes to flags if needed */
6659                if (local->config.authType != currentAuthType)
6660                        set_bit (FLAG_COMMIT, &local->flags);
6661                break;
6662
6663        case IW_AUTH_80211_AUTH_ALG: {
6664                        /* FIXME: What about AUTH_OPEN?  This API seems to
6665                         * disallow setting our auth to AUTH_OPEN.
6666                         */
6667                        if (param->value & IW_AUTH_ALG_SHARED_KEY) {
6668                                local->config.authType = AUTH_SHAREDKEY;
6669                        } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
6670                                local->config.authType = AUTH_ENCRYPT;
6671                        } else
6672                                return -EINVAL;
6673                        break;
6674
6675                        /* Commit the changes to flags if needed */
6676                        if (local->config.authType != currentAuthType)
6677                                set_bit (FLAG_COMMIT, &local->flags);
6678                }
6679
6680        case IW_AUTH_WPA_ENABLED:
6681                /* Silently accept disable of WPA */
6682                if (param->value > 0)
6683                        return -EOPNOTSUPP;
6684                break;
6685
6686        default:
6687                return -EOPNOTSUPP;
6688        }
6689        return -EINPROGRESS;
6690}
6691
6692
6693/*------------------------------------------------------------------*/
6694/*
6695 * Wireless Handler : get extended authentication parameters
6696 */
6697static int airo_get_auth(struct net_device *dev,
6698                               struct iw_request_info *info,
6699                               union iwreq_data *wrqu, char *extra)
6700{
6701        struct airo_info *local = dev->priv;
6702        struct iw_param *param = &wrqu->param;
6703        u16 currentAuthType = local->config.authType;
6704
6705        switch (param->flags & IW_AUTH_INDEX) {
6706        case IW_AUTH_DROP_UNENCRYPTED:
6707                switch (currentAuthType) {
6708                case AUTH_SHAREDKEY:
6709                case AUTH_ENCRYPT:
6710                        param->value = 1;
6711                        break;
6712                default:
6713                        param->value = 0;
6714                        break;
6715                }
6716                break;
6717
6718        case IW_AUTH_80211_AUTH_ALG:
6719                switch (currentAuthType) {
6720                case AUTH_SHAREDKEY:
6721                        param->value = IW_AUTH_ALG_SHARED_KEY;
6722                        break;
6723                case AUTH_ENCRYPT:
6724                default:
6725                        param->value = IW_AUTH_ALG_OPEN_SYSTEM;
6726                        break;
6727                }
6728                break;
6729
6730        case IW_AUTH_WPA_ENABLED:
6731                param->value = 0;
6732                break;
6733
6734        default:
6735                return -EOPNOTSUPP;
6736        }
6737        return 0;
6738}
6739
6740
6741/*------------------------------------------------------------------*/
6742/*
6743 * Wireless Handler : set Tx-Power
6744 */
6745static int airo_set_txpow(struct net_device *dev,
6746                          struct iw_request_info *info,
6747                          struct iw_param *vwrq,
6748                          char *extra)
6749{
6750        struct airo_info *local = dev->priv;
6751        CapabilityRid cap_rid;          /* Card capability info */
6752        int i;
6753        int rc = -EINVAL;
6754
6755        readCapabilityRid(local, &cap_rid, 1);
6756
6757        if (vwrq->disabled) {
6758                set_bit (FLAG_RADIO_OFF, &local->flags);
6759                set_bit (FLAG_COMMIT, &local->flags);
6760                return -EINPROGRESS;            /* Call commit handler */
6761        }
6762        if (vwrq->flags != IW_TXPOW_MWATT) {
6763                return -EINVAL;
6764        }
6765        clear_bit (FLAG_RADIO_OFF, &local->flags);
6766        for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
6767                if ((vwrq->value==cap_rid.txPowerLevels[i])) {
6768                        readConfigRid(local, 1);
6769                        local->config.txPower = vwrq->value;
6770                        set_bit (FLAG_COMMIT, &local->flags);
6771                        rc = -EINPROGRESS;      /* Call commit handler */
6772                        break;
6773                }
6774        return rc;
6775}
6776
6777/*------------------------------------------------------------------*/
6778/*
6779 * Wireless Handler : get Tx-Power
6780 */
6781static int airo_get_txpow(struct net_device *dev,
6782                          struct iw_request_info *info,
6783                          struct iw_param *vwrq,
6784                          char *extra)
6785{
6786        struct airo_info *local = dev->priv;
6787
6788        readConfigRid(local, 1);
6789        vwrq->value = local->config.txPower;
6790        vwrq->fixed = 1;        /* No power control */
6791        vwrq->disabled = test_bit(FLAG_RADIO_OFF, &local->flags);
6792        vwrq->flags = IW_TXPOW_MWATT;
6793
6794        return 0;
6795}
6796
6797/*------------------------------------------------------------------*/
6798/*
6799 * Wireless Handler : set Retry limits
6800 */
6801static int airo_set_retry(struct net_device *dev,
6802                          struct iw_request_info *info,
6803                          struct iw_param *vwrq,
6804                          char *extra)
6805{
6806        struct airo_info *local = dev->priv;
6807        int rc = -EINVAL;
6808
6809        if(vwrq->disabled) {
6810                return -EINVAL;
6811        }
6812        readConfigRid(local, 1);
6813        if(vwrq->flags & IW_RETRY_LIMIT) {
6814                if(vwrq->flags & IW_RETRY_LONG)
6815                        local->config.longRetryLimit = vwrq->value;
6816                else if (vwrq->flags & IW_RETRY_SHORT)
6817                        local->config.shortRetryLimit = vwrq->value;
6818                else {
6819                        /* No modifier : set both */
6820                        local->config.longRetryLimit = vwrq->value;
6821                        local->config.shortRetryLimit = vwrq->value;
6822                }
6823                set_bit (FLAG_COMMIT, &local->flags);
6824                rc = -EINPROGRESS;              /* Call commit handler */
6825        }
6826        if(vwrq->flags & IW_RETRY_LIFETIME) {
6827                local->config.txLifetime = vwrq->value / 1024;
6828                set_bit (FLAG_COMMIT, &local->flags);
6829                rc = -EINPROGRESS;              /* Call commit handler */
6830        }
6831        return rc;
6832}
6833
6834/*------------------------------------------------------------------*/
6835/*
6836 * Wireless Handler : get Retry limits
6837 */
6838static int airo_get_retry(struct net_device *dev,
6839                          struct iw_request_info *info,
6840                          struct iw_param *vwrq,
6841                          char *extra)
6842{
6843        struct airo_info *local = dev->priv;
6844
6845        vwrq->disabled = 0;      /* Can't be disabled */
6846
6847        readConfigRid(local, 1);
6848        /* Note : by default, display the min retry number */
6849        if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
6850                vwrq->flags = IW_RETRY_LIFETIME;
6851                vwrq->value = (int)local->config.txLifetime * 1024;
6852        } else if((vwrq->flags & IW_RETRY_LONG)) {
6853                vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
6854                vwrq->value = (int)local->config.longRetryLimit;
6855        } else {
6856                vwrq->flags = IW_RETRY_LIMIT;
6857                vwrq->value = (int)local->config.shortRetryLimit;
6858                if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
6859                        vwrq->flags |= IW_RETRY_SHORT;
6860        }
6861
6862        return 0;
6863}
6864
6865/*------------------------------------------------------------------*/
6866/*
6867 * Wireless Handler : get range info
6868 */
6869static int airo_get_range(struct net_device *dev,
6870                          struct iw_request_info *info,
6871                          struct iw_point *dwrq,
6872                          char *extra)
6873{
6874        struct airo_info *local = dev->priv;
6875        struct iw_range *range = (struct iw_range *) extra;
6876        CapabilityRid cap_rid;          /* Card capability info */
6877        int             i;
6878        int             k;
6879
6880        readCapabilityRid(local, &cap_rid, 1);
6881
6882        dwrq->length = sizeof(struct iw_range);
6883        memset(range, 0, sizeof(*range));
6884        range->min_nwid = 0x0000;
6885        range->max_nwid = 0x0000;
6886        range->num_channels = 14;
6887        /* Should be based on cap_rid.country to give only
6888         * what the current card support */
6889        k = 0;
6890        for(i = 0; i < 14; i++) {
6891                range->freq[k].i = i + 1; /* List index */
6892                range->freq[k].m = frequency_list[i] * 100000;
6893                range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
6894        }
6895        range->num_frequency = k;
6896
6897        range->sensitivity = 65535;
6898
6899        /* Hum... Should put the right values there */
6900        if (local->rssi)
6901                range->max_qual.qual = 100;     /* % */
6902        else
6903                range->max_qual.qual = airo_get_max_quality(&cap_rid);
6904        range->max_qual.level = 0x100 - 120;    /* -120 dBm */
6905        range->max_qual.noise = 0x100 - 120;    /* -120 dBm */
6906
6907        /* Experimental measurements - boundary 11/5.5 Mb/s */
6908        /* Note : with or without the (local->rssi), results
6909         * are somewhat different. - Jean II */
6910        if (local->rssi) {
6911                range->avg_qual.qual = 50;              /* % */
6912                range->avg_qual.level = 0x100 - 70;     /* -70 dBm */
6913        } else {
6914                range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
6915                range->avg_qual.level = 0x100 - 80;     /* -80 dBm */
6916        }
6917        range->avg_qual.noise = 0x100 - 85;             /* -85 dBm */
6918
6919        for(i = 0 ; i < 8 ; i++) {
6920                range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
6921                if(range->bitrate[i] == 0)
6922                        break;
6923        }
6924        range->num_bitrates = i;
6925
6926        /* Set an indication of the max TCP throughput
6927         * in bit/s that we can expect using this interface.
6928         * May be use for QoS stuff... Jean II */
6929        if(i > 2)
6930                range->throughput = 5000 * 1000;
6931        else
6932                range->throughput = 1500 * 1000;
6933
6934        range->min_rts = 0;
6935        range->max_rts = AIRO_DEF_MTU;
6936        range->min_frag = 256;
6937        range->max_frag = AIRO_DEF_MTU;
6938
6939        if(cap_rid.softCap & 2) {
6940                // WEP: RC4 40 bits
6941                range->encoding_size[0] = 5;
6942                // RC4 ~128 bits
6943                if (cap_rid.softCap & 0x100) {
6944                        range->encoding_size[1] = 13;
6945                        range->num_encoding_sizes = 2;
6946                } else
6947                        range->num_encoding_sizes = 1;
6948                range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
6949        } else {
6950                range->num_encoding_sizes = 0;
6951                range->max_encoding_tokens = 0;
6952        }
6953        range->min_pmp = 0;
6954        range->max_pmp = 5000000;       /* 5 secs */
6955        range->min_pmt = 0;
6956        range->max_pmt = 65535 * 1024;  /* ??? */
6957        range->pmp_flags = IW_POWER_PERIOD;
6958        range->pmt_flags = IW_POWER_TIMEOUT;
6959        range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
6960
6961        /* Transmit Power - values are in mW */
6962        for(i = 0 ; i < 8 ; i++) {
6963                range->txpower[i] = cap_rid.txPowerLevels[i];
6964                if(range->txpower[i] == 0)
6965                        break;
6966        }
6967        range->num_txpower = i;
6968        range->txpower_capa = IW_TXPOW_MWATT;
6969        range->we_version_source = 19;
6970        range->we_version_compiled = WIRELESS_EXT;
6971        range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
6972        range->retry_flags = IW_RETRY_LIMIT;
6973        range->r_time_flags = IW_RETRY_LIFETIME;
6974        range->min_retry = 1;
6975        range->max_retry = 65535;
6976        range->min_r_time = 1024;
6977        range->max_r_time = 65535 * 1024;
6978
6979        /* Event capability (kernel + driver) */
6980        range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
6981                                IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
6982                                IW_EVENT_CAPA_MASK(SIOCGIWAP) |
6983                                IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
6984        range->event_capa[1] = IW_EVENT_CAPA_K_1;
6985        range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVTXDROP);
6986        return 0;
6987}
6988
6989/*------------------------------------------------------------------*/
6990/*
6991 * Wireless Handler : set Power Management
6992 */
6993static int airo_set_power(struct net_device *dev,
6994                          struct iw_request_info *info,
6995                          struct iw_param *vwrq,
6996                          char *extra)
6997{
6998        struct airo_info *local = dev->priv;
6999
7000        readConfigRid(local, 1);
7001        if (vwrq->disabled) {
7002                if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
7003                        return -EINVAL;
7004                }
7005                local->config.powerSaveMode = POWERSAVE_CAM;
7006                local->config.rmode &= 0xFF00;
7007                local->config.rmode |= RXMODE_BC_MC_ADDR;
7008                set_bit (FLAG_COMMIT, &local->flags);
7009                return -EINPROGRESS;            /* Call commit handler */
7010        }
7011        if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
7012                local->config.fastListenDelay = (vwrq->value + 500) / 1024;
7013                local->config.powerSaveMode = POWERSAVE_PSPCAM;
7014                set_bit (FLAG_COMMIT, &local->flags);
7015        } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
7016                local->config.fastListenInterval = local->config.listenInterval = (vwrq->value + 500) / 1024;
7017                local->config.powerSaveMode = POWERSAVE_PSPCAM;
7018                set_bit (FLAG_COMMIT, &local->flags);
7019        }
7020        switch (vwrq->flags & IW_POWER_MODE) {
7021                case IW_POWER_UNICAST_R:
7022                        if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
7023                                return -EINVAL;
7024                        }
7025                        local->config.rmode &= 0xFF00;
7026                        local->config.rmode |= RXMODE_ADDR;
7027                        set_bit (FLAG_COMMIT, &local->flags);
7028                        break;
7029                case IW_POWER_ALL_R:
7030                        if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
7031                                return -EINVAL;
7032                        }
7033                        local->config.rmode &= 0xFF00;
7034                        local->config.rmode |= RXMODE_BC_MC_ADDR;
7035                        set_bit (FLAG_COMMIT, &local->flags);
7036                case IW_POWER_ON:
7037                        /* This is broken, fixme ;-) */
7038                        break;
7039                default:
7040                        return -EINVAL;
7041        }
7042        // Note : we may want to factor local->need_commit here
7043        // Note2 : may also want to factor RXMODE_RFMON test
7044        return -EINPROGRESS;            /* Call commit handler */
7045}
7046
7047/*------------------------------------------------------------------*/
7048/*
7049 * Wireless Handler : get Power Management
7050 */
7051static int airo_get_power(struct net_device *dev,
7052                          struct iw_request_info *info,
7053                          struct iw_param *vwrq,
7054                          char *extra)
7055{
7056        struct airo_info *local = dev->priv;
7057        int mode;
7058
7059        readConfigRid(local, 1);
7060        mode = local->config.powerSaveMode;
7061        if ((vwrq->disabled = (mode == POWERSAVE_CAM)))
7062                return 0;
7063        if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
7064                vwrq->value = (int)local->config.fastListenDelay * 1024;
7065                vwrq->flags = IW_POWER_TIMEOUT;
7066        } else {
7067                vwrq->value = (int)local->config.fastListenInterval * 1024;
7068                vwrq->flags = IW_POWER_PERIOD;
7069        }
7070        if ((local->config.rmode & 0xFF) == RXMODE_ADDR)
7071                vwrq->flags |= IW_POWER_UNICAST_R;
7072        else
7073                vwrq->flags |= IW_POWER_ALL_R;
7074
7075        return 0;
7076}
7077
7078/*------------------------------------------------------------------*/
7079/*
7080 * Wireless Handler : set Sensitivity
7081 */
7082static int airo_set_sens(struct net_device *dev,
7083                         struct iw_request_info *info,
7084                         struct iw_param *vwrq,
7085                         char *extra)
7086{
7087        struct airo_info *local = dev->priv;
7088
7089        readConfigRid(local, 1);
7090        local->config.rssiThreshold = vwrq->disabled ? RSSI_DEFAULT : vwrq->value;
7091        set_bit (FLAG_COMMIT, &local->flags);
7092
7093        return -EINPROGRESS;            /* Call commit handler */
7094}
7095
7096/*------------------------------------------------------------------*/
7097/*
7098 * Wireless Handler : get Sensitivity
7099 */
7100static int airo_get_sens(struct net_device *dev,
7101                         struct iw_request_info *info,
7102                         struct iw_param *vwrq,
7103                         char *extra)
7104{
7105        struct airo_info *local = dev->priv;
7106
7107        readConfigRid(local, 1);
7108        vwrq->value = local->config.rssiThreshold;
7109        vwrq->disabled = (vwrq->value == 0);
7110        vwrq->fixed = 1;
7111
7112        return 0;
7113}
7114
7115/*------------------------------------------------------------------*/
7116/*
7117 * Wireless Handler : get AP List
7118 * Note : this is deprecated in favor of IWSCAN
7119 */
7120static int airo_get_aplist(struct net_device *dev,
7121                           struct iw_request_info *info,
7122                           struct iw_point *dwrq,
7123                           char *extra)
7124{
7125        struct airo_info *local = dev->priv;
7126        struct sockaddr *address = (struct sockaddr *) extra;
7127        struct iw_quality qual[IW_MAX_AP];
7128        BSSListRid BSSList;
7129        int i;
7130        int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
7131
7132        for (i = 0; i < IW_MAX_AP; i++) {
7133                if (readBSSListRid(local, loseSync, &BSSList))
7134                        break;
7135                loseSync = 0;
7136                memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
7137                address[i].sa_family = ARPHRD_ETHER;
7138                if (local->rssi) {
7139                        qual[i].level = 0x100 - BSSList.dBm;
7140                        qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
7141                        qual[i].updated = IW_QUAL_QUAL_UPDATED
7142                                        | IW_QUAL_LEVEL_UPDATED
7143                                        | IW_QUAL_DBM;
7144                } else {
7145                        qual[i].level = (BSSList.dBm + 321) / 2;
7146                        qual[i].qual = 0;
7147                        qual[i].updated = IW_QUAL_QUAL_INVALID
7148                                        | IW_QUAL_LEVEL_UPDATED
7149                                        | IW_QUAL_DBM;
7150                }
7151                qual[i].noise = local->wstats.qual.noise;
7152                if (BSSList.index == 0xffff)
7153                        break;
7154        }
7155        if (!i) {
7156                StatusRid status_rid;           /* Card status info */
7157                readStatusRid(local, &status_rid, 1);
7158                for (i = 0;
7159                     i < min(IW_MAX_AP, 4) &&
7160                             (status_rid.bssid[i][0]
7161                              & status_rid.bssid[i][1]
7162                              & status_rid.bssid[i][2]
7163                              & status_rid.bssid[i][3]
7164                              & status_rid.bssid[i][4]
7165                              & status_rid.bssid[i][5])!=0xff &&
7166                             (status_rid.bssid[i][0]
7167                              | status_rid.bssid[i][1]
7168                              | status_rid.bssid[i][2]
7169                              | status_rid.bssid[i][3]
7170                              | status_rid.bssid[i][4]
7171                              | status_rid.bssid[i][5]);
7172                     i++) {
7173                        memcpy(address[i].sa_data,
7174                               status_rid.bssid[i], ETH_ALEN);
7175                        address[i].sa_family = ARPHRD_ETHER;
7176                }
7177        } else {
7178                dwrq->flags = 1; /* Should be define'd */
7179                memcpy(extra + sizeof(struct sockaddr)*i,
7180                       &qual,  sizeof(struct iw_quality)*i);
7181        }
7182        dwrq->length = i;
7183
7184        return 0;
7185}
7186
7187/*------------------------------------------------------------------*/
7188/*
7189 * Wireless Handler : Initiate Scan
7190 */
7191static int airo_set_scan(struct net_device *dev,
7192                         struct iw_request_info *info,
7193                         struct iw_param *vwrq,
7194                         char *extra)
7195{
7196        struct airo_info *ai = dev->priv;
7197        Cmd cmd;
7198        Resp rsp;
7199        int wake = 0;
7200
7201        /* Note : you may have realised that, as this is a SET operation,
7202         * this is privileged and therefore a normal user can't
7203         * perform scanning.
7204         * This is not an error, while the device perform scanning,
7205         * traffic doesn't flow, so it's a perfect DoS...
7206         * Jean II */
7207        if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
7208
7209        if (down_interruptible(&ai->sem))
7210                return -ERESTARTSYS;
7211
7212        /* If there's already a scan in progress, don't
7213         * trigger another one. */
7214        if (ai->scan_timeout > 0)
7215                goto out;
7216
7217        /* Initiate a scan command */
7218        ai->scan_timeout = RUN_AT(3*HZ);
7219        memset(&cmd, 0, sizeof(cmd));
7220        cmd.cmd=CMD_LISTBSS;
7221        issuecommand(ai, &cmd, &rsp);
7222        wake = 1;
7223
7224out:
7225        up(&ai->sem);
7226        if (wake)
7227                wake_up_interruptible(&ai->thr_wait);
7228        return 0;
7229}
7230
7231/*------------------------------------------------------------------*/
7232/*
7233 * Translate scan data returned from the card to a card independent
7234 * format that the Wireless Tools will understand - Jean II
7235 */
7236static inline char *airo_translate_scan(struct net_device *dev,
7237                                        char *current_ev,
7238                                        char *end_buf,
7239                                        BSSListRid *bss)
7240{
7241        struct airo_info *ai = dev->priv;
7242        struct iw_event         iwe;            /* Temporary buffer */
7243        u16                     capabilities;
7244        char *                  current_val;    /* For rates */
7245        int                     i;
7246        char *          buf;
7247
7248        /* First entry *MUST* be the AP MAC address */
7249        iwe.cmd = SIOCGIWAP;
7250        iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
7251        memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
7252        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
7253
7254        /* Other entries will be displayed in the order we give them */
7255
7256        /* Add the ESSID */
7257        iwe.u.data.length = bss->ssidLen;
7258        if(iwe.u.data.length > 32)
7259                iwe.u.data.length = 32;
7260        iwe.cmd = SIOCGIWESSID;
7261        iwe.u.data.flags = 1;
7262        current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
7263
7264        /* Add mode */
7265        iwe.cmd = SIOCGIWMODE;
7266        capabilities = le16_to_cpu(bss->cap);
7267        if(capabilities & (CAP_ESS | CAP_IBSS)) {
7268                if(capabilities & CAP_ESS)
7269                        iwe.u.mode = IW_MODE_MASTER;
7270                else
7271                        iwe.u.mode = IW_MODE_ADHOC;
7272                current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
7273        }
7274
7275        /* Add frequency */
7276        iwe.cmd = SIOCGIWFREQ;
7277        iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
7278        /* iwe.u.freq.m containt the channel (starting 1), our 
7279         * frequency_list array start at index 0...
7280         */
7281        iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
7282        iwe.u.freq.e = 1;
7283        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
7284
7285        /* Add quality statistics */
7286        iwe.cmd = IWEVQUAL;
7287        if (ai->rssi) {
7288                iwe.u.qual.level = 0x100 - bss->dBm;
7289                iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
7290                iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
7291                                | IW_QUAL_LEVEL_UPDATED
7292                                | IW_QUAL_DBM;
7293        } else {
7294                iwe.u.qual.level = (bss->dBm + 321) / 2;
7295                iwe.u.qual.qual = 0;
7296                iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
7297                                | IW_QUAL_LEVEL_UPDATED
7298                                | IW_QUAL_DBM;
7299        }
7300        iwe.u.qual.noise = ai->wstats.qual.noise;
7301        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
7302
7303        /* Add encryption capability */
7304        iwe.cmd = SIOCGIWENCODE;
7305        if(capabilities & CAP_PRIVACY)
7306                iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
7307        else
7308                iwe.u.data.flags = IW_ENCODE_DISABLED;
7309        iwe.u.data.length = 0;
7310        current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
7311
7312        /* Rate : stuffing multiple values in a single event require a bit
7313         * more of magic - Jean II */
7314        current_val = current_ev + IW_EV_LCP_LEN;
7315
7316        iwe.cmd = SIOCGIWRATE;
7317        /* Those two flags are ignored... */
7318        iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
7319        /* Max 8 values */
7320        for(i = 0 ; i < 8 ; i++) {
7321                /* NULL terminated */
7322                if(bss->rates[i] == 0)
7323                        break;
7324                /* Bit rate given in 500 kb/s units (+ 0x80) */
7325                iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
7326                /* Add new value to event */
7327                current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
7328        }
7329        /* Check if we added any event */
7330        if((current_val - current_ev) > IW_EV_LCP_LEN)
7331                current_ev = current_val;
7332
7333        /* Beacon interval */
7334        buf = kmalloc(30, GFP_KERNEL);
7335        if (buf) {
7336                iwe.cmd = IWEVCUSTOM;
7337                sprintf(buf, "bcn_int=%d", bss->beaconInterval);
7338                iwe.u.data.length = strlen(buf);
7339                current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);
7340                kfree(buf);
7341        }
7342
7343        /* Put WPA/RSN Information Elements into the event stream */
7344        if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
7345                unsigned int num_null_ies = 0;
7346                u16 length = sizeof (bss->extra.iep);
7347                struct ieee80211_info_element *info_element =
7348                        (struct ieee80211_info_element *) &bss->extra.iep;
7349
7350                while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
7351                        if (sizeof(*info_element) + info_element->len > length) {
7352                                /* Invalid element, don't continue parsing IE */
7353                                break;
7354                        }
7355
7356                        switch (info_element->id) {
7357                        case MFIE_TYPE_SSID:
7358                                /* Two zero-length SSID elements
7359                                 * mean we're done parsing elements */
7360                                if (!info_element->len)
7361                                        num_null_ies++;
7362                                break;
7363
7364                        case MFIE_TYPE_GENERIC:
7365                                if (info_element->len >= 4 &&
7366                                    info_element->data[0] == 0x00 &&
7367                                    info_element->data[1] == 0x50 &&
7368                                    info_element->data[2] == 0xf2 &&
7369                                    info_element->data[3] == 0x01) {
7370                                        iwe.cmd = IWEVGENIE;
7371                                        iwe.u.data.length = min(info_element->len + 2,
7372                                                                  MAX_WPA_IE_LEN);
7373                                        current_ev = iwe_stream_add_point(current_ev, end_buf,
7374                                                        &iwe, (char *) info_element);
7375                                }
7376                                break;
7377
7378                        case MFIE_TYPE_RSN:
7379                                iwe.cmd = IWEVGENIE;
7380                                iwe.u.data.length = min(info_element->len + 2,
7381                                                          MAX_WPA_IE_LEN);
7382                                current_ev = iwe_stream_add_point(current_ev, end_buf,
7383                                                &iwe, (char *) info_element);
7384                                break;
7385
7386                        default:
7387                                break;
7388                        }
7389
7390                        length -= sizeof(*info_element) + info_element->len;
7391                        info_element =
7392                            (struct ieee80211_info_element *)&info_element->
7393                            data[info_element->len];
7394                }
7395        }
7396        return current_ev;
7397}
7398
7399/*------------------------------------------------------------------*/
7400/*
7401 * Wireless Handler : Read Scan Results
7402 */
7403static int airo_get_scan(struct net_device *dev,
7404                         struct iw_request_info *info,
7405                         struct iw_point *dwrq,
7406                         char *extra)
7407{
7408        struct airo_info *ai = dev->priv;
7409        BSSListElement *net;
7410        int err = 0;
7411        char *current_ev = extra;
7412
7413        /* If a scan is in-progress, return -EAGAIN */
7414        if (ai->scan_timeout > 0)
7415                return -EAGAIN;
7416
7417        if (down_interruptible(&ai->sem))
7418                return -EAGAIN;
7419
7420        list_for_each_entry (net, &ai->network_list, list) {
7421                /* Translate to WE format this entry */
7422                current_ev = airo_translate_scan(dev, current_ev,
7423                                                 extra + dwrq->length,
7424                                                 &net->bss);
7425
7426                /* Check if there is space for one more entry */
7427                if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
7428                        /* Ask user space to try again with a bigger buffer */
7429                        err = -E2BIG;
7430                        goto out;
7431                }
7432        }
7433
7434        /* Length of data */
7435        dwrq->length = (current_ev - extra);
7436        dwrq->flags = 0;        /* todo */
7437
7438out:
7439        up(&ai->sem);
7440        return err;
7441}
7442
7443/*------------------------------------------------------------------*/
7444/*
7445 * Commit handler : called after a bunch of SET operations
7446 */
7447static int airo_config_commit(struct net_device *dev,
7448                              struct iw_request_info *info,     /* NULL */
7449                              void *zwrq,                       /* NULL */
7450                              char *extra)                      /* NULL */
7451{
7452        struct airo_info *local = dev->priv;
7453
7454        if (!test_bit (FLAG_COMMIT, &local->flags))
7455                return 0;
7456
7457        /* Some of the "SET" function may have modified some of the
7458         * parameters. It's now time to commit them in the card */
7459        disable_MAC(local, 1);
7460        if (test_bit (FLAG_RESET, &local->flags)) {
7461                APListRid APList_rid;
7462                SsidRid SSID_rid;
7463
7464                readAPListRid(local, &APList_rid);
7465                readSsidRid(local, &SSID_rid);
7466                if (test_bit(FLAG_MPI,&local->flags))
7467                        setup_card(local, dev->dev_addr, 1 );
7468                else
7469                        reset_airo_card(dev);
7470                disable_MAC(local, 1);
7471                writeSsidRid(local, &SSID_rid, 1);
7472                writeAPListRid(local, &APList_rid, 1);
7473        }
7474        if (down_interruptible(&local->sem))
7475                return -ERESTARTSYS;
7476        writeConfigRid(local, 0);
7477        enable_MAC(local, 0);
7478        if (test_bit (FLAG_RESET, &local->flags))
7479                airo_set_promisc(local);
7480        else
7481                up(&local->sem);
7482
7483        return 0;
7484}
7485
7486/*------------------------------------------------------------------*/
7487/*
7488 * Structures to export the Wireless Handlers
7489 */
7490
7491static const struct iw_priv_args airo_private_args[] = {
7492/*{ cmd,         set_args,                            get_args, name } */
7493  { AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl),
7494    IW_PRIV_TYPE_BYTE | 2047, "airoioctl" },
7495  { AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl),
7496    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" },
7497};
7498
7499static const iw_handler         airo_handler[] =
7500{
7501        (iw_handler) airo_config_commit,        /* SIOCSIWCOMMIT */
7502        (iw_handler) airo_get_name,             /* SIOCGIWNAME */
7503        (iw_handler) NULL,                      /* SIOCSIWNWID */
7504        (iw_handler) NULL,                      /* SIOCGIWNWID */
7505        (iw_handler) airo_set_freq,             /* SIOCSIWFREQ */
7506        (iw_handler) airo_get_freq,             /* SIOCGIWFREQ */
7507        (iw_handler) airo_set_mode,             /* SIOCSIWMODE */
7508        (iw_handler) airo_get_mode,             /* SIOCGIWMODE */
7509        (iw_handler) airo_set_sens,             /* SIOCSIWSENS */
7510        (iw_handler) airo_get_sens,             /* SIOCGIWSENS */
7511        (iw_handler) NULL,                      /* SIOCSIWRANGE */
7512        (iw_handler) airo_get_range,            /* SIOCGIWRANGE */
7513        (iw_handler) NULL,                      /* SIOCSIWPRIV */
7514        (iw_handler) NULL,                      /* SIOCGIWPRIV */
7515        (iw_handler) NULL,                      /* SIOCSIWSTATS */
7516        (iw_handler) NULL,                      /* SIOCGIWSTATS */
7517        iw_handler_set_spy,                     /* SIOCSIWSPY */
7518        iw_handler_get_spy,                     /* SIOCGIWSPY */
7519        iw_handler_set_thrspy,                  /* SIOCSIWTHRSPY */
7520        iw_handler_get_thrspy,                  /* SIOCGIWTHRSPY */
7521        (iw_handler) airo_set_wap,              /* SIOCSIWAP */
7522        (iw_handler) airo_get_wap,              /* SIOCGIWAP */
7523        (iw_handler) NULL,                      /* -- hole -- */
7524        (iw_handler) airo_get_aplist,           /* SIOCGIWAPLIST */
7525        (iw_handler) airo_set_scan,             /* SIOCSIWSCAN */
7526        (iw_handler) airo_get_scan,             /* SIOCGIWSCAN */
7527        (iw_handler) airo_set_essid,            /* SIOCSIWESSID */
7528        (iw_handler) airo_get_essid,            /* SIOCGIWESSID */
7529        (iw_handler) airo_set_nick,             /* SIOCSIWNICKN */
7530        (iw_handler) airo_get_nick,             /* SIOCGIWNICKN */
7531        (iw_handler) NULL,                      /* -- hole -- */
7532        (iw_handler) NULL,                      /* -- hole -- */
7533        (iw_handler) airo_set_rate,             /* SIOCSIWRATE */
7534        (iw_handler) airo_get_rate,             /* SIOCGIWRATE */
7535        (iw_handler) airo_set_rts,              /* SIOCSIWRTS */
7536        (iw_handler) airo_get_rts,              /* SIOCGIWRTS */
7537        (iw_handler) airo_set_frag,             /* SIOCSIWFRAG */
7538        (iw_handler) airo_get_frag,             /* SIOCGIWFRAG */
7539        (iw_handler) airo_set_txpow,            /* SIOCSIWTXPOW */
7540        (iw_handler) airo_get_txpow,            /* SIOCGIWTXPOW */
7541        (iw_handler) airo_set_retry,            /* SIOCSIWRETRY */
7542        (iw_handler) airo_get_retry,            /* SIOCGIWRETRY */
7543        (iw_handler) airo_set_encode,           /* SIOCSIWENCODE */
7544        (iw_handler) airo_get_encode,           /* SIOCGIWENCODE */
7545        (iw_handler) airo_set_power,            /* SIOCSIWPOWER */
7546        (iw_handler) airo_get_power,            /* SIOCGIWPOWER */
7547        (iw_handler) NULL,                      /* -- hole -- */
7548        (iw_handler) NULL,                      /* -- hole -- */
7549        (iw_handler) NULL,                      /* SIOCSIWGENIE */
7550        (iw_handler) NULL,                      /* SIOCGIWGENIE */
7551        (iw_handler) airo_set_auth,             /* SIOCSIWAUTH */
7552        (iw_handler) airo_get_auth,             /* SIOCGIWAUTH */
7553        (iw_handler) airo_set_encodeext,        /* SIOCSIWENCODEEXT */
7554        (iw_handler) airo_get_encodeext,        /* SIOCGIWENCODEEXT */
7555        (iw_handler) NULL,                      /* SIOCSIWPMKSA */
7556};
7557
7558/* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
7559 * We want to force the use of the ioctl code, because those can't be
7560 * won't work the iw_handler code (because they simultaneously read
7561 * and write data and iw_handler can't do that).
7562 * Note that it's perfectly legal to read/write on a single ioctl command,
7563 * you just can't use iwpriv and need to force it via the ioctl handler.
7564 * Jean II */
7565static const iw_handler         airo_private_handler[] =
7566{
7567        NULL,                           /* SIOCIWFIRSTPRIV */
7568};
7569
7570static const struct iw_handler_def      airo_handler_def =
7571{
7572        .num_standard   = ARRAY_SIZE(airo_handler),
7573        .num_private    = ARRAY_SIZE(airo_private_handler),
7574        .num_private_args = ARRAY_SIZE(airo_private_args),
7575        .standard       = airo_handler,
7576        .private        = airo_private_handler,
7577        .private_args   = airo_private_args,
7578        .get_wireless_stats = airo_get_wireless_stats,
7579};
7580
7581/*
7582 * This defines the configuration part of the Wireless Extensions
7583 * Note : irq and spinlock protection will occur in the subroutines
7584 *
7585 * TODO :
7586 *      o Check input value more carefully and fill correct values in range
7587 *      o Test and shakeout the bugs (if any)
7588 *
7589 * Jean II
7590 *
7591 * Javier Achirica did a great job of merging code from the unnamed CISCO
7592 * developer that added support for flashing the card.
7593 */
7594static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
7595{
7596        int rc = 0;
7597        struct airo_info *ai = (struct airo_info *)dev->priv;
7598
7599        if (ai->power.event)
7600                return 0;
7601
7602        switch (cmd) {
7603#ifdef CISCO_EXT
7604        case AIROIDIFC:
7605#ifdef AIROOLDIDIFC
7606        case AIROOLDIDIFC:
7607#endif
7608        {
7609                int val = AIROMAGIC;
7610                aironet_ioctl com;
7611                if (copy_from_user(&com,rq->ifr_data,sizeof(com)))
7612                        rc = -EFAULT;
7613                else if (copy_to_user(com.data,(char *)&val,sizeof(val)))
7614                        rc = -EFAULT;
7615        }
7616        break;
7617
7618        case AIROIOCTL:
7619#ifdef AIROOLDIOCTL
7620        case AIROOLDIOCTL:
7621#endif
7622                /* Get the command struct and hand it off for evaluation by
7623                 * the proper subfunction
7624                 */
7625        {
7626                aironet_ioctl com;
7627                if (copy_from_user(&com,rq->ifr_data,sizeof(com))) {
7628                        rc = -EFAULT;
7629                        break;
7630                }
7631
7632                /* Separate R/W functions bracket legality here
7633                 */
7634                if ( com.command == AIRORSWVERSION ) {
7635                        if (copy_to_user(com.data, swversion, sizeof(swversion)))
7636                                rc = -EFAULT;
7637                        else
7638                                rc = 0;
7639                }
7640                else if ( com.command <= AIRORRID)
7641                        rc = readrids(dev,&com);
7642                else if ( com.command >= AIROPCAP && com.command <= (AIROPLEAPUSR+2) )
7643                        rc = writerids(dev,&com);
7644                else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART )
7645                        rc = flashcard(dev,&com);
7646                else
7647                        rc = -EINVAL;      /* Bad command in ioctl */
7648        }
7649        break;
7650#endif /* CISCO_EXT */
7651
7652        // All other calls are currently unsupported
7653        default:
7654                rc = -EOPNOTSUPP;
7655        }
7656        return rc;
7657}
7658
7659/*
7660 * Get the Wireless stats out of the driver
7661 * Note : irq and spinlock protection will occur in the subroutines
7662 *
7663 * TODO :
7664 *      o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs)
7665 *
7666 * Jean
7667 */
7668static void airo_read_wireless_stats(struct airo_info *local)
7669{
7670        StatusRid status_rid;
7671        StatsRid stats_rid;
7672        CapabilityRid cap_rid;
7673        u32 *vals = stats_rid.vals;
7674
7675        /* Get stats out of the card */
7676        clear_bit(JOB_WSTATS, &local->jobs);
7677        if (local->power.event) {
7678                up(&local->sem);
7679                return;
7680        }
7681        readCapabilityRid(local, &cap_rid, 0);
7682        readStatusRid(local, &status_rid, 0);
7683        readStatsRid(local, &stats_rid, RID_STATS, 0);
7684        up(&local->sem);
7685
7686        /* The status */
7687        local->wstats.status = status_rid.mode;
7688
7689        /* Signal quality and co */
7690        if (local->rssi) {
7691                local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality );
7692                /* normalizedSignalStrength appears to be a percentage */
7693                local->wstats.qual.qual = status_rid.normalizedSignalStrength;
7694        } else {
7695                local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
7696                local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
7697        }
7698        if (status_rid.len >= 124) {
7699                local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
7700                local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
7701        } else {
7702                local->wstats.qual.noise = 0;
7703                local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM;
7704        }
7705
7706        /* Packets discarded in the wireless adapter due to wireless
7707         * specific problems */
7708        local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */
7709        local->wstats.discard.code = vals[6];/* RxWepErr */
7710        local->wstats.discard.fragment = vals[30];
7711        local->wstats.discard.retries = vals[10];
7712        local->wstats.discard.misc = vals[1] + vals[32];
7713        local->wstats.miss.beacon = vals[34];
7714}
7715
7716static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
7717{
7718        struct airo_info *local =  dev->priv;
7719
7720        if (!test_bit(JOB_WSTATS, &local->jobs)) {
7721                /* Get stats out of the card if available */
7722                if (down_trylock(&local->sem) != 0) {
7723                        set_bit(JOB_WSTATS, &local->jobs);
7724                        wake_up_interruptible(&local->thr_wait);
7725                } else
7726                        airo_read_wireless_stats(local);
7727        }
7728
7729        return &local->wstats;
7730}
7731
7732#ifdef CISCO_EXT
7733/*
7734 * This just translates from driver IOCTL codes to the command codes to
7735 * feed to the radio's host interface. Things can be added/deleted
7736 * as needed.  This represents the READ side of control I/O to
7737 * the card
7738 */
7739static int readrids(struct net_device *dev, aironet_ioctl *comp) {
7740        unsigned short ridcode;
7741        unsigned char *iobuf;
7742        int len;
7743        struct airo_info *ai = dev->priv;
7744
7745        if (test_bit(FLAG_FLASHING, &ai->flags))
7746                return -EIO;
7747
7748        switch(comp->command)
7749        {
7750        case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
7751        case AIROGCFG:      ridcode = RID_CONFIG;
7752                if (test_bit(FLAG_COMMIT, &ai->flags)) {
7753                        disable_MAC (ai, 1);
7754                        writeConfigRid (ai, 1);
7755                        enable_MAC(ai, 1);
7756                }
7757                break;
7758        case AIROGSLIST:    ridcode = RID_SSID;         break;
7759        case AIROGVLIST:    ridcode = RID_APLIST;       break;
7760        case AIROGDRVNAM:   ridcode = RID_DRVNAME;      break;
7761        case AIROGEHTENC:   ridcode = RID_ETHERENCAP;   break;
7762        case AIROGWEPKTMP:  ridcode = RID_WEP_TEMP;
7763                /* Only super-user can read WEP keys */
7764                if (!capable(CAP_NET_ADMIN))
7765                        return -EPERM;
7766                break;
7767        case AIROGWEPKNV:   ridcode = RID_WEP_PERM;
7768                /* Only super-user can read WEP keys */
7769                if (!capable(CAP_NET_ADMIN))
7770                        return -EPERM;
7771                break;
7772        case AIROGSTAT:     ridcode = RID_STATUS;       break;
7773        case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
7774        case AIROGSTATSC32: ridcode = RID_STATS;        break;
7775        case AIROGMICSTATS:
7776                if (copy_to_user(comp->data, &ai->micstats,
7777                                 min((int)comp->len,(int)sizeof(ai->micstats))))
7778                        return -EFAULT;
7779                return 0;
7780        case AIRORRID:      ridcode = comp->ridnum;     break;
7781        default:
7782                return -EINVAL;
7783                break;
7784        }
7785
7786        if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
7787                return -ENOMEM;
7788
7789        PC4500_readrid(ai,ridcode,iobuf,RIDSIZE, 1);
7790        /* get the count of bytes in the rid  docs say 1st 2 bytes is it.
7791         * then return it to the user
7792         * 9/22/2000 Honor user given length
7793         */
7794        len = comp->len;
7795
7796        if (copy_to_user(comp->data, iobuf, min(len, (int)RIDSIZE))) {
7797                kfree (iobuf);
7798                return -EFAULT;
7799        }
7800        kfree (iobuf);
7801        return 0;
7802}
7803
7804/*
7805 * Danger Will Robinson write the rids here
7806 */
7807
7808static int writerids(struct net_device *dev, aironet_ioctl *comp) {
7809        struct airo_info *ai = dev->priv;
7810        int  ridcode;
7811        int  enabled;
7812        static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
7813        unsigned char *iobuf;
7814
7815        /* Only super-user can write RIDs */
7816        if (!capable(CAP_NET_ADMIN))
7817                return -EPERM;
7818
7819        if (test_bit(FLAG_FLASHING, &ai->flags))
7820                return -EIO;
7821
7822        ridcode = 0;
7823        writer = do_writerid;
7824
7825        switch(comp->command)
7826        {
7827        case AIROPSIDS:     ridcode = RID_SSID;         break;
7828        case AIROPCAP:      ridcode = RID_CAPABILITIES; break;
7829        case AIROPAPLIST:   ridcode = RID_APLIST;       break;
7830        case AIROPCFG: ai->config.len = 0;
7831                            clear_bit(FLAG_COMMIT, &ai->flags);
7832                            ridcode = RID_CONFIG;       break;
7833        case AIROPWEPKEYNV: ridcode = RID_WEP_PERM;     break;
7834        case AIROPLEAPUSR:  ridcode = RID_LEAPUSERNAME; break;
7835        case AIROPLEAPPWD:  ridcode = RID_LEAPPASSWORD; break;
7836        case AIROPWEPKEY:   ridcode = RID_WEP_TEMP; writer = PC4500_writerid;
7837                break;
7838        case AIROPLEAPUSR+1: ridcode = 0xFF2A;          break;
7839        case AIROPLEAPUSR+2: ridcode = 0xFF2B;          break;
7840
7841                /* this is not really a rid but a command given to the card
7842                 * same with MAC off
7843                 */
7844        case AIROPMACON:
7845                if (enable_MAC(ai, 1) != 0)
7846                        return -EIO;
7847                return 0;
7848
7849                /*
7850                 * Evidently this code in the airo driver does not get a symbol
7851                 * as disable_MAC. it's probably so short the compiler does not gen one.
7852                 */
7853        case AIROPMACOFF:
7854                disable_MAC(ai, 1);
7855                return 0;
7856
7857                /* This command merely clears the counts does not actually store any data
7858                 * only reads rid. But as it changes the cards state, I put it in the
7859                 * writerid routines.
7860                 */
7861        case AIROPSTCLR:
7862                if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
7863                        return -ENOMEM;
7864
7865                PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1);
7866
7867                enabled = ai->micstats.enabled;
7868                memset(&ai->micstats,0,sizeof(ai->micstats));
7869                ai->micstats.enabled = enabled;
7870
7871                if (copy_to_user(comp->data, iobuf,
7872                                 min((int)comp->len, (int)RIDSIZE))) {
7873                        kfree (iobuf);
7874                        return -EFAULT;
7875                }
7876                kfree (iobuf);
7877                return 0;
7878
7879        default:
7880                return -EOPNOTSUPP;     /* Blarg! */
7881        }
7882        if(comp->len > RIDSIZE)
7883                return -EINVAL;
7884
7885        if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
7886                return -ENOMEM;
7887
7888        if (copy_from_user(iobuf,comp->data,comp->len)) {
7889                kfree (iobuf);
7890                return -EFAULT;
7891        }
7892
7893        if (comp->command == AIROPCFG) {
7894                ConfigRid *cfg = (ConfigRid *)iobuf;
7895
7896                if (test_bit(FLAG_MIC_CAPABLE, &ai->flags))
7897                        cfg->opmode |= MODE_MIC;
7898
7899                if ((cfg->opmode & 0xFF) == MODE_STA_IBSS)
7900                        set_bit (FLAG_ADHOC, &ai->flags);
7901                else
7902                        clear_bit (FLAG_ADHOC, &ai->flags);
7903        }
7904
7905        if((*writer)(ai, ridcode, iobuf,comp->len,1)) {
7906                kfree (iobuf);
7907                return -EIO;
7908        }
7909        kfree (iobuf);
7910        return 0;
7911}
7912
7913/*****************************************************************************
7914 * Ancillary flash / mod functions much black magic lurkes here              *
7915 *****************************************************************************
7916 */
7917
7918/*
7919 * Flash command switch table
7920 */
7921
7922static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
7923        int z;
7924
7925        /* Only super-user can modify flash */
7926        if (!capable(CAP_NET_ADMIN))
7927                return -EPERM;
7928
7929        switch(comp->command)
7930        {
7931        case AIROFLSHRST:
7932                return cmdreset((struct airo_info *)dev->priv);
7933
7934        case AIROFLSHSTFL:
7935                if (!((struct airo_info *)dev->priv)->flash &&
7936                        (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
7937                        return -ENOMEM;
7938                return setflashmode((struct airo_info *)dev->priv);
7939
7940        case AIROFLSHGCHR: /* Get char from aux */
7941                if(comp->len != sizeof(int))
7942                        return -EINVAL;
7943                if (copy_from_user(&z,comp->data,comp->len))
7944                        return -EFAULT;
7945                return flashgchar((struct airo_info *)dev->priv,z,8000);
7946
7947        case AIROFLSHPCHR: /* Send char to card. */
7948                if(comp->len != sizeof(int))
7949                        return -EINVAL;
7950                if (copy_from_user(&z,comp->data,comp->len))
7951                        return -EFAULT;
7952                return flashpchar((struct airo_info *)dev->priv,z,8000);
7953
7954        case AIROFLPUTBUF: /* Send 32k to card */
7955                if (!((struct airo_info *)dev->priv)->flash)
7956                        return -ENOMEM;
7957                if(comp->len > FLASHSIZE)
7958                        return -EINVAL;
7959                if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
7960                        return -EFAULT;
7961
7962                flashputbuf((struct airo_info *)dev->priv);
7963                return 0;
7964
7965        case AIRORESTART:
7966                if(flashrestart((struct airo_info *)dev->priv,dev))
7967                        return -EIO;
7968                return 0;
7969        }
7970        return -EINVAL;
7971}
7972
7973#define FLASH_COMMAND  0x7e7e
7974
7975/*
7976 * STEP 1)
7977 * Disable MAC and do soft reset on
7978 * card.
7979 */
7980
7981static int cmdreset(struct airo_info *ai) {
7982        disable_MAC(ai, 1);
7983
7984        if(!waitbusy (ai)){
7985                airo_print_info(ai->dev->name, "Waitbusy hang before RESET");
7986                return -EBUSY;
7987        }
7988
7989        OUT4500(ai,COMMAND,CMD_SOFTRESET);
7990
7991        ssleep(1);                      /* WAS 600 12/7/00 */
7992
7993        if(!waitbusy (ai)){
7994                airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET");
7995                return -EBUSY;
7996        }
7997        return 0;
7998}
7999
8000/* STEP 2)
8001 * Put the card in legendary flash
8002 * mode
8003 */
8004
8005static int setflashmode (struct airo_info *ai) {
8006        set_bit (FLAG_FLASHING, &ai->flags);
8007
8008        OUT4500(ai, SWS0, FLASH_COMMAND);
8009        OUT4500(ai, SWS1, FLASH_COMMAND);
8010        if (probe) {
8011                OUT4500(ai, SWS0, FLASH_COMMAND);
8012                OUT4500(ai, COMMAND,0x10);
8013        } else {
8014                OUT4500(ai, SWS2, FLASH_COMMAND);
8015                OUT4500(ai, SWS3, FLASH_COMMAND);
8016                OUT4500(ai, COMMAND,0);
8017        }
8018        msleep(500);            /* 500ms delay */
8019
8020        if(!waitbusy(ai)) {
8021                clear_bit (FLAG_FLASHING, &ai->flags);
8022                airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode");
8023                return -EIO;
8024        }
8025        return 0;
8026}
8027
8028/* Put character to SWS0 wait for dwelltime
8029 * x 50us for  echo .
8030 */
8031
8032static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
8033        int echo;
8034        int waittime;
8035
8036        byte |= 0x8000;
8037
8038        if(dwelltime == 0 )
8039                dwelltime = 200;
8040
8041        waittime=dwelltime;
8042
8043        /* Wait for busy bit d15 to go false indicating buffer empty */
8044        while ((IN4500 (ai, SWS0) & 0x8000) && waittime > 0) {
8045                udelay (50);
8046                waittime -= 50;
8047        }
8048
8049        /* timeout for busy clear wait */
8050        if(waittime <= 0 ){
8051                airo_print_info(ai->dev->name, "flash putchar busywait timeout!");
8052                return -EBUSY;
8053        }
8054
8055        /* Port is clear now write byte and wait for it to echo back */
8056        do {
8057                OUT4500(ai,SWS0,byte);
8058                udelay(50);
8059                dwelltime -= 50;
8060                echo = IN4500(ai,SWS1);
8061        } while (dwelltime >= 0 && echo != byte);
8062
8063        OUT4500(ai,SWS1,0);
8064
8065        return (echo == byte) ? 0 : -EIO;
8066}
8067
8068/*
8069 * Get a character from the card matching matchbyte
8070 * Step 3)
8071 */
8072static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
8073        int           rchar;
8074        unsigned char rbyte=0;
8075
8076        do {
8077                rchar = IN4500(ai,SWS1);
8078
8079                if(dwelltime && !(0x8000 & rchar)){
8080                        dwelltime -= 10;
8081                        mdelay(10);
8082                        continue;
8083                }
8084                rbyte = 0xff & rchar;
8085
8086                if( (rbyte == matchbyte) && (0x8000 & rchar) ){
8087                        OUT4500(ai,SWS1,0);
8088                        return 0;
8089                }
8090                if( rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar)
8091                        break;
8092                OUT4500(ai,SWS1,0);
8093
8094        }while(dwelltime > 0);
8095        return -EIO;
8096}
8097
8098/*
8099 * Transfer 32k of firmware data from user buffer to our buffer and
8100 * send to the card
8101 */
8102
8103static int flashputbuf(struct airo_info *ai){
8104        int            nwords;
8105
8106        /* Write stuff */
8107        if (test_bit(FLAG_MPI,&ai->flags))
8108                memcpy_toio(ai->pciaux + 0x8000, ai->flash, FLASHSIZE);
8109        else {
8110                OUT4500(ai,AUXPAGE,0x100);
8111                OUT4500(ai,AUXOFF,0);
8112
8113                for(nwords=0;nwords != FLASHSIZE / 2;nwords++){
8114                        OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff);
8115                }
8116        }
8117        OUT4500(ai,SWS0,0x8000);
8118
8119        return 0;
8120}
8121
8122/*
8123 *
8124 */
8125static int flashrestart(struct airo_info *ai,struct net_device *dev){
8126        int    i,status;
8127
8128        ssleep(1);                      /* Added 12/7/00 */
8129        clear_bit (FLAG_FLASHING, &ai->flags);
8130        if (test_bit(FLAG_MPI, &ai->flags)) {
8131                status = mpi_init_descriptors(ai);
8132                if (status != SUCCESS)
8133                        return status;
8134        }
8135        status = setup_card(ai, dev->dev_addr, 1);
8136
8137        if (!test_bit(FLAG_MPI,&ai->flags))
8138                for( i = 0; i < MAX_FIDS; i++ ) {
8139                        ai->fids[i] = transmit_allocate
8140                                ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 );
8141                }
8142
8143        ssleep(1);                      /* Added 12/7/00 */
8144        return status;
8145}
8146#endif /* CISCO_EXT */
8147
8148/*
8149    This program is free software; you can redistribute it and/or
8150    modify it under the terms of the GNU General Public License
8151    as published by the Free Software Foundation; either version 2
8152    of the License, or (at your option) any later version.
8153
8154    This program is distributed in the hope that it will be useful,
8155    but WITHOUT ANY WARRANTY; without even the implied warranty of
8156    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8157    GNU General Public License for more details.
8158
8159    In addition:
8160
8161    Redistribution and use in source and binary forms, with or without
8162    modification, are permitted provided that the following conditions
8163    are met:
8164
8165    1. Redistributions of source code must retain the above copyright
8166       notice, this list of conditions and the following disclaimer.
8167    2. Redistributions in binary form must reproduce the above copyright
8168       notice, this list of conditions and the following disclaimer in the
8169       documentation and/or other materials provided with the distribution.
8170    3. The name of the author may not be used to endorse or promote
8171       products derived from this software without specific prior written
8172       permission.
8173
8174    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
8175    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
8176    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8177    ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
8178    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
8179    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
8180    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8181    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
8182    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
8183    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
8184    POSSIBILITY OF SUCH DAMAGE.
8185*/
8186
8187module_init(airo_init_module);
8188module_exit(airo_cleanup_module);
8189