linux/drivers/net/wireless/atmel.c
<<
>>
Prefs
   1/*** -*- linux-c -*- **********************************************************
   2
   3     Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
   4
   5        Copyright 2000-2001 ATMEL Corporation.
   6        Copyright 2003-2004 Simon Kelley.
   7
   8    This code was developed from version 2.1.1 of the Atmel drivers,
   9    released by Atmel corp. under the GPL in December 2002. It also
  10    includes code from the Linux aironet drivers (C) Benjamin Reed,
  11    and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
  12    extensions, (C) Jean Tourrilhes.
  13
  14    The firmware module for reading the MAC address of the card comes from
  15    net.russotto.AtmelMACFW, written by Matthew T. Russotto and copyright
  16    by him. net.russotto.AtmelMACFW is used under the GPL license version 2.
  17    This file contains the module in binary form and, under the terms
  18    of the GPL, in source form. The source is located at the end of the file.
  19
  20    This program is free software; you can redistribute it and/or modify
  21    it under the terms of the GNU General Public License as published by
  22    the Free Software Foundation; either version 2 of the License, or
  23    (at your option) any later version.
  24
  25    This software is distributed in the hope that it will be useful,
  26    but WITHOUT ANY WARRANTY; without even the implied warranty of
  27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28    GNU General Public License for more details.
  29
  30    You should have received a copy of the GNU General Public License
  31    along with Atmel wireless lan drivers; if not, write to the Free Software
  32    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  33
  34    For all queries about this code, please contact the current author,
  35    Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
  36
  37    Credit is due to HP UK and Cambridge Online Systems Ltd for supplying
  38    hardware used during development of this driver.
  39
  40******************************************************************************/
  41
  42#include <linux/init.h>
  43#include <linux/interrupt.h>
  44
  45#include <linux/kernel.h>
  46#include <linux/ptrace.h>
  47#include <linux/slab.h>
  48#include <linux/string.h>
  49#include <linux/ctype.h>
  50#include <linux/timer.h>
  51#include <asm/byteorder.h>
  52#include <asm/io.h>
  53#include <asm/uaccess.h>
  54#include <linux/module.h>
  55#include <linux/netdevice.h>
  56#include <linux/etherdevice.h>
  57#include <linux/skbuff.h>
  58#include <linux/if_arp.h>
  59#include <linux/ioport.h>
  60#include <linux/fcntl.h>
  61#include <linux/delay.h>
  62#include <linux/wireless.h>
  63#include <net/iw_handler.h>
  64#include <linux/crc32.h>
  65#include <linux/proc_fs.h>
  66#include <linux/seq_file.h>
  67#include <linux/device.h>
  68#include <linux/moduleparam.h>
  69#include <linux/firmware.h>
  70#include <linux/jiffies.h>
  71#include <linux/ieee80211.h>
  72#include "atmel.h"
  73
  74#define DRIVER_MAJOR 0
  75#define DRIVER_MINOR 98
  76
  77MODULE_AUTHOR("Simon Kelley");
  78MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
  79MODULE_LICENSE("GPL");
  80MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
  81
  82/* The name of the firmware file to be loaded
  83   over-rides any automatic selection */
  84static char *firmware = NULL;
  85module_param(firmware, charp, 0);
  86
  87/* table of firmware file names */
  88static struct {
  89        AtmelFWType fw_type;
  90        const char *fw_file;
  91        const char *fw_file_ext;
  92} fw_table[] = {
  93        { ATMEL_FW_TYPE_502,            "atmel_at76c502",       "bin" },
  94        { ATMEL_FW_TYPE_502D,           "atmel_at76c502d",      "bin" },
  95        { ATMEL_FW_TYPE_502E,           "atmel_at76c502e",      "bin" },
  96        { ATMEL_FW_TYPE_502_3COM,       "atmel_at76c502_3com",  "bin" },
  97        { ATMEL_FW_TYPE_504,            "atmel_at76c504",       "bin" },
  98        { ATMEL_FW_TYPE_504_2958,       "atmel_at76c504_2958",  "bin" },
  99        { ATMEL_FW_TYPE_504A_2958,      "atmel_at76c504a_2958", "bin" },
 100        { ATMEL_FW_TYPE_506,            "atmel_at76c506",       "bin" },
 101        { ATMEL_FW_TYPE_NONE,           NULL,                   NULL }
 102};
 103MODULE_FIRMWARE("atmel_at76c502-wpa.bin");
 104MODULE_FIRMWARE("atmel_at76c502.bin");
 105MODULE_FIRMWARE("atmel_at76c502d-wpa.bin");
 106MODULE_FIRMWARE("atmel_at76c502d.bin");
 107MODULE_FIRMWARE("atmel_at76c502e-wpa.bin");
 108MODULE_FIRMWARE("atmel_at76c502e.bin");
 109MODULE_FIRMWARE("atmel_at76c502_3com-wpa.bin");
 110MODULE_FIRMWARE("atmel_at76c502_3com.bin");
 111MODULE_FIRMWARE("atmel_at76c504-wpa.bin");
 112MODULE_FIRMWARE("atmel_at76c504.bin");
 113MODULE_FIRMWARE("atmel_at76c504_2958-wpa.bin");
 114MODULE_FIRMWARE("atmel_at76c504_2958.bin");
 115MODULE_FIRMWARE("atmel_at76c504a_2958-wpa.bin");
 116MODULE_FIRMWARE("atmel_at76c504a_2958.bin");
 117MODULE_FIRMWARE("atmel_at76c506-wpa.bin");
 118MODULE_FIRMWARE("atmel_at76c506.bin");
 119
 120#define MAX_SSID_LENGTH 32
 121#define MGMT_JIFFIES (256 * HZ / 100)
 122
 123#define MAX_BSS_ENTRIES 64
 124
 125/* registers */
 126#define GCR  0x00    /* (SIR0)  General Configuration Register */
 127#define BSR  0x02    /* (SIR1)  Bank Switching Select Register */
 128#define AR   0x04
 129#define DR   0x08
 130#define MR1  0x12    /* Mirror Register 1 */
 131#define MR2  0x14    /* Mirror Register 2 */
 132#define MR3  0x16    /* Mirror Register 3 */
 133#define MR4  0x18    /* Mirror Register 4 */
 134
 135#define GPR1                            0x0c
 136#define GPR2                            0x0e
 137#define GPR3                            0x10
 138/*
 139 * Constants for the GCR register.
 140 */
 141#define GCR_REMAP     0x0400          /* Remap internal SRAM to 0 */
 142#define GCR_SWRES     0x0080          /* BIU reset (ARM and PAI are NOT reset) */
 143#define GCR_CORES     0x0060          /* Core Reset (ARM and PAI are reset) */
 144#define GCR_ENINT     0x0002          /* Enable Interrupts */
 145#define GCR_ACKINT    0x0008          /* Acknowledge Interrupts */
 146
 147#define BSS_SRAM      0x0200          /* AMBA module selection --> SRAM */
 148#define BSS_IRAM      0x0100          /* AMBA module selection --> IRAM */
 149/*
 150 *Constants for the MR registers.
 151 */
 152#define MAC_INIT_COMPLETE       0x0001        /* MAC init has been completed */
 153#define MAC_BOOT_COMPLETE       0x0010        /* MAC boot has been completed */
 154#define MAC_INIT_OK             0x0002        /* MAC boot has been completed */
 155
 156#define MIB_MAX_DATA_BYTES    212
 157#define MIB_HEADER_SIZE       4    /* first four fields */
 158
 159struct get_set_mib {
 160        u8 type;
 161        u8 size;
 162        u8 index;
 163        u8 reserved;
 164        u8 data[MIB_MAX_DATA_BYTES];
 165};
 166
 167struct rx_desc {
 168        u32          Next;
 169        u16          MsduPos;
 170        u16          MsduSize;
 171
 172        u8           State;
 173        u8           Status;
 174        u8           Rate;
 175        u8           Rssi;
 176        u8           LinkQuality;
 177        u8           PreambleType;
 178        u16          Duration;
 179        u32          RxTime;
 180};
 181
 182#define RX_DESC_FLAG_VALID       0x80
 183#define RX_DESC_FLAG_CONSUMED    0x40
 184#define RX_DESC_FLAG_IDLE        0x00
 185
 186#define RX_STATUS_SUCCESS        0x00
 187
 188#define RX_DESC_MSDU_POS_OFFSET      4
 189#define RX_DESC_MSDU_SIZE_OFFSET     6
 190#define RX_DESC_FLAGS_OFFSET         8
 191#define RX_DESC_STATUS_OFFSET        9
 192#define RX_DESC_RSSI_OFFSET          11
 193#define RX_DESC_LINK_QUALITY_OFFSET  12
 194#define RX_DESC_PREAMBLE_TYPE_OFFSET 13
 195#define RX_DESC_DURATION_OFFSET      14
 196#define RX_DESC_RX_TIME_OFFSET       16
 197
 198struct tx_desc {
 199        u32       NextDescriptor;
 200        u16       TxStartOfFrame;
 201        u16       TxLength;
 202
 203        u8        TxState;
 204        u8        TxStatus;
 205        u8        RetryCount;
 206
 207        u8        TxRate;
 208
 209        u8        KeyIndex;
 210        u8        ChiperType;
 211        u8        ChipreLength;
 212        u8        Reserved1;
 213
 214        u8        Reserved;
 215        u8        PacketType;
 216        u16       HostTxLength;
 217};
 218
 219#define TX_DESC_NEXT_OFFSET          0
 220#define TX_DESC_POS_OFFSET           4
 221#define TX_DESC_SIZE_OFFSET          6
 222#define TX_DESC_FLAGS_OFFSET         8
 223#define TX_DESC_STATUS_OFFSET        9
 224#define TX_DESC_RETRY_OFFSET         10
 225#define TX_DESC_RATE_OFFSET          11
 226#define TX_DESC_KEY_INDEX_OFFSET     12
 227#define TX_DESC_CIPHER_TYPE_OFFSET   13
 228#define TX_DESC_CIPHER_LENGTH_OFFSET 14
 229#define TX_DESC_PACKET_TYPE_OFFSET   17
 230#define TX_DESC_HOST_LENGTH_OFFSET   18
 231
 232/*
 233 * Host-MAC interface
 234 */
 235
 236#define TX_STATUS_SUCCESS       0x00
 237
 238#define TX_FIRM_OWN             0x80
 239#define TX_DONE                 0x40
 240
 241#define TX_ERROR                0x01
 242
 243#define TX_PACKET_TYPE_DATA     0x01
 244#define TX_PACKET_TYPE_MGMT     0x02
 245
 246#define ISR_EMPTY               0x00        /* no bits set in ISR */
 247#define ISR_TxCOMPLETE          0x01        /* packet transmitted */
 248#define ISR_RxCOMPLETE          0x02        /* packet received */
 249#define ISR_RxFRAMELOST         0x04        /* Rx Frame lost */
 250#define ISR_FATAL_ERROR         0x08        /* Fatal error */
 251#define ISR_COMMAND_COMPLETE    0x10        /* command completed */
 252#define ISR_OUT_OF_RANGE        0x20        /* command completed */
 253#define ISR_IBSS_MERGE          0x40        /* (4.1.2.30): IBSS merge */
 254#define ISR_GENERIC_IRQ         0x80
 255
 256#define Local_Mib_Type          0x01
 257#define Mac_Address_Mib_Type    0x02
 258#define Mac_Mib_Type            0x03
 259#define Statistics_Mib_Type     0x04
 260#define Mac_Mgmt_Mib_Type       0x05
 261#define Mac_Wep_Mib_Type        0x06
 262#define Phy_Mib_Type            0x07
 263#define Multi_Domain_MIB        0x08
 264
 265#define MAC_MGMT_MIB_CUR_BSSID_POS            14
 266#define MAC_MIB_FRAG_THRESHOLD_POS            8
 267#define MAC_MIB_RTS_THRESHOLD_POS             10
 268#define MAC_MIB_SHORT_RETRY_POS               16
 269#define MAC_MIB_LONG_RETRY_POS                17
 270#define MAC_MIB_SHORT_RETRY_LIMIT_POS         16
 271#define MAC_MGMT_MIB_BEACON_PER_POS           0
 272#define MAC_MGMT_MIB_STATION_ID_POS           6
 273#define MAC_MGMT_MIB_CUR_PRIVACY_POS          11
 274#define MAC_MGMT_MIB_CUR_BSSID_POS            14
 275#define MAC_MGMT_MIB_PS_MODE_POS              53
 276#define MAC_MGMT_MIB_LISTEN_INTERVAL_POS      54
 277#define MAC_MGMT_MIB_MULTI_DOMAIN_IMPLEMENTED 56
 278#define MAC_MGMT_MIB_MULTI_DOMAIN_ENABLED     57
 279#define PHY_MIB_CHANNEL_POS                   14
 280#define PHY_MIB_RATE_SET_POS                  20
 281#define PHY_MIB_REG_DOMAIN_POS                26
 282#define LOCAL_MIB_AUTO_TX_RATE_POS            3
 283#define LOCAL_MIB_SSID_SIZE                   5
 284#define LOCAL_MIB_TX_PROMISCUOUS_POS          6
 285#define LOCAL_MIB_TX_MGMT_RATE_POS            7
 286#define LOCAL_MIB_TX_CONTROL_RATE_POS         8
 287#define LOCAL_MIB_PREAMBLE_TYPE               9
 288#define MAC_ADDR_MIB_MAC_ADDR_POS             0
 289
 290#define         CMD_Set_MIB_Vars              0x01
 291#define         CMD_Get_MIB_Vars              0x02
 292#define         CMD_Scan                      0x03
 293#define         CMD_Join                      0x04
 294#define         CMD_Start                     0x05
 295#define         CMD_EnableRadio               0x06
 296#define         CMD_DisableRadio              0x07
 297#define         CMD_SiteSurvey                0x0B
 298
 299#define         CMD_STATUS_IDLE                   0x00
 300#define         CMD_STATUS_COMPLETE               0x01
 301#define         CMD_STATUS_UNKNOWN                0x02
 302#define         CMD_STATUS_INVALID_PARAMETER      0x03
 303#define         CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
 304#define         CMD_STATUS_TIME_OUT               0x07
 305#define         CMD_STATUS_IN_PROGRESS            0x08
 306#define         CMD_STATUS_REJECTED_RADIO_OFF     0x09
 307#define         CMD_STATUS_HOST_ERROR             0xFF
 308#define         CMD_STATUS_BUSY                   0xFE
 309
 310#define CMD_BLOCK_COMMAND_OFFSET        0
 311#define CMD_BLOCK_STATUS_OFFSET         1
 312#define CMD_BLOCK_PARAMETERS_OFFSET     4
 313
 314#define SCAN_OPTIONS_SITE_SURVEY        0x80
 315
 316#define MGMT_FRAME_BODY_OFFSET          24
 317#define MAX_AUTHENTICATION_RETRIES      3
 318#define MAX_ASSOCIATION_RETRIES         3
 319
 320#define AUTHENTICATION_RESPONSE_TIME_OUT  1000
 321
 322#define MAX_WIRELESS_BODY  2316 /* mtu is 2312, CRC is 4 */
 323#define LOOP_RETRY_LIMIT   500000
 324
 325#define ACTIVE_MODE     1
 326#define PS_MODE         2
 327
 328#define MAX_ENCRYPTION_KEYS 4
 329#define MAX_ENCRYPTION_KEY_SIZE 40
 330
 331/*
 332 * 802.11 related definitions
 333 */
 334
 335/*
 336 * Regulatory Domains
 337 */
 338
 339#define REG_DOMAIN_FCC          0x10    /* Channels     1-11    USA                             */
 340#define REG_DOMAIN_DOC          0x20    /* Channel      1-11    Canada                          */
 341#define REG_DOMAIN_ETSI         0x30    /* Channel      1-13    Europe (ex Spain/France)        */
 342#define REG_DOMAIN_SPAIN        0x31    /* Channel      10-11   Spain                           */
 343#define REG_DOMAIN_FRANCE       0x32    /* Channel      10-13   France                          */
 344#define REG_DOMAIN_MKK          0x40    /* Channel      14      Japan                           */
 345#define REG_DOMAIN_MKK1         0x41    /* Channel      1-14    Japan(MKK1)                     */
 346#define REG_DOMAIN_ISRAEL       0x50    /* Channel      3-9     ISRAEL                          */
 347
 348#define BSS_TYPE_AD_HOC         1
 349#define BSS_TYPE_INFRASTRUCTURE 2
 350
 351#define SCAN_TYPE_ACTIVE        0
 352#define SCAN_TYPE_PASSIVE       1
 353
 354#define LONG_PREAMBLE           0
 355#define SHORT_PREAMBLE          1
 356#define AUTO_PREAMBLE           2
 357
 358#define DATA_FRAME_WS_HEADER_SIZE   30
 359
 360/* promiscuous mode control */
 361#define PROM_MODE_OFF                   0x0
 362#define PROM_MODE_UNKNOWN               0x1
 363#define PROM_MODE_CRC_FAILED            0x2
 364#define PROM_MODE_DUPLICATED            0x4
 365#define PROM_MODE_MGMT                  0x8
 366#define PROM_MODE_CTRL                  0x10
 367#define PROM_MODE_BAD_PROTOCOL          0x20
 368
 369#define IFACE_INT_STATUS_OFFSET         0
 370#define IFACE_INT_MASK_OFFSET           1
 371#define IFACE_LOCKOUT_HOST_OFFSET       2
 372#define IFACE_LOCKOUT_MAC_OFFSET        3
 373#define IFACE_FUNC_CTRL_OFFSET          28
 374#define IFACE_MAC_STAT_OFFSET           30
 375#define IFACE_GENERIC_INT_TYPE_OFFSET   32
 376
 377#define CIPHER_SUITE_NONE     0
 378#define CIPHER_SUITE_WEP_64   1
 379#define CIPHER_SUITE_TKIP     2
 380#define CIPHER_SUITE_AES      3
 381#define CIPHER_SUITE_CCX      4
 382#define CIPHER_SUITE_WEP_128  5
 383
 384/*
 385 * IFACE MACROS & definitions
 386 */
 387
 388/*
 389 * FuncCtrl field:
 390 */
 391#define FUNC_CTRL_TxENABLE              0x10
 392#define FUNC_CTRL_RxENABLE              0x20
 393#define FUNC_CTRL_INIT_COMPLETE         0x01
 394
 395/* A stub firmware image which reads the MAC address from NVRAM on the card.
 396   For copyright information and source see the end of this file. */
 397static u8 mac_reader[] = {
 398        0x06, 0x00, 0x00, 0xea, 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea,
 399        0x01, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea,
 400        0xd3, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x0e, 0x04, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
 401        0x81, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x1c, 0x10, 0x90, 0xe5,
 402        0x10, 0x10, 0xc1, 0xe3, 0x1c, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x08, 0x10, 0x80, 0xe5,
 403        0x02, 0x03, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0xb0, 0x10, 0xc0, 0xe1, 0xb4, 0x10, 0xc0, 0xe1,
 404        0xb8, 0x10, 0xc0, 0xe1, 0xbc, 0x10, 0xc0, 0xe1, 0x56, 0xdc, 0xa0, 0xe3, 0x21, 0x00, 0x00, 0xeb,
 405        0x0a, 0x00, 0xa0, 0xe3, 0x1a, 0x00, 0x00, 0xeb, 0x10, 0x00, 0x00, 0xeb, 0x07, 0x00, 0x00, 0xeb,
 406        0x02, 0x03, 0xa0, 0xe3, 0x02, 0x14, 0xa0, 0xe3, 0xb4, 0x10, 0xc0, 0xe1, 0x4c, 0x10, 0x9f, 0xe5,
 407        0xbc, 0x10, 0xc0, 0xe1, 0x10, 0x10, 0xa0, 0xe3, 0xb8, 0x10, 0xc0, 0xe1, 0xfe, 0xff, 0xff, 0xea,
 408        0x00, 0x40, 0x2d, 0xe9, 0x00, 0x20, 0xa0, 0xe3, 0x02, 0x3c, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
 409        0x28, 0x00, 0x9f, 0xe5, 0x37, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1,
 410        0x00, 0x40, 0x2d, 0xe9, 0x12, 0x2e, 0xa0, 0xe3, 0x06, 0x30, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
 411        0x02, 0x04, 0xa0, 0xe3, 0x2f, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1,
 412        0x00, 0x02, 0x00, 0x02, 0x80, 0x01, 0x90, 0xe0, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe2,
 413        0xfc, 0xff, 0xff, 0xea, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0x10, 0xa0, 0xe3, 0xf3, 0x06, 0xa0, 0xe3,
 414        0x00, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
 415        0x04, 0x10, 0x80, 0xe5, 0x00, 0x10, 0x80, 0xe5, 0x0e, 0x34, 0xa0, 0xe3, 0x1c, 0x10, 0x93, 0xe5,
 416        0x02, 0x1a, 0x81, 0xe3, 0x1c, 0x10, 0x83, 0xe5, 0x58, 0x11, 0x9f, 0xe5, 0x30, 0x10, 0x80, 0xe5,
 417        0x54, 0x11, 0x9f, 0xe5, 0x34, 0x10, 0x80, 0xe5, 0x38, 0x10, 0x80, 0xe5, 0x3c, 0x10, 0x80, 0xe5,
 418        0x10, 0x10, 0x90, 0xe5, 0x08, 0x00, 0x90, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf3, 0x16, 0xa0, 0xe3,
 419        0x08, 0x00, 0x91, 0xe5, 0x05, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, 0x10, 0x00, 0x91, 0xe5,
 420        0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0xff, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5,
 421        0x10, 0x00, 0x91, 0xe5, 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5,
 422        0x10, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5,
 423        0xff, 0x00, 0x00, 0xe2, 0x1e, 0xff, 0x2f, 0xe1, 0x30, 0x40, 0x2d, 0xe9, 0x00, 0x50, 0xa0, 0xe1,
 424        0x03, 0x40, 0xa0, 0xe1, 0xa2, 0x02, 0xa0, 0xe1, 0x08, 0x00, 0x00, 0xe2, 0x03, 0x00, 0x80, 0xe2,
 425        0xd8, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0xc1, 0xe5, 0x01, 0x20, 0xc1, 0xe5, 0xe2, 0xff, 0xff, 0xeb,
 426        0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x1a, 0x14, 0x00, 0xa0, 0xe3, 0xc4, 0xff, 0xff, 0xeb,
 427        0x04, 0x20, 0xa0, 0xe1, 0x05, 0x10, 0xa0, 0xe1, 0x02, 0x00, 0xa0, 0xe3, 0x01, 0x00, 0x00, 0xeb,
 428        0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x70, 0x40, 0x2d, 0xe9, 0xf3, 0x46, 0xa0, 0xe3,
 429        0x00, 0x30, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x08, 0x00, 0x00, 0x9a, 0x8c, 0x50, 0x9f, 0xe5,
 430        0x03, 0x60, 0xd5, 0xe7, 0x0c, 0x60, 0x84, 0xe5, 0x10, 0x60, 0x94, 0xe5, 0x02, 0x00, 0x16, 0xe3,
 431        0xfc, 0xff, 0xff, 0x0a, 0x01, 0x30, 0x83, 0xe2, 0x00, 0x00, 0x53, 0xe1, 0xf7, 0xff, 0xff, 0x3a,
 432        0xff, 0x30, 0xa0, 0xe3, 0x0c, 0x30, 0x84, 0xe5, 0x08, 0x00, 0x94, 0xe5, 0x10, 0x00, 0x94, 0xe5,
 433        0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x94, 0xe5, 0x00, 0x00, 0xa0, 0xe3,
 434        0x00, 0x00, 0x52, 0xe3, 0x0b, 0x00, 0x00, 0x9a, 0x10, 0x50, 0x94, 0xe5, 0x02, 0x00, 0x15, 0xe3,
 435        0xfc, 0xff, 0xff, 0x0a, 0x0c, 0x30, 0x84, 0xe5, 0x10, 0x50, 0x94, 0xe5, 0x01, 0x00, 0x15, 0xe3,
 436        0xfc, 0xff, 0xff, 0x0a, 0x08, 0x50, 0x94, 0xe5, 0x01, 0x50, 0xc1, 0xe4, 0x01, 0x00, 0x80, 0xe2,
 437        0x02, 0x00, 0x50, 0xe1, 0xf3, 0xff, 0xff, 0x3a, 0xc8, 0x00, 0xa0, 0xe3, 0x98, 0xff, 0xff, 0xeb,
 438        0x70, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x02, 0x00, 0x02,
 439        0x00, 0x01, 0x00, 0x02
 440};
 441
 442struct atmel_private {
 443        void *card; /* Bus dependent structure varies for PCcard */
 444        int (*present_callback)(void *); /* And callback which uses it */
 445        char firmware_id[32];
 446        AtmelFWType firmware_type;
 447        u8 *firmware;
 448        int firmware_length;
 449        struct timer_list management_timer;
 450        struct net_device *dev;
 451        struct device *sys_dev;
 452        struct iw_statistics wstats;
 453        spinlock_t irqlock, timerlock;  /* spinlocks */
 454        enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
 455        enum {
 456                CARD_TYPE_PARALLEL_FLASH,
 457                CARD_TYPE_SPI_FLASH,
 458                CARD_TYPE_EEPROM
 459        } card_type;
 460        int do_rx_crc; /* If we need to CRC incoming packets */
 461        int probe_crc; /* set if we don't yet know */
 462        int crc_ok_cnt, crc_ko_cnt; /* counters for probing */
 463        u16 rx_desc_head;
 464        u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
 465        u16 tx_free_mem, tx_buff_head, tx_buff_tail;
 466
 467        u16 frag_seq, frag_len, frag_no;
 468        u8 frag_source[6];
 469
 470        u8 wep_is_on, default_key, exclude_unencrypted, encryption_level;
 471        u8 group_cipher_suite, pairwise_cipher_suite;
 472        u8 wep_keys[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
 473        int wep_key_len[MAX_ENCRYPTION_KEYS];
 474        int use_wpa, radio_on_broken; /* firmware dependent stuff. */
 475
 476        u16 host_info_base;
 477        struct host_info_struct {
 478                /* NB this is matched to the hardware, don't change. */
 479                u8 volatile int_status;
 480                u8 volatile int_mask;
 481                u8 volatile lockout_host;
 482                u8 volatile lockout_mac;
 483
 484                u16 tx_buff_pos;
 485                u16 tx_buff_size;
 486                u16 tx_desc_pos;
 487                u16 tx_desc_count;
 488
 489                u16 rx_buff_pos;
 490                u16 rx_buff_size;
 491                u16 rx_desc_pos;
 492                u16 rx_desc_count;
 493
 494                u16 build_version;
 495                u16 command_pos;
 496
 497                u16 major_version;
 498                u16 minor_version;
 499
 500                u16 func_ctrl;
 501                u16 mac_status;
 502                u16 generic_IRQ_type;
 503                u8  reserved[2];
 504        } host_info;
 505
 506        enum {
 507                STATION_STATE_SCANNING,
 508                STATION_STATE_JOINNING,
 509                STATION_STATE_AUTHENTICATING,
 510                STATION_STATE_ASSOCIATING,
 511                STATION_STATE_READY,
 512                STATION_STATE_REASSOCIATING,
 513                STATION_STATE_DOWN,
 514                STATION_STATE_MGMT_ERROR
 515        } station_state;
 516
 517        int operating_mode, power_mode;
 518        time_t last_qual;
 519        int beacons_this_sec;
 520        int channel;
 521        int reg_domain, config_reg_domain;
 522        int tx_rate;
 523        int auto_tx_rate;
 524        int rts_threshold;
 525        int frag_threshold;
 526        int long_retry, short_retry;
 527        int preamble;
 528        int default_beacon_period, beacon_period, listen_interval;
 529        int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
 530        int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
 531        enum {
 532                SITE_SURVEY_IDLE,
 533                SITE_SURVEY_IN_PROGRESS,
 534                SITE_SURVEY_COMPLETED
 535        } site_survey_state;
 536        unsigned long last_survey;
 537
 538        int station_was_associated, station_is_associated;
 539        int fast_scan;
 540
 541        struct bss_info {
 542                int channel;
 543                int SSIDsize;
 544                int RSSI;
 545                int UsingWEP;
 546                int preamble;
 547                int beacon_period;
 548                int BSStype;
 549                u8 BSSID[6];
 550                u8 SSID[MAX_SSID_LENGTH];
 551        } BSSinfo[MAX_BSS_ENTRIES];
 552        int BSS_list_entries, current_BSS;
 553        int connect_to_any_BSS;
 554        int SSID_size, new_SSID_size;
 555        u8 CurrentBSSID[6], BSSID[6];
 556        u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
 557        u64 last_beacon_timestamp;
 558        u8 rx_buf[MAX_WIRELESS_BODY];
 559};
 560
 561static u8 atmel_basic_rates[4] = {0x82, 0x84, 0x0b, 0x16};
 562
 563static const struct {
 564        int reg_domain;
 565        int min, max;
 566        char *name;
 567} channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
 568                      { REG_DOMAIN_DOC, 1, 11, "Canada" },
 569                      { REG_DOMAIN_ETSI, 1, 13, "Europe" },
 570                      { REG_DOMAIN_SPAIN, 10, 11, "Spain" },
 571                      { REG_DOMAIN_FRANCE, 10, 13, "France" },
 572                      { REG_DOMAIN_MKK, 14, 14, "MKK" },
 573                      { REG_DOMAIN_MKK1, 1, 14, "MKK1" },
 574                      { REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
 575
 576static void build_wpa_mib(struct atmel_private *priv);
 577static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 578static void atmel_copy_to_card(struct net_device *dev, u16 dest,
 579                               const unsigned char *src, u16 len);
 580static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
 581                               u16 src, u16 len);
 582static void atmel_set_gcr(struct net_device *dev, u16 mask);
 583static void atmel_clear_gcr(struct net_device *dev, u16 mask);
 584static int atmel_lock_mac(struct atmel_private *priv);
 585static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
 586static void atmel_command_irq(struct atmel_private *priv);
 587static int atmel_validate_channel(struct atmel_private *priv, int channel);
 588static void atmel_management_frame(struct atmel_private *priv,
 589                                   struct ieee80211_hdr *header,
 590                                   u16 frame_len, u8 rssi);
 591static void atmel_management_timer(u_long a);
 592static void atmel_send_command(struct atmel_private *priv, int command,
 593                               void *cmd, int cmd_size);
 594static int atmel_send_command_wait(struct atmel_private *priv, int command,
 595                                   void *cmd, int cmd_size);
 596static void atmel_transmit_management_frame(struct atmel_private *priv,
 597                                            struct ieee80211_hdr *header,
 598                                            u8 *body, int body_len);
 599
 600static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
 601static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index,
 602                           u8 data);
 603static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
 604                            u16 data);
 605static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
 606                          u8 *data, int data_len);
 607static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
 608                          u8 *data, int data_len);
 609static void atmel_scan(struct atmel_private *priv, int specific_ssid);
 610static void atmel_join_bss(struct atmel_private *priv, int bss_index);
 611static void atmel_smooth_qual(struct atmel_private *priv);
 612static void atmel_writeAR(struct net_device *dev, u16 data);
 613static int probe_atmel_card(struct net_device *dev);
 614static int reset_atmel_card(struct net_device *dev);
 615static void atmel_enter_state(struct atmel_private *priv, int new_state);
 616int atmel_open (struct net_device *dev);
 617
 618static inline u16 atmel_hi(struct atmel_private *priv, u16 offset)
 619{
 620        return priv->host_info_base + offset;
 621}
 622
 623static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
 624{
 625        return priv->host_info.command_pos + offset;
 626}
 627
 628static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
 629{
 630        return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
 631}
 632
 633static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
 634{
 635        return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
 636}
 637
 638static inline u8 atmel_read8(struct net_device *dev, u16 offset)
 639{
 640        return inb(dev->base_addr + offset);
 641}
 642
 643static inline void atmel_write8(struct net_device *dev, u16 offset, u8 data)
 644{
 645        outb(data, dev->base_addr + offset);
 646}
 647
 648static inline u16 atmel_read16(struct net_device *dev, u16 offset)
 649{
 650        return inw(dev->base_addr + offset);
 651}
 652
 653static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
 654{
 655        outw(data, dev->base_addr + offset);
 656}
 657
 658static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
 659{
 660        atmel_writeAR(priv->dev, pos);
 661        return atmel_read8(priv->dev, DR);
 662}
 663
 664static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
 665{
 666        atmel_writeAR(priv->dev, pos);
 667        atmel_write8(priv->dev, DR, data);
 668}
 669
 670static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
 671{
 672        atmel_writeAR(priv->dev, pos);
 673        return atmel_read16(priv->dev, DR);
 674}
 675
 676static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
 677{
 678        atmel_writeAR(priv->dev, pos);
 679        atmel_write16(priv->dev, DR, data);
 680}
 681
 682static const struct iw_handler_def atmel_handler_def;
 683
 684static void tx_done_irq(struct atmel_private *priv)
 685{
 686        int i;
 687
 688        for (i = 0;
 689             atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
 690                     i < priv->host_info.tx_desc_count;
 691             i++) {
 692                u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
 693                u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
 694                u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
 695
 696                atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head), 0);
 697
 698                priv->tx_free_mem += msdu_size;
 699                priv->tx_desc_free++;
 700
 701                if (priv->tx_buff_head + msdu_size > (priv->host_info.tx_buff_pos + priv->host_info.tx_buff_size))
 702                        priv->tx_buff_head = 0;
 703                else
 704                        priv->tx_buff_head += msdu_size;
 705
 706                if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
 707                        priv->tx_desc_head++ ;
 708                else
 709                        priv->tx_desc_head = 0;
 710
 711                if (type == TX_PACKET_TYPE_DATA) {
 712                        if (status == TX_STATUS_SUCCESS)
 713                                priv->dev->stats.tx_packets++;
 714                        else
 715                                priv->dev->stats.tx_errors++;
 716                        netif_wake_queue(priv->dev);
 717                }
 718        }
 719}
 720
 721static u16 find_tx_buff(struct atmel_private *priv, u16 len)
 722{
 723        u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
 724
 725        if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
 726                return 0;
 727
 728        if (bottom_free >= len)
 729                return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
 730
 731        if (priv->tx_free_mem - bottom_free >= len) {
 732                priv->tx_buff_tail = 0;
 733                return priv->host_info.tx_buff_pos;
 734        }
 735
 736        return 0;
 737}
 738
 739static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
 740                                 u16 len, u16 buff, u8 type)
 741{
 742        atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
 743        atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
 744        if (!priv->use_wpa)
 745                atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len);
 746        atmel_wmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_tail), type);
 747        atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RATE_OFFSET, priv->tx_desc_tail), priv->tx_rate);
 748        atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RETRY_OFFSET, priv->tx_desc_tail), 0);
 749        if (priv->use_wpa) {
 750                int cipher_type, cipher_length;
 751                if (is_bcast) {
 752                        cipher_type = priv->group_cipher_suite;
 753                        if (cipher_type == CIPHER_SUITE_WEP_64 ||
 754                            cipher_type == CIPHER_SUITE_WEP_128)
 755                                cipher_length = 8;
 756                        else if (cipher_type == CIPHER_SUITE_TKIP)
 757                                cipher_length = 12;
 758                        else if (priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_64 ||
 759                                 priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_128) {
 760                                cipher_type = priv->pairwise_cipher_suite;
 761                                cipher_length = 8;
 762                        } else {
 763                                cipher_type = CIPHER_SUITE_NONE;
 764                                cipher_length = 0;
 765                        }
 766                } else {
 767                        cipher_type = priv->pairwise_cipher_suite;
 768                        if (cipher_type == CIPHER_SUITE_WEP_64 ||
 769                            cipher_type == CIPHER_SUITE_WEP_128)
 770                                cipher_length = 8;
 771                        else if (cipher_type == CIPHER_SUITE_TKIP)
 772                                cipher_length = 12;
 773                        else if (priv->group_cipher_suite == CIPHER_SUITE_WEP_64 ||
 774                                 priv->group_cipher_suite == CIPHER_SUITE_WEP_128) {
 775                                cipher_type = priv->group_cipher_suite;
 776                                cipher_length = 8;
 777                        } else {
 778                                cipher_type = CIPHER_SUITE_NONE;
 779                                cipher_length = 0;
 780                        }
 781                }
 782
 783                atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail),
 784                            cipher_type);
 785                atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail),
 786                            cipher_length);
 787        }
 788        atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_tail), 0x80000000L);
 789        atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_tail), TX_FIRM_OWN);
 790        if (priv->tx_desc_previous != priv->tx_desc_tail)
 791                atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
 792        priv->tx_desc_previous = priv->tx_desc_tail;
 793        if (priv->tx_desc_tail < (priv->host_info.tx_desc_count - 1))
 794                priv->tx_desc_tail++;
 795        else
 796                priv->tx_desc_tail = 0;
 797        priv->tx_desc_free--;
 798        priv->tx_free_mem -= len;
 799}
 800
 801static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
 802{
 803        static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 804        struct atmel_private *priv = netdev_priv(dev);
 805        struct ieee80211_hdr header;
 806        unsigned long flags;
 807        u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
 808
 809        if (priv->card && priv->present_callback &&
 810            !(*priv->present_callback)(priv->card)) {
 811                dev->stats.tx_errors++;
 812                dev_kfree_skb(skb);
 813                return NETDEV_TX_OK;
 814        }
 815
 816        if (priv->station_state != STATION_STATE_READY) {
 817                dev->stats.tx_errors++;
 818                dev_kfree_skb(skb);
 819                return NETDEV_TX_OK;
 820        }
 821
 822        /* first ensure the timer func cannot run */
 823        spin_lock_bh(&priv->timerlock);
 824        /* then stop the hardware ISR */
 825        spin_lock_irqsave(&priv->irqlock, flags);
 826        /* nb doing the above in the opposite order will deadlock */
 827
 828        /* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
 829           12 first bytes (containing DA/SA) and put them in the appropriate
 830           fields of the Wireless Header. Thus the packet length is then the
 831           initial + 18 (+30-12) */
 832
 833        if (!(buff = find_tx_buff(priv, len + 18))) {
 834                dev->stats.tx_dropped++;
 835                spin_unlock_irqrestore(&priv->irqlock, flags);
 836                spin_unlock_bh(&priv->timerlock);
 837                netif_stop_queue(dev);
 838                return NETDEV_TX_BUSY;
 839        }
 840
 841        frame_ctl = IEEE80211_FTYPE_DATA;
 842        header.duration_id = 0;
 843        header.seq_ctrl = 0;
 844        if (priv->wep_is_on)
 845                frame_ctl |= IEEE80211_FCTL_PROTECTED;
 846        if (priv->operating_mode == IW_MODE_ADHOC) {
 847                skb_copy_from_linear_data(skb, &header.addr1, 6);
 848                memcpy(&header.addr2, dev->dev_addr, 6);
 849                memcpy(&header.addr3, priv->BSSID, 6);
 850        } else {
 851                frame_ctl |= IEEE80211_FCTL_TODS;
 852                memcpy(&header.addr1, priv->CurrentBSSID, 6);
 853                memcpy(&header.addr2, dev->dev_addr, 6);
 854                skb_copy_from_linear_data(skb, &header.addr3, 6);
 855        }
 856
 857        if (priv->use_wpa)
 858                memcpy(&header.addr4, SNAP_RFC1024, 6);
 859
 860        header.frame_control = cpu_to_le16(frame_ctl);
 861        /* Copy the wireless header into the card */
 862        atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
 863        /* Copy the packet sans its 802.3 header addresses which have been replaced */
 864        atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
 865        priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
 866
 867        /* low bit of first byte of destination tells us if broadcast */
 868        tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
 869        dev->stats.tx_bytes += len;
 870
 871        spin_unlock_irqrestore(&priv->irqlock, flags);
 872        spin_unlock_bh(&priv->timerlock);
 873        dev_kfree_skb(skb);
 874
 875        return NETDEV_TX_OK;
 876}
 877
 878static void atmel_transmit_management_frame(struct atmel_private *priv,
 879                                            struct ieee80211_hdr *header,
 880                                            u8 *body, int body_len)
 881{
 882        u16 buff;
 883        int len = MGMT_FRAME_BODY_OFFSET + body_len;
 884
 885        if (!(buff = find_tx_buff(priv, len)))
 886                return;
 887
 888        atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
 889        atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len);
 890        priv->tx_buff_tail += len;
 891        tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
 892}
 893
 894static void fast_rx_path(struct atmel_private *priv,
 895                         struct ieee80211_hdr *header,
 896                         u16 msdu_size, u16 rx_packet_loc, u32 crc)
 897{
 898        /* fast path: unfragmented packet copy directly into skbuf */
 899        u8 mac4[6];
 900        struct sk_buff  *skb;
 901        unsigned char *skbp;
 902
 903        /* get the final, mac 4 header field, this tells us encapsulation */
 904        atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
 905        msdu_size -= 6;
 906
 907        if (priv->do_rx_crc) {
 908                crc = crc32_le(crc, mac4, 6);
 909                msdu_size -= 4;
 910        }
 911
 912        if (!(skb = dev_alloc_skb(msdu_size + 14))) {
 913                priv->dev->stats.rx_dropped++;
 914                return;
 915        }
 916
 917        skb_reserve(skb, 2);
 918        skbp = skb_put(skb, msdu_size + 12);
 919        atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
 920
 921        if (priv->do_rx_crc) {
 922                u32 netcrc;
 923                crc = crc32_le(crc, skbp + 12, msdu_size);
 924                atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);
 925                if ((crc ^ 0xffffffff) != netcrc) {
 926                        priv->dev->stats.rx_crc_errors++;
 927                        dev_kfree_skb(skb);
 928                        return;
 929                }
 930        }
 931
 932        memcpy(skbp, header->addr1, 6); /* destination address */
 933        if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
 934                memcpy(&skbp[6], header->addr3, 6);
 935        else
 936                memcpy(&skbp[6], header->addr2, 6); /* source address */
 937
 938        skb->protocol = eth_type_trans(skb, priv->dev);
 939        skb->ip_summed = CHECKSUM_NONE;
 940        netif_rx(skb);
 941        priv->dev->stats.rx_bytes += 12 + msdu_size;
 942        priv->dev->stats.rx_packets++;
 943}
 944
 945/* Test to see if the packet in card memory at packet_loc has a valid CRC
 946   It doesn't matter that this is slow: it is only used to proble the first few
 947   packets. */
 948static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
 949{
 950        int i = msdu_size - 4;
 951        u32 netcrc, crc = 0xffffffff;
 952
 953        if (msdu_size < 4)
 954                return 0;
 955
 956        atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
 957
 958        atmel_writeAR(priv->dev, packet_loc);
 959        while (i--) {
 960                u8 octet = atmel_read8(priv->dev, DR);
 961                crc = crc32_le(crc, &octet, 1);
 962        }
 963
 964        return (crc ^ 0xffffffff) == netcrc;
 965}
 966
 967static void frag_rx_path(struct atmel_private *priv,
 968                         struct ieee80211_hdr *header,
 969                         u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
 970                         u8 frag_no, int more_frags)
 971{
 972        u8 mac4[6];
 973        u8 source[6];
 974        struct sk_buff *skb;
 975
 976        if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
 977                memcpy(source, header->addr3, 6);
 978        else
 979                memcpy(source, header->addr2, 6);
 980
 981        rx_packet_loc += 24; /* skip header */
 982
 983        if (priv->do_rx_crc)
 984                msdu_size -= 4;
 985
 986        if (frag_no == 0) { /* first fragment */
 987                atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, 6);
 988                msdu_size -= 6;
 989                rx_packet_loc += 6;
 990
 991                if (priv->do_rx_crc)
 992                        crc = crc32_le(crc, mac4, 6);
 993
 994                priv->frag_seq = seq_no;
 995                priv->frag_no = 1;
 996                priv->frag_len = msdu_size;
 997                memcpy(priv->frag_source, source, 6);
 998                memcpy(&priv->rx_buf[6], source, 6);
 999                memcpy(priv->rx_buf, header->addr1, 6);
1000
1001                atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
1002
1003                if (priv->do_rx_crc) {
1004                        u32 netcrc;
1005                        crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);
1006                        atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
1007                        if ((crc ^ 0xffffffff) != netcrc) {
1008                                priv->dev->stats.rx_crc_errors++;
1009                                memset(priv->frag_source, 0xff, 6);
1010                        }
1011                }
1012
1013        } else if (priv->frag_no == frag_no &&
1014                   priv->frag_seq == seq_no &&
1015                   memcmp(priv->frag_source, source, 6) == 0) {
1016
1017                atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
1018                                   rx_packet_loc, msdu_size);
1019                if (priv->do_rx_crc) {
1020                        u32 netcrc;
1021                        crc = crc32_le(crc,
1022                                       &priv->rx_buf[12 + priv->frag_len],
1023                                       msdu_size);
1024                        atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
1025                        if ((crc ^ 0xffffffff) != netcrc) {
1026                                priv->dev->stats.rx_crc_errors++;
1027                                memset(priv->frag_source, 0xff, 6);
1028                                more_frags = 1; /* don't send broken assembly */
1029                        }
1030                }
1031
1032                priv->frag_len += msdu_size;
1033                priv->frag_no++;
1034
1035                if (!more_frags) { /* last one */
1036                        memset(priv->frag_source, 0xff, 6);
1037                        if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {
1038                                priv->dev->stats.rx_dropped++;
1039                        } else {
1040                                skb_reserve(skb, 2);
1041                                memcpy(skb_put(skb, priv->frag_len + 12),
1042                                       priv->rx_buf,
1043                                       priv->frag_len + 12);
1044                                skb->protocol = eth_type_trans(skb, priv->dev);
1045                                skb->ip_summed = CHECKSUM_NONE;
1046                                netif_rx(skb);
1047                                priv->dev->stats.rx_bytes += priv->frag_len + 12;
1048                                priv->dev->stats.rx_packets++;
1049                        }
1050                }
1051        } else
1052                priv->wstats.discard.fragment++;
1053}
1054
1055static void rx_done_irq(struct atmel_private *priv)
1056{
1057        int i;
1058        struct ieee80211_hdr header;
1059
1060        for (i = 0;
1061             atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
1062                     i < priv->host_info.rx_desc_count;
1063             i++) {
1064
1065                u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
1066                u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
1067                u32 crc = 0xffffffff;
1068
1069                if (status != RX_STATUS_SUCCESS) {
1070                        if (status == 0xc1) /* determined by experiment */
1071                                priv->wstats.discard.nwid++;
1072                        else
1073                                priv->dev->stats.rx_errors++;
1074                        goto next;
1075                }
1076
1077                msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
1078                rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
1079
1080                if (msdu_size < 30) {
1081                        priv->dev->stats.rx_errors++;
1082                        goto next;
1083                }
1084
1085                /* Get header as far as end of seq_ctrl */
1086                atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
1087                frame_ctl = le16_to_cpu(header.frame_control);
1088                seq_control = le16_to_cpu(header.seq_ctrl);
1089
1090                /* probe for CRC use here if needed  once five packets have
1091                   arrived with the same crc status, we assume we know what's
1092                   happening and stop probing */
1093                if (priv->probe_crc) {
1094                        if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
1095                                priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
1096                        } else {
1097                                priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
1098                        }
1099                        if (priv->do_rx_crc) {
1100                                if (priv->crc_ok_cnt++ > 5)
1101                                        priv->probe_crc = 0;
1102                        } else {
1103                                if (priv->crc_ko_cnt++ > 5)
1104                                        priv->probe_crc = 0;
1105                        }
1106                }
1107
1108                /* don't CRC header when WEP in use */
1109                if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
1110                        crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
1111                }
1112                msdu_size -= 24; /* header */
1113
1114                if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
1115                        int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
1116                        u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
1117                        u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
1118
1119                        if (!more_fragments && packet_fragment_no == 0) {
1120                                fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
1121                        } else {
1122                                frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
1123                                             packet_sequence_no, packet_fragment_no, more_fragments);
1124                        }
1125                }
1126
1127                if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
1128                        /* copy rest of packet into buffer */
1129                        atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
1130
1131                        /* we use the same buffer for frag reassembly and control packets */
1132                        memset(priv->frag_source, 0xff, 6);
1133
1134                        if (priv->do_rx_crc) {
1135                                /* last 4 octets is crc */
1136                                msdu_size -= 4;
1137                                crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);
1138                                if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {
1139                                        priv->dev->stats.rx_crc_errors++;
1140                                        goto next;
1141                                }
1142                        }
1143
1144                        atmel_management_frame(priv, &header, msdu_size,
1145                                               atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
1146                }
1147
1148next:
1149                /* release descriptor */
1150                atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
1151
1152                if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
1153                        priv->rx_desc_head++;
1154                else
1155                        priv->rx_desc_head = 0;
1156        }
1157}
1158
1159static irqreturn_t service_interrupt(int irq, void *dev_id)
1160{
1161        struct net_device *dev = (struct net_device *) dev_id;
1162        struct atmel_private *priv = netdev_priv(dev);
1163        u8 isr;
1164        int i = -1;
1165        static const u8 irq_order[] = {
1166                ISR_OUT_OF_RANGE,
1167                ISR_RxCOMPLETE,
1168                ISR_TxCOMPLETE,
1169                ISR_RxFRAMELOST,
1170                ISR_FATAL_ERROR,
1171                ISR_COMMAND_COMPLETE,
1172                ISR_IBSS_MERGE,
1173                ISR_GENERIC_IRQ
1174        };
1175
1176        if (priv->card && priv->present_callback &&
1177            !(*priv->present_callback)(priv->card))
1178                return IRQ_HANDLED;
1179
1180        /* In this state upper-level code assumes it can mess with
1181           the card unhampered by interrupts which may change register state.
1182           Note that even though the card shouldn't generate interrupts
1183           the inturrupt line may be shared. This allows card setup
1184           to go on without disabling interrupts for a long time. */
1185        if (priv->station_state == STATION_STATE_DOWN)
1186                return IRQ_NONE;
1187
1188        atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
1189
1190        while (1) {
1191                if (!atmel_lock_mac(priv)) {
1192                        /* failed to contact card */
1193                        printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
1194                        return IRQ_HANDLED;
1195                }
1196
1197                isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
1198                atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
1199
1200                if (!isr) {
1201                        atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
1202                        return i == -1 ? IRQ_NONE : IRQ_HANDLED;
1203                }
1204
1205                atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
1206
1207                for (i = 0; i < ARRAY_SIZE(irq_order); i++)
1208                        if (isr & irq_order[i])
1209                                break;
1210
1211                if (!atmel_lock_mac(priv)) {
1212                        /* failed to contact card */
1213                        printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
1214                        return IRQ_HANDLED;
1215                }
1216
1217                isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
1218                isr ^= irq_order[i];
1219                atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
1220                atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
1221
1222                switch (irq_order[i]) {
1223
1224                case ISR_OUT_OF_RANGE:
1225                        if (priv->operating_mode == IW_MODE_INFRA &&
1226                            priv->station_state == STATION_STATE_READY) {
1227                                priv->station_is_associated = 0;
1228                                atmel_scan(priv, 1);
1229                        }
1230                        break;
1231
1232                case ISR_RxFRAMELOST:
1233                        priv->wstats.discard.misc++;
1234                        /* fall through */
1235                case ISR_RxCOMPLETE:
1236                        rx_done_irq(priv);
1237                        break;
1238
1239                case ISR_TxCOMPLETE:
1240                        tx_done_irq(priv);
1241                        break;
1242
1243                case ISR_FATAL_ERROR:
1244                        printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
1245                        atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
1246                        break;
1247
1248                case ISR_COMMAND_COMPLETE:
1249                        atmel_command_irq(priv);
1250                        break;
1251
1252                case ISR_IBSS_MERGE:
1253                        atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
1254                                      priv->CurrentBSSID, 6);
1255                        /* The WPA stuff cares about the current AP address */
1256                        if (priv->use_wpa)
1257                                build_wpa_mib(priv);
1258                        break;
1259                case ISR_GENERIC_IRQ:
1260                        printk(KERN_INFO "%s: Generic_irq received.\n", dev->name);
1261                        break;
1262                }
1263        }
1264}
1265
1266static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
1267{
1268        struct atmel_private *priv = netdev_priv(dev);
1269
1270        /* update the link quality here in case we are seeing no beacons
1271           at all to drive the process */
1272        atmel_smooth_qual(priv);
1273
1274        priv->wstats.status = priv->station_state;
1275
1276        if (priv->operating_mode == IW_MODE_INFRA) {
1277                if (priv->station_state != STATION_STATE_READY) {
1278                        priv->wstats.qual.qual = 0;
1279                        priv->wstats.qual.level = 0;
1280                        priv->wstats.qual.updated = (IW_QUAL_QUAL_INVALID
1281                                        | IW_QUAL_LEVEL_INVALID);
1282                }
1283                priv->wstats.qual.noise = 0;
1284                priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
1285        } else {
1286                /* Quality levels cannot be determined in ad-hoc mode,
1287                   because we can 'hear' more that one remote station. */
1288                priv->wstats.qual.qual = 0;
1289                priv->wstats.qual.level = 0;
1290                priv->wstats.qual.noise = 0;
1291                priv->wstats.qual.updated = IW_QUAL_QUAL_INVALID
1292                                        | IW_QUAL_LEVEL_INVALID
1293                                        | IW_QUAL_NOISE_INVALID;
1294                priv->wstats.miss.beacon = 0;
1295        }
1296
1297        return &priv->wstats;
1298}
1299
1300static int atmel_change_mtu(struct net_device *dev, int new_mtu)
1301{
1302        if ((new_mtu < 68) || (new_mtu > 2312))
1303                return -EINVAL;
1304        dev->mtu = new_mtu;
1305        return 0;
1306}
1307
1308static int atmel_set_mac_address(struct net_device *dev, void *p)
1309{
1310        struct sockaddr *addr = p;
1311
1312        memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
1313        return atmel_open(dev);
1314}
1315
1316EXPORT_SYMBOL(atmel_open);
1317
1318int atmel_open(struct net_device *dev)
1319{
1320        struct atmel_private *priv = netdev_priv(dev);
1321        int i, channel, err;
1322
1323        /* any scheduled timer is no longer needed and might screw things up.. */
1324        del_timer_sync(&priv->management_timer);
1325
1326        /* Interrupts will not touch the card once in this state... */
1327        priv->station_state = STATION_STATE_DOWN;
1328
1329        if (priv->new_SSID_size) {
1330                memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
1331                priv->SSID_size = priv->new_SSID_size;
1332                priv->new_SSID_size = 0;
1333        }
1334        priv->BSS_list_entries = 0;
1335
1336        priv->AuthenticationRequestRetryCnt = 0;
1337        priv->AssociationRequestRetryCnt = 0;
1338        priv->ReAssociationRequestRetryCnt = 0;
1339        priv->CurrentAuthentTransactionSeqNum = 0x0001;
1340        priv->ExpectedAuthentTransactionSeqNum = 0x0002;
1341
1342        priv->site_survey_state = SITE_SURVEY_IDLE;
1343        priv->station_is_associated = 0;
1344
1345        err = reset_atmel_card(dev);
1346        if (err)
1347                return err;
1348
1349        if (priv->config_reg_domain) {
1350                priv->reg_domain = priv->config_reg_domain;
1351                atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain);
1352        } else {
1353                priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
1354                for (i = 0; i < ARRAY_SIZE(channel_table); i++)
1355                        if (priv->reg_domain == channel_table[i].reg_domain)
1356                                break;
1357                if (i == ARRAY_SIZE(channel_table)) {
1358                        priv->reg_domain = REG_DOMAIN_MKK1;
1359                        printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
1360                }
1361        }
1362
1363        if ((channel = atmel_validate_channel(priv, priv->channel)))
1364                priv->channel = channel;
1365
1366        /* this moves station_state on.... */
1367        atmel_scan(priv, 1);
1368
1369        atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
1370        return 0;
1371}
1372
1373static int atmel_close(struct net_device *dev)
1374{
1375        struct atmel_private *priv = netdev_priv(dev);
1376
1377        /* Send event to userspace that we are disassociating */
1378        if (priv->station_state == STATION_STATE_READY) {
1379                union iwreq_data wrqu;
1380
1381                wrqu.data.length = 0;
1382                wrqu.data.flags = 0;
1383                wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1384                memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
1385                wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
1386        }
1387
1388        atmel_enter_state(priv, STATION_STATE_DOWN);
1389
1390        if (priv->bus_type == BUS_TYPE_PCCARD)
1391                atmel_write16(dev, GCR, 0x0060);
1392        atmel_write16(dev, GCR, 0x0040);
1393        return 0;
1394}
1395
1396static int atmel_validate_channel(struct atmel_private *priv, int channel)
1397{
1398        /* check that channel is OK, if so return zero,
1399           else return suitable default channel */
1400        int i;
1401
1402        for (i = 0; i < ARRAY_SIZE(channel_table); i++)
1403                if (priv->reg_domain == channel_table[i].reg_domain) {
1404                        if (channel >= channel_table[i].min &&
1405                            channel <= channel_table[i].max)
1406                                return 0;
1407                        else
1408                                return channel_table[i].min;
1409                }
1410        return 0;
1411}
1412
1413static int atmel_proc_show(struct seq_file *m, void *v)
1414{
1415        struct atmel_private *priv = m->private;
1416        int i;
1417        char *s, *r, *c;
1418
1419        seq_printf(m, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
1420
1421        if (priv->station_state != STATION_STATE_DOWN) {
1422                seq_printf(m,
1423                           "Firmware version:\t%d.%d build %d\n"
1424                           "Firmware location:\t",
1425                           priv->host_info.major_version,
1426                           priv->host_info.minor_version,
1427                           priv->host_info.build_version);
1428
1429                if (priv->card_type != CARD_TYPE_EEPROM)
1430                        seq_puts(m, "on card\n");
1431                else if (priv->firmware)
1432                        seq_printf(m, "%s loaded by host\n", priv->firmware_id);
1433                else
1434                        seq_printf(m, "%s loaded by hotplug\n", priv->firmware_id);
1435
1436                switch (priv->card_type) {
1437                case CARD_TYPE_PARALLEL_FLASH:
1438                        c = "Parallel flash";
1439                        break;
1440                case CARD_TYPE_SPI_FLASH:
1441                        c = "SPI flash\n";
1442                        break;
1443                case CARD_TYPE_EEPROM:
1444                        c = "EEPROM";
1445                        break;
1446                default:
1447                        c = "<unknown>";
1448                }
1449
1450                r = "<unknown>";
1451                for (i = 0; i < ARRAY_SIZE(channel_table); i++)
1452                        if (priv->reg_domain == channel_table[i].reg_domain)
1453                                r = channel_table[i].name;
1454
1455                seq_printf(m, "MAC memory type:\t%s\n", c);
1456                seq_printf(m, "Regulatory domain:\t%s\n", r);
1457                seq_printf(m, "Host CRC checking:\t%s\n",
1458                         priv->do_rx_crc ? "On" : "Off");
1459                seq_printf(m, "WPA-capable firmware:\t%s\n",
1460                         priv->use_wpa ? "Yes" : "No");
1461        }
1462
1463        switch (priv->station_state) {
1464        case STATION_STATE_SCANNING:
1465                s = "Scanning";
1466                break;
1467        case STATION_STATE_JOINNING:
1468                s = "Joining";
1469                break;
1470        case STATION_STATE_AUTHENTICATING:
1471                s = "Authenticating";
1472                break;
1473        case STATION_STATE_ASSOCIATING:
1474                s = "Associating";
1475                break;
1476        case STATION_STATE_READY:
1477                s = "Ready";
1478                break;
1479        case STATION_STATE_REASSOCIATING:
1480                s = "Reassociating";
1481                break;
1482        case STATION_STATE_MGMT_ERROR:
1483                s = "Management error";
1484                break;
1485        case STATION_STATE_DOWN:
1486                s = "Down";
1487                break;
1488        default:
1489                s = "<unknown>";
1490        }
1491
1492        seq_printf(m, "Current state:\t\t%s\n", s);
1493        return 0;
1494}
1495
1496static int atmel_proc_open(struct inode *inode, struct file *file)
1497{
1498        return single_open(file, atmel_proc_show, PDE_DATA(inode));
1499}
1500
1501static const struct file_operations atmel_proc_fops = {
1502        .open           = atmel_proc_open,
1503        .read           = seq_read,
1504        .llseek         = seq_lseek,
1505        .release        = single_release,
1506};
1507
1508static const struct net_device_ops atmel_netdev_ops = {
1509        .ndo_open               = atmel_open,
1510        .ndo_stop               = atmel_close,
1511        .ndo_change_mtu         = atmel_change_mtu,
1512        .ndo_set_mac_address    = atmel_set_mac_address,
1513        .ndo_start_xmit         = start_tx,
1514        .ndo_do_ioctl           = atmel_ioctl,
1515        .ndo_validate_addr      = eth_validate_addr,
1516};
1517
1518struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
1519                                   const AtmelFWType fw_type,
1520                                   struct device *sys_dev,
1521                                   int (*card_present)(void *), void *card)
1522{
1523        struct net_device *dev;
1524        struct atmel_private *priv;
1525        int rc;
1526
1527        /* Create the network device object. */
1528        dev = alloc_etherdev(sizeof(*priv));
1529        if (!dev)
1530                return NULL;
1531
1532        if (dev_alloc_name(dev, dev->name) < 0) {
1533                printk(KERN_ERR "atmel: Couldn't get name!\n");
1534                goto err_out_free;
1535        }
1536
1537        priv = netdev_priv(dev);
1538        priv->dev = dev;
1539        priv->sys_dev = sys_dev;
1540        priv->present_callback = card_present;
1541        priv->card = card;
1542        priv->firmware = NULL;
1543        priv->firmware_id[0] = '\0';
1544        priv->firmware_type = fw_type;
1545        if (firmware) /* module parameter */
1546                strcpy(priv->firmware_id, firmware);
1547        priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
1548        priv->station_state = STATION_STATE_DOWN;
1549        priv->do_rx_crc = 0;
1550        /* For PCMCIA cards, some chips need CRC, some don't
1551           so we have to probe. */
1552        if (priv->bus_type == BUS_TYPE_PCCARD) {
1553                priv->probe_crc = 1;
1554                priv->crc_ok_cnt = priv->crc_ko_cnt = 0;
1555        } else
1556                priv->probe_crc = 0;
1557        priv->last_qual = jiffies;
1558        priv->last_beacon_timestamp = 0;
1559        memset(priv->frag_source, 0xff, sizeof(priv->frag_source));
1560        memset(priv->BSSID, 0, 6);
1561        priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
1562        priv->station_was_associated = 0;
1563
1564        priv->last_survey = jiffies;
1565        priv->preamble = LONG_PREAMBLE;
1566        priv->operating_mode = IW_MODE_INFRA;
1567        priv->connect_to_any_BSS = 0;
1568        priv->config_reg_domain = 0;
1569        priv->reg_domain = 0;
1570        priv->tx_rate = 3;
1571        priv->auto_tx_rate = 1;
1572        priv->channel = 4;
1573        priv->power_mode = 0;
1574        priv->SSID[0] = '\0';
1575        priv->SSID_size = 0;
1576        priv->new_SSID_size = 0;
1577        priv->frag_threshold = 2346;
1578        priv->rts_threshold = 2347;
1579        priv->short_retry = 7;
1580        priv->long_retry = 4;
1581
1582        priv->wep_is_on = 0;
1583        priv->default_key = 0;
1584        priv->encryption_level = 0;
1585        priv->exclude_unencrypted = 0;
1586        priv->group_cipher_suite = priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
1587        priv->use_wpa = 0;
1588        memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
1589        memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
1590
1591        priv->default_beacon_period = priv->beacon_period = 100;
1592        priv->listen_interval = 1;
1593
1594        init_timer(&priv->management_timer);
1595        spin_lock_init(&priv->irqlock);
1596        spin_lock_init(&priv->timerlock);
1597        priv->management_timer.function = atmel_management_timer;
1598        priv->management_timer.data = (unsigned long) dev;
1599
1600        dev->netdev_ops = &atmel_netdev_ops;
1601        dev->wireless_handlers = &atmel_handler_def;
1602        dev->irq = irq;
1603        dev->base_addr = port;
1604
1605        SET_NETDEV_DEV(dev, sys_dev);
1606
1607        if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) {
1608                printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc);
1609                goto err_out_free;
1610        }
1611
1612        if (!request_region(dev->base_addr, 32,
1613                            priv->bus_type == BUS_TYPE_PCCARD ?  "atmel_cs" : "atmel_pci")) {
1614                goto err_out_irq;
1615        }
1616
1617        if (register_netdev(dev))
1618                goto err_out_res;
1619
1620        if (!probe_atmel_card(dev)) {
1621                unregister_netdev(dev);
1622                goto err_out_res;
1623        }
1624
1625        netif_carrier_off(dev);
1626
1627        if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv))
1628                printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
1629
1630        printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
1631               dev->name, DRIVER_MAJOR, DRIVER_MINOR, dev->dev_addr);
1632
1633        return dev;
1634
1635err_out_res:
1636        release_region(dev->base_addr, 32);
1637err_out_irq:
1638        free_irq(dev->irq, dev);
1639err_out_free:
1640        free_netdev(dev);
1641        return NULL;
1642}
1643
1644EXPORT_SYMBOL(init_atmel_card);
1645
1646void stop_atmel_card(struct net_device *dev)
1647{
1648        struct atmel_private *priv = netdev_priv(dev);
1649
1650        /* put a brick on it... */
1651        if (priv->bus_type == BUS_TYPE_PCCARD)
1652                atmel_write16(dev, GCR, 0x0060);
1653        atmel_write16(dev, GCR, 0x0040);
1654
1655        del_timer_sync(&priv->management_timer);
1656        unregister_netdev(dev);
1657        remove_proc_entry("driver/atmel", NULL);
1658        free_irq(dev->irq, dev);
1659        kfree(priv->firmware);
1660        release_region(dev->base_addr, 32);
1661        free_netdev(dev);
1662}
1663
1664EXPORT_SYMBOL(stop_atmel_card);
1665
1666static int atmel_set_essid(struct net_device *dev,
1667                           struct iw_request_info *info,
1668                           struct iw_point *dwrq,
1669                           char *extra)
1670{
1671        struct atmel_private *priv = netdev_priv(dev);
1672
1673        /* Check if we asked for `any' */
1674        if (dwrq->flags == 0) {
1675                priv->connect_to_any_BSS = 1;
1676        } else {
1677                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1678
1679                priv->connect_to_any_BSS = 0;
1680
1681                /* Check the size of the string */
1682                if (dwrq->length > MAX_SSID_LENGTH)
1683                         return -E2BIG;
1684                if (index != 0)
1685                        return -EINVAL;
1686
1687                memcpy(priv->new_SSID, extra, dwrq->length);
1688                priv->new_SSID_size = dwrq->length;
1689        }
1690
1691        return -EINPROGRESS;
1692}
1693
1694static int atmel_get_essid(struct net_device *dev,
1695                           struct iw_request_info *info,
1696                           struct iw_point *dwrq,
1697                           char *extra)
1698{
1699        struct atmel_private *priv = netdev_priv(dev);
1700
1701        /* Get the current SSID */
1702        if (priv->new_SSID_size != 0) {
1703                memcpy(extra, priv->new_SSID, priv->new_SSID_size);
1704                dwrq->length = priv->new_SSID_size;
1705        } else {
1706                memcpy(extra, priv->SSID, priv->SSID_size);
1707                dwrq->length = priv->SSID_size;
1708        }
1709
1710        dwrq->flags = !priv->connect_to_any_BSS; /* active */
1711
1712        return 0;
1713}
1714
1715static int atmel_get_wap(struct net_device *dev,
1716                         struct iw_request_info *info,
1717                         struct sockaddr *awrq,
1718                         char *extra)
1719{
1720        struct atmel_private *priv = netdev_priv(dev);
1721        memcpy(awrq->sa_data, priv->CurrentBSSID, 6);
1722        awrq->sa_family = ARPHRD_ETHER;
1723
1724        return 0;
1725}
1726
1727static int atmel_set_encode(struct net_device *dev,
1728                            struct iw_request_info *info,
1729                            struct iw_point *dwrq,
1730                            char *extra)
1731{
1732        struct atmel_private *priv = netdev_priv(dev);
1733
1734        /* Basic checking: do we have a key to set ?
1735         * Note : with the new API, it's impossible to get a NULL pointer.
1736         * Therefore, we need to check a key size == 0 instead.
1737         * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
1738         * when no key is present (only change flags), but older versions
1739         * don't do it. - Jean II */
1740        if (dwrq->length > 0) {
1741                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1742                int current_index = priv->default_key;
1743                /* Check the size of the key */
1744                if (dwrq->length > 13) {
1745                        return -EINVAL;
1746                }
1747                /* Check the index (none -> use current) */
1748                if (index < 0 || index >= 4)
1749                        index = current_index;
1750                else
1751                        priv->default_key = index;
1752                /* Set the length */
1753                if (dwrq->length > 5)
1754                        priv->wep_key_len[index] = 13;
1755                else
1756                        if (dwrq->length > 0)
1757                                priv->wep_key_len[index] = 5;
1758                        else
1759                                /* Disable the key */
1760                                priv->wep_key_len[index] = 0;
1761                /* Check if the key is not marked as invalid */
1762                if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
1763                        /* Cleanup */
1764                        memset(priv->wep_keys[index], 0, 13);
1765                        /* Copy the key in the driver */
1766                        memcpy(priv->wep_keys[index], extra, dwrq->length);
1767                }
1768                /* WE specify that if a valid key is set, encryption
1769                 * should be enabled (user may turn it off later)
1770                 * This is also how "iwconfig ethX key on" works */
1771                if (index == current_index &&
1772                    priv->wep_key_len[index] > 0) {
1773                        priv->wep_is_on = 1;
1774                        priv->exclude_unencrypted = 1;
1775                        if (priv->wep_key_len[index] > 5) {
1776                                priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
1777                                priv->encryption_level = 2;
1778                        } else {
1779                                priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
1780                                priv->encryption_level = 1;
1781                        }
1782                }
1783        } else {
1784                /* Do we want to just set the transmit key index ? */
1785                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1786                if (index >= 0 && index < 4) {
1787                        priv->default_key = index;
1788                } else
1789                        /* Don't complain if only change the mode */
1790                        if (!(dwrq->flags & IW_ENCODE_MODE))
1791                                return -EINVAL;
1792        }
1793        /* Read the flags */
1794        if (dwrq->flags & IW_ENCODE_DISABLED) {
1795                priv->wep_is_on = 0;
1796                priv->encryption_level = 0;
1797                priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
1798        } else {
1799                priv->wep_is_on = 1;
1800                if (priv->wep_key_len[priv->default_key] > 5) {
1801                        priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
1802                        priv->encryption_level = 2;
1803                } else {
1804                        priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
1805                        priv->encryption_level = 1;
1806                }
1807        }
1808        if (dwrq->flags & IW_ENCODE_RESTRICTED)
1809                priv->exclude_unencrypted = 1;
1810        if (dwrq->flags & IW_ENCODE_OPEN)
1811                priv->exclude_unencrypted = 0;
1812
1813        return -EINPROGRESS;            /* Call commit handler */
1814}
1815
1816static int atmel_get_encode(struct net_device *dev,
1817                            struct iw_request_info *info,
1818                            struct iw_point *dwrq,
1819                            char *extra)
1820{
1821        struct atmel_private *priv = netdev_priv(dev);
1822        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1823
1824        if (!priv->wep_is_on)
1825                dwrq->flags = IW_ENCODE_DISABLED;
1826        else {
1827                if (priv->exclude_unencrypted)
1828                        dwrq->flags = IW_ENCODE_RESTRICTED;
1829                else
1830                        dwrq->flags = IW_ENCODE_OPEN;
1831        }
1832                /* Which key do we want ? -1 -> tx index */
1833        if (index < 0 || index >= 4)
1834                index = priv->default_key;
1835        dwrq->flags |= index + 1;
1836        /* Copy the key to the user buffer */
1837        dwrq->length = priv->wep_key_len[index];
1838        if (dwrq->length > 16) {
1839                dwrq->length = 0;
1840        } else {
1841                memset(extra, 0, 16);
1842                memcpy(extra, priv->wep_keys[index], dwrq->length);
1843        }
1844
1845        return 0;
1846}
1847
1848static int atmel_set_encodeext(struct net_device *dev,
1849                            struct iw_request_info *info,
1850                            union iwreq_data *wrqu,
1851                            char *extra)
1852{
1853        struct atmel_private *priv = netdev_priv(dev);
1854        struct iw_point *encoding = &wrqu->encoding;
1855        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1856        int idx, key_len, alg = ext->alg, set_key = 1;
1857
1858        /* Determine and validate the key index */
1859        idx = encoding->flags & IW_ENCODE_INDEX;
1860        if (idx) {
1861                if (idx < 1 || idx > 4)
1862                        return -EINVAL;
1863                idx--;
1864        } else
1865                idx = priv->default_key;
1866
1867        if (encoding->flags & IW_ENCODE_DISABLED)
1868            alg = IW_ENCODE_ALG_NONE;
1869
1870        if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
1871                priv->default_key = idx;
1872                set_key = ext->key_len > 0 ? 1 : 0;
1873        }
1874
1875        if (set_key) {
1876                /* Set the requested key first */
1877                switch (alg) {
1878                case IW_ENCODE_ALG_NONE:
1879                        priv->wep_is_on = 0;
1880                        priv->encryption_level = 0;
1881                        priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
1882                        break;
1883                case IW_ENCODE_ALG_WEP:
1884                        if (ext->key_len > 5) {
1885                                priv->wep_key_len[idx] = 13;
1886                                priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
1887                                priv->encryption_level = 2;
1888                        } else if (ext->key_len > 0) {
1889                                priv->wep_key_len[idx] = 5;
1890                                priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
1891                                priv->encryption_level = 1;
1892                        } else {
1893                                return -EINVAL;
1894                        }
1895                        priv->wep_is_on = 1;
1896                        memset(priv->wep_keys[idx], 0, 13);
1897                        key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
1898                        memcpy(priv->wep_keys[idx], ext->key, key_len);
1899                        break;
1900                default:
1901                        return -EINVAL;
1902                }
1903        }
1904
1905        return -EINPROGRESS;
1906}
1907
1908static int atmel_get_encodeext(struct net_device *dev,
1909                            struct iw_request_info *info,
1910                            union iwreq_data *wrqu,
1911                            char *extra)
1912{
1913        struct atmel_private *priv = netdev_priv(dev);
1914        struct iw_point *encoding = &wrqu->encoding;
1915        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1916        int idx, max_key_len;
1917
1918        max_key_len = encoding->length - sizeof(*ext);
1919        if (max_key_len < 0)
1920                return -EINVAL;
1921
1922        idx = encoding->flags & IW_ENCODE_INDEX;
1923        if (idx) {
1924                if (idx < 1 || idx > 4)
1925                        return -EINVAL;
1926                idx--;
1927        } else
1928                idx = priv->default_key;
1929
1930        encoding->flags = idx + 1;
1931        memset(ext, 0, sizeof(*ext));
1932
1933        if (!priv->wep_is_on) {
1934                ext->alg = IW_ENCODE_ALG_NONE;
1935                ext->key_len = 0;
1936                encoding->flags |= IW_ENCODE_DISABLED;
1937        } else {
1938                if (priv->encryption_level > 0)
1939                        ext->alg = IW_ENCODE_ALG_WEP;
1940                else
1941                        return -EINVAL;
1942
1943                ext->key_len = priv->wep_key_len[idx];
1944                memcpy(ext->key, priv->wep_keys[idx], ext->key_len);
1945                encoding->flags |= IW_ENCODE_ENABLED;
1946        }
1947
1948        return 0;
1949}
1950
1951static int atmel_set_auth(struct net_device *dev,
1952                               struct iw_request_info *info,
1953                               union iwreq_data *wrqu, char *extra)
1954{
1955        struct atmel_private *priv = netdev_priv(dev);
1956        struct iw_param *param = &wrqu->param;
1957
1958        switch (param->flags & IW_AUTH_INDEX) {
1959        case IW_AUTH_WPA_VERSION:
1960        case IW_AUTH_CIPHER_PAIRWISE:
1961        case IW_AUTH_CIPHER_GROUP:
1962        case IW_AUTH_KEY_MGMT:
1963        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1964        case IW_AUTH_PRIVACY_INVOKED:
1965                /*
1966                 * atmel does not use these parameters
1967                 */
1968                break;
1969
1970        case IW_AUTH_DROP_UNENCRYPTED:
1971                priv->exclude_unencrypted = param->value ? 1 : 0;
1972                break;
1973
1974        case IW_AUTH_80211_AUTH_ALG: {
1975                        if (param->value & IW_AUTH_ALG_SHARED_KEY) {
1976                                priv->exclude_unencrypted = 1;
1977                        } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1978                                priv->exclude_unencrypted = 0;
1979                        } else
1980                                return -EINVAL;
1981                        break;
1982                }
1983
1984        case IW_AUTH_WPA_ENABLED:
1985                /* Silently accept disable of WPA */
1986                if (param->value > 0)
1987                        return -EOPNOTSUPP;
1988                break;
1989
1990        default:
1991                return -EOPNOTSUPP;
1992        }
1993        return -EINPROGRESS;
1994}
1995
1996static int atmel_get_auth(struct net_device *dev,
1997                               struct iw_request_info *info,
1998                               union iwreq_data *wrqu, char *extra)
1999{
2000        struct atmel_private *priv = netdev_priv(dev);
2001        struct iw_param *param = &wrqu->param;
2002
2003        switch (param->flags & IW_AUTH_INDEX) {
2004        case IW_AUTH_DROP_UNENCRYPTED:
2005                param->value = priv->exclude_unencrypted;
2006                break;
2007
2008        case IW_AUTH_80211_AUTH_ALG:
2009                if (priv->exclude_unencrypted == 1)
2010                        param->value = IW_AUTH_ALG_SHARED_KEY;
2011                else
2012                        param->value = IW_AUTH_ALG_OPEN_SYSTEM;
2013                break;
2014
2015        case IW_AUTH_WPA_ENABLED:
2016                param->value = 0;
2017                break;
2018
2019        default:
2020                return -EOPNOTSUPP;
2021        }
2022        return 0;
2023}
2024
2025
2026static int atmel_get_name(struct net_device *dev,
2027                          struct iw_request_info *info,
2028                          char *cwrq,
2029                          char *extra)
2030{
2031        strcpy(cwrq, "IEEE 802.11-DS");
2032        return 0;
2033}
2034
2035static int atmel_set_rate(struct net_device *dev,
2036                          struct iw_request_info *info,
2037                          struct iw_param *vwrq,
2038                          char *extra)
2039{
2040        struct atmel_private *priv = netdev_priv(dev);
2041
2042        if (vwrq->fixed == 0) {
2043                priv->tx_rate = 3;
2044                priv->auto_tx_rate = 1;
2045        } else {
2046                priv->auto_tx_rate = 0;
2047
2048                /* Which type of value ? */
2049                if ((vwrq->value < 4) && (vwrq->value >= 0)) {
2050                        /* Setting by rate index */
2051                        priv->tx_rate = vwrq->value;
2052                } else {
2053                /* Setting by frequency value */
2054                        switch (vwrq->value) {
2055                        case  1000000:
2056                                priv->tx_rate = 0;
2057                                break;
2058                        case  2000000:
2059                                priv->tx_rate = 1;
2060                                break;
2061                        case  5500000:
2062                                priv->tx_rate = 2;
2063                                break;
2064                        case 11000000:
2065                                priv->tx_rate = 3;
2066                                break;
2067                        default:
2068                                return -EINVAL;
2069                        }
2070                }
2071        }
2072
2073        return -EINPROGRESS;
2074}
2075
2076static int atmel_set_mode(struct net_device *dev,
2077                          struct iw_request_info *info,
2078                          __u32 *uwrq,
2079                          char *extra)
2080{
2081        struct atmel_private *priv = netdev_priv(dev);
2082
2083        if (*uwrq != IW_MODE_ADHOC && *uwrq != IW_MODE_INFRA)
2084                return -EINVAL;
2085
2086        priv->operating_mode = *uwrq;
2087        return -EINPROGRESS;
2088}
2089
2090static int atmel_get_mode(struct net_device *dev,
2091                          struct iw_request_info *info,
2092                          __u32 *uwrq,
2093                          char *extra)
2094{
2095        struct atmel_private *priv = netdev_priv(dev);
2096
2097        *uwrq = priv->operating_mode;
2098        return 0;
2099}
2100
2101static int atmel_get_rate(struct net_device *dev,
2102                         struct iw_request_info *info,
2103                         struct iw_param *vwrq,
2104                         char *extra)
2105{
2106        struct atmel_private *priv = netdev_priv(dev);
2107
2108        if (priv->auto_tx_rate) {
2109                vwrq->fixed = 0;
2110                vwrq->value = 11000000;
2111        } else {
2112                vwrq->fixed = 1;
2113                switch (priv->tx_rate) {
2114                case 0:
2115                        vwrq->value =  1000000;
2116                        break;
2117                case 1:
2118                        vwrq->value =  2000000;
2119                        break;
2120                case 2:
2121                        vwrq->value =  5500000;
2122                        break;
2123                case 3:
2124                        vwrq->value = 11000000;
2125                        break;
2126                }
2127        }
2128        return 0;
2129}
2130
2131static int atmel_set_power(struct net_device *dev,
2132                           struct iw_request_info *info,
2133                           struct iw_param *vwrq,
2134                           char *extra)
2135{
2136        struct atmel_private *priv = netdev_priv(dev);
2137        priv->power_mode = vwrq->disabled ? 0 : 1;
2138        return -EINPROGRESS;
2139}
2140
2141static int atmel_get_power(struct net_device *dev,
2142                           struct iw_request_info *info,
2143                           struct iw_param *vwrq,
2144                           char *extra)
2145{
2146        struct atmel_private *priv = netdev_priv(dev);
2147        vwrq->disabled = priv->power_mode ? 0 : 1;
2148        vwrq->flags = IW_POWER_ON;
2149        return 0;
2150}
2151
2152static int atmel_set_retry(struct net_device *dev,
2153                           struct iw_request_info *info,
2154                           struct iw_param *vwrq,
2155                           char *extra)
2156{
2157        struct atmel_private *priv = netdev_priv(dev);
2158
2159        if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
2160                if (vwrq->flags & IW_RETRY_LONG)
2161                        priv->long_retry = vwrq->value;
2162                else if (vwrq->flags & IW_RETRY_SHORT)
2163                        priv->short_retry = vwrq->value;
2164                else {
2165                        /* No modifier : set both */
2166                        priv->long_retry = vwrq->value;
2167                        priv->short_retry = vwrq->value;
2168                }
2169                return -EINPROGRESS;
2170        }
2171
2172        return -EINVAL;
2173}
2174
2175static int atmel_get_retry(struct net_device *dev,
2176                           struct iw_request_info *info,
2177                           struct iw_param *vwrq,
2178                           char *extra)
2179{
2180        struct atmel_private *priv = netdev_priv(dev);
2181
2182        vwrq->disabled = 0;      /* Can't be disabled */
2183
2184        /* Note : by default, display the short retry number */
2185        if (vwrq->flags & IW_RETRY_LONG) {
2186                vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
2187                vwrq->value = priv->long_retry;
2188        } else {
2189                vwrq->flags = IW_RETRY_LIMIT;
2190                vwrq->value = priv->short_retry;
2191                if (priv->long_retry != priv->short_retry)
2192                        vwrq->flags |= IW_RETRY_SHORT;
2193        }
2194
2195        return 0;
2196}
2197
2198static int atmel_set_rts(struct net_device *dev,
2199                         struct iw_request_info *info,
2200                         struct iw_param *vwrq,
2201                         char *extra)
2202{
2203        struct atmel_private *priv = netdev_priv(dev);
2204        int rthr = vwrq->value;
2205
2206        if (vwrq->disabled)
2207                rthr = 2347;
2208        if ((rthr < 0) || (rthr > 2347)) {
2209                return -EINVAL;
2210        }
2211        priv->rts_threshold = rthr;
2212
2213        return -EINPROGRESS;            /* Call commit handler */
2214}
2215
2216static int atmel_get_rts(struct net_device *dev,
2217                         struct iw_request_info *info,
2218                         struct iw_param *vwrq,
2219                         char *extra)
2220{
2221        struct atmel_private *priv = netdev_priv(dev);
2222
2223        vwrq->value = priv->rts_threshold;
2224        vwrq->disabled = (vwrq->value >= 2347);
2225        vwrq->fixed = 1;
2226
2227        return 0;
2228}
2229
2230static int atmel_set_frag(struct net_device *dev,
2231                          struct iw_request_info *info,
2232                          struct iw_param *vwrq,
2233                          char *extra)
2234{
2235        struct atmel_private *priv = netdev_priv(dev);
2236        int fthr = vwrq->value;
2237
2238        if (vwrq->disabled)
2239                fthr = 2346;
2240        if ((fthr < 256) || (fthr > 2346)) {
2241                return -EINVAL;
2242        }
2243        fthr &= ~0x1;   /* Get an even value - is it really needed ??? */
2244        priv->frag_threshold = fthr;
2245
2246        return -EINPROGRESS;            /* Call commit handler */
2247}
2248
2249static int atmel_get_frag(struct net_device *dev,
2250                          struct iw_request_info *info,
2251                          struct iw_param *vwrq,
2252                          char *extra)
2253{
2254        struct atmel_private *priv = netdev_priv(dev);
2255
2256        vwrq->value = priv->frag_threshold;
2257        vwrq->disabled = (vwrq->value >= 2346);
2258        vwrq->fixed = 1;
2259
2260        return 0;
2261}
2262
2263static int atmel_set_freq(struct net_device *dev,
2264                          struct iw_request_info *info,
2265                          struct iw_freq *fwrq,
2266                          char *extra)
2267{
2268        struct atmel_private *priv = netdev_priv(dev);
2269        int rc = -EINPROGRESS;          /* Call commit handler */
2270
2271        /* If setting by frequency, convert to a channel */
2272        if (fwrq->e == 1) {
2273                int f = fwrq->m / 100000;
2274
2275                /* Hack to fall through... */
2276                fwrq->e = 0;
2277                fwrq->m = ieee80211_freq_to_dsss_chan(f);
2278        }
2279        /* Setting by channel number */
2280        if ((fwrq->m > 1000) || (fwrq->e > 0))
2281                rc = -EOPNOTSUPP;
2282        else {
2283                int channel = fwrq->m;
2284                if (atmel_validate_channel(priv, channel) == 0) {
2285                        priv->channel = channel;
2286                } else {
2287                        rc = -EINVAL;
2288                }
2289        }
2290        return rc;
2291}
2292
2293static int atmel_get_freq(struct net_device *dev,
2294                          struct iw_request_info *info,
2295                          struct iw_freq *fwrq,
2296                          char *extra)
2297{
2298        struct atmel_private *priv = netdev_priv(dev);
2299
2300        fwrq->m = priv->channel;
2301        fwrq->e = 0;
2302        return 0;
2303}
2304
2305static int atmel_set_scan(struct net_device *dev,
2306                          struct iw_request_info *info,
2307                          struct iw_point *dwrq,
2308                          char *extra)
2309{
2310        struct atmel_private *priv = netdev_priv(dev);
2311        unsigned long flags;
2312
2313        /* Note : you may have realised that, as this is a SET operation,
2314         * this is privileged and therefore a normal user can't
2315         * perform scanning.
2316         * This is not an error, while the device perform scanning,
2317         * traffic doesn't flow, so it's a perfect DoS...
2318         * Jean II */
2319
2320        if (priv->station_state == STATION_STATE_DOWN)
2321                return -EAGAIN;
2322
2323        /* Timeout old surveys. */
2324        if (time_after(jiffies, priv->last_survey + 20 * HZ))
2325                priv->site_survey_state = SITE_SURVEY_IDLE;
2326        priv->last_survey = jiffies;
2327
2328        /* Initiate a scan command */
2329        if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
2330                return -EBUSY;
2331
2332        del_timer_sync(&priv->management_timer);
2333        spin_lock_irqsave(&priv->irqlock, flags);
2334
2335        priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
2336        priv->fast_scan = 0;
2337        atmel_scan(priv, 0);
2338        spin_unlock_irqrestore(&priv->irqlock, flags);
2339
2340        return 0;
2341}
2342
2343static int atmel_get_scan(struct net_device *dev,
2344                          struct iw_request_info *info,
2345                          struct iw_point *dwrq,
2346                          char *extra)
2347{
2348        struct atmel_private *priv = netdev_priv(dev);
2349        int i;
2350        char *current_ev = extra;
2351        struct iw_event iwe;
2352
2353        if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
2354                return -EAGAIN;
2355
2356        for (i = 0; i < priv->BSS_list_entries; i++) {
2357                iwe.cmd = SIOCGIWAP;
2358                iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
2359                memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
2360                current_ev = iwe_stream_add_event(info, current_ev,
2361                                                  extra + IW_SCAN_MAX_DATA,
2362                                                  &iwe, IW_EV_ADDR_LEN);
2363
2364                iwe.u.data.length =  priv->BSSinfo[i].SSIDsize;
2365                if (iwe.u.data.length > 32)
2366                        iwe.u.data.length = 32;
2367                iwe.cmd = SIOCGIWESSID;
2368                iwe.u.data.flags = 1;
2369                current_ev = iwe_stream_add_point(info, current_ev,
2370                                                  extra + IW_SCAN_MAX_DATA,
2371                                                  &iwe, priv->BSSinfo[i].SSID);
2372
2373                iwe.cmd = SIOCGIWMODE;
2374                iwe.u.mode = priv->BSSinfo[i].BSStype;
2375                current_ev = iwe_stream_add_event(info, current_ev,
2376                                                  extra + IW_SCAN_MAX_DATA,
2377                                                  &iwe, IW_EV_UINT_LEN);
2378
2379                iwe.cmd = SIOCGIWFREQ;
2380                iwe.u.freq.m = priv->BSSinfo[i].channel;
2381                iwe.u.freq.e = 0;
2382                current_ev = iwe_stream_add_event(info, current_ev,
2383                                                  extra + IW_SCAN_MAX_DATA,
2384                                                  &iwe, IW_EV_FREQ_LEN);
2385
2386                /* Add quality statistics */
2387                iwe.cmd = IWEVQUAL;
2388                iwe.u.qual.level = priv->BSSinfo[i].RSSI;
2389                iwe.u.qual.qual  = iwe.u.qual.level;
2390                /* iwe.u.qual.noise  = SOMETHING */
2391                current_ev = iwe_stream_add_event(info, current_ev,
2392                                                  extra + IW_SCAN_MAX_DATA,
2393                                                  &iwe, IW_EV_QUAL_LEN);
2394
2395
2396                iwe.cmd = SIOCGIWENCODE;
2397                if (priv->BSSinfo[i].UsingWEP)
2398                        iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
2399                else
2400                        iwe.u.data.flags = IW_ENCODE_DISABLED;
2401                iwe.u.data.length = 0;
2402                current_ev = iwe_stream_add_point(info, current_ev,
2403                                                  extra + IW_SCAN_MAX_DATA,
2404                                                  &iwe, NULL);
2405        }
2406
2407        /* Length of data */
2408        dwrq->length = (current_ev - extra);
2409        dwrq->flags = 0;
2410
2411        return 0;
2412}
2413
2414static int atmel_get_range(struct net_device *dev,
2415                           struct iw_request_info *info,
2416                           struct iw_point *dwrq,
2417                           char *extra)
2418{
2419        struct atmel_private *priv = netdev_priv(dev);
2420        struct iw_range *range = (struct iw_range *) extra;
2421        int k, i, j;
2422
2423        dwrq->length = sizeof(struct iw_range);
2424        memset(range, 0, sizeof(struct iw_range));
2425        range->min_nwid = 0x0000;
2426        range->max_nwid = 0x0000;
2427        range->num_channels = 0;
2428        for (j = 0; j < ARRAY_SIZE(channel_table); j++)
2429                if (priv->reg_domain == channel_table[j].reg_domain) {
2430                        range->num_channels = channel_table[j].max - channel_table[j].min + 1;
2431                        break;
2432                }
2433        if (range->num_channels != 0) {
2434                for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
2435                        range->freq[k].i = i; /* List index */
2436
2437                        /* Values in MHz -> * 10^5 * 10 */
2438                        range->freq[k].m = (ieee80211_dsss_chan_to_freq(i) *
2439                                            100000);
2440                        range->freq[k++].e = 1;
2441                }
2442                range->num_frequency = k;
2443        }
2444
2445        range->max_qual.qual = 100;
2446        range->max_qual.level = 100;
2447        range->max_qual.noise = 0;
2448        range->max_qual.updated = IW_QUAL_NOISE_INVALID;
2449
2450        range->avg_qual.qual = 50;
2451        range->avg_qual.level = 50;
2452        range->avg_qual.noise = 0;
2453        range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
2454
2455        range->sensitivity = 0;
2456
2457        range->bitrate[0] =  1000000;
2458        range->bitrate[1] =  2000000;
2459        range->bitrate[2] =  5500000;
2460        range->bitrate[3] = 11000000;
2461        range->num_bitrates = 4;
2462
2463        range->min_rts = 0;
2464        range->max_rts = 2347;
2465        range->min_frag = 256;
2466        range->max_frag = 2346;
2467
2468        range->encoding_size[0] = 5;
2469        range->encoding_size[1] = 13;
2470        range->num_encoding_sizes = 2;
2471        range->max_encoding_tokens = 4;
2472
2473        range->pmp_flags = IW_POWER_ON;
2474        range->pmt_flags = IW_POWER_ON;
2475        range->pm_capa = 0;
2476
2477        range->we_version_source = WIRELESS_EXT;
2478        range->we_version_compiled = WIRELESS_EXT;
2479        range->retry_capa = IW_RETRY_LIMIT ;
2480        range->retry_flags = IW_RETRY_LIMIT;
2481        range->r_time_flags = 0;
2482        range->min_retry = 1;
2483        range->max_retry = 65535;
2484
2485        return 0;
2486}
2487
2488static int atmel_set_wap(struct net_device *dev,
2489                         struct iw_request_info *info,
2490                         struct sockaddr *awrq,
2491                         char *extra)
2492{
2493        struct atmel_private *priv = netdev_priv(dev);
2494        int i;
2495        static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2496        static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2497        unsigned long flags;
2498
2499        if (awrq->sa_family != ARPHRD_ETHER)
2500                return -EINVAL;
2501
2502        if (!memcmp(any, awrq->sa_data, 6) ||
2503            !memcmp(off, awrq->sa_data, 6)) {
2504                del_timer_sync(&priv->management_timer);
2505                spin_lock_irqsave(&priv->irqlock, flags);
2506                atmel_scan(priv, 1);
2507                spin_unlock_irqrestore(&priv->irqlock, flags);
2508                return 0;
2509        }
2510
2511        for (i = 0; i < priv->BSS_list_entries; i++) {
2512                if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
2513                        if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) {
2514                                return -EINVAL;
2515                        } else if  (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) {
2516                                return -EINVAL;
2517                        } else {
2518                                del_timer_sync(&priv->management_timer);
2519                                spin_lock_irqsave(&priv->irqlock, flags);
2520                                atmel_join_bss(priv, i);
2521                                spin_unlock_irqrestore(&priv->irqlock, flags);
2522                                return 0;
2523                        }
2524                }
2525        }
2526
2527        return -EINVAL;
2528}
2529
2530static int atmel_config_commit(struct net_device *dev,
2531                               struct iw_request_info *info,    /* NULL */
2532                               void *zwrq,                      /* NULL */
2533                               char *extra)                     /* NULL */
2534{
2535        return atmel_open(dev);
2536}
2537
2538static const iw_handler atmel_handler[] =
2539{
2540        (iw_handler) atmel_config_commit,       /* SIOCSIWCOMMIT */
2541        (iw_handler) atmel_get_name,            /* SIOCGIWNAME */
2542        (iw_handler) NULL,                      /* SIOCSIWNWID */
2543        (iw_handler) NULL,                      /* SIOCGIWNWID */
2544        (iw_handler) atmel_set_freq,            /* SIOCSIWFREQ */
2545        (iw_handler) atmel_get_freq,            /* SIOCGIWFREQ */
2546        (iw_handler) atmel_set_mode,            /* SIOCSIWMODE */
2547        (iw_handler) atmel_get_mode,            /* SIOCGIWMODE */
2548        (iw_handler) NULL,                      /* SIOCSIWSENS */
2549        (iw_handler) NULL,                      /* SIOCGIWSENS */
2550        (iw_handler) NULL,                      /* SIOCSIWRANGE */
2551        (iw_handler) atmel_get_range,           /* SIOCGIWRANGE */
2552        (iw_handler) NULL,                      /* SIOCSIWPRIV */
2553        (iw_handler) NULL,                      /* SIOCGIWPRIV */
2554        (iw_handler) NULL,                      /* SIOCSIWSTATS */
2555        (iw_handler) NULL,                      /* SIOCGIWSTATS */
2556        (iw_handler) NULL,                      /* SIOCSIWSPY */
2557        (iw_handler) NULL,                      /* SIOCGIWSPY */
2558        (iw_handler) NULL,                      /* -- hole -- */
2559        (iw_handler) NULL,                      /* -- hole -- */
2560        (iw_handler) atmel_set_wap,             /* SIOCSIWAP */
2561        (iw_handler) atmel_get_wap,             /* SIOCGIWAP */
2562        (iw_handler) NULL,                      /* -- hole -- */
2563        (iw_handler) NULL,                      /* SIOCGIWAPLIST */
2564        (iw_handler) atmel_set_scan,            /* SIOCSIWSCAN */
2565        (iw_handler) atmel_get_scan,            /* SIOCGIWSCAN */
2566        (iw_handler) atmel_set_essid,           /* SIOCSIWESSID */
2567        (iw_handler) atmel_get_essid,           /* SIOCGIWESSID */
2568        (iw_handler) NULL,                      /* SIOCSIWNICKN */
2569        (iw_handler) NULL,                      /* SIOCGIWNICKN */
2570        (iw_handler) NULL,                      /* -- hole -- */
2571        (iw_handler) NULL,                      /* -- hole -- */
2572        (iw_handler) atmel_set_rate,            /* SIOCSIWRATE */
2573        (iw_handler) atmel_get_rate,            /* SIOCGIWRATE */
2574        (iw_handler) atmel_set_rts,             /* SIOCSIWRTS */
2575        (iw_handler) atmel_get_rts,             /* SIOCGIWRTS */
2576        (iw_handler) atmel_set_frag,            /* SIOCSIWFRAG */
2577        (iw_handler) atmel_get_frag,            /* SIOCGIWFRAG */
2578        (iw_handler) NULL,                      /* SIOCSIWTXPOW */
2579        (iw_handler) NULL,                      /* SIOCGIWTXPOW */
2580        (iw_handler) atmel_set_retry,           /* SIOCSIWRETRY */
2581        (iw_handler) atmel_get_retry,           /* SIOCGIWRETRY */
2582        (iw_handler) atmel_set_encode,          /* SIOCSIWENCODE */
2583        (iw_handler) atmel_get_encode,          /* SIOCGIWENCODE */
2584        (iw_handler) atmel_set_power,           /* SIOCSIWPOWER */
2585        (iw_handler) atmel_get_power,           /* SIOCGIWPOWER */
2586        (iw_handler) NULL,                      /* -- hole -- */
2587        (iw_handler) NULL,                      /* -- hole -- */
2588        (iw_handler) NULL,                      /* SIOCSIWGENIE */
2589        (iw_handler) NULL,                      /* SIOCGIWGENIE */
2590        (iw_handler) atmel_set_auth,            /* SIOCSIWAUTH */
2591        (iw_handler) atmel_get_auth,            /* SIOCGIWAUTH */
2592        (iw_handler) atmel_set_encodeext,       /* SIOCSIWENCODEEXT */
2593        (iw_handler) atmel_get_encodeext,       /* SIOCGIWENCODEEXT */
2594        (iw_handler) NULL,                      /* SIOCSIWPMKSA */
2595};
2596
2597static const iw_handler atmel_private_handler[] =
2598{
2599        NULL,                           /* SIOCIWFIRSTPRIV */
2600};
2601
2602typedef struct atmel_priv_ioctl {
2603        char id[32];
2604        unsigned char __user *data;
2605        unsigned short len;
2606} atmel_priv_ioctl;
2607
2608#define ATMELFWL        SIOCIWFIRSTPRIV
2609#define ATMELIDIFC      ATMELFWL + 1
2610#define ATMELRD         ATMELFWL + 2
2611#define ATMELMAGIC 0x51807
2612#define REGDOMAINSZ 20
2613
2614static const struct iw_priv_args atmel_private_args[] = {
2615        {
2616                .cmd = ATMELFWL,
2617                .set_args = IW_PRIV_TYPE_BYTE
2618                                | IW_PRIV_SIZE_FIXED
2619                                | sizeof (atmel_priv_ioctl),
2620                .get_args = IW_PRIV_TYPE_NONE,
2621                .name = "atmelfwl"
2622        }, {
2623                .cmd = ATMELIDIFC,
2624                .set_args = IW_PRIV_TYPE_NONE,
2625                .get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
2626                .name = "atmelidifc"
2627        }, {
2628                .cmd = ATMELRD,
2629                .set_args = IW_PRIV_TYPE_CHAR | REGDOMAINSZ,
2630                .get_args = IW_PRIV_TYPE_NONE,
2631                .name = "regdomain"
2632        },
2633};
2634
2635static const struct iw_handler_def atmel_handler_def = {
2636        .num_standard   = ARRAY_SIZE(atmel_handler),
2637        .num_private    = ARRAY_SIZE(atmel_private_handler),
2638        .num_private_args = ARRAY_SIZE(atmel_private_args),
2639        .standard       = (iw_handler *) atmel_handler,
2640        .private        = (iw_handler *) atmel_private_handler,
2641        .private_args   = (struct iw_priv_args *) atmel_private_args,
2642        .get_wireless_stats = atmel_get_wireless_stats
2643};
2644
2645static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2646{
2647        int i, rc = 0;
2648        struct atmel_private *priv = netdev_priv(dev);
2649        atmel_priv_ioctl com;
2650        struct iwreq *wrq = (struct iwreq *) rq;
2651        unsigned char *new_firmware;
2652        char domain[REGDOMAINSZ + 1];
2653
2654        switch (cmd) {
2655        case ATMELIDIFC:
2656                wrq->u.param.value = ATMELMAGIC;
2657                break;
2658
2659        case ATMELFWL:
2660                if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
2661                        rc = -EFAULT;
2662                        break;
2663                }
2664
2665                if (!capable(CAP_NET_ADMIN)) {
2666                        rc = -EPERM;
2667                        break;
2668                }
2669
2670                if (!(new_firmware = kmalloc(com.len, GFP_KERNEL))) {
2671                        rc = -ENOMEM;
2672                        break;
2673                }
2674
2675                if (copy_from_user(new_firmware, com.data, com.len)) {
2676                        kfree(new_firmware);
2677                        rc = -EFAULT;
2678                        break;
2679                }
2680
2681                kfree(priv->firmware);
2682
2683                priv->firmware = new_firmware;
2684                priv->firmware_length = com.len;
2685                strncpy(priv->firmware_id, com.id, 31);
2686                priv->firmware_id[31] = '\0';
2687                break;
2688
2689        case ATMELRD:
2690                if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) {
2691                        rc = -EFAULT;
2692                        break;
2693                }
2694
2695                if (!capable(CAP_NET_ADMIN)) {
2696                        rc = -EPERM;
2697                        break;
2698                }
2699
2700                domain[REGDOMAINSZ] = 0;
2701                rc = -EINVAL;
2702                for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
2703                        /* strcasecmp doesn't exist in the library */
2704                        char *a = channel_table[i].name;
2705                        char *b = domain;
2706                        while (*a) {
2707                                char c1 = *a++;
2708                                char c2 = *b++;
2709                                if (tolower(c1) != tolower(c2))
2710                                        break;
2711                        }
2712                        if (!*a && !*b) {
2713                                priv->config_reg_domain = channel_table[i].reg_domain;
2714                                rc = 0;
2715                        }
2716                }
2717
2718                if (rc == 0 &&  priv->station_state != STATION_STATE_DOWN)
2719                        rc = atmel_open(dev);
2720                break;
2721
2722        default:
2723                rc = -EOPNOTSUPP;
2724        }
2725
2726        return rc;
2727}
2728
2729struct auth_body {
2730        __le16 alg;
2731        __le16 trans_seq;
2732        __le16 status;
2733        u8 el_id;
2734        u8 chall_text_len;
2735        u8 chall_text[253];
2736};
2737
2738static void atmel_enter_state(struct atmel_private *priv, int new_state)
2739{
2740        int old_state = priv->station_state;
2741
2742        if (new_state == old_state)
2743                return;
2744
2745        priv->station_state = new_state;
2746
2747        if (new_state == STATION_STATE_READY) {
2748                netif_start_queue(priv->dev);
2749                netif_carrier_on(priv->dev);
2750        }
2751
2752        if (old_state == STATION_STATE_READY) {
2753                netif_carrier_off(priv->dev);
2754                if (netif_running(priv->dev))
2755                        netif_stop_queue(priv->dev);
2756                priv->last_beacon_timestamp = 0;
2757        }
2758}
2759
2760static void atmel_scan(struct atmel_private *priv, int specific_ssid)
2761{
2762        struct {
2763                u8 BSSID[6];
2764                u8 SSID[MAX_SSID_LENGTH];
2765                u8 scan_type;
2766                u8 channel;
2767                __le16 BSS_type;
2768                __le16 min_channel_time;
2769                __le16 max_channel_time;
2770                u8 options;
2771                u8 SSID_size;
2772        } cmd;
2773
2774        memset(cmd.BSSID, 0xff, 6);
2775
2776        if (priv->fast_scan) {
2777                cmd.SSID_size = priv->SSID_size;
2778                memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
2779                cmd.min_channel_time = cpu_to_le16(10);
2780                cmd.max_channel_time = cpu_to_le16(50);
2781        } else {
2782                priv->BSS_list_entries = 0;
2783                cmd.SSID_size = 0;
2784                cmd.min_channel_time = cpu_to_le16(10);
2785                cmd.max_channel_time = cpu_to_le16(120);
2786        }
2787
2788        cmd.options = 0;
2789
2790        if (!specific_ssid)
2791                cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
2792
2793        cmd.channel = (priv->channel & 0x7f);
2794        cmd.scan_type = SCAN_TYPE_ACTIVE;
2795        cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
2796                BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
2797
2798        atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
2799
2800        /* This must come after all hardware access to avoid being messed up
2801           by stuff happening in interrupt context after we leave STATE_DOWN */
2802        atmel_enter_state(priv, STATION_STATE_SCANNING);
2803}
2804
2805static void join(struct atmel_private *priv, int type)
2806{
2807        struct {
2808                u8 BSSID[6];
2809                u8 SSID[MAX_SSID_LENGTH];
2810                u8 BSS_type; /* this is a short in a scan command - weird */
2811                u8 channel;
2812                __le16 timeout;
2813                u8 SSID_size;
2814                u8 reserved;
2815        } cmd;
2816
2817        cmd.SSID_size = priv->SSID_size;
2818        memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
2819        memcpy(cmd.BSSID, priv->CurrentBSSID, 6);
2820        cmd.channel = (priv->channel & 0x7f);
2821        cmd.BSS_type = type;
2822        cmd.timeout = cpu_to_le16(2000);
2823
2824        atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
2825}
2826
2827static void start(struct atmel_private *priv, int type)
2828{
2829        struct {
2830                u8 BSSID[6];
2831                u8 SSID[MAX_SSID_LENGTH];
2832                u8 BSS_type;
2833                u8 channel;
2834                u8 SSID_size;
2835                u8 reserved[3];
2836        } cmd;
2837
2838        cmd.SSID_size = priv->SSID_size;
2839        memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
2840        memcpy(cmd.BSSID, priv->BSSID, 6);
2841        cmd.BSS_type = type;
2842        cmd.channel = (priv->channel & 0x7f);
2843
2844        atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
2845}
2846
2847static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
2848                                u8 channel)
2849{
2850        int rejoin = 0;
2851        int new = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
2852                SHORT_PREAMBLE : LONG_PREAMBLE;
2853
2854        if (priv->preamble != new) {
2855                priv->preamble = new;
2856                rejoin = 1;
2857                atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
2858        }
2859
2860        if (priv->channel != channel) {
2861                priv->channel = channel;
2862                rejoin = 1;
2863                atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
2864        }
2865
2866        if (rejoin) {
2867                priv->station_is_associated = 0;
2868                atmel_enter_state(priv, STATION_STATE_JOINNING);
2869
2870                if (priv->operating_mode == IW_MODE_INFRA)
2871                        join(priv, BSS_TYPE_INFRASTRUCTURE);
2872                else
2873                        join(priv, BSS_TYPE_AD_HOC);
2874        }
2875}
2876
2877static void send_authentication_request(struct atmel_private *priv, u16 system,
2878                                        u8 *challenge, int challenge_len)
2879{
2880        struct ieee80211_hdr header;
2881        struct auth_body auth;
2882
2883        header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
2884        header.duration_id = cpu_to_le16(0x8000);
2885        header.seq_ctrl = 0;
2886        memcpy(header.addr1, priv->CurrentBSSID, 6);
2887        memcpy(header.addr2, priv->dev->dev_addr, 6);
2888        memcpy(header.addr3, priv->CurrentBSSID, 6);
2889
2890        if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
2891                /* no WEP for authentication frames with TrSeqNo 1 */
2892                header.frame_control |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
2893
2894        auth.alg = cpu_to_le16(system);
2895
2896        auth.status = 0;
2897        auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
2898        priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
2899        priv->CurrentAuthentTransactionSeqNum += 2;
2900
2901        if (challenge_len != 0) {
2902                auth.el_id = 16; /* challenge_text */
2903                auth.chall_text_len = challenge_len;
2904                memcpy(auth.chall_text, challenge, challenge_len);
2905                atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 8 + challenge_len);
2906        } else {
2907                atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 6);
2908        }
2909}
2910
2911static void send_association_request(struct atmel_private *priv, int is_reassoc)
2912{
2913        u8 *ssid_el_p;
2914        int bodysize;
2915        struct ieee80211_hdr header;
2916        struct ass_req_format {
2917                __le16 capability;
2918                __le16 listen_interval;
2919                u8 ap[6]; /* nothing after here directly accessible */
2920                u8 ssid_el_id;
2921                u8 ssid_len;
2922                u8 ssid[MAX_SSID_LENGTH];
2923                u8 sup_rates_el_id;
2924                u8 sup_rates_len;
2925                u8 rates[4];
2926        } body;
2927
2928        header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2929                (is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
2930        header.duration_id = cpu_to_le16(0x8000);
2931        header.seq_ctrl = 0;
2932
2933        memcpy(header.addr1, priv->CurrentBSSID, 6);
2934        memcpy(header.addr2, priv->dev->dev_addr, 6);
2935        memcpy(header.addr3, priv->CurrentBSSID, 6);
2936
2937        body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
2938        if (priv->wep_is_on)
2939                body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
2940        if (priv->preamble == SHORT_PREAMBLE)
2941                body.capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
2942
2943        body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
2944
2945        /* current AP address - only in reassoc frame */
2946        if (is_reassoc) {
2947                memcpy(body.ap, priv->CurrentBSSID, 6);
2948                ssid_el_p = &body.ssid_el_id;
2949                bodysize = 18 + priv->SSID_size;
2950        } else {
2951                ssid_el_p = &body.ap[0];
2952                bodysize = 12 + priv->SSID_size;
2953        }
2954
2955        ssid_el_p[0] = WLAN_EID_SSID;
2956        ssid_el_p[1] = priv->SSID_size;
2957        memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
2958        ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
2959        ssid_el_p[3 + priv->SSID_size] = 4; /* len of supported rates */
2960        memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
2961
2962        atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
2963}
2964
2965static int is_frame_from_current_bss(struct atmel_private *priv,
2966                                     struct ieee80211_hdr *header)
2967{
2968        if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
2969                return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
2970        else
2971                return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
2972}
2973
2974static int retrieve_bss(struct atmel_private *priv)
2975{
2976        int i;
2977        int max_rssi = -128;
2978        int max_index = -1;
2979
2980        if (priv->BSS_list_entries == 0)
2981                return -1;
2982
2983        if (priv->connect_to_any_BSS) {
2984                /* Select a BSS with the max-RSSI but of the same type and of
2985                   the same WEP mode and that it is not marked as 'bad' (i.e.
2986                   we had previously failed to connect to this BSS with the
2987                   settings that we currently use) */
2988                priv->current_BSS = 0;
2989                for (i = 0; i < priv->BSS_list_entries; i++) {
2990                        if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
2991                            ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
2992                             (priv->wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
2993                            !(priv->BSSinfo[i].channel & 0x80)) {
2994                                max_rssi = priv->BSSinfo[i].RSSI;
2995                                priv->current_BSS = max_index = i;
2996                        }
2997                }
2998                return max_index;
2999        }
3000
3001        for (i = 0; i < priv->BSS_list_entries; i++) {
3002                if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
3003                    memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
3004                    priv->operating_mode == priv->BSSinfo[i].BSStype &&
3005                    atmel_validate_channel(priv, priv->BSSinfo[i].channel) == 0) {
3006                        if (priv->BSSinfo[i].RSSI >= max_rssi) {
3007                                max_rssi = priv->BSSinfo[i].RSSI;
3008                                max_index = i;
3009                        }
3010                }
3011        }
3012        return max_index;
3013}
3014
3015static void store_bss_info(struct atmel_private *priv,
3016                           struct ieee80211_hdr *header, u16 capability,
3017                           u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
3018                           u8 *ssid, int is_beacon)
3019{
3020        u8 *bss = capability & WLAN_CAPABILITY_ESS ? header->addr2 : header->addr3;
3021        int i, index;
3022
3023        for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
3024                if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
3025                        index = i;
3026
3027        /* If we process a probe and an entry from this BSS exists
3028           we will update the BSS entry with the info from this BSS.
3029           If we process a beacon we will only update RSSI */
3030
3031        if (index == -1) {
3032                if (priv->BSS_list_entries == MAX_BSS_ENTRIES)
3033                        return;
3034                index = priv->BSS_list_entries++;
3035                memcpy(priv->BSSinfo[index].BSSID, bss, 6);
3036                priv->BSSinfo[index].RSSI = rssi;
3037        } else {
3038                if (rssi > priv->BSSinfo[index].RSSI)
3039                        priv->BSSinfo[index].RSSI = rssi;
3040                if (is_beacon)
3041                        return;
3042        }
3043
3044        priv->BSSinfo[index].channel = channel;
3045        priv->BSSinfo[index].beacon_period = beacon_period;
3046        priv->BSSinfo[index].UsingWEP = capability & WLAN_CAPABILITY_PRIVACY;
3047        memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len);
3048        priv->BSSinfo[index].SSIDsize = ssid_len;
3049
3050        if (capability & WLAN_CAPABILITY_IBSS)
3051                priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
3052        else if (capability & WLAN_CAPABILITY_ESS)
3053                priv->BSSinfo[index].BSStype = IW_MODE_INFRA;
3054
3055        priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
3056                SHORT_PREAMBLE : LONG_PREAMBLE;
3057}
3058
3059static void authenticate(struct atmel_private *priv, u16 frame_len)
3060{
3061        struct auth_body *auth = (struct auth_body *)priv->rx_buf;
3062        u16 status = le16_to_cpu(auth->status);
3063        u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
3064        u16 system = le16_to_cpu(auth->alg);
3065
3066        if (status == WLAN_STATUS_SUCCESS && !priv->wep_is_on) {
3067                /* no WEP */
3068                if (priv->station_was_associated) {
3069                        atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
3070                        send_association_request(priv, 1);
3071                        return;
3072                } else {
3073                        atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
3074                        send_association_request(priv, 0);
3075                        return;
3076                }
3077        }
3078
3079        if (status == WLAN_STATUS_SUCCESS && priv->wep_is_on) {
3080                int should_associate = 0;
3081                /* WEP */
3082                if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
3083                        return;
3084
3085                if (system == WLAN_AUTH_OPEN) {
3086                        if (trans_seq_no == 0x0002) {
3087                                should_associate = 1;
3088                        }
3089                } else if (system == WLAN_AUTH_SHARED_KEY) {
3090                        if (trans_seq_no == 0x0002 &&
3091                            auth->el_id == WLAN_EID_CHALLENGE) {
3092                                send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
3093                                return;
3094                        } else if (trans_seq_no == 0x0004) {
3095                                should_associate = 1;
3096                        }
3097                }
3098
3099                if (should_associate) {
3100                        if (priv->station_was_associated) {
3101                                atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
3102                                send_association_request(priv, 1);
3103                                return;
3104                        } else {
3105                                atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
3106                                send_association_request(priv, 0);
3107                                return;
3108                        }
3109                }
3110        }
3111
3112        if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
3113                /* Flip back and forth between WEP auth modes until the max
3114                 * authentication tries has been exceeded.
3115                 */
3116                if (system == WLAN_AUTH_OPEN) {
3117                        priv->CurrentAuthentTransactionSeqNum = 0x001;
3118                        priv->exclude_unencrypted = 1;
3119                        send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0);
3120                        return;
3121                } else if (system == WLAN_AUTH_SHARED_KEY
3122                           && priv->wep_is_on) {
3123                        priv->CurrentAuthentTransactionSeqNum = 0x001;
3124                        priv->exclude_unencrypted = 0;
3125                        send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0);
3126                        return;
3127                } else if (priv->connect_to_any_BSS) {
3128                        int bss_index;
3129
3130                        priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
3131
3132                        if ((bss_index  = retrieve_bss(priv)) != -1) {
3133                                atmel_join_bss(priv, bss_index);
3134                                return;
3135                        }
3136                }
3137        }
3138
3139        priv->AuthenticationRequestRetryCnt = 0;
3140        atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
3141        priv->station_is_associated = 0;
3142}
3143
3144static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
3145{
3146        struct ass_resp_format {
3147                __le16 capability;
3148                __le16 status;
3149                __le16 ass_id;
3150                u8 el_id;
3151                u8 length;
3152                u8 rates[4];
3153        } *ass_resp = (struct ass_resp_format *)priv->rx_buf;
3154
3155        u16 status = le16_to_cpu(ass_resp->status);
3156        u16 ass_id = le16_to_cpu(ass_resp->ass_id);
3157        u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
3158
3159        union iwreq_data wrqu;
3160
3161        if (frame_len < 8 + rates_len)
3162                return;
3163
3164        if (status == WLAN_STATUS_SUCCESS) {
3165                if (subtype == IEEE80211_STYPE_ASSOC_RESP)
3166                        priv->AssociationRequestRetryCnt = 0;
3167                else
3168                        priv->ReAssociationRequestRetryCnt = 0;
3169
3170                atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
3171                                MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
3172                atmel_set_mib(priv, Phy_Mib_Type,
3173                              PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
3174                if (priv->power_mode == 0) {
3175                        priv->listen_interval = 1;
3176                        atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
3177                                       MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
3178                        atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
3179                                        MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
3180                } else {
3181                        priv->listen_interval = 2;
3182                        atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
3183                                       MAC_MGMT_MIB_PS_MODE_POS,  PS_MODE);
3184                        atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
3185                                        MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
3186                }
3187
3188                priv->station_is_associated = 1;
3189                priv->station_was_associated = 1;
3190                atmel_enter_state(priv, STATION_STATE_READY);
3191
3192                /* Send association event to userspace */
3193                wrqu.data.length = 0;
3194                wrqu.data.flags = 0;
3195                memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN);
3196                wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3197                wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
3198
3199                return;
3200        }
3201
3202        if (subtype == IEEE80211_STYPE_ASSOC_RESP &&
3203            status != WLAN_STATUS_ASSOC_DENIED_RATES &&
3204            status != WLAN_STATUS_CAPS_UNSUPPORTED &&
3205            priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
3206                mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
3207                priv->AssociationRequestRetryCnt++;
3208                send_association_request(priv, 0);
3209                return;
3210        }
3211
3212        if (subtype == IEEE80211_STYPE_REASSOC_RESP &&
3213            status != WLAN_STATUS_ASSOC_DENIED_RATES &&
3214            status != WLAN_STATUS_CAPS_UNSUPPORTED &&
3215            priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
3216                mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
3217                priv->ReAssociationRequestRetryCnt++;
3218                send_association_request(priv, 1);
3219                return;
3220        }
3221
3222        atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
3223        priv->station_is_associated = 0;
3224
3225        if (priv->connect_to_any_BSS) {
3226                int bss_index;
3227                priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
3228
3229                if ((bss_index = retrieve_bss(priv)) != -1)
3230                        atmel_join_bss(priv, bss_index);
3231        }
3232}
3233
3234static void atmel_join_bss(struct atmel_private *priv, int bss_index)
3235{
3236        struct bss_info *bss =  &priv->BSSinfo[bss_index];
3237
3238        memcpy(priv->CurrentBSSID, bss->BSSID, 6);
3239        memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize);
3240
3241        /* The WPA stuff cares about the current AP address */
3242        if (priv->use_wpa)
3243                build_wpa_mib(priv);
3244
3245        /* When switching to AdHoc turn OFF Power Save if needed */
3246
3247        if (bss->BSStype == IW_MODE_ADHOC &&
3248            priv->operating_mode != IW_MODE_ADHOC &&
3249            priv->power_mode) {
3250                priv->power_mode = 0;
3251                priv->listen_interval = 1;
3252                atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
3253                               MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
3254                atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
3255                                MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
3256        }
3257
3258        priv->operating_mode = bss->BSStype;
3259        priv->channel = bss->channel & 0x7f;
3260        priv->beacon_period = bss->beacon_period;
3261
3262        if (priv->preamble != bss->preamble) {
3263                priv->preamble = bss->preamble;
3264                atmel_set_mib8(priv, Local_Mib_Type,
3265                               LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
3266        }
3267
3268        if (!priv->wep_is_on && bss->UsingWEP) {
3269                atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
3270                priv->station_is_associated = 0;
3271                return;
3272        }
3273
3274        if (priv->wep_is_on && !bss->UsingWEP) {
3275                atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
3276                priv->station_is_associated = 0;
3277                return;
3278        }
3279
3280        atmel_enter_state(priv, STATION_STATE_JOINNING);
3281
3282        if (priv->operating_mode == IW_MODE_INFRA)
3283                join(priv, BSS_TYPE_INFRASTRUCTURE);
3284        else
3285                join(priv, BSS_TYPE_AD_HOC);
3286}
3287
3288static void restart_search(struct atmel_private *priv)
3289{
3290        int bss_index;
3291
3292        if (!priv->connect_to_any_BSS) {
3293                atmel_scan(priv, 1);
3294        } else {
3295                priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
3296
3297                if ((bss_index = retrieve_bss(priv)) != -1)
3298                        atmel_join_bss(priv, bss_index);
3299                else
3300                        atmel_scan(priv, 0);
3301        }
3302}
3303
3304static void smooth_rssi(struct atmel_private *priv, u8 rssi)
3305{
3306        u8 old = priv->wstats.qual.level;
3307        u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */
3308
3309        switch (priv->firmware_type) {
3310        case ATMEL_FW_TYPE_502E:
3311                max_rssi = 63; /* 502-rmfd-reve max by experiment */
3312                break;
3313        default:
3314                break;
3315        }
3316
3317        rssi = rssi * 100 / max_rssi;
3318        if ((rssi + old) % 2)
3319                priv->wstats.qual.level = (rssi + old) / 2 + 1;
3320        else
3321                priv->wstats.qual.level = (rssi + old) / 2;
3322        priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
3323        priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID;
3324}
3325
3326static void atmel_smooth_qual(struct atmel_private *priv)
3327{
3328        unsigned long time_diff = (jiffies - priv->last_qual) / HZ;
3329        while (time_diff--) {
3330                priv->last_qual += HZ;
3331                priv->wstats.qual.qual = priv->wstats.qual.qual / 2;
3332                priv->wstats.qual.qual +=
3333                        priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
3334                priv->beacons_this_sec = 0;
3335        }
3336        priv->wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
3337        priv->wstats.qual.updated &= ~IW_QUAL_QUAL_INVALID;
3338}
3339
3340/* deals with incoming management frames. */
3341static void atmel_management_frame(struct atmel_private *priv,
3342                                   struct ieee80211_hdr *header,
3343                                   u16 frame_len, u8 rssi)
3344{
3345        u16 subtype;
3346
3347        subtype = le16_to_cpu(header->frame_control) & IEEE80211_FCTL_STYPE;
3348        switch (subtype) {
3349        case IEEE80211_STYPE_BEACON:
3350        case IEEE80211_STYPE_PROBE_RESP:
3351
3352                /* beacon frame has multiple variable-length fields -
3353                   never let an engineer loose with a data structure design. */
3354                {
3355                        struct beacon_format {
3356                                __le64 timestamp;
3357                                __le16 interval;
3358                                __le16 capability;
3359                                u8 ssid_el_id;
3360                                u8 ssid_length;
3361                                /* ssid here */
3362                                u8 rates_el_id;
3363                                u8 rates_length;
3364                                /* rates here */
3365                                u8 ds_el_id;
3366                                u8 ds_length;
3367                                /* ds here */
3368                        } *beacon = (struct beacon_format *)priv->rx_buf;
3369
3370                        u8 channel, rates_length, ssid_length;
3371                        u64 timestamp = le64_to_cpu(beacon->timestamp);
3372                        u16 beacon_interval = le16_to_cpu(beacon->interval);
3373                        u16 capability = le16_to_cpu(beacon->capability);
3374                        u8 *beaconp = priv->rx_buf;
3375                        ssid_length = beacon->ssid_length;
3376                        /* this blows chunks. */
3377                        if (frame_len < 14 || frame_len < ssid_length + 15)
3378                                return;
3379                        rates_length = beaconp[beacon->ssid_length + 15];
3380                        if (frame_len < ssid_length + rates_length + 18)
3381                                return;
3382                        if (ssid_length >  MAX_SSID_LENGTH)
3383                                return;
3384                        channel = beaconp[ssid_length + rates_length + 18];
3385
3386                        if (priv->station_state == STATION_STATE_READY) {
3387                                smooth_rssi(priv, rssi);
3388                                if (is_frame_from_current_bss(priv, header)) {
3389                                        priv->beacons_this_sec++;
3390                                        atmel_smooth_qual(priv);
3391                                        if (priv->last_beacon_timestamp) {
3392                                                /* Note truncate this to 32 bits - kernel can't divide a long long */
3393                                                u32 beacon_delay = timestamp - priv->last_beacon_timestamp;
3394                                                int beacons = beacon_delay / (beacon_interval * 1000);
3395                                                if (beacons > 1)
3396                                                        priv->wstats.miss.beacon += beacons - 1;
3397                                        }
3398                                        priv->last_beacon_timestamp = timestamp;
3399                                        handle_beacon_probe(priv, capability, channel);
3400                                }
3401                        }
3402
3403                        if (priv->station_state == STATION_STATE_SCANNING)
3404                                store_bss_info(priv, header, capability,
3405                                               beacon_interval, channel, rssi,
3406                                               ssid_length,
3407                                               &beacon->rates_el_id,
3408                                               subtype == IEEE80211_STYPE_BEACON);
3409                }
3410                break;
3411
3412        case IEEE80211_STYPE_AUTH:
3413
3414                if (priv->station_state == STATION_STATE_AUTHENTICATING)
3415                        authenticate(priv, frame_len);
3416
3417                break;
3418
3419        case IEEE80211_STYPE_ASSOC_RESP:
3420        case IEEE80211_STYPE_REASSOC_RESP:
3421
3422                if (priv->station_state == STATION_STATE_ASSOCIATING ||
3423                    priv->station_state == STATION_STATE_REASSOCIATING)
3424                        associate(priv, frame_len, subtype);
3425
3426                break;
3427
3428        case IEEE80211_STYPE_DISASSOC:
3429                if (priv->station_is_associated &&
3430                    priv->operating_mode == IW_MODE_INFRA &&
3431                    is_frame_from_current_bss(priv, header)) {
3432                        priv->station_was_associated = 0;
3433                        priv->station_is_associated = 0;
3434
3435                        atmel_enter_state(priv, STATION_STATE_JOINNING);
3436                        join(priv, BSS_TYPE_INFRASTRUCTURE);
3437                }
3438
3439                break;
3440
3441        case IEEE80211_STYPE_DEAUTH:
3442                if (priv->operating_mode == IW_MODE_INFRA &&
3443                    is_frame_from_current_bss(priv, header)) {
3444                        priv->station_was_associated = 0;
3445
3446                        atmel_enter_state(priv, STATION_STATE_JOINNING);
3447                        join(priv, BSS_TYPE_INFRASTRUCTURE);
3448                }
3449
3450                break;
3451        }
3452}
3453
3454/* run when timer expires */
3455static void atmel_management_timer(u_long a)
3456{
3457        struct net_device *dev = (struct net_device *) a;
3458        struct atmel_private *priv = netdev_priv(dev);
3459        unsigned long flags;
3460
3461        /* Check if the card has been yanked. */
3462        if (priv->card && priv->present_callback &&
3463                !(*priv->present_callback)(priv->card))
3464                return;
3465
3466        spin_lock_irqsave(&priv->irqlock, flags);
3467
3468        switch (priv->station_state) {
3469
3470        case STATION_STATE_AUTHENTICATING:
3471                if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
3472                        atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
3473                        priv->station_is_associated = 0;
3474                        priv->AuthenticationRequestRetryCnt = 0;
3475                        restart_search(priv);
3476                } else {
3477                        int auth = WLAN_AUTH_OPEN;
3478                        priv->AuthenticationRequestRetryCnt++;
3479                        priv->CurrentAuthentTransactionSeqNum = 0x0001;
3480                        mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
3481                        if (priv->wep_is_on && priv->exclude_unencrypted)
3482                                auth = WLAN_AUTH_SHARED_KEY;
3483                        send_authentication_request(priv, auth, NULL, 0);
3484          }
3485          break;
3486
3487        case STATION_STATE_ASSOCIATING:
3488                if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
3489                        atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
3490                        priv->station_is_associated = 0;
3491                        priv->AssociationRequestRetryCnt = 0;
3492                        restart_search(priv);
3493                } else {
3494                        priv->AssociationRequestRetryCnt++;
3495                        mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
3496                        send_association_request(priv, 0);
3497                }
3498          break;
3499
3500        case STATION_STATE_REASSOCIATING:
3501                if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
3502                        atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
3503                        priv->station_is_associated = 0;
3504                        priv->ReAssociationRequestRetryCnt = 0;
3505                        restart_search(priv);
3506                } else {
3507                        priv->ReAssociationRequestRetryCnt++;
3508                        mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
3509                        send_association_request(priv, 1);
3510                }
3511                break;
3512
3513        default:
3514                break;
3515        }
3516
3517        spin_unlock_irqrestore(&priv->irqlock, flags);
3518}
3519
3520static void atmel_command_irq(struct atmel_private *priv)
3521{
3522        u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
3523        u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
3524        int fast_scan;
3525        union iwreq_data wrqu;
3526
3527        if (status == CMD_STATUS_IDLE ||
3528            status == CMD_STATUS_IN_PROGRESS)
3529                return;
3530
3531        switch (command) {
3532        case CMD_Start:
3533                if (status == CMD_STATUS_COMPLETE) {
3534                        priv->station_was_associated = priv->station_is_associated;
3535                        atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
3536                                      (u8 *)priv->CurrentBSSID, 6);
3537                        atmel_enter_state(priv, STATION_STATE_READY);
3538                }
3539                break;
3540
3541        case CMD_Scan:
3542                fast_scan = priv->fast_scan;
3543                priv->fast_scan = 0;
3544
3545                if (status != CMD_STATUS_COMPLETE) {
3546                        atmel_scan(priv, 1);
3547                } else {
3548                        int bss_index = retrieve_bss(priv);
3549                        int notify_scan_complete = 1;
3550                        if (bss_index != -1) {
3551                                atmel_join_bss(priv, bss_index);
3552                        } else if (priv->operating_mode == IW_MODE_ADHOC &&
3553                                   priv->SSID_size != 0) {
3554                                start(priv, BSS_TYPE_AD_HOC);
3555                        } else {
3556                                priv->fast_scan = !fast_scan;
3557                                atmel_scan(priv, 1);
3558                                notify_scan_complete = 0;
3559                        }
3560                        priv->site_survey_state = SITE_SURVEY_COMPLETED;
3561                        if (notify_scan_complete) {
3562                                wrqu.data.length = 0;
3563                                wrqu.data.flags = 0;
3564                                wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
3565                        }
3566                }
3567                break;
3568
3569        case CMD_SiteSurvey:
3570                priv->fast_scan = 0;
3571
3572                if (status != CMD_STATUS_COMPLETE)
3573                        return;
3574
3575                priv->site_survey_state = SITE_SURVEY_COMPLETED;
3576                if (priv->station_is_associated) {
3577                        atmel_enter_state(priv, STATION_STATE_READY);
3578                        wrqu.data.length = 0;
3579                        wrqu.data.flags = 0;
3580                        wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
3581                } else {
3582                        atmel_scan(priv, 1);
3583                }
3584                break;
3585
3586        case CMD_Join:
3587                if (status == CMD_STATUS_COMPLETE) {
3588                        if (priv->operating_mode == IW_MODE_ADHOC) {
3589                                priv->station_was_associated = priv->station_is_associated;
3590                                atmel_enter_state(priv, STATION_STATE_READY);
3591                        } else {
3592                                int auth = WLAN_AUTH_OPEN;
3593                                priv->AuthenticationRequestRetryCnt = 0;
3594                                atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
3595
3596                                mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
3597                                priv->CurrentAuthentTransactionSeqNum = 0x0001;
3598                                if (priv->wep_is_on && priv->exclude_unencrypted)
3599                                        auth = WLAN_AUTH_SHARED_KEY;
3600                                send_authentication_request(priv, auth, NULL, 0);
3601                        }
3602                        return;
3603                }
3604
3605                atmel_scan(priv, 1);
3606        }
3607}
3608
3609static int atmel_wakeup_firmware(struct atmel_private *priv)
3610{
3611        struct host_info_struct *iface = &priv->host_info;
3612        u16 mr1, mr3;
3613        int i;
3614
3615        if (priv->card_type == CARD_TYPE_SPI_FLASH)
3616                atmel_set_gcr(priv->dev, GCR_REMAP);
3617
3618        /* wake up on-board processor */
3619        atmel_clear_gcr(priv->dev, 0x0040);
3620        atmel_write16(priv->dev, BSR, BSS_SRAM);
3621
3622        if (priv->card_type == CARD_TYPE_SPI_FLASH)
3623                mdelay(100);
3624
3625        /* and wait for it */
3626        for (i = LOOP_RETRY_LIMIT; i; i--) {
3627                mr1 = atmel_read16(priv->dev, MR1);
3628                mr3 = atmel_read16(priv->dev, MR3);
3629
3630                if (mr3 & MAC_BOOT_COMPLETE)
3631                        break;
3632                if (mr1 & MAC_BOOT_COMPLETE &&
3633                    priv->bus_type == BUS_TYPE_PCCARD)
3634                        break;
3635        }
3636
3637        if (i == 0) {
3638                printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
3639                return -EIO;
3640        }
3641
3642        if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
3643                printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
3644                return -ENODEV;
3645        }
3646
3647        /* now check for completion of MAC initialization through
3648           the FunCtrl field of the IFACE, poll MR1 to detect completion of
3649           MAC initialization, check completion status, set interrupt mask,
3650           enables interrupts and calls Tx and Rx initialization functions */
3651
3652        atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
3653
3654        for (i = LOOP_RETRY_LIMIT; i; i--) {
3655                mr1 = atmel_read16(priv->dev, MR1);
3656                mr3 = atmel_read16(priv->dev, MR3);
3657
3658                if (mr3 & MAC_INIT_COMPLETE)
3659                        break;
3660                if (mr1 & MAC_INIT_COMPLETE &&
3661                    priv->bus_type == BUS_TYPE_PCCARD)
3662                        break;
3663        }
3664
3665        if (i == 0) {
3666                printk(KERN_ALERT "%s: MAC failed to initialise.\n",
3667                                priv->dev->name);
3668                return -EIO;
3669        }
3670
3671        /* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
3672        if ((mr3 & MAC_INIT_COMPLETE) &&
3673            !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
3674                printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name);
3675                return -EIO;
3676        }
3677        if ((mr1 & MAC_INIT_COMPLETE) &&
3678            !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) {
3679                printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
3680                return -EIO;
3681        }
3682
3683        atmel_copy_to_host(priv->dev, (unsigned char *)iface,
3684                           priv->host_info_base, sizeof(*iface));
3685
3686        iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
3687        iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
3688        iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
3689        iface->tx_desc_count = le16_to_cpu(iface->tx_desc_count);
3690        iface->rx_buff_pos = le16_to_cpu(iface->rx_buff_pos);
3691        iface->rx_buff_size = le16_to_cpu(iface->rx_buff_size);
3692        iface->rx_desc_pos = le16_to_cpu(iface->rx_desc_pos);
3693        iface->rx_desc_count = le16_to_cpu(iface->rx_desc_count);
3694        iface->build_version = le16_to_cpu(iface->build_version);
3695        iface->command_pos = le16_to_cpu(iface->command_pos);
3696        iface->major_version = le16_to_cpu(iface->major_version);
3697        iface->minor_version = le16_to_cpu(iface->minor_version);
3698        iface->func_ctrl = le16_to_cpu(iface->func_ctrl);
3699        iface->mac_status = le16_to_cpu(iface->mac_status);
3700
3701        return 0;
3702}
3703
3704/* determine type of memory and MAC address */
3705static int probe_atmel_card(struct net_device *dev)
3706{
3707        int rc = 0;
3708        struct atmel_private *priv = netdev_priv(dev);
3709
3710        /* reset pccard */
3711        if (priv->bus_type == BUS_TYPE_PCCARD)
3712                atmel_write16(dev, GCR, 0x0060);
3713
3714        atmel_write16(dev, GCR, 0x0040);
3715        mdelay(500);
3716
3717        if (atmel_read16(dev, MR2) == 0) {
3718                /* No stored firmware so load a small stub which just
3719                   tells us the MAC address */
3720                int i;
3721                priv->card_type = CARD_TYPE_EEPROM;
3722                atmel_write16(dev, BSR, BSS_IRAM);
3723                atmel_copy_to_card(dev, 0, mac_reader, sizeof(mac_reader));
3724                atmel_set_gcr(dev, GCR_REMAP);
3725                atmel_clear_gcr(priv->dev, 0x0040);
3726                atmel_write16(dev, BSR, BSS_SRAM);
3727                for (i = LOOP_RETRY_LIMIT; i; i--)
3728                        if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
3729                                break;
3730                if (i == 0) {
3731                        printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
3732                } else {
3733                        atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
3734                        /* got address, now squash it again until the network
3735                           interface is opened */
3736                        if (priv->bus_type == BUS_TYPE_PCCARD)
3737                                atmel_write16(dev, GCR, 0x0060);
3738                        atmel_write16(dev, GCR, 0x0040);
3739                        rc = 1;
3740                }
3741        } else if (atmel_read16(dev, MR4) == 0) {
3742                /* Mac address easy in this case. */
3743                priv->card_type = CARD_TYPE_PARALLEL_FLASH;
3744                atmel_write16(dev,  BSR, 1);
3745                atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
3746                atmel_write16(dev,  BSR, 0x200);
3747                rc = 1;
3748        } else {
3749                /* Standard firmware in flash, boot it up and ask
3750                   for the Mac Address */
3751                priv->card_type = CARD_TYPE_SPI_FLASH;
3752                if (atmel_wakeup_firmware(priv) == 0) {
3753                        atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
3754
3755                        /* got address, now squash it again until the network
3756                           interface is opened */
3757                        if (priv->bus_type == BUS_TYPE_PCCARD)
3758                                atmel_write16(dev, GCR, 0x0060);
3759                        atmel_write16(dev, GCR, 0x0040);
3760                        rc = 1;
3761                }
3762        }
3763
3764        if (rc) {
3765                if (dev->dev_addr[0] == 0xFF) {
3766                        static const u8 default_mac[] = {
3767                                0x00, 0x04, 0x25, 0x00, 0x00, 0x00
3768                        };
3769                        printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
3770                        memcpy(dev->dev_addr, default_mac, 6);
3771                }
3772        }
3773
3774        return rc;
3775}
3776
3777/* Move the encyption information on the MIB structure.
3778   This routine is for the pre-WPA firmware: later firmware has
3779   a different format MIB and a different routine. */
3780static void build_wep_mib(struct atmel_private *priv)
3781{
3782        struct { /* NB this is matched to the hardware, don't change. */
3783                u8 wep_is_on;
3784                u8 default_key; /* 0..3 */
3785                u8 reserved;
3786                u8 exclude_unencrypted;
3787
3788                u32 WEPICV_error_count;
3789                u32 WEP_excluded_count;
3790
3791                u8 wep_keys[MAX_ENCRYPTION_KEYS][13];
3792                u8 encryption_level; /* 0, 1, 2 */
3793                u8 reserved2[3];
3794        } mib;
3795        int i;
3796
3797        mib.wep_is_on = priv->wep_is_on;
3798        if (priv->wep_is_on) {
3799                if (priv->wep_key_len[priv->default_key] > 5)
3800                        mib.encryption_level = 2;
3801                else
3802                        mib.encryption_level = 1;
3803        } else {
3804                mib.encryption_level = 0;
3805        }
3806
3807        mib.default_key = priv->default_key;
3808        mib.exclude_unencrypted = priv->exclude_unencrypted;
3809
3810        for (i = 0; i < MAX_ENCRYPTION_KEYS; i++)
3811                memcpy(mib.wep_keys[i], priv->wep_keys[i], 13);
3812
3813        atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
3814}
3815
3816static void build_wpa_mib(struct atmel_private *priv)
3817{
3818        /* This is for the later (WPA enabled) firmware. */
3819
3820        struct { /* NB this is matched to the hardware, don't change. */
3821                u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
3822                u8 receiver_address[6];
3823                u8 wep_is_on;
3824                u8 default_key; /* 0..3 */
3825                u8 group_key;
3826                u8 exclude_unencrypted;
3827                u8 encryption_type;
3828                u8 reserved;
3829
3830                u32 WEPICV_error_count;
3831                u32 WEP_excluded_count;
3832
3833                u8 key_RSC[4][8];
3834        } mib;
3835
3836        int i;
3837
3838        mib.wep_is_on = priv->wep_is_on;
3839        mib.exclude_unencrypted = priv->exclude_unencrypted;
3840        memcpy(mib.receiver_address, priv->CurrentBSSID, 6);
3841
3842        /* zero all the keys before adding in valid ones. */
3843        memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value));
3844
3845        if (priv->wep_is_on) {
3846                /* There's a comment in the Atmel code to the effect that this
3847                   is only valid when still using WEP, it may need to be set to
3848                   something to use WPA */
3849                memset(mib.key_RSC, 0, sizeof(mib.key_RSC));
3850
3851                mib.default_key = mib.group_key = 255;
3852                for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) {
3853                        if (priv->wep_key_len[i] > 0) {
3854                                memcpy(mib.cipher_default_key_value[i], priv->wep_keys[i], MAX_ENCRYPTION_KEY_SIZE);
3855                                if (i == priv->default_key) {
3856                                        mib.default_key = i;
3857                                        mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 7;
3858                                        mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
3859                                } else {
3860                                        mib.group_key = i;
3861                                        priv->group_cipher_suite = priv->pairwise_cipher_suite;
3862                                        mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1;
3863                                        mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
3864                                }
3865                        }
3866                }
3867                if (mib.default_key == 255)
3868                        mib.default_key = mib.group_key != 255 ? mib.group_key : 0;
3869                if (mib.group_key == 255)
3870                        mib.group_key = mib.default_key;
3871
3872        }
3873
3874        atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
3875}
3876
3877static int reset_atmel_card(struct net_device *dev)
3878{
3879        /* do everything necessary to wake up the hardware, including
3880           waiting for the lightning strike and throwing the knife switch....
3881
3882           set all the Mib values which matter in the card to match
3883           their settings in the atmel_private structure. Some of these
3884           can be altered on the fly, but many (WEP, infrastucture or ad-hoc)
3885           can only be changed by tearing down the world and coming back through
3886           here.
3887
3888           This routine is also responsible for initialising some
3889           hardware-specific fields in the atmel_private structure,
3890           including a copy of the firmware's hostinfo structure
3891           which is the route into the rest of the firmware datastructures. */
3892
3893        struct atmel_private *priv = netdev_priv(dev);
3894        u8 configuration;
3895        int old_state = priv->station_state;
3896        int err = 0;
3897
3898        /* data to add to the firmware names, in priority order
3899           this implemenents firmware versioning */
3900
3901        static char *firmware_modifier[] = {
3902                "-wpa",
3903                "",
3904                NULL
3905        };
3906
3907        /* reset pccard */
3908        if (priv->bus_type == BUS_TYPE_PCCARD)
3909                atmel_write16(priv->dev, GCR, 0x0060);
3910
3911        /* stop card , disable interrupts */
3912        atmel_write16(priv->dev, GCR, 0x0040);
3913
3914        if (priv->card_type == CARD_TYPE_EEPROM) {
3915                /* copy in firmware if needed */
3916                const struct firmware *fw_entry = NULL;
3917                const unsigned char *fw;
3918                int len = priv->firmware_length;
3919                if (!(fw = priv->firmware)) {
3920                        if (priv->firmware_type == ATMEL_FW_TYPE_NONE) {
3921                                if (strlen(priv->firmware_id) == 0) {
3922                                        printk(KERN_INFO
3923                                               "%s: card type is unknown: assuming at76c502 firmware is OK.\n",
3924                                               dev->name);
3925                                        printk(KERN_INFO
3926                                               "%s: if not, use the firmware= module parameter.\n",
3927                                               dev->name);
3928                                        strcpy(priv->firmware_id, "atmel_at76c502.bin");
3929                                }
3930                                err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev);
3931                                if (err != 0) {
3932                                        printk(KERN_ALERT
3933                                               "%s: firmware %s is missing, cannot continue.\n",
3934                                               dev->name, priv->firmware_id);
3935                                        return err;
3936                                }
3937                        } else {
3938                                int fw_index = 0;
3939                                int success = 0;
3940
3941                                /* get firmware filename entry based on firmware type ID */
3942                                while (fw_table[fw_index].fw_type != priv->firmware_type
3943                                                && fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
3944                                        fw_index++;
3945
3946                                /* construct the actual firmware file name */
3947                                if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
3948                                        int i;
3949                                        for (i = 0; firmware_modifier[i]; i++) {
3950                                                snprintf(priv->firmware_id, 32, "%s%s.%s", fw_table[fw_index].fw_file,
3951                                                        firmware_modifier[i], fw_table[fw_index].fw_file_ext);
3952                                                priv->firmware_id[31] = '\0';
3953                                                if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0) {
3954                                                        success = 1;
3955                                                        break;
3956                                                }
3957                                        }
3958                                }
3959                                if (!success) {
3960                                        printk(KERN_ALERT
3961                                               "%s: firmware %s is missing, cannot start.\n",
3962                                               dev->name, priv->firmware_id);
3963                                        priv->firmware_id[0] = '\0';
3964                                        return -ENOENT;
3965                                }
3966                        }
3967
3968                        fw = fw_entry->data;
3969                        len = fw_entry->size;
3970                }
3971
3972                if (len <= 0x6000) {
3973                        atmel_write16(priv->dev, BSR, BSS_IRAM);
3974                        atmel_copy_to_card(priv->dev, 0, fw, len);
3975                        atmel_set_gcr(priv->dev, GCR_REMAP);
3976                } else {
3977                        /* Remap */
3978                        atmel_set_gcr(priv->dev, GCR_REMAP);
3979                        atmel_write16(priv->dev, BSR, BSS_IRAM);
3980                        atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
3981                        atmel_write16(priv->dev, BSR, 0x2ff);
3982                        atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000);
3983                }
3984
3985                release_firmware(fw_entry);
3986        }
3987
3988        err = atmel_wakeup_firmware(priv);
3989        if (err != 0)
3990                return err;
3991
3992        /* Check the version and set the correct flag for wpa stuff,
3993           old and new firmware is incompatible.
3994           The pre-wpa 3com firmware reports major version 5,
3995           the wpa 3com firmware is major version 4 and doesn't need
3996           the 3com broken-ness filter. */
3997        priv->use_wpa = (priv->host_info.major_version == 4);
3998        priv->radio_on_broken = (priv->host_info.major_version == 5);
3999
4000        /* unmask all irq sources */
4001        atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
4002
4003        /* int Tx system and enable Tx */
4004        atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
4005        atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
4006        atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
4007        atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
4008
4009        priv->tx_desc_free = priv->host_info.tx_desc_count;
4010        priv->tx_desc_head = 0;
4011        priv->tx_desc_tail = 0;
4012        priv->tx_desc_previous = 0;
4013        priv->tx_free_mem = priv->host_info.tx_buff_size;
4014        priv->tx_buff_head = 0;
4015        priv->tx_buff_tail = 0;
4016
4017        configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
4018        atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
4019                                   configuration | FUNC_CTRL_TxENABLE);
4020
4021        /* init Rx system and enable */
4022        priv->rx_desc_head = 0;
4023
4024        configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
4025        atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
4026                                   configuration | FUNC_CTRL_RxENABLE);
4027
4028        if (!priv->radio_on_broken) {
4029                if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
4030                    CMD_STATUS_REJECTED_RADIO_OFF) {
4031                        printk(KERN_INFO "%s: cannot turn the radio on.\n",
4032                               dev->name);
4033                        return -EIO;
4034                }
4035        }
4036
4037        /* set up enough MIB values to run. */
4038        atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
4039        atmel_set_mib8(priv, Local_Mib_Type,  LOCAL_MIB_TX_PROMISCUOUS_POS,  PROM_MODE_OFF);
4040        atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_RTS_THRESHOLD_POS, priv->rts_threshold);
4041        atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_FRAG_THRESHOLD_POS, priv->frag_threshold);
4042        atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
4043        atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
4044        atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
4045        atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
4046                      priv->dev->dev_addr, 6);
4047        atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
4048        atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
4049        atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_BEACON_PER_POS, priv->default_beacon_period);
4050        atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, atmel_basic_rates, 4);
4051        atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep_is_on);
4052        if (priv->use_wpa)
4053                build_wpa_mib(priv);
4054        else
4055                build_wep_mib(priv);
4056
4057        if (old_state == STATION_STATE_READY) {
4058                union iwreq_data wrqu;
4059
4060                wrqu.data.length = 0;
4061                wrqu.data.flags = 0;
4062                wrqu.ap_addr.sa_family = ARPHRD_ETHER;
4063                memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
4064                wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
4065        }
4066
4067        return 0;
4068}
4069
4070static void atmel_send_command(struct atmel_private *priv, int command,
4071                               void *cmd, int cmd_size)
4072{
4073        if (cmd)
4074                atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
4075                                   cmd, cmd_size);
4076
4077        atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
4078        atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
4079}
4080
4081static int atmel_send_command_wait(struct atmel_private *priv, int command,
4082                                   void *cmd, int cmd_size)
4083{
4084        int i, status;
4085
4086        atmel_send_command(priv, command, cmd, cmd_size);
4087
4088        for (i = 5000; i; i--) {
4089                status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
4090                if (status != CMD_STATUS_IDLE &&
4091                    status != CMD_STATUS_IN_PROGRESS)
4092                        break;
4093                udelay(20);
4094        }
4095
4096        if (i == 0) {
4097                printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
4098                status =  CMD_STATUS_HOST_ERROR;
4099        } else {
4100                if (command != CMD_EnableRadio)
4101                        status = CMD_STATUS_COMPLETE;
4102        }
4103
4104        return status;
4105}
4106
4107static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index)
4108{
4109        struct get_set_mib m;
4110        m.type = type;
4111        m.size = 1;
4112        m.index = index;
4113
4114        atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
4115        return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE));
4116}
4117
4118static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data)
4119{
4120        struct get_set_mib m;
4121        m.type = type;
4122        m.size = 1;
4123        m.index = index;
4124        m.data[0] = data;
4125
4126        atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
4127}
4128
4129static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
4130                            u16 data)
4131{
4132        struct get_set_mib m;
4133        m.type = type;
4134        m.size = 2;
4135        m.index = index;
4136        m.data[0] = data;
4137        m.data[1] = data >> 8;
4138
4139        atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 2);
4140}
4141
4142static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
4143                          u8 *data, int data_len)
4144{
4145        struct get_set_mib m;
4146        m.type = type;
4147        m.size = data_len;
4148        m.index = index;
4149
4150        if (data_len > MIB_MAX_DATA_BYTES)
4151                printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
4152
4153        memcpy(m.data, data, data_len);
4154        atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
4155}
4156
4157static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
4158                          u8 *data, int data_len)
4159{
4160        struct get_set_mib m;
4161        m.type = type;
4162        m.size = data_len;
4163        m.index = index;
4164
4165        if (data_len > MIB_MAX_DATA_BYTES)
4166                printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
4167
4168        atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
4169        atmel_copy_to_host(priv->dev, data,
4170                           atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len);
4171}
4172
4173static void atmel_writeAR(struct net_device *dev, u16 data)
4174{
4175        int i;
4176        outw(data, dev->base_addr + AR);
4177        /* Address register appears to need some convincing..... */
4178        for (i = 0; data != inw(dev->base_addr + AR) && i < 10; i++)
4179                outw(data, dev->base_addr + AR);
4180}
4181
4182static void atmel_copy_to_card(struct net_device *dev, u16 dest,
4183                               const unsigned char *src, u16 len)
4184{
4185        int i;
4186        atmel_writeAR(dev, dest);
4187        if (dest % 2) {
4188                atmel_write8(dev, DR, *src);
4189                src++; len--;
4190        }
4191        for (i = len; i > 1 ; i -= 2) {
4192                u8 lb = *src++;
4193                u8 hb = *src++;
4194                atmel_write16(dev, DR, lb | (hb << 8));
4195        }
4196        if (i)
4197                atmel_write8(dev, DR, *src);
4198}
4199
4200static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
4201                               u16 src, u16 len)
4202{
4203        int i;
4204        atmel_writeAR(dev, src);
4205        if (src % 2) {
4206                *dest = atmel_read8(dev, DR);
4207                dest++; len--;
4208        }
4209        for (i = len; i > 1 ; i -= 2) {
4210                u16 hw = atmel_read16(dev, DR);
4211                *dest++ = hw;
4212                *dest++ = hw >> 8;
4213        }
4214        if (i)
4215                *dest = atmel_read8(dev, DR);
4216}
4217
4218static void atmel_set_gcr(struct net_device *dev, u16 mask)
4219{
4220        outw(inw(dev->base_addr + GCR) | mask, dev->base_addr + GCR);
4221}
4222
4223static void atmel_clear_gcr(struct net_device *dev, u16 mask)
4224{
4225        outw(inw(dev->base_addr + GCR) & ~mask, dev->base_addr + GCR);
4226}
4227
4228static int atmel_lock_mac(struct atmel_private *priv)
4229{
4230        int i, j = 20;
4231 retry:
4232        for (i = 5000; i; i--) {
4233                if (!atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)))
4234                        break;
4235                udelay(20);
4236        }
4237
4238        if (!i)
4239                return 0; /* timed out */
4240
4241        atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
4242        if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
4243                atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
4244                if (!j--)
4245                        return 0; /* timed out */
4246                goto retry;
4247        }
4248
4249        return 1;
4250}
4251
4252static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
4253{
4254        atmel_writeAR(priv->dev, pos);
4255        atmel_write16(priv->dev, DR, data); /* card is little-endian */
4256        atmel_write16(priv->dev, DR, data >> 16);
4257}
4258
4259/***************************************************************************/
4260/* There follows the source form of the MAC address reading firmware       */
4261/***************************************************************************/
4262#if 0
4263
4264/* Copyright 2003 Matthew T. Russotto                                      */
4265/* But derived from the Atmel 76C502 firmware written by Atmel and         */
4266/* included in "atmel wireless lan drivers" package                        */
4267/**
4268    This file is part of net.russotto.AtmelMACFW, hereto referred to
4269    as AtmelMACFW
4270
4271    AtmelMACFW is free software; you can redistribute it and/or modify
4272    it under the terms of the GNU General Public License version 2
4273    as published by the Free Software Foundation.
4274
4275    AtmelMACFW is distributed in the hope that it will be useful,
4276    but WITHOUT ANY WARRANTY; without even the implied warranty of
4277    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4278    GNU General Public License for more details.
4279
4280    You should have received a copy of the GNU General Public License
4281    along with AtmelMACFW; if not, write to the Free Software
4282    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
4283
4284****************************************************************************/
4285/* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E        */
4286/* It will probably work on the 76C504 and 76C502 RFMD_3COM                */
4287/* It only works on SPI EEPROM versions of the card.                       */
4288
4289/* This firmware initializes the SPI controller and clock, reads the MAC   */
4290/* address from the EEPROM into SRAM, and puts the SRAM offset of the MAC  */
4291/* address in MR2, and sets MR3 to 0x10 to indicate it is done             */
4292/* It also puts a complete copy of the EEPROM in SRAM with the offset in   */
4293/* MR4, for investigational purposes (maybe we can determine chip type     */
4294/* from that?)                                                             */
4295
4296        .org 0
4297    .set MRBASE, 0x8000000
4298        .set CPSR_INITIAL, 0xD3 /* IRQ/FIQ disabled, ARM mode, Supervisor state */
4299        .set CPSR_USER, 0xD1 /* IRQ/FIQ disabled, ARM mode, USER state */
4300        .set SRAM_BASE,  0x02000000
4301        .set SP_BASE,    0x0F300000
4302        .set UNK_BASE,   0x0F000000 /* Some internal device, but which one? */
4303        .set SPI_CGEN_BASE,  0x0E000000 /* Some internal device, but which one? */
4304        .set UNK3_BASE,  0x02014000 /* Some internal device, but which one? */
4305        .set STACK_BASE, 0x5600
4306        .set SP_SR, 0x10
4307        .set SP_TDRE, 2 /* status register bit -- TDR empty */
4308        .set SP_RDRF, 1 /* status register bit -- RDR full */
4309        .set SP_SWRST, 0x80
4310        .set SP_SPIEN, 0x1
4311        .set SP_CR, 0   /* control register */
4312        .set SP_MR, 4   /* mode register */
4313        .set SP_RDR, 0x08 /* Read Data Register */
4314        .set SP_TDR, 0x0C /* Transmit Data Register */
4315        .set SP_CSR0, 0x30 /* chip select registers */
4316        .set SP_CSR1, 0x34
4317        .set SP_CSR2, 0x38
4318        .set SP_CSR3, 0x3C
4319        .set NVRAM_CMD_RDSR, 5 /* read status register */
4320        .set NVRAM_CMD_READ, 3 /* read data */
4321        .set NVRAM_SR_RDY, 1 /* RDY bit.  This bit is inverted */
4322        .set SPI_8CLOCKS, 0xFF /* Writing this to the TDR doesn't do anything to the
4323                                  serial output, since SO is normally high.  But it
4324                                  does cause 8 clock cycles and thus 8 bits to be
4325                                  clocked in to the chip.  See Atmel's SPI
4326                                  controller (e.g. AT91M55800) timing and 4K
4327                                  SPI EEPROM manuals */
4328
4329        .set NVRAM_SCRATCH, 0x02000100  /* arbitrary area for scratchpad memory */
4330        .set NVRAM_IMAGE, 0x02000200
4331        .set NVRAM_LENGTH, 0x0200
4332        .set MAC_ADDRESS_MIB, SRAM_BASE
4333        .set MAC_ADDRESS_LENGTH, 6
4334        .set MAC_BOOT_FLAG, 0x10
4335        .set MR1, 0
4336        .set MR2, 4
4337        .set MR3, 8
4338        .set MR4, 0xC
4339RESET_VECTOR:
4340        b RESET_HANDLER
4341UNDEF_VECTOR:
4342        b HALT1
4343SWI_VECTOR:
4344        b HALT1
4345IABORT_VECTOR:
4346        b HALT1
4347DABORT_VECTOR:
4348RESERVED_VECTOR:
4349        b HALT1
4350IRQ_VECTOR:
4351        b HALT1
4352FIQ_VECTOR:
4353        b HALT1
4354HALT1:  b HALT1
4355RESET_HANDLER:
4356        mov     r0, #CPSR_INITIAL
4357        msr     CPSR_c, r0      /* This is probably unnecessary */
4358
4359/* I'm guessing this is initializing clock generator electronics for SPI */
4360        ldr     r0, =SPI_CGEN_BASE
4361        mov     r1, #0
4362        mov     r1, r1, lsl #3
4363        orr     r1, r1, #0
4364        str     r1, [r0]
4365        ldr     r1, [r0, #28]
4366        bic     r1, r1, #16
4367        str     r1, [r0, #28]
4368        mov     r1, #1
4369        str     r1, [r0, #8]
4370
4371        ldr     r0, =MRBASE
4372        mov     r1, #0
4373        strh    r1, [r0, #MR1]
4374        strh    r1, [r0, #MR2]
4375        strh    r1, [r0, #MR3]
4376        strh    r1, [r0, #MR4]
4377
4378        mov     sp, #STACK_BASE
4379        bl      SP_INIT
4380        mov     r0, #10
4381        bl      DELAY9
4382        bl      GET_MAC_ADDR
4383        bl      GET_WHOLE_NVRAM
4384        ldr     r0, =MRBASE
4385        ldr     r1, =MAC_ADDRESS_MIB
4386        strh    r1, [r0, #MR2]
4387        ldr     r1, =NVRAM_IMAGE
4388        strh    r1, [r0, #MR4]
4389        mov     r1, #MAC_BOOT_FLAG
4390        strh    r1, [r0, #MR3]
4391HALT2:  b HALT2
4392.func Get_Whole_NVRAM, GET_WHOLE_NVRAM
4393GET_WHOLE_NVRAM:
4394        stmdb   sp!, {lr}
4395        mov     r2, #0 /* 0th bytes of NVRAM */
4396        mov     r3, #NVRAM_LENGTH
4397        mov     r1, #0          /* not used in routine */
4398        ldr     r0, =NVRAM_IMAGE
4399        bl      NVRAM_XFER
4400        ldmia   sp!, {lr}
4401        bx      lr
4402.endfunc
4403
4404.func Get_MAC_Addr, GET_MAC_ADDR
4405GET_MAC_ADDR:
4406        stmdb   sp!, {lr}
4407        mov     r2, #0x120      /* address of MAC Address within NVRAM */
4408        mov     r3, #MAC_ADDRESS_LENGTH
4409        mov     r1, #0          /* not used in routine */
4410        ldr     r0, =MAC_ADDRESS_MIB
4411        bl      NVRAM_XFER
4412        ldmia   sp!, {lr}
4413        bx      lr
4414.endfunc
4415.ltorg
4416.func Delay9, DELAY9
4417DELAY9:
4418        adds    r0, r0, r0, LSL #3   /* r0 = r0 * 9 */
4419DELAYLOOP:
4420        beq     DELAY9_done
4421        subs    r0, r0, #1
4422        b       DELAYLOOP
4423DELAY9_done:
4424        bx      lr
4425.endfunc
4426
4427.func SP_Init, SP_INIT
4428SP_INIT:
4429        mov     r1, #SP_SWRST
4430        ldr     r0, =SP_BASE
4431        str     r1, [r0, #SP_CR] /* reset the SPI */
4432        mov     r1, #0
4433        str     r1, [r0, #SP_CR] /* release SPI from reset state */
4434        mov     r1, #SP_SPIEN
4435        str     r1, [r0, #SP_MR] /* set the SPI to MASTER mode*/
4436        str     r1, [r0, #SP_CR] /* enable the SPI */
4437
4438/*  My guess would be this turns on the SPI clock */
4439        ldr     r3, =SPI_CGEN_BASE
4440        ldr     r1, [r3, #28]
4441        orr     r1, r1, #0x2000
4442        str     r1, [r3, #28]
4443
4444        ldr     r1, =0x2000c01
4445        str     r1, [r0, #SP_CSR0]
4446        ldr     r1, =0x2000201
4447        str     r1, [r0, #SP_CSR1]
4448        str     r1, [r0, #SP_CSR2]
4449        str     r1, [r0, #SP_CSR3]
4450        ldr     r1, [r0, #SP_SR]
4451        ldr     r0, [r0, #SP_RDR]
4452        bx      lr
4453.endfunc
4454.func NVRAM_Init, NVRAM_INIT
4455NVRAM_INIT:
4456        ldr     r1, =SP_BASE
4457        ldr     r0, [r1, #SP_RDR]
4458        mov     r0, #NVRAM_CMD_RDSR
4459        str     r0, [r1, #SP_TDR]
4460SP_loop1:
4461        ldr     r0, [r1, #SP_SR]
4462        tst     r0, #SP_TDRE
4463        beq     SP_loop1
4464
4465        mov     r0, #SPI_8CLOCKS
4466        str     r0, [r1, #SP_TDR]
4467SP_loop2:
4468        ldr     r0, [r1, #SP_SR]
4469        tst     r0, #SP_TDRE
4470        beq     SP_loop2
4471
4472        ldr     r0, [r1, #SP_RDR]
4473SP_loop3:
4474        ldr     r0, [r1, #SP_SR]
4475        tst     r0, #SP_RDRF
4476        beq     SP_loop3
4477
4478        ldr     r0, [r1, #SP_RDR]
4479        and     r0, r0, #255
4480        bx      lr
4481.endfunc
4482
4483.func NVRAM_Xfer, NVRAM_XFER
4484        /* r0 = dest address */
4485        /* r1 = not used */
4486        /* r2 = src address within NVRAM */
4487        /* r3 = length */
4488NVRAM_XFER:
4489        stmdb   sp!, {r4, r5, lr}
4490        mov     r5, r0          /* save r0 (dest address) */
4491        mov     r4, r3          /* save r3 (length) */
4492        mov     r0, r2, LSR #5 /*  SPI memories put A8 in the command field */
4493        and     r0, r0, #8
4494        add     r0, r0, #NVRAM_CMD_READ
4495        ldr     r1, =NVRAM_SCRATCH
4496        strb    r0, [r1, #0]    /* save command in NVRAM_SCRATCH[0] */
4497        strb    r2, [r1, #1]    /* save low byte of source address in NVRAM_SCRATCH[1] */
4498_local1:
4499        bl      NVRAM_INIT
4500        tst     r0, #NVRAM_SR_RDY
4501        bne     _local1
4502        mov     r0, #20
4503        bl      DELAY9
4504        mov     r2, r4          /* length */
4505        mov     r1, r5          /* dest address */
4506        mov     r0, #2          /* bytes to transfer in command */
4507        bl      NVRAM_XFER2
4508        ldmia   sp!, {r4, r5, lr}
4509        bx      lr
4510.endfunc
4511
4512.func NVRAM_Xfer2, NVRAM_XFER2
4513NVRAM_XFER2:
4514        stmdb   sp!, {r4, r5, r6, lr}
4515        ldr     r4, =SP_BASE
4516        mov     r3, #0
4517        cmp     r0, #0
4518        bls     _local2
4519        ldr     r5, =NVRAM_SCRATCH
4520_local4:
4521        ldrb    r6, [r5, r3]
4522        str     r6, [r4, #SP_TDR]
4523_local3:
4524        ldr     r6, [r4, #SP_SR]
4525        tst     r6, #SP_TDRE
4526        beq     _local3
4527        add     r3, r3, #1
4528        cmp     r3, r0 /* r0 is # of bytes to send out (command+addr) */
4529        blo     _local4
4530_local2:
4531        mov     r3, #SPI_8CLOCKS
4532        str     r3, [r4, #SP_TDR]
4533        ldr     r0, [r4, #SP_RDR]
4534_local5:
4535        ldr     r0, [r4, #SP_SR]
4536        tst     r0, #SP_RDRF
4537        beq     _local5
4538        ldr     r0, [r4, #SP_RDR] /* what's this byte?  It's the byte read while writing the TDR -- nonsense, because the NVRAM doesn't read and write at the same time */
4539        mov     r0, #0
4540        cmp     r2, #0  /* r2 is # of bytes to copy in */
4541        bls     _local6
4542_local7:
4543        ldr     r5, [r4, #SP_SR]
4544        tst     r5, #SP_TDRE
4545        beq     _local7
4546        str     r3, [r4, #SP_TDR]  /* r3 has SPI_8CLOCKS */
4547_local8:
4548        ldr     r5, [r4, #SP_SR]
4549        tst     r5, #SP_RDRF
4550        beq     _local8
4551        ldr     r5, [r4, #SP_RDR] /* but didn't we read this byte above? */
4552        strb    r5, [r1], #1 /* postindexed */
4553        add     r0, r0, #1
4554        cmp     r0, r2
4555        blo     _local7 /* since we don't send another address, the NVRAM must be capable of sequential reads */
4556_local6:
4557        mov     r0, #200
4558        bl      DELAY9
4559        ldmia   sp!, {r4, r5, r6, lr}
4560        bx      lr
4561#endif
4562