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