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