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