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