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