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