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