Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*** -*- linux-c -*- **********************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)      Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5) 	Copyright 2000-2001 ATMEL Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) 	Copyright 2003-2004 Simon Kelley.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)     This code was developed from version 2.1.1 of the Atmel drivers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)     released by Atmel corp. under the GPL in December 2002. It also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)     includes code from the Linux aironet drivers (C) Benjamin Reed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)     and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)     extensions, (C) Jean Tourrilhes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)     The firmware module for reading the MAC address of the card comes from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)     net.russotto.AtmelMACFW, written by Matthew T. Russotto and copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)     by him. net.russotto.AtmelMACFW is used under the GPL license version 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)     This file contains the module in binary form and, under the terms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)     of the GPL, in source form. The source is located at the end of the file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)     This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)     it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)     the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)     (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)     This software is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)     but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)     GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)     You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)     along with Atmel wireless lan drivers; if not, see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32)     <http://www.gnu.org/licenses/>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34)     For all queries about this code, please contact the current author,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35)     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37)     Credit is due to HP UK and Cambridge Online Systems Ltd for supplying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38)     hardware used during development of this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #include <linux/wireless.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #include <net/iw_handler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #include <linux/crc32.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #include <net/cfg80211.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #include "atmel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define DRIVER_MAJOR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #define DRIVER_MINOR 98
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) MODULE_AUTHOR("Simon Kelley");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) /* The name of the firmware file to be loaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81)    over-rides any automatic selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) static char *firmware = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) module_param(firmware, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) /* table of firmware file names */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 	AtmelFWType fw_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 	const char *fw_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	const char *fw_file_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) } fw_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	{ ATMEL_FW_TYPE_502,		"atmel_at76c502",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 	{ ATMEL_FW_TYPE_502D,		"atmel_at76c502d",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 	{ ATMEL_FW_TYPE_502E,		"atmel_at76c502e",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 	{ ATMEL_FW_TYPE_502_3COM,	"atmel_at76c502_3com",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 	{ ATMEL_FW_TYPE_504,		"atmel_at76c504",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	{ ATMEL_FW_TYPE_504_2958,	"atmel_at76c504_2958",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	{ ATMEL_FW_TYPE_504A_2958,	"atmel_at76c504a_2958",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	{ ATMEL_FW_TYPE_506,		"atmel_at76c506",	"bin" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	{ ATMEL_FW_TYPE_NONE,		NULL,			NULL }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) MODULE_FIRMWARE("atmel_at76c502-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) MODULE_FIRMWARE("atmel_at76c502.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) MODULE_FIRMWARE("atmel_at76c502d-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) MODULE_FIRMWARE("atmel_at76c502d.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) MODULE_FIRMWARE("atmel_at76c502e-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) MODULE_FIRMWARE("atmel_at76c502e.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) MODULE_FIRMWARE("atmel_at76c502_3com-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) MODULE_FIRMWARE("atmel_at76c502_3com.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) MODULE_FIRMWARE("atmel_at76c504-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) MODULE_FIRMWARE("atmel_at76c504.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) MODULE_FIRMWARE("atmel_at76c504_2958-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) MODULE_FIRMWARE("atmel_at76c504_2958.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) MODULE_FIRMWARE("atmel_at76c504a_2958-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) MODULE_FIRMWARE("atmel_at76c504a_2958.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) MODULE_FIRMWARE("atmel_at76c506-wpa.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) MODULE_FIRMWARE("atmel_at76c506.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #define MAX_SSID_LENGTH 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #define MGMT_JIFFIES (256 * HZ / 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) #define MAX_BSS_ENTRIES	64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) /* registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) #define GCR  0x00    /* (SIR0)  General Configuration Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) #define BSR  0x02    /* (SIR1)  Bank Switching Select Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) #define AR   0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) #define DR   0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) #define MR1  0x12    /* Mirror Register 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) #define MR2  0x14    /* Mirror Register 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) #define MR3  0x16    /* Mirror Register 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) #define MR4  0x18    /* Mirror Register 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) #define GPR1                            0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) #define GPR2                            0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) #define GPR3                            0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137)  * Constants for the GCR register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) #define GCR_REMAP     0x0400          /* Remap internal SRAM to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) #define GCR_SWRES     0x0080          /* BIU reset (ARM and PAI are NOT reset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) #define GCR_CORES     0x0060          /* Core Reset (ARM and PAI are reset) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) #define GCR_ENINT     0x0002          /* Enable Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) #define GCR_ACKINT    0x0008          /* Acknowledge Interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) #define BSS_SRAM      0x0200          /* AMBA module selection --> SRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) #define BSS_IRAM      0x0100          /* AMBA module selection --> IRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148)  *Constants for the MR registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) #define MAC_INIT_COMPLETE       0x0001        /* MAC init has been completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) #define MAC_BOOT_COMPLETE       0x0010        /* MAC boot has been completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) #define MAC_INIT_OK             0x0002        /* MAC boot has been completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) #define MIB_MAX_DATA_BYTES    212
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) #define MIB_HEADER_SIZE       4    /* first four fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) struct get_set_mib {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	u8 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	u8 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	u8 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	u8 data[MIB_MAX_DATA_BYTES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) struct rx_desc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 	u32          Next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 	u16          MsduPos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 	u16          MsduSize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	u8           State;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	u8           Status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	u8           Rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	u8           Rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	u8           LinkQuality;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	u8           PreambleType;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	u16          Duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	u32          RxTime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) #define RX_DESC_FLAG_VALID       0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) #define RX_DESC_FLAG_CONSUMED    0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) #define RX_DESC_FLAG_IDLE        0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) #define RX_STATUS_SUCCESS        0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) #define RX_DESC_MSDU_POS_OFFSET      4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) #define RX_DESC_MSDU_SIZE_OFFSET     6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) #define RX_DESC_FLAGS_OFFSET         8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) #define RX_DESC_STATUS_OFFSET        9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) #define RX_DESC_RSSI_OFFSET          11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) #define RX_DESC_LINK_QUALITY_OFFSET  12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) #define RX_DESC_PREAMBLE_TYPE_OFFSET 13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) #define RX_DESC_DURATION_OFFSET      14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) #define RX_DESC_RX_TIME_OFFSET       16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) struct tx_desc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	u32       NextDescriptor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	u16       TxStartOfFrame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	u16       TxLength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	u8        TxState;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	u8        TxStatus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	u8        RetryCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	u8        TxRate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	u8        KeyIndex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	u8        ChiperType;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	u8        ChipreLength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	u8        Reserved1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	u8        Reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	u8        PacketType;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	u16       HostTxLength;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) #define TX_DESC_NEXT_OFFSET          0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) #define TX_DESC_POS_OFFSET           4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) #define TX_DESC_SIZE_OFFSET          6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) #define TX_DESC_FLAGS_OFFSET         8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) #define TX_DESC_STATUS_OFFSET        9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) #define TX_DESC_RETRY_OFFSET         10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) #define TX_DESC_RATE_OFFSET          11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) #define TX_DESC_KEY_INDEX_OFFSET     12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) #define TX_DESC_CIPHER_TYPE_OFFSET   13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) #define TX_DESC_CIPHER_LENGTH_OFFSET 14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) #define TX_DESC_PACKET_TYPE_OFFSET   17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) #define TX_DESC_HOST_LENGTH_OFFSET   18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231)  * Host-MAC interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) #define TX_STATUS_SUCCESS       0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) #define TX_FIRM_OWN             0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) #define TX_DONE                 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) #define TX_ERROR                0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) #define TX_PACKET_TYPE_DATA     0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) #define TX_PACKET_TYPE_MGMT     0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) #define ISR_EMPTY               0x00        /* no bits set in ISR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) #define ISR_TxCOMPLETE          0x01        /* packet transmitted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) #define ISR_RxCOMPLETE          0x02        /* packet received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) #define ISR_RxFRAMELOST         0x04        /* Rx Frame lost */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) #define ISR_FATAL_ERROR         0x08        /* Fatal error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) #define ISR_COMMAND_COMPLETE    0x10        /* command completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) #define ISR_OUT_OF_RANGE        0x20        /* command completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) #define ISR_IBSS_MERGE          0x40        /* (4.1.2.30): IBSS merge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) #define ISR_GENERIC_IRQ         0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) #define Local_Mib_Type          0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) #define Mac_Address_Mib_Type    0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) #define Mac_Mib_Type            0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) #define Statistics_Mib_Type     0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) #define Mac_Mgmt_Mib_Type       0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) #define Mac_Wep_Mib_Type        0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) #define Phy_Mib_Type            0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) #define Multi_Domain_MIB        0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) #define MAC_MGMT_MIB_CUR_BSSID_POS            14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) #define MAC_MIB_FRAG_THRESHOLD_POS            8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) #define MAC_MIB_RTS_THRESHOLD_POS             10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) #define MAC_MIB_SHORT_RETRY_POS               16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) #define MAC_MIB_LONG_RETRY_POS                17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) #define MAC_MIB_SHORT_RETRY_LIMIT_POS         16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) #define MAC_MGMT_MIB_BEACON_PER_POS           0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) #define MAC_MGMT_MIB_STATION_ID_POS           6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) #define MAC_MGMT_MIB_CUR_PRIVACY_POS          11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) #define MAC_MGMT_MIB_CUR_BSSID_POS            14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) #define MAC_MGMT_MIB_PS_MODE_POS              53
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) #define MAC_MGMT_MIB_LISTEN_INTERVAL_POS      54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) #define MAC_MGMT_MIB_MULTI_DOMAIN_IMPLEMENTED 56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) #define MAC_MGMT_MIB_MULTI_DOMAIN_ENABLED     57
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) #define PHY_MIB_CHANNEL_POS                   14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) #define PHY_MIB_RATE_SET_POS                  20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) #define PHY_MIB_REG_DOMAIN_POS                26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) #define LOCAL_MIB_AUTO_TX_RATE_POS            3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) #define LOCAL_MIB_SSID_SIZE                   5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) #define LOCAL_MIB_TX_PROMISCUOUS_POS          6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) #define LOCAL_MIB_TX_MGMT_RATE_POS            7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) #define LOCAL_MIB_TX_CONTROL_RATE_POS         8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) #define LOCAL_MIB_PREAMBLE_TYPE               9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) #define MAC_ADDR_MIB_MAC_ADDR_POS             0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) #define         CMD_Set_MIB_Vars              0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) #define         CMD_Get_MIB_Vars              0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) #define         CMD_Scan                      0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) #define         CMD_Join                      0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) #define         CMD_Start                     0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) #define         CMD_EnableRadio               0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) #define         CMD_DisableRadio              0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) #define         CMD_SiteSurvey                0x0B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) #define         CMD_STATUS_IDLE                   0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) #define         CMD_STATUS_COMPLETE               0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) #define         CMD_STATUS_UNKNOWN                0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) #define         CMD_STATUS_INVALID_PARAMETER      0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) #define         CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) #define         CMD_STATUS_TIME_OUT               0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) #define         CMD_STATUS_IN_PROGRESS            0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) #define         CMD_STATUS_REJECTED_RADIO_OFF     0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) #define         CMD_STATUS_HOST_ERROR             0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) #define         CMD_STATUS_BUSY                   0xFE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) #define CMD_BLOCK_COMMAND_OFFSET        0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) #define CMD_BLOCK_STATUS_OFFSET         1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) #define CMD_BLOCK_PARAMETERS_OFFSET     4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) #define SCAN_OPTIONS_SITE_SURVEY        0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) #define MGMT_FRAME_BODY_OFFSET		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) #define MAX_AUTHENTICATION_RETRIES	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) #define MAX_ASSOCIATION_RETRIES		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) #define AUTHENTICATION_RESPONSE_TIME_OUT  1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) #define MAX_WIRELESS_BODY  2316 /* mtu is 2312, CRC is 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) #define LOOP_RETRY_LIMIT   500000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) #define ACTIVE_MODE	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) #define PS_MODE		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) #define MAX_ENCRYPTION_KEYS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) #define MAX_ENCRYPTION_KEY_SIZE 40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)  * 802.11 related definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334)  * Regulatory Domains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) #define REG_DOMAIN_FCC		0x10	/* Channels	1-11	USA				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) #define REG_DOMAIN_DOC		0x20	/* Channel	1-11	Canada				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) #define REG_DOMAIN_ETSI		0x30	/* Channel	1-13	Europe (ex Spain/France)	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) #define REG_DOMAIN_SPAIN	0x31	/* Channel	10-11	Spain				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) #define REG_DOMAIN_FRANCE	0x32	/* Channel	10-13	France				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) #define REG_DOMAIN_MKK		0x40	/* Channel	14	Japan				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) #define REG_DOMAIN_MKK1		0x41	/* Channel	1-14	Japan(MKK1)			*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) #define REG_DOMAIN_ISRAEL	0x50	/* Channel	3-9	ISRAEL				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) #define BSS_TYPE_AD_HOC		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) #define BSS_TYPE_INFRASTRUCTURE 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) #define SCAN_TYPE_ACTIVE	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) #define SCAN_TYPE_PASSIVE	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) #define LONG_PREAMBLE		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) #define SHORT_PREAMBLE		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) #define AUTO_PREAMBLE		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) #define DATA_FRAME_WS_HEADER_SIZE   30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) /* promiscuous mode control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) #define PROM_MODE_OFF			0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) #define PROM_MODE_UNKNOWN		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) #define PROM_MODE_CRC_FAILED		0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) #define PROM_MODE_DUPLICATED		0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) #define PROM_MODE_MGMT			0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) #define PROM_MODE_CTRL			0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) #define PROM_MODE_BAD_PROTOCOL		0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) #define IFACE_INT_STATUS_OFFSET		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) #define IFACE_INT_MASK_OFFSET		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) #define IFACE_LOCKOUT_HOST_OFFSET	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) #define IFACE_LOCKOUT_MAC_OFFSET	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) #define IFACE_FUNC_CTRL_OFFSET		28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) #define IFACE_MAC_STAT_OFFSET		30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) #define IFACE_GENERIC_INT_TYPE_OFFSET	32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) #define CIPHER_SUITE_NONE     0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) #define CIPHER_SUITE_WEP_64   1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) #define CIPHER_SUITE_TKIP     2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) #define CIPHER_SUITE_AES      3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) #define CIPHER_SUITE_CCX      4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) #define CIPHER_SUITE_WEP_128  5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383)  * IFACE MACROS & definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387)  * FuncCtrl field:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) #define FUNC_CTRL_TxENABLE		0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) #define FUNC_CTRL_RxENABLE		0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) #define FUNC_CTRL_INIT_COMPLETE		0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) /* A stub firmware image which reads the MAC address from NVRAM on the card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)    For copyright information and source see the end of this file. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) static u8 mac_reader[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	0x06, 0x00, 0x00, 0xea, 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	0x01, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	0xd3, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x0e, 0x04, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	0x81, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x1c, 0x10, 0x90, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	0x10, 0x10, 0xc1, 0xe3, 0x1c, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x08, 0x10, 0x80, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	0x02, 0x03, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0xb0, 0x10, 0xc0, 0xe1, 0xb4, 0x10, 0xc0, 0xe1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	0xb8, 0x10, 0xc0, 0xe1, 0xbc, 0x10, 0xc0, 0xe1, 0x56, 0xdc, 0xa0, 0xe3, 0x21, 0x00, 0x00, 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	0x0a, 0x00, 0xa0, 0xe3, 0x1a, 0x00, 0x00, 0xeb, 0x10, 0x00, 0x00, 0xeb, 0x07, 0x00, 0x00, 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	0x02, 0x03, 0xa0, 0xe3, 0x02, 0x14, 0xa0, 0xe3, 0xb4, 0x10, 0xc0, 0xe1, 0x4c, 0x10, 0x9f, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	0xbc, 0x10, 0xc0, 0xe1, 0x10, 0x10, 0xa0, 0xe3, 0xb8, 0x10, 0xc0, 0xe1, 0xfe, 0xff, 0xff, 0xea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	0x00, 0x40, 0x2d, 0xe9, 0x00, 0x20, 0xa0, 0xe3, 0x02, 0x3c, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	0x28, 0x00, 0x9f, 0xe5, 0x37, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	0x00, 0x40, 0x2d, 0xe9, 0x12, 0x2e, 0xa0, 0xe3, 0x06, 0x30, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	0x02, 0x04, 0xa0, 0xe3, 0x2f, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	0x00, 0x02, 0x00, 0x02, 0x80, 0x01, 0x90, 0xe0, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	0xfc, 0xff, 0xff, 0xea, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0x10, 0xa0, 0xe3, 0xf3, 0x06, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	0x00, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	0x04, 0x10, 0x80, 0xe5, 0x00, 0x10, 0x80, 0xe5, 0x0e, 0x34, 0xa0, 0xe3, 0x1c, 0x10, 0x93, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	0x02, 0x1a, 0x81, 0xe3, 0x1c, 0x10, 0x83, 0xe5, 0x58, 0x11, 0x9f, 0xe5, 0x30, 0x10, 0x80, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	0x54, 0x11, 0x9f, 0xe5, 0x34, 0x10, 0x80, 0xe5, 0x38, 0x10, 0x80, 0xe5, 0x3c, 0x10, 0x80, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	0x10, 0x10, 0x90, 0xe5, 0x08, 0x00, 0x90, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf3, 0x16, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	0x08, 0x00, 0x91, 0xe5, 0x05, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, 0x10, 0x00, 0x91, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0xff, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	0x10, 0x00, 0x91, 0xe5, 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	0x10, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	0xff, 0x00, 0x00, 0xe2, 0x1e, 0xff, 0x2f, 0xe1, 0x30, 0x40, 0x2d, 0xe9, 0x00, 0x50, 0xa0, 0xe1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	0x03, 0x40, 0xa0, 0xe1, 0xa2, 0x02, 0xa0, 0xe1, 0x08, 0x00, 0x00, 0xe2, 0x03, 0x00, 0x80, 0xe2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	0xd8, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0xc1, 0xe5, 0x01, 0x20, 0xc1, 0xe5, 0xe2, 0xff, 0xff, 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x1a, 0x14, 0x00, 0xa0, 0xe3, 0xc4, 0xff, 0xff, 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	0x04, 0x20, 0xa0, 0xe1, 0x05, 0x10, 0xa0, 0xe1, 0x02, 0x00, 0xa0, 0xe3, 0x01, 0x00, 0x00, 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x70, 0x40, 0x2d, 0xe9, 0xf3, 0x46, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	0x00, 0x30, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x08, 0x00, 0x00, 0x9a, 0x8c, 0x50, 0x9f, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	0x03, 0x60, 0xd5, 0xe7, 0x0c, 0x60, 0x84, 0xe5, 0x10, 0x60, 0x94, 0xe5, 0x02, 0x00, 0x16, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	0xfc, 0xff, 0xff, 0x0a, 0x01, 0x30, 0x83, 0xe2, 0x00, 0x00, 0x53, 0xe1, 0xf7, 0xff, 0xff, 0x3a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	0xff, 0x30, 0xa0, 0xe3, 0x0c, 0x30, 0x84, 0xe5, 0x08, 0x00, 0x94, 0xe5, 0x10, 0x00, 0x94, 0xe5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x94, 0xe5, 0x00, 0x00, 0xa0, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	0x00, 0x00, 0x52, 0xe3, 0x0b, 0x00, 0x00, 0x9a, 0x10, 0x50, 0x94, 0xe5, 0x02, 0x00, 0x15, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	0xfc, 0xff, 0xff, 0x0a, 0x0c, 0x30, 0x84, 0xe5, 0x10, 0x50, 0x94, 0xe5, 0x01, 0x00, 0x15, 0xe3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	0xfc, 0xff, 0xff, 0x0a, 0x08, 0x50, 0x94, 0xe5, 0x01, 0x50, 0xc1, 0xe4, 0x01, 0x00, 0x80, 0xe2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	0x02, 0x00, 0x50, 0xe1, 0xf3, 0xff, 0xff, 0x3a, 0xc8, 0x00, 0xa0, 0xe3, 0x98, 0xff, 0xff, 0xeb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	0x70, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x02, 0x00, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	0x00, 0x01, 0x00, 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) struct atmel_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	void *card; /* Bus dependent structure varies for PCcard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	int (*present_callback)(void *); /* And callback which uses it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	char firmware_id[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	AtmelFWType firmware_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	u8 *firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	int firmware_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	struct timer_list management_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	struct device *sys_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	struct iw_statistics wstats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	spinlock_t irqlock, timerlock;	/* spinlocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		CARD_TYPE_PARALLEL_FLASH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		CARD_TYPE_SPI_FLASH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		CARD_TYPE_EEPROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	} card_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	int do_rx_crc; /* If we need to CRC incoming packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	int probe_crc; /* set if we don't yet know */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	int crc_ok_cnt, crc_ko_cnt; /* counters for probing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	u16 rx_desc_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	u16 tx_free_mem, tx_buff_head, tx_buff_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	u16 frag_seq, frag_len, frag_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	u8 frag_source[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	u8 wep_is_on, default_key, exclude_unencrypted, encryption_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 	u8 group_cipher_suite, pairwise_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	u8 wep_keys[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	int wep_key_len[MAX_ENCRYPTION_KEYS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	int use_wpa, radio_on_broken; /* firmware dependent stuff. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	u16 host_info_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	struct host_info_struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		/* NB this is matched to the hardware, don't change. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		u8 volatile int_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		u8 volatile int_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		u8 volatile lockout_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		u8 volatile lockout_mac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		u16 tx_buff_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 		u16 tx_buff_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 		u16 tx_desc_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		u16 tx_desc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		u16 rx_buff_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		u16 rx_buff_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 		u16 rx_desc_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		u16 rx_desc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		u16 build_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		u16 command_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 		u16 major_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 		u16 minor_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		u16 func_ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		u16 mac_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		u16 generic_IRQ_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		u8  reserved[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	} host_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		STATION_STATE_SCANNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		STATION_STATE_JOINNING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		STATION_STATE_AUTHENTICATING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		STATION_STATE_ASSOCIATING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 		STATION_STATE_READY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 		STATION_STATE_REASSOCIATING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 		STATION_STATE_DOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		STATION_STATE_MGMT_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	} station_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	int operating_mode, power_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	unsigned long last_qual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	int beacons_this_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	int reg_domain, config_reg_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	int tx_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	int auto_tx_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	int rts_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 	int frag_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	int long_retry, short_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	int preamble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	int default_beacon_period, beacon_period, listen_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 		SITE_SURVEY_IDLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 		SITE_SURVEY_IN_PROGRESS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		SITE_SURVEY_COMPLETED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	} site_survey_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	unsigned long last_survey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	int station_was_associated, station_is_associated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	int fast_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	struct bss_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 		int SSIDsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		int RSSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		int UsingWEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		int preamble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 		int beacon_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		int BSStype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		u8 BSSID[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		u8 SSID[MAX_SSID_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	} BSSinfo[MAX_BSS_ENTRIES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	int BSS_list_entries, current_BSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	int connect_to_any_BSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	int SSID_size, new_SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	u8 CurrentBSSID[6], BSSID[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	u64 last_beacon_timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	u8 rx_buf[MAX_WIRELESS_BODY];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) static u8 atmel_basic_rates[4] = {0x82, 0x84, 0x0b, 0x16};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	int reg_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	int min, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) } channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		      { REG_DOMAIN_DOC, 1, 11, "Canada" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		      { REG_DOMAIN_ETSI, 1, 13, "Europe" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		      { REG_DOMAIN_SPAIN, 10, 11, "Spain" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		      { REG_DOMAIN_FRANCE, 10, 13, "France" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		      { REG_DOMAIN_MKK, 14, 14, "MKK" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 		      { REG_DOMAIN_MKK1, 1, 14, "MKK1" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		      { REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) static void build_wpa_mib(struct atmel_private *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) static void atmel_copy_to_card(struct net_device *dev, u16 dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 			       const unsigned char *src, u16 len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 			       u16 src, u16 len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) static void atmel_set_gcr(struct net_device *dev, u16 mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) static void atmel_clear_gcr(struct net_device *dev, u16 mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) static int atmel_lock_mac(struct atmel_private *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) static void atmel_command_irq(struct atmel_private *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) static int atmel_validate_channel(struct atmel_private *priv, int channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) static void atmel_management_frame(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 				   struct ieee80211_hdr *header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 				   u16 frame_len, u8 rssi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) static void atmel_management_timer(struct timer_list *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) static void atmel_send_command(struct atmel_private *priv, int command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 			       void *cmd, int cmd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) static int atmel_send_command_wait(struct atmel_private *priv, int command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 				   void *cmd, int cmd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) static void atmel_transmit_management_frame(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 					    struct ieee80211_hdr *header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 					    u8 *body, int body_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 			   u8 data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 			    u16 data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 			  u8 *data, int data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 			  u8 *data, int data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) static void atmel_scan(struct atmel_private *priv, int specific_ssid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) static void atmel_join_bss(struct atmel_private *priv, int bss_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) static void atmel_smooth_qual(struct atmel_private *priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) static void atmel_writeAR(struct net_device *dev, u16 data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) static int probe_atmel_card(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) static int reset_atmel_card(struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) static void atmel_enter_state(struct atmel_private *priv, int new_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) int atmel_open (struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) static inline u16 atmel_hi(struct atmel_private *priv, u16 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	return priv->host_info_base + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	return priv->host_info.command_pos + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) static inline u8 atmel_read8(struct net_device *dev, u16 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	return inb(dev->base_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) static inline void atmel_write8(struct net_device *dev, u16 offset, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 	outb(data, dev->base_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) static inline u16 atmel_read16(struct net_device *dev, u16 offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	return inw(dev->base_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	outw(data, dev->base_addr + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	atmel_writeAR(priv->dev, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	return atmel_read8(priv->dev, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	atmel_writeAR(priv->dev, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	atmel_write8(priv->dev, DR, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	atmel_writeAR(priv->dev, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	return atmel_read16(priv->dev, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 	atmel_writeAR(priv->dev, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	atmel_write16(priv->dev, DR, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) static const struct iw_handler_def atmel_handler_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) static void tx_done_irq(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	for (i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	     atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		     i < priv->host_info.tx_desc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	     i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		priv->tx_free_mem += msdu_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		priv->tx_desc_free++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		if (priv->tx_buff_head + msdu_size > (priv->host_info.tx_buff_pos + priv->host_info.tx_buff_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 			priv->tx_buff_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 			priv->tx_buff_head += msdu_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 			priv->tx_desc_head++ ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 			priv->tx_desc_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		if (type == TX_PACKET_TYPE_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 			if (status == TX_STATUS_SUCCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 				priv->dev->stats.tx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 				priv->dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 			netif_wake_queue(priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) static u16 find_tx_buff(struct atmel_private *priv, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	if (bottom_free >= len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	if (priv->tx_free_mem - bottom_free >= len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		priv->tx_buff_tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		return priv->host_info.tx_buff_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 				 u16 len, u16 buff, u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	if (!priv->use_wpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_tail), type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RATE_OFFSET, priv->tx_desc_tail), priv->tx_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RETRY_OFFSET, priv->tx_desc_tail), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	if (priv->use_wpa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 		int cipher_type, cipher_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		if (is_bcast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 			cipher_type = priv->group_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 			if (cipher_type == CIPHER_SUITE_WEP_64 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 			    cipher_type == CIPHER_SUITE_WEP_128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 				cipher_length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 			else if (cipher_type == CIPHER_SUITE_TKIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 				cipher_length = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 			else if (priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_64 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 				 priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 				cipher_type = priv->pairwise_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 				cipher_length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 				cipher_type = CIPHER_SUITE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 				cipher_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 			cipher_type = priv->pairwise_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 			if (cipher_type == CIPHER_SUITE_WEP_64 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 			    cipher_type == CIPHER_SUITE_WEP_128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 				cipher_length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 			else if (cipher_type == CIPHER_SUITE_TKIP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 				cipher_length = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 			else if (priv->group_cipher_suite == CIPHER_SUITE_WEP_64 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 				 priv->group_cipher_suite == CIPHER_SUITE_WEP_128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 				cipher_type = priv->group_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 				cipher_length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 				cipher_type = CIPHER_SUITE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 				cipher_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 			    cipher_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 			    cipher_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_tail), 0x80000000L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_tail), TX_FIRM_OWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	if (priv->tx_desc_previous != priv->tx_desc_tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 	priv->tx_desc_previous = priv->tx_desc_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	if (priv->tx_desc_tail < (priv->host_info.tx_desc_count - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		priv->tx_desc_tail++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		priv->tx_desc_tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	priv->tx_desc_free--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	priv->tx_free_mem -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	struct ieee80211_hdr header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	if (priv->card && priv->present_callback &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	    !(*priv->present_callback)(priv->card)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (priv->station_state != STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		dev->stats.tx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	/* first ensure the timer func cannot run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	spin_lock_bh(&priv->timerlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	/* then stop the hardware ISR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	spin_lock_irqsave(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	/* nb doing the above in the opposite order will deadlock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	/* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	   12 first bytes (containing DA/SA) and put them in the appropriate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	   fields of the Wireless Header. Thus the packet length is then the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	   initial + 18 (+30-12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	if (!(buff = find_tx_buff(priv, len + 18))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		dev->stats.tx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 		spin_unlock_irqrestore(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		spin_unlock_bh(&priv->timerlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 		netif_stop_queue(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 		return NETDEV_TX_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 	frame_ctl = IEEE80211_FTYPE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	header.duration_id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	header.seq_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	if (priv->wep_is_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		frame_ctl |= IEEE80211_FCTL_PROTECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	if (priv->operating_mode == IW_MODE_ADHOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		skb_copy_from_linear_data(skb, &header.addr1, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 		memcpy(&header.addr2, dev->dev_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		memcpy(&header.addr3, priv->BSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		frame_ctl |= IEEE80211_FCTL_TODS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		memcpy(&header.addr1, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		memcpy(&header.addr2, dev->dev_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 		skb_copy_from_linear_data(skb, &header.addr3, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	if (priv->use_wpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		memcpy(&header.addr4, rfc1042_header, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	header.frame_control = cpu_to_le16(frame_ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	/* Copy the wireless header into the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	/* Copy the packet sans its 802.3 header addresses which have been replaced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	/* low bit of first byte of destination tells us if broadcast */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	dev->stats.tx_bytes += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	spin_unlock_irqrestore(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	spin_unlock_bh(&priv->timerlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	return NETDEV_TX_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) static void atmel_transmit_management_frame(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 					    struct ieee80211_hdr *header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 					    u8 *body, int body_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 	u16 buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 	int len = MGMT_FRAME_BODY_OFFSET + body_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	if (!(buff = find_tx_buff(priv, len)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	priv->tx_buff_tail += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) static void fast_rx_path(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 			 struct ieee80211_hdr *header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 			 u16 msdu_size, u16 rx_packet_loc, u32 crc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	/* fast path: unfragmented packet copy directly into skbuf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	u8 mac4[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	struct sk_buff	*skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	unsigned char *skbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	/* get the final, mac 4 header field, this tells us encapsulation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	msdu_size -= 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	if (priv->do_rx_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		crc = crc32_le(crc, mac4, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		msdu_size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	if (!(skb = dev_alloc_skb(msdu_size + 14))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		priv->dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	skb_reserve(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	skbp = skb_put(skb, msdu_size + 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	if (priv->do_rx_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		u32 netcrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		crc = crc32_le(crc, skbp + 12, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		if ((crc ^ 0xffffffff) != netcrc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 			priv->dev->stats.rx_crc_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 			dev_kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	memcpy(skbp, header->addr1, ETH_ALEN); /* destination address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		memcpy(&skbp[ETH_ALEN], header->addr3, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 		memcpy(&skbp[ETH_ALEN], header->addr2, ETH_ALEN); /* source address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	skb->protocol = eth_type_trans(skb, priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	priv->dev->stats.rx_bytes += 12 + msdu_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	priv->dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) /* Test to see if the packet in card memory at packet_loc has a valid CRC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943)    It doesn't matter that this is slow: it is only used to proble the first few
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944)    packets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	int i = msdu_size - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	u32 netcrc, crc = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	if (msdu_size < 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	atmel_writeAR(priv->dev, packet_loc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	while (i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 		u8 octet = atmel_read8(priv->dev, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		crc = crc32_le(crc, &octet, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	return (crc ^ 0xffffffff) == netcrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) static void frag_rx_path(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			 struct ieee80211_hdr *header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 			 u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			 u8 frag_no, int more_frags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	u8 mac4[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	u8 source[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		memcpy(source, header->addr3, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 		memcpy(source, header->addr2, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	rx_packet_loc += 24; /* skip header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	if (priv->do_rx_crc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		msdu_size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	if (frag_no == 0) { /* first fragment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		msdu_size -= ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		rx_packet_loc += ETH_ALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 		if (priv->do_rx_crc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 			crc = crc32_le(crc, mac4, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 		priv->frag_seq = seq_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 		priv->frag_no = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		priv->frag_len = msdu_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		memcpy(priv->frag_source, source, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 		memcpy(&priv->rx_buf[ETH_ALEN], source, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		memcpy(priv->rx_buf, header->addr1, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		if (priv->do_rx_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 			u32 netcrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 			crc = crc32_le(crc, &priv->rx_buf[12], msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 			if ((crc ^ 0xffffffff) != netcrc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 				priv->dev->stats.rx_crc_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 				eth_broadcast_addr(priv->frag_source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	} else if (priv->frag_no == frag_no &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		   priv->frag_seq == seq_no &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		   memcmp(priv->frag_source, source, ETH_ALEN) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 		atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 				   rx_packet_loc, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 		if (priv->do_rx_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 			u32 netcrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 			crc = crc32_le(crc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 				       &priv->rx_buf[12 + priv->frag_len],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 				       msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 			atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 			if ((crc ^ 0xffffffff) != netcrc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 				priv->dev->stats.rx_crc_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 				eth_broadcast_addr(priv->frag_source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 				more_frags = 1; /* don't send broken assembly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 		priv->frag_len += msdu_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		priv->frag_no++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		if (!more_frags) { /* last one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 			eth_broadcast_addr(priv->frag_source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 			if (!(skb = dev_alloc_skb(priv->frag_len + 14))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 				priv->dev->stats.rx_dropped++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 				skb_reserve(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 				skb_put_data(skb, priv->rx_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 				             priv->frag_len + 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 				skb->protocol = eth_type_trans(skb, priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 				skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 				netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 				priv->dev->stats.rx_bytes += priv->frag_len + 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 				priv->dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 		priv->wstats.discard.fragment++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) static void rx_done_irq(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 	struct ieee80211_hdr header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 	for (i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 	     atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 		     i < priv->host_info.rx_desc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	     i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 		u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 		u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 		u32 crc = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 		if (status != RX_STATUS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 			if (status == 0xc1) /* determined by experiment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 				priv->wstats.discard.nwid++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 				priv->dev->stats.rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 			goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 		msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 		rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 		if (msdu_size < 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 			priv->dev->stats.rx_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 			goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 		/* Get header as far as end of seq_ctrl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 		atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		frame_ctl = le16_to_cpu(header.frame_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 		seq_control = le16_to_cpu(header.seq_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 		/* probe for CRC use here if needed  once five packets have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 		   arrived with the same crc status, we assume we know what's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		   happening and stop probing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 		if (priv->probe_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 			if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 				priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 				priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 			if (priv->do_rx_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 				if (priv->crc_ok_cnt++ > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 					priv->probe_crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 				if (priv->crc_ko_cnt++ > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 					priv->probe_crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 		/* don't CRC header when WEP in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 			crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		msdu_size -= 24; /* header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 			u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 			u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 			if (!more_fragments && packet_fragment_no == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 				fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 				frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 					     packet_sequence_no, packet_fragment_no, more_fragments);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 			/* copy rest of packet into buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 			atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 			/* we use the same buffer for frag reassembly and control packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 			eth_broadcast_addr(priv->frag_source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 			if (priv->do_rx_crc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 				/* last 4 octets is crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 				msdu_size -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 				crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 				if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 					priv->dev->stats.rx_crc_errors++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 					goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 			atmel_management_frame(priv, &header, msdu_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 					       atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 		/* release descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 		atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 		if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 			priv->rx_desc_head++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 			priv->rx_desc_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static irqreturn_t service_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	struct net_device *dev = (struct net_device *) dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	u8 isr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	int i = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	static const u8 irq_order[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 		ISR_OUT_OF_RANGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 		ISR_RxCOMPLETE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 		ISR_TxCOMPLETE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 		ISR_RxFRAMELOST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 		ISR_FATAL_ERROR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 		ISR_COMMAND_COMPLETE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 		ISR_IBSS_MERGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		ISR_GENERIC_IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 	if (priv->card && priv->present_callback &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	    !(*priv->present_callback)(priv->card))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	/* In this state upper-level code assumes it can mess with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	   the card unhampered by interrupts which may change register state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	   Note that even though the card shouldn't generate interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	   the inturrupt line may be shared. This allows card setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	   to go on without disabling interrupts for a long time. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	if (priv->station_state == STATION_STATE_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 	atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 		if (!atmel_lock_mac(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 			/* failed to contact card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 			printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 			return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 		isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 		if (!isr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 			atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 			return i == -1 ? IRQ_NONE : IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 		atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 		for (i = 0; i < ARRAY_SIZE(irq_order); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 			if (isr & irq_order[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 		if (!atmel_lock_mac(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 			/* failed to contact card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 			printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 			return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 		isr ^= irq_order[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 		atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 		switch (irq_order[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 		case ISR_OUT_OF_RANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 			if (priv->operating_mode == IW_MODE_INFRA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 			    priv->station_state == STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 				priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 				atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 		case ISR_RxFRAMELOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 			priv->wstats.discard.misc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 			fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		case ISR_RxCOMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 			rx_done_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		case ISR_TxCOMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 			tx_done_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 		case ISR_FATAL_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 			printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 		case ISR_COMMAND_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 			atmel_command_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 		case ISR_IBSS_MERGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 				      priv->CurrentBSSID, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 			/* The WPA stuff cares about the current AP address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 			if (priv->use_wpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 				build_wpa_mib(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		case ISR_GENERIC_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 			printk(KERN_INFO "%s: Generic_irq received.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	/* update the link quality here in case we are seeing no beacons
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	   at all to drive the process */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	atmel_smooth_qual(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	priv->wstats.status = priv->station_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	if (priv->operating_mode == IW_MODE_INFRA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 		if (priv->station_state != STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 			priv->wstats.qual.qual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 			priv->wstats.qual.level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 			priv->wstats.qual.updated = (IW_QUAL_QUAL_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 					| IW_QUAL_LEVEL_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 		priv->wstats.qual.noise = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 		priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 		/* Quality levels cannot be determined in ad-hoc mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 		   because we can 'hear' more that one remote station. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 		priv->wstats.qual.qual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 		priv->wstats.qual.level	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 		priv->wstats.qual.noise	= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 		priv->wstats.qual.updated = IW_QUAL_QUAL_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 					| IW_QUAL_LEVEL_INVALID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 					| IW_QUAL_NOISE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 		priv->wstats.miss.beacon = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	return &priv->wstats;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) static int atmel_set_mac_address(struct net_device *dev, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	struct sockaddr *addr = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	return atmel_open(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) EXPORT_SYMBOL(atmel_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) int atmel_open(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	int i, channel, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	/* any scheduled timer is no longer needed and might screw things up.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	del_timer_sync(&priv->management_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 	/* Interrupts will not touch the card once in this state... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 	priv->station_state = STATION_STATE_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 	if (priv->new_SSID_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 		memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 		priv->SSID_size = priv->new_SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 		priv->new_SSID_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	priv->BSS_list_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) 	priv->AuthenticationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 	priv->AssociationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) 	priv->ReAssociationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	priv->CurrentAuthentTransactionSeqNum = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) 	priv->ExpectedAuthentTransactionSeqNum = 0x0002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	priv->site_survey_state = SITE_SURVEY_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	err = reset_atmel_card(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 	if (priv->config_reg_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) 		priv->reg_domain = priv->config_reg_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) 		atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) 		priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 		for (i = 0; i < ARRAY_SIZE(channel_table); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) 			if (priv->reg_domain == channel_table[i].reg_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) 		if (i == ARRAY_SIZE(channel_table)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) 			priv->reg_domain = REG_DOMAIN_MKK1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) 			printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) 	if ((channel = atmel_validate_channel(priv, priv->channel)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) 		priv->channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) 	/* this moves station_state on.... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) 	atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) 	atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) static int atmel_close(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) 	/* Send event to userspace that we are disassociating */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) 	if (priv->station_state == STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) 		union iwreq_data wrqu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) 		wrqu.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) 		wrqu.data.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) 		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) 		eth_zero_addr(wrqu.ap_addr.sa_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) 		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) 	atmel_enter_state(priv, STATION_STATE_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) 	if (priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) 		atmel_write16(dev, GCR, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) 	atmel_write16(dev, GCR, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) static int atmel_validate_channel(struct atmel_private *priv, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) 	/* check that channel is OK, if so return zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) 	   else return suitable default channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) 	for (i = 0; i < ARRAY_SIZE(channel_table); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) 		if (priv->reg_domain == channel_table[i].reg_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) 			if (channel >= channel_table[i].min &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) 			    channel <= channel_table[i].max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) 				return channel_table[i].min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) #ifdef CONFIG_PROC_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) static int atmel_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) 	struct atmel_private *priv = m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) 	char *s, *r, *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) 	seq_printf(m, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) 	if (priv->station_state != STATION_STATE_DOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) 		seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) 			   "Firmware version:\t%d.%d build %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) 			   "Firmware location:\t",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) 			   priv->host_info.major_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) 			   priv->host_info.minor_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) 			   priv->host_info.build_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) 		if (priv->card_type != CARD_TYPE_EEPROM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) 			seq_puts(m, "on card\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) 		else if (priv->firmware)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) 			seq_printf(m, "%s loaded by host\n", priv->firmware_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) 			seq_printf(m, "%s loaded by hotplug\n", priv->firmware_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) 		switch (priv->card_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) 		case CARD_TYPE_PARALLEL_FLASH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) 			c = "Parallel flash";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) 		case CARD_TYPE_SPI_FLASH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) 			c = "SPI flash\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) 		case CARD_TYPE_EEPROM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) 			c = "EEPROM";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) 			c = "<unknown>";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) 		r = "<unknown>";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) 		for (i = 0; i < ARRAY_SIZE(channel_table); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) 			if (priv->reg_domain == channel_table[i].reg_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) 				r = channel_table[i].name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) 		seq_printf(m, "MAC memory type:\t%s\n", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) 		seq_printf(m, "Regulatory domain:\t%s\n", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) 		seq_printf(m, "Host CRC checking:\t%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) 			 priv->do_rx_crc ? "On" : "Off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) 		seq_printf(m, "WPA-capable firmware:\t%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) 			 priv->use_wpa ? "Yes" : "No");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) 	switch (priv->station_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) 	case STATION_STATE_SCANNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) 		s = "Scanning";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) 	case STATION_STATE_JOINNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) 		s = "Joining";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) 	case STATION_STATE_AUTHENTICATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) 		s = "Authenticating";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) 	case STATION_STATE_ASSOCIATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) 		s = "Associating";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) 	case STATION_STATE_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) 		s = "Ready";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) 	case STATION_STATE_REASSOCIATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) 		s = "Reassociating";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) 	case STATION_STATE_MGMT_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) 		s = "Management error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) 	case STATION_STATE_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) 		s = "Down";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) 		s = "<unknown>";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) 	seq_printf(m, "Current state:\t\t%s\n", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) static const struct net_device_ops atmel_netdev_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) 	.ndo_open 		= atmel_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) 	.ndo_stop		= atmel_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) 	.ndo_set_mac_address 	= atmel_set_mac_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) 	.ndo_start_xmit 	= start_tx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) 	.ndo_do_ioctl 		= atmel_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) 	.ndo_validate_addr	= eth_validate_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) 				   const AtmelFWType fw_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) 				   struct device *sys_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) 				   int (*card_present)(void *), void *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) 	struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) 	struct atmel_private *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) 	/* Create the network device object. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) 	dev = alloc_etherdev(sizeof(*priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) 	if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) 	if (dev_alloc_name(dev, dev->name) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) 		printk(KERN_ERR "atmel: Couldn't get name!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) 		goto err_out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) 	priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) 	priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) 	priv->sys_dev = sys_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) 	priv->present_callback = card_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) 	priv->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) 	priv->firmware = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) 	priv->firmware_type = fw_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) 	if (firmware) /* module parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) 		strlcpy(priv->firmware_id, firmware, sizeof(priv->firmware_id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) 	priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) 	priv->station_state = STATION_STATE_DOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) 	priv->do_rx_crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) 	/* For PCMCIA cards, some chips need CRC, some don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) 	   so we have to probe. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) 	if (priv->bus_type == BUS_TYPE_PCCARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) 		priv->probe_crc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) 		priv->crc_ok_cnt = priv->crc_ko_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) 		priv->probe_crc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) 	priv->last_qual = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) 	priv->last_beacon_timestamp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) 	memset(priv->frag_source, 0xff, sizeof(priv->frag_source));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) 	eth_zero_addr(priv->BSSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) 	priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) 	priv->station_was_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) 	priv->last_survey = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) 	priv->preamble = LONG_PREAMBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) 	priv->operating_mode = IW_MODE_INFRA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) 	priv->connect_to_any_BSS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) 	priv->config_reg_domain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) 	priv->reg_domain = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) 	priv->tx_rate = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) 	priv->auto_tx_rate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) 	priv->channel = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) 	priv->power_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) 	priv->SSID[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) 	priv->SSID_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) 	priv->new_SSID_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) 	priv->frag_threshold = 2346;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) 	priv->rts_threshold = 2347;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) 	priv->short_retry = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) 	priv->long_retry = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) 	priv->wep_is_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) 	priv->default_key = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) 	priv->encryption_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) 	priv->exclude_unencrypted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) 	priv->group_cipher_suite = priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) 	priv->use_wpa = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) 	memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) 	memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) 	priv->default_beacon_period = priv->beacon_period = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) 	priv->listen_interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) 	timer_setup(&priv->management_timer, atmel_management_timer, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) 	spin_lock_init(&priv->irqlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) 	spin_lock_init(&priv->timerlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) 	dev->netdev_ops = &atmel_netdev_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) 	dev->wireless_handlers = &atmel_handler_def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) 	dev->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) 	dev->base_addr = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) 	/* MTU range: 68 - 2312 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) 	dev->min_mtu = 68;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) 	dev->max_mtu = MAX_WIRELESS_BODY - ETH_FCS_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 	SET_NETDEV_DEV(dev, sys_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) 	if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) 		printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) 		goto err_out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) 	if (!request_region(dev->base_addr, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) 			    priv->bus_type == BUS_TYPE_PCCARD ?  "atmel_cs" : "atmel_pci")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) 		goto err_out_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) 	if (register_netdev(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) 		goto err_out_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 	if (!probe_atmel_card(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) 		unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) 		goto err_out_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) 	netif_carrier_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) 	if (!proc_create_single_data("driver/atmel", 0, NULL, atmel_proc_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) 			priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) 		printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) 	printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) 	       dev->name, DRIVER_MAJOR, DRIVER_MINOR, dev->dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) 	return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) err_out_res:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) 	release_region(dev->base_addr, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) err_out_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) 	free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) err_out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) 	free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) EXPORT_SYMBOL(init_atmel_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) void stop_atmel_card(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) 	/* put a brick on it... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) 	if (priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) 		atmel_write16(dev, GCR, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) 	atmel_write16(dev, GCR, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) 	del_timer_sync(&priv->management_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) 	unregister_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) 	remove_proc_entry("driver/atmel", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) 	free_irq(dev->irq, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) 	kfree(priv->firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) 	release_region(dev->base_addr, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) 	free_netdev(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) EXPORT_SYMBOL(stop_atmel_card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) static int atmel_set_essid(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) 			   struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 	/* Check if we asked for `any' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) 	if (dwrq->flags == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) 		priv->connect_to_any_BSS = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) 		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) 		priv->connect_to_any_BSS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) 		/* Check the size of the string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) 		if (dwrq->length > MAX_SSID_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) 			 return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) 		if (index != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) 		memcpy(priv->new_SSID, extra, dwrq->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) 		priv->new_SSID_size = dwrq->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) 	return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) static int atmel_get_essid(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) 			   struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) 	/* Get the current SSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) 	if (priv->new_SSID_size != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) 		memcpy(extra, priv->new_SSID, priv->new_SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) 		dwrq->length = priv->new_SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) 		memcpy(extra, priv->SSID, priv->SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) 		dwrq->length = priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) 	dwrq->flags = !priv->connect_to_any_BSS; /* active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) static int atmel_get_wap(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) 			 struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) 			 struct sockaddr *awrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) 			 char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) 	memcpy(awrq->sa_data, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) 	awrq->sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) static int atmel_set_encode(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) 			    struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) 			    struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) 			    char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) 	/* Basic checking: do we have a key to set ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) 	 * Note : with the new API, it's impossible to get a NULL pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) 	 * Therefore, we need to check a key size == 0 instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) 	 * New version of iwconfig properly set the IW_ENCODE_NOKEY flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) 	 * when no key is present (only change flags), but older versions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) 	 * don't do it. - Jean II */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) 	if (dwrq->length > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) 		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) 		int current_index = priv->default_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) 		/* Check the size of the key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) 		if (dwrq->length > 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) 		/* Check the index (none -> use current) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) 		if (index < 0 || index >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) 			index = current_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) 			priv->default_key = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) 		/* Set the length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) 		if (dwrq->length > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) 			priv->wep_key_len[index] = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) 			if (dwrq->length > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) 				priv->wep_key_len[index] = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) 				/* Disable the key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) 				priv->wep_key_len[index] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) 		/* Check if the key is not marked as invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) 		if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) 			/* Cleanup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) 			memset(priv->wep_keys[index], 0, 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) 			/* Copy the key in the driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) 			memcpy(priv->wep_keys[index], extra, dwrq->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) 		/* WE specify that if a valid key is set, encryption
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) 		 * should be enabled (user may turn it off later)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) 		 * This is also how "iwconfig ethX key on" works */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) 		if (index == current_index &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) 		    priv->wep_key_len[index] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) 			priv->wep_is_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) 			priv->exclude_unencrypted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) 			if (priv->wep_key_len[index] > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) 				priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) 				priv->encryption_level = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) 				priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) 				priv->encryption_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) 		/* Do we want to just set the transmit key index ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) 		int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) 		if (index >= 0 && index < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) 			priv->default_key = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) 			/* Don't complain if only change the mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) 			if (!(dwrq->flags & IW_ENCODE_MODE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) 	/* Read the flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) 	if (dwrq->flags & IW_ENCODE_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) 		priv->wep_is_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) 		priv->encryption_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) 		priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) 		priv->wep_is_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) 		if (priv->wep_key_len[priv->default_key] > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) 			priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) 			priv->encryption_level = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) 			priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) 			priv->encryption_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) 	if (dwrq->flags & IW_ENCODE_RESTRICTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) 		priv->exclude_unencrypted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) 	if (dwrq->flags & IW_ENCODE_OPEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) 		priv->exclude_unencrypted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) 	return -EINPROGRESS;		/* Call commit handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) static int atmel_get_encode(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) 			    struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) 			    struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) 			    char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) 	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) 	if (!priv->wep_is_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) 		dwrq->flags = IW_ENCODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) 		if (priv->exclude_unencrypted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) 			dwrq->flags = IW_ENCODE_RESTRICTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) 			dwrq->flags = IW_ENCODE_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) 		/* Which key do we want ? -1 -> tx index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) 	if (index < 0 || index >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) 		index = priv->default_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) 	dwrq->flags |= index + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) 	/* Copy the key to the user buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) 	dwrq->length = priv->wep_key_len[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) 	if (dwrq->length > 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) 		dwrq->length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) 		memset(extra, 0, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) 		memcpy(extra, priv->wep_keys[index], dwrq->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) static int atmel_set_encodeext(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) 			    struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) 			    union iwreq_data *wrqu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) 			    char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) 	struct iw_point *encoding = &wrqu->encoding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) 	int idx, key_len, alg = ext->alg, set_key = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) 	/* Determine and validate the key index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) 	idx = encoding->flags & IW_ENCODE_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) 	if (idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) 		if (idx < 1 || idx > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) 		idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) 		idx = priv->default_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) 	if (encoding->flags & IW_ENCODE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) 	    alg = IW_ENCODE_ALG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) 	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) 		priv->default_key = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) 		set_key = ext->key_len > 0 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) 	if (set_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) 		/* Set the requested key first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) 		switch (alg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) 		case IW_ENCODE_ALG_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) 			priv->wep_is_on = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) 			priv->encryption_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) 			priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) 		case IW_ENCODE_ALG_WEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) 			if (ext->key_len > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) 				priv->wep_key_len[idx] = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) 				priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) 				priv->encryption_level = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) 			} else if (ext->key_len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) 				priv->wep_key_len[idx] = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) 				priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) 				priv->encryption_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) 			priv->wep_is_on = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) 			memset(priv->wep_keys[idx], 0, 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) 			key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) 			memcpy(priv->wep_keys[idx], ext->key, key_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) 	return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) static int atmel_get_encodeext(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) 			    struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) 			    union iwreq_data *wrqu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) 			    char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) 	struct iw_point *encoding = &wrqu->encoding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) 	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) 	int idx, max_key_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) 	max_key_len = encoding->length - sizeof(*ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) 	if (max_key_len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) 	idx = encoding->flags & IW_ENCODE_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) 	if (idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) 		if (idx < 1 || idx > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) 		idx--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) 		idx = priv->default_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) 	encoding->flags = idx + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) 	memset(ext, 0, sizeof(*ext));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) 	if (!priv->wep_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) 		ext->alg = IW_ENCODE_ALG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) 		ext->key_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) 		encoding->flags |= IW_ENCODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) 		if (priv->encryption_level > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) 			ext->alg = IW_ENCODE_ALG_WEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) 		ext->key_len = priv->wep_key_len[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) 		memcpy(ext->key, priv->wep_keys[idx], ext->key_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) 		encoding->flags |= IW_ENCODE_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) static int atmel_set_auth(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) 			       struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) 			       union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) 	struct iw_param *param = &wrqu->param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) 	switch (param->flags & IW_AUTH_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) 	case IW_AUTH_WPA_VERSION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) 	case IW_AUTH_CIPHER_PAIRWISE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) 	case IW_AUTH_CIPHER_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) 	case IW_AUTH_KEY_MGMT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) 	case IW_AUTH_PRIVACY_INVOKED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) 		 * atmel does not use these parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) 	case IW_AUTH_DROP_UNENCRYPTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) 		priv->exclude_unencrypted = param->value ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) 	case IW_AUTH_80211_AUTH_ALG: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) 			if (param->value & IW_AUTH_ALG_SHARED_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) 				priv->exclude_unencrypted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) 			} else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) 				priv->exclude_unencrypted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) 	case IW_AUTH_WPA_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) 		/* Silently accept disable of WPA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) 		if (param->value > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) 			return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) 	return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) static int atmel_get_auth(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) 			       struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) 			       union iwreq_data *wrqu, char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) 	struct iw_param *param = &wrqu->param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) 	switch (param->flags & IW_AUTH_INDEX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) 	case IW_AUTH_DROP_UNENCRYPTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) 		param->value = priv->exclude_unencrypted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) 	case IW_AUTH_80211_AUTH_ALG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) 		if (priv->exclude_unencrypted == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) 			param->value = IW_AUTH_ALG_SHARED_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) 			param->value = IW_AUTH_ALG_OPEN_SYSTEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) 	case IW_AUTH_WPA_ENABLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) 		param->value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) static int atmel_get_name(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) 			  char *cwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) 	strcpy(cwrq, "IEEE 802.11-DS");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) static int atmel_set_rate(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) 			  struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) 	if (vwrq->fixed == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) 		priv->tx_rate = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) 		priv->auto_tx_rate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) 		priv->auto_tx_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) 		/* Which type of value ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) 		if ((vwrq->value < 4) && (vwrq->value >= 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) 			/* Setting by rate index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) 			priv->tx_rate = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) 		/* Setting by frequency value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) 			switch (vwrq->value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) 			case  1000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) 				priv->tx_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) 			case  2000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) 				priv->tx_rate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) 			case  5500000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) 				priv->tx_rate = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) 			case 11000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) 				priv->tx_rate = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) 			default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) 	return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) static int atmel_set_mode(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) 			  __u32 *uwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) 	if (*uwrq != IW_MODE_ADHOC && *uwrq != IW_MODE_INFRA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) 	priv->operating_mode = *uwrq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) 	return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) static int atmel_get_mode(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) 			  __u32 *uwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) 	*uwrq = priv->operating_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) static int atmel_get_rate(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) 			 struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) 			 struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) 			 char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) 	if (priv->auto_tx_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) 		vwrq->fixed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) 		vwrq->value = 11000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) 		vwrq->fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) 		switch (priv->tx_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) 			vwrq->value =  1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) 		case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) 			vwrq->value =  2000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) 			vwrq->value =  5500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) 		case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) 			vwrq->value = 11000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) static int atmel_set_power(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) 			   struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) 	priv->power_mode = vwrq->disabled ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) 	return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) static int atmel_get_power(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) 			   struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) 	vwrq->disabled = priv->power_mode ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) 	vwrq->flags = IW_POWER_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) static int atmel_set_retry(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) 			   struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) 	if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) 		if (vwrq->flags & IW_RETRY_LONG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) 			priv->long_retry = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) 		else if (vwrq->flags & IW_RETRY_SHORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) 			priv->short_retry = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) 		else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) 			/* No modifier : set both */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) 			priv->long_retry = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) 			priv->short_retry = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) 		return -EINPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) static int atmel_get_retry(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) 			   struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) 	vwrq->disabled = 0;      /* Can't be disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) 	/* Note : by default, display the short retry number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) 	if (vwrq->flags & IW_RETRY_LONG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) 		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) 		vwrq->value = priv->long_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) 		vwrq->flags = IW_RETRY_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) 		vwrq->value = priv->short_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) 		if (priv->long_retry != priv->short_retry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) 			vwrq->flags |= IW_RETRY_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) static int atmel_set_rts(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) 			 struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) 			 struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) 			 char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) 	int rthr = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) 	if (vwrq->disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) 		rthr = 2347;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) 	if ((rthr < 0) || (rthr > 2347)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) 	priv->rts_threshold = rthr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) 	return -EINPROGRESS;		/* Call commit handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) static int atmel_get_rts(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) 			 struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) 			 struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) 			 char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) 	vwrq->value = priv->rts_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) 	vwrq->disabled = (vwrq->value >= 2347);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) 	vwrq->fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) static int atmel_set_frag(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) 			  struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) 	int fthr = vwrq->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) 	if (vwrq->disabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) 		fthr = 2346;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) 	if ((fthr < 256) || (fthr > 2346)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) 	fthr &= ~0x1;	/* Get an even value - is it really needed ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) 	priv->frag_threshold = fthr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) 	return -EINPROGRESS;		/* Call commit handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) static int atmel_get_frag(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) 			  struct iw_param *vwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) 	vwrq->value = priv->frag_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) 	vwrq->disabled = (vwrq->value >= 2346);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) 	vwrq->fixed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) static int atmel_set_freq(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) 			  struct iw_freq *fwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) 	int rc = -EINPROGRESS;		/* Call commit handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) 	/* If setting by frequency, convert to a channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) 	if (fwrq->e == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) 		int f = fwrq->m / 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) 		/* Hack to fall through... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) 		fwrq->e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) 		fwrq->m = ieee80211_frequency_to_channel(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) 	/* Setting by channel number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) 	if (fwrq->m < 0 || fwrq->m > 1000 || fwrq->e > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) 		rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) 		int channel = fwrq->m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) 		if (atmel_validate_channel(priv, channel) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) 			priv->channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) 			rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) static int atmel_get_freq(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) 			  struct iw_freq *fwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) 	fwrq->m = priv->channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) 	fwrq->e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) static int atmel_set_scan(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) 			  struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) 	/* Note : you may have realised that, as this is a SET operation,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) 	 * this is privileged and therefore a normal user can't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) 	 * perform scanning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) 	 * This is not an error, while the device perform scanning,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) 	 * traffic doesn't flow, so it's a perfect DoS...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) 	 * Jean II */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) 	if (priv->station_state == STATION_STATE_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) 	/* Timeout old surveys. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) 	if (time_after(jiffies, priv->last_survey + 20 * HZ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) 		priv->site_survey_state = SITE_SURVEY_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) 	priv->last_survey = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) 	/* Initiate a scan command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) 	if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) 	del_timer_sync(&priv->management_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) 	spin_lock_irqsave(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) 	priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) 	priv->fast_scan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) 	atmel_scan(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) 	spin_unlock_irqrestore(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) static int atmel_get_scan(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) 			  struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) 			  struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) 			  char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) 	char *current_ev = extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) 	struct iw_event	iwe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332) 	if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) 		return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) 	for (i = 0; i < priv->BSS_list_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) 		iwe.cmd = SIOCGIWAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) 		memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) 		current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) 						  extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) 						  &iwe, IW_EV_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) 		iwe.u.data.length =  priv->BSSinfo[i].SSIDsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) 		if (iwe.u.data.length > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) 			iwe.u.data.length = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) 		iwe.cmd = SIOCGIWESSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) 		iwe.u.data.flags = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) 		current_ev = iwe_stream_add_point(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) 						  extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) 						  &iwe, priv->BSSinfo[i].SSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) 		iwe.cmd = SIOCGIWMODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) 		iwe.u.mode = priv->BSSinfo[i].BSStype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) 		current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) 						  extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) 						  &iwe, IW_EV_UINT_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) 		iwe.cmd = SIOCGIWFREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) 		iwe.u.freq.m = priv->BSSinfo[i].channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) 		iwe.u.freq.e = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) 		current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) 						  extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) 						  &iwe, IW_EV_FREQ_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) 		/* Add quality statistics */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) 		iwe.cmd = IWEVQUAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) 		iwe.u.qual.level = priv->BSSinfo[i].RSSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) 		iwe.u.qual.qual  = iwe.u.qual.level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) 		/* iwe.u.qual.noise  = SOMETHING */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) 		current_ev = iwe_stream_add_event(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) 						  extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) 						  &iwe, IW_EV_QUAL_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) 		iwe.cmd = SIOCGIWENCODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) 		if (priv->BSSinfo[i].UsingWEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) 			iwe.u.data.flags = IW_ENCODE_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) 		iwe.u.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) 		current_ev = iwe_stream_add_point(info, current_ev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) 						  extra + IW_SCAN_MAX_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) 						  &iwe, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) 	/* Length of data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) 	dwrq->length = (current_ev - extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) 	dwrq->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) static int atmel_get_range(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) 			   struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) 			   struct iw_point *dwrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) 			   char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) 	struct iw_range *range = (struct iw_range *) extra;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) 	int k, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) 	dwrq->length = sizeof(struct iw_range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) 	memset(range, 0, sizeof(struct iw_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) 	range->min_nwid = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) 	range->max_nwid = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) 	range->num_channels = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) 	for (j = 0; j < ARRAY_SIZE(channel_table); j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) 		if (priv->reg_domain == channel_table[j].reg_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) 			range->num_channels = channel_table[j].max - channel_table[j].min + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) 	if (range->num_channels != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) 		for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) 			range->freq[k].i = i; /* List index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) 			/* Values in MHz -> * 10^5 * 10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) 			range->freq[k].m = 100000 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) 			 ieee80211_channel_to_frequency(i, NL80211_BAND_2GHZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) 			range->freq[k++].e = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) 		range->num_frequency = k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) 	range->max_qual.qual = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) 	range->max_qual.level = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) 	range->max_qual.noise = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) 	range->max_qual.updated = IW_QUAL_NOISE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) 	range->avg_qual.qual = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) 	range->avg_qual.level = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) 	range->avg_qual.noise = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) 	range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) 	range->sensitivity = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) 	range->bitrate[0] =  1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) 	range->bitrate[1] =  2000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) 	range->bitrate[2] =  5500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) 	range->bitrate[3] = 11000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) 	range->num_bitrates = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) 	range->min_rts = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) 	range->max_rts = 2347;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) 	range->min_frag = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) 	range->max_frag = 2346;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) 	range->encoding_size[0] = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) 	range->encoding_size[1] = 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) 	range->num_encoding_sizes = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) 	range->max_encoding_tokens = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) 	range->pmp_flags = IW_POWER_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) 	range->pmt_flags = IW_POWER_ON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) 	range->pm_capa = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) 	range->we_version_source = WIRELESS_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) 	range->we_version_compiled = WIRELESS_EXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) 	range->retry_capa = IW_RETRY_LIMIT ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) 	range->retry_flags = IW_RETRY_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) 	range->r_time_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) 	range->min_retry = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) 	range->max_retry = 65535;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) static int atmel_set_wap(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) 			 struct iw_request_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) 			 struct sockaddr *awrq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) 			 char *extra)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) 	static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) 	static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) 	if (awrq->sa_family != ARPHRD_ETHER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) 	if (!memcmp(any, awrq->sa_data, 6) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) 	    !memcmp(off, awrq->sa_data, 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) 		del_timer_sync(&priv->management_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) 		spin_lock_irqsave(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) 		atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) 		spin_unlock_irqrestore(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) 	for (i = 0; i < priv->BSS_list_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) 		if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) 			if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) 			} else if  (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) 				del_timer_sync(&priv->management_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) 				spin_lock_irqsave(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) 				atmel_join_bss(priv, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) 				spin_unlock_irqrestore(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) static int atmel_config_commit(struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) 			       struct iw_request_info *info,	/* NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) 			       void *zwrq,			/* NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) 			       char *extra)			/* NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) 	return atmel_open(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) static const iw_handler atmel_handler[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) 	(iw_handler) atmel_config_commit,	/* SIOCSIWCOMMIT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) 	(iw_handler) atmel_get_name,		/* SIOCGIWNAME */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) 	(iw_handler) NULL,			/* SIOCSIWNWID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) 	(iw_handler) NULL,			/* SIOCGIWNWID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) 	(iw_handler) atmel_set_freq,		/* SIOCSIWFREQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) 	(iw_handler) atmel_get_freq,		/* SIOCGIWFREQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) 	(iw_handler) atmel_set_mode,		/* SIOCSIWMODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) 	(iw_handler) atmel_get_mode,		/* SIOCGIWMODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) 	(iw_handler) NULL,			/* SIOCSIWSENS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) 	(iw_handler) NULL,			/* SIOCGIWSENS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) 	(iw_handler) NULL,			/* SIOCSIWRANGE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) 	(iw_handler) atmel_get_range,           /* SIOCGIWRANGE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) 	(iw_handler) NULL,			/* SIOCSIWPRIV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) 	(iw_handler) NULL,			/* SIOCGIWPRIV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) 	(iw_handler) NULL,			/* SIOCSIWSTATS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) 	(iw_handler) NULL,			/* SIOCGIWSTATS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) 	(iw_handler) NULL,			/* SIOCSIWSPY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) 	(iw_handler) NULL,			/* SIOCGIWSPY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) 	(iw_handler) atmel_set_wap,		/* SIOCSIWAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) 	(iw_handler) atmel_get_wap,		/* SIOCGIWAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) 	(iw_handler) NULL,			/* SIOCGIWAPLIST */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) 	(iw_handler) atmel_set_scan,		/* SIOCSIWSCAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) 	(iw_handler) atmel_get_scan,		/* SIOCGIWSCAN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) 	(iw_handler) atmel_set_essid,		/* SIOCSIWESSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) 	(iw_handler) atmel_get_essid,		/* SIOCGIWESSID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) 	(iw_handler) NULL,			/* SIOCSIWNICKN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) 	(iw_handler) NULL,			/* SIOCGIWNICKN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) 	(iw_handler) atmel_set_rate,		/* SIOCSIWRATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) 	(iw_handler) atmel_get_rate,		/* SIOCGIWRATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) 	(iw_handler) atmel_set_rts,		/* SIOCSIWRTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) 	(iw_handler) atmel_get_rts,		/* SIOCGIWRTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) 	(iw_handler) atmel_set_frag,		/* SIOCSIWFRAG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) 	(iw_handler) atmel_get_frag,		/* SIOCGIWFRAG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) 	(iw_handler) NULL,			/* SIOCSIWTXPOW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) 	(iw_handler) NULL,			/* SIOCGIWTXPOW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) 	(iw_handler) atmel_set_retry,		/* SIOCSIWRETRY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) 	(iw_handler) atmel_get_retry,		/* SIOCGIWRETRY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) 	(iw_handler) atmel_set_encode,		/* SIOCSIWENCODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) 	(iw_handler) atmel_get_encode,		/* SIOCGIWENCODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) 	(iw_handler) atmel_set_power,		/* SIOCSIWPOWER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) 	(iw_handler) atmel_get_power,		/* SIOCGIWPOWER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) 	(iw_handler) NULL,			/* -- hole -- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) 	(iw_handler) NULL,			/* SIOCSIWGENIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) 	(iw_handler) NULL,			/* SIOCGIWGENIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) 	(iw_handler) atmel_set_auth,		/* SIOCSIWAUTH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) 	(iw_handler) atmel_get_auth,		/* SIOCGIWAUTH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) 	(iw_handler) atmel_set_encodeext,	/* SIOCSIWENCODEEXT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) 	(iw_handler) atmel_get_encodeext,	/* SIOCGIWENCODEEXT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) 	(iw_handler) NULL,			/* SIOCSIWPMKSA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) static const iw_handler atmel_private_handler[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) 	NULL,				/* SIOCIWFIRSTPRIV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) struct atmel_priv_ioctl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) 	char id[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) 	unsigned char __user *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) 	unsigned short len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) #define ATMELFWL	SIOCIWFIRSTPRIV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) #define ATMELIDIFC	ATMELFWL + 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) #define ATMELRD		ATMELFWL + 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) #define ATMELMAGIC 0x51807
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) #define REGDOMAINSZ 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) static const struct iw_priv_args atmel_private_args[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) 		.cmd = ATMELFWL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) 		.set_args = IW_PRIV_TYPE_BYTE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) 				| IW_PRIV_SIZE_FIXED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) 				| sizeof(struct atmel_priv_ioctl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) 		.get_args = IW_PRIV_TYPE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) 		.name = "atmelfwl"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) 		.cmd = ATMELIDIFC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) 		.set_args = IW_PRIV_TYPE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) 		.get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) 		.name = "atmelidifc"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) 		.cmd = ATMELRD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) 		.set_args = IW_PRIV_TYPE_CHAR | REGDOMAINSZ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) 		.get_args = IW_PRIV_TYPE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) 		.name = "regdomain"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) static const struct iw_handler_def atmel_handler_def = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) 	.num_standard	= ARRAY_SIZE(atmel_handler),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) 	.num_private	= ARRAY_SIZE(atmel_private_handler),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) 	.num_private_args = ARRAY_SIZE(atmel_private_args),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) 	.standard	= (iw_handler *) atmel_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) 	.private	= (iw_handler *) atmel_private_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) 	.private_args	= (struct iw_priv_args *) atmel_private_args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621) 	.get_wireless_stats = atmel_get_wireless_stats
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) 	int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) 	struct atmel_priv_ioctl com;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) 	struct iwreq *wrq = (struct iwreq *) rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) 	unsigned char *new_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) 	char domain[REGDOMAINSZ + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) 	case ATMELIDIFC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) 		wrq->u.param.value = ATMELMAGIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) 	case ATMELFWL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) 		if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) 			rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) 		if (!capable(CAP_NET_ADMIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) 			rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) 		new_firmware = memdup_user(com.data, com.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) 		if (IS_ERR(new_firmware)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) 			rc = PTR_ERR(new_firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) 		kfree(priv->firmware);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) 		priv->firmware = new_firmware;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) 		priv->firmware_length = com.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) 		strncpy(priv->firmware_id, com.id, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) 		priv->firmware_id[31] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) 	case ATMELRD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) 		if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) 			rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) 		if (!capable(CAP_NET_ADMIN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) 			rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) 		domain[REGDOMAINSZ] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) 		for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) 			if (!strcasecmp(channel_table[i].name, domain)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) 				priv->config_reg_domain = channel_table[i].reg_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) 				rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) 		if (rc == 0 &&  priv->station_state != STATION_STATE_DOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) 			rc = atmel_open(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) 		rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) struct auth_body {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) 	__le16 alg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) 	__le16 trans_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) 	__le16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) 	u8 el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) 	u8 chall_text_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) 	u8 chall_text[253];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) static void atmel_enter_state(struct atmel_private *priv, int new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) 	int old_state = priv->station_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) 	if (new_state == old_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) 	priv->station_state = new_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) 	if (new_state == STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) 		netif_start_queue(priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) 		netif_carrier_on(priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) 	if (old_state == STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) 		netif_carrier_off(priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) 		if (netif_running(priv->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) 			netif_stop_queue(priv->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) 		priv->last_beacon_timestamp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) static void atmel_scan(struct atmel_private *priv, int specific_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) 		u8 BSSID[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) 		u8 SSID[MAX_SSID_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) 		u8 scan_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) 		u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) 		__le16 BSS_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) 		__le16 min_channel_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) 		__le16 max_channel_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) 		u8 options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) 		u8 SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) 	} cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) 	eth_broadcast_addr(cmd.BSSID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) 	if (priv->fast_scan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) 		cmd.SSID_size = priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) 		memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) 		cmd.min_channel_time = cpu_to_le16(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) 		cmd.max_channel_time = cpu_to_le16(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) 		priv->BSS_list_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) 		cmd.SSID_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) 		cmd.min_channel_time = cpu_to_le16(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) 		cmd.max_channel_time = cpu_to_le16(120);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) 	cmd.options = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) 	if (!specific_ssid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) 		cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) 	cmd.channel = (priv->channel & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) 	cmd.scan_type = SCAN_TYPE_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) 	cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) 		BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) 	atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) 	/* This must come after all hardware access to avoid being messed up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) 	   by stuff happening in interrupt context after we leave STATE_DOWN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) 	atmel_enter_state(priv, STATION_STATE_SCANNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) static void join(struct atmel_private *priv, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) 		u8 BSSID[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) 		u8 SSID[MAX_SSID_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) 		u8 BSS_type; /* this is a short in a scan command - weird */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) 		u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) 		__le16 timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) 		u8 SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) 		u8 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) 	} cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) 	cmd.SSID_size = priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) 	memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) 	memcpy(cmd.BSSID, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) 	cmd.channel = (priv->channel & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) 	cmd.BSS_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) 	cmd.timeout = cpu_to_le16(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) 	atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) static void start(struct atmel_private *priv, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) 		u8 BSSID[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) 		u8 SSID[MAX_SSID_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) 		u8 BSS_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) 		u8 channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) 		u8 SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) 		u8 reserved[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) 	} cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) 	cmd.SSID_size = priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) 	memcpy(cmd.SSID, priv->SSID, priv->SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) 	memcpy(cmd.BSSID, priv->BSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) 	cmd.BSS_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) 	cmd.channel = (priv->channel & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) 	atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) 				u8 channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) 	int rejoin = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) 	int new = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) 		SHORT_PREAMBLE : LONG_PREAMBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) 	if (priv->preamble != new) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) 		priv->preamble = new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) 		rejoin = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) 		atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) 	if (priv->channel != channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) 		priv->channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) 		rejoin = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) 		atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) 	if (rejoin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) 		priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) 		atmel_enter_state(priv, STATION_STATE_JOINNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) 		if (priv->operating_mode == IW_MODE_INFRA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) 			join(priv, BSS_TYPE_INFRASTRUCTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) 			join(priv, BSS_TYPE_AD_HOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842) static void send_authentication_request(struct atmel_private *priv, u16 system,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) 					u8 *challenge, int challenge_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) 	struct ieee80211_hdr header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) 	struct auth_body auth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) 	header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) 	header.duration_id = cpu_to_le16(0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) 	header.seq_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) 	memcpy(header.addr1, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) 	memcpy(header.addr2, priv->dev->dev_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) 	memcpy(header.addr3, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) 	if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) 		/* no WEP for authentication frames with TrSeqNo 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) 		header.frame_control |=  cpu_to_le16(IEEE80211_FCTL_PROTECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) 	auth.alg = cpu_to_le16(system);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) 	auth.status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) 	auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) 	priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) 	priv->CurrentAuthentTransactionSeqNum += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) 	if (challenge_len != 0)	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) 		auth.el_id = 16; /* challenge_text */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) 		auth.chall_text_len = challenge_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) 		memcpy(auth.chall_text, challenge, challenge_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) 		atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 8 + challenge_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) 		atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) static void send_association_request(struct atmel_private *priv, int is_reassoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) 	u8 *ssid_el_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) 	int bodysize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) 	struct ieee80211_hdr header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) 	struct ass_req_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) 		__le16 capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) 		__le16 listen_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) 		u8 ap[ETH_ALEN]; /* nothing after here directly accessible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) 		u8 ssid_el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) 		u8 ssid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) 		u8 ssid[MAX_SSID_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) 		u8 sup_rates_el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) 		u8 sup_rates_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) 		u8 rates[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) 	} body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) 	header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) 		(is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) 	header.duration_id = cpu_to_le16(0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) 	header.seq_ctrl = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) 	memcpy(header.addr1, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) 	memcpy(header.addr2, priv->dev->dev_addr, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) 	memcpy(header.addr3, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) 	body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) 	if (priv->wep_is_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) 		body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) 	if (priv->preamble == SHORT_PREAMBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) 		body.capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) 	body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) 	/* current AP address - only in reassoc frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) 	if (is_reassoc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) 		memcpy(body.ap, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) 		ssid_el_p = &body.ssid_el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) 		bodysize = 18 + priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) 		ssid_el_p = &body.ap[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) 		bodysize = 12 + priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) 	ssid_el_p[0] = WLAN_EID_SSID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) 	ssid_el_p[1] = priv->SSID_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) 	memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) 	ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) 	ssid_el_p[3 + priv->SSID_size] = 4; /* len of supported rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) 	memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) 	atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) static int is_frame_from_current_bss(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) 				     struct ieee80211_hdr *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) 	if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) 		return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) 		return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) static int retrieve_bss(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) 	int max_rssi = -128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) 	int max_index = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) 	if (priv->BSS_list_entries == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) 	if (priv->connect_to_any_BSS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) 		/* Select a BSS with the max-RSSI but of the same type and of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) 		   the same WEP mode and that it is not marked as 'bad' (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) 		   we had previously failed to connect to this BSS with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) 		   settings that we currently use) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) 		priv->current_BSS = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) 		for (i = 0; i < priv->BSS_list_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955) 			if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) 			    ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) 			     (priv->wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) 			    !(priv->BSSinfo[i].channel & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) 				max_rssi = priv->BSSinfo[i].RSSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) 				priv->current_BSS = max_index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) 		return max_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) 	for (i = 0; i < priv->BSS_list_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) 		if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) 		    memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) 		    priv->operating_mode == priv->BSSinfo[i].BSStype &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) 		    atmel_validate_channel(priv, priv->BSSinfo[i].channel) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) 			if (priv->BSSinfo[i].RSSI >= max_rssi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) 				max_rssi = priv->BSSinfo[i].RSSI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) 				max_index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) 	return max_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) static void store_bss_info(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) 			   struct ieee80211_hdr *header, u16 capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) 			   u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) 			   u8 *ssid, int is_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) 	u8 *bss = capability & WLAN_CAPABILITY_ESS ? header->addr2 : header->addr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) 	int i, index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) 	for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) 		if (memcmp(bss, priv->BSSinfo[i].BSSID, ETH_ALEN) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) 			index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) 	/* If we process a probe and an entry from this BSS exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) 	   we will update the BSS entry with the info from this BSS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) 	   If we process a beacon we will only update RSSI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) 	if (index == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) 		if (priv->BSS_list_entries == MAX_BSS_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) 		index = priv->BSS_list_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) 		memcpy(priv->BSSinfo[index].BSSID, bss, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) 		priv->BSSinfo[index].RSSI = rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) 		if (rssi > priv->BSSinfo[index].RSSI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) 			priv->BSSinfo[index].RSSI = rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) 		if (is_beacon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) 	priv->BSSinfo[index].channel = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) 	priv->BSSinfo[index].beacon_period = beacon_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) 	priv->BSSinfo[index].UsingWEP = capability & WLAN_CAPABILITY_PRIVACY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) 	memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) 	priv->BSSinfo[index].SSIDsize = ssid_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) 	if (capability & WLAN_CAPABILITY_IBSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) 		priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) 	else if (capability & WLAN_CAPABILITY_ESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) 		priv->BSSinfo[index].BSStype = IW_MODE_INFRA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) 	priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) 		SHORT_PREAMBLE : LONG_PREAMBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) static void authenticate(struct atmel_private *priv, u16 frame_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) 	struct auth_body *auth = (struct auth_body *)priv->rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) 	u16 status = le16_to_cpu(auth->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) 	u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) 	u16 system = le16_to_cpu(auth->alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) 	if (status == WLAN_STATUS_SUCCESS && !priv->wep_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) 		/* no WEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) 		if (priv->station_was_associated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) 			atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) 			send_association_request(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) 			atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) 			send_association_request(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) 	if (status == WLAN_STATUS_SUCCESS && priv->wep_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) 		int should_associate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) 		/* WEP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) 		if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) 		if (system == WLAN_AUTH_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) 			if (trans_seq_no == 0x0002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) 				should_associate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) 		} else if (system == WLAN_AUTH_SHARED_KEY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) 			if (trans_seq_no == 0x0002 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) 			    auth->el_id == WLAN_EID_CHALLENGE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) 				send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) 			} else if (trans_seq_no == 0x0004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) 				should_associate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) 		if (should_associate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) 			if (priv->station_was_associated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) 				atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) 				send_association_request(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) 				atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) 				send_association_request(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) 	if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) 		/* Flip back and forth between WEP auth modes until the max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) 		 * authentication tries has been exceeded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) 		if (system == WLAN_AUTH_OPEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) 			priv->CurrentAuthentTransactionSeqNum = 0x001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) 			priv->exclude_unencrypted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) 			send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) 		} else if (system == WLAN_AUTH_SHARED_KEY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) 			   && priv->wep_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) 			priv->CurrentAuthentTransactionSeqNum = 0x001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) 			priv->exclude_unencrypted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) 			send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) 		} else if (priv->connect_to_any_BSS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) 			int bss_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) 			priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) 			if ((bss_index  = retrieve_bss(priv)) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) 				atmel_join_bss(priv, bss_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) 	priv->AuthenticationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) 	atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) 	priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111) 	struct ass_resp_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) 		__le16 capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) 		__le16 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) 		__le16 ass_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) 		u8 el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) 		u8 length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) 		u8 rates[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) 	} *ass_resp = (struct ass_resp_format *)priv->rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) 	u16 status = le16_to_cpu(ass_resp->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) 	u16 ass_id = le16_to_cpu(ass_resp->ass_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) 	u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) 	union iwreq_data wrqu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) 	if (frame_len < 8 + rates_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) 	if (status == WLAN_STATUS_SUCCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) 		if (subtype == IEEE80211_STYPE_ASSOC_RESP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) 			priv->AssociationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) 			priv->ReAssociationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) 		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) 				MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) 		atmel_set_mib(priv, Phy_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) 			      PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) 		if (priv->power_mode == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) 			priv->listen_interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) 			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) 				       MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) 			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) 					MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) 			priv->listen_interval = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) 			atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) 				       MAC_MGMT_MIB_PS_MODE_POS,  PS_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) 			atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) 					MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) 		priv->station_is_associated = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) 		priv->station_was_associated = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) 		atmel_enter_state(priv, STATION_STATE_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) 		/* Send association event to userspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) 		wrqu.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) 		wrqu.data.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) 		memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) 		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) 		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) 	if (subtype == IEEE80211_STYPE_ASSOC_RESP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) 	    status != WLAN_STATUS_ASSOC_DENIED_RATES &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) 	    status != WLAN_STATUS_CAPS_UNSUPPORTED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) 	    priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) 		mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) 		priv->AssociationRequestRetryCnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) 		send_association_request(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) 	if (subtype == IEEE80211_STYPE_REASSOC_RESP &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) 	    status != WLAN_STATUS_ASSOC_DENIED_RATES &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) 	    status != WLAN_STATUS_CAPS_UNSUPPORTED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) 	    priv->ReAssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) 		mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) 		priv->ReAssociationRequestRetryCnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) 		send_association_request(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) 	atmel_enter_state(priv,  STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) 	priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) 	if (priv->connect_to_any_BSS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) 		int bss_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) 		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) 		if ((bss_index = retrieve_bss(priv)) != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) 			atmel_join_bss(priv, bss_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) static void atmel_join_bss(struct atmel_private *priv, int bss_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) 	struct bss_info *bss =  &priv->BSSinfo[bss_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203) 	memcpy(priv->CurrentBSSID, bss->BSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) 	memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) 	/* The WPA stuff cares about the current AP address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) 	if (priv->use_wpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) 		build_wpa_mib(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) 	/* When switching to AdHoc turn OFF Power Save if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) 	if (bss->BSStype == IW_MODE_ADHOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213) 	    priv->operating_mode != IW_MODE_ADHOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) 	    priv->power_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) 		priv->power_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) 		priv->listen_interval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) 		atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) 			       MAC_MGMT_MIB_PS_MODE_POS,  ACTIVE_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) 		atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) 				MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) 	priv->operating_mode = bss->BSStype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) 	priv->channel = bss->channel & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) 	priv->beacon_period = bss->beacon_period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) 	if (priv->preamble != bss->preamble) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) 		priv->preamble = bss->preamble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229) 		atmel_set_mib8(priv, Local_Mib_Type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) 			       LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) 	if (!priv->wep_is_on && bss->UsingWEP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) 		atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235) 		priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) 	if (priv->wep_is_on && !bss->UsingWEP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) 		atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) 		priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245) 	atmel_enter_state(priv, STATION_STATE_JOINNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) 	if (priv->operating_mode == IW_MODE_INFRA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) 		join(priv, BSS_TYPE_INFRASTRUCTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) 		join(priv, BSS_TYPE_AD_HOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) static void restart_search(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) 	int bss_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) 	if (!priv->connect_to_any_BSS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) 		atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) 		priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) 		if ((bss_index = retrieve_bss(priv)) != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) 			atmel_join_bss(priv, bss_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) 			atmel_scan(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) static void smooth_rssi(struct atmel_private *priv, u8 rssi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) 	u8 old = priv->wstats.qual.level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) 	u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) 	switch (priv->firmware_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) 	case ATMEL_FW_TYPE_502E:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) 		max_rssi = 63; /* 502-rmfd-reve max by experiment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) 	rssi = rssi * 100 / max_rssi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) 	if ((rssi + old) % 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) 		priv->wstats.qual.level = (rssi + old) / 2 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) 		priv->wstats.qual.level = (rssi + old) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) 	priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) 	priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) static void atmel_smooth_qual(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) 	unsigned long time_diff = (jiffies - priv->last_qual) / HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) 	while (time_diff--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) 		priv->last_qual += HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) 		priv->wstats.qual.qual = priv->wstats.qual.qual / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) 		priv->wstats.qual.qual +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) 			priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) 		priv->beacons_this_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) 	priv->wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) 	priv->wstats.qual.updated &= ~IW_QUAL_QUAL_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305) /* deals with incoming management frames. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) static void atmel_management_frame(struct atmel_private *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307) 				   struct ieee80211_hdr *header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) 				   u16 frame_len, u8 rssi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) 	u16 subtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) 	subtype = le16_to_cpu(header->frame_control) & IEEE80211_FCTL_STYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) 	switch (subtype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314) 	case IEEE80211_STYPE_BEACON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) 	case IEEE80211_STYPE_PROBE_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) 		/* beacon frame has multiple variable-length fields -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) 		   never let an engineer loose with a data structure design. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) 			struct beacon_format {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321) 				__le64 timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) 				__le16 interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) 				__le16 capability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324) 				u8 ssid_el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325) 				u8 ssid_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) 				/* ssid here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) 				u8 rates_el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) 				u8 rates_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) 				/* rates here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) 				u8 ds_el_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) 				u8 ds_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332) 				/* ds here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) 			} *beacon = (struct beacon_format *)priv->rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) 			u8 channel, rates_length, ssid_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) 			u64 timestamp = le64_to_cpu(beacon->timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337) 			u16 beacon_interval = le16_to_cpu(beacon->interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) 			u16 capability = le16_to_cpu(beacon->capability);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339) 			u8 *beaconp = priv->rx_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) 			ssid_length = beacon->ssid_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) 			/* this blows chunks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342) 			if (frame_len < 14 || frame_len < ssid_length + 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344) 			rates_length = beaconp[beacon->ssid_length + 15];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) 			if (frame_len < ssid_length + rates_length + 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) 			if (ssid_length >  MAX_SSID_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) 				return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) 			channel = beaconp[ssid_length + rates_length + 18];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) 			if (priv->station_state == STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) 				smooth_rssi(priv, rssi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) 				if (is_frame_from_current_bss(priv, header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) 					priv->beacons_this_sec++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) 					atmel_smooth_qual(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) 					if (priv->last_beacon_timestamp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) 						/* Note truncate this to 32 bits - kernel can't divide a long long */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358) 						u32 beacon_delay = timestamp - priv->last_beacon_timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) 						int beacons = beacon_delay / (beacon_interval * 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) 						if (beacons > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) 							priv->wstats.miss.beacon += beacons - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363) 					priv->last_beacon_timestamp = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) 					handle_beacon_probe(priv, capability, channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) 			if (priv->station_state == STATION_STATE_SCANNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) 				store_bss_info(priv, header, capability,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) 					       beacon_interval, channel, rssi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) 					       ssid_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) 					       &beacon->rates_el_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373) 					       subtype == IEEE80211_STYPE_BEACON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) 	case IEEE80211_STYPE_AUTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) 		if (priv->station_state == STATION_STATE_AUTHENTICATING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) 			authenticate(priv, frame_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384) 	case IEEE80211_STYPE_ASSOC_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) 	case IEEE80211_STYPE_REASSOC_RESP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) 		if (priv->station_state == STATION_STATE_ASSOCIATING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) 		    priv->station_state == STATION_STATE_REASSOCIATING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) 			associate(priv, frame_len, subtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) 	case IEEE80211_STYPE_DISASSOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) 		if (priv->station_is_associated &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) 		    priv->operating_mode == IW_MODE_INFRA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) 		    is_frame_from_current_bss(priv, header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) 			priv->station_was_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398) 			priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) 			atmel_enter_state(priv, STATION_STATE_JOINNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401) 			join(priv, BSS_TYPE_INFRASTRUCTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) 	case IEEE80211_STYPE_DEAUTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407) 		if (priv->operating_mode == IW_MODE_INFRA &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) 		    is_frame_from_current_bss(priv, header)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) 			priv->station_was_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) 			atmel_enter_state(priv, STATION_STATE_JOINNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) 			join(priv, BSS_TYPE_INFRASTRUCTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) /* run when timer expires */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) static void atmel_management_timer(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) 	struct atmel_private *priv = from_timer(priv, t, management_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) 	/* Check if the card has been yanked. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) 	if (priv->card && priv->present_callback &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) 		!(*priv->present_callback)(priv->card))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) 	spin_lock_irqsave(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) 	switch (priv->station_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) 	case STATION_STATE_AUTHENTICATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) 		if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436) 			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) 			priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) 			priv->AuthenticationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439) 			restart_search(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) 			int auth = WLAN_AUTH_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) 			priv->AuthenticationRequestRetryCnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) 			priv->CurrentAuthentTransactionSeqNum = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) 			mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) 			if (priv->wep_is_on && priv->exclude_unencrypted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) 				auth = WLAN_AUTH_SHARED_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) 			send_authentication_request(priv, auth, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) 	  }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) 	  break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) 	case STATION_STATE_ASSOCIATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) 		if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453) 			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) 			priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) 			priv->AssociationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) 			restart_search(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) 			priv->AssociationRequestRetryCnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) 			mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) 			send_association_request(priv, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) 	  break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) 	case STATION_STATE_REASSOCIATING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) 		if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) 			atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) 			priv->station_is_associated = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) 			priv->ReAssociationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) 			restart_search(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) 			priv->ReAssociationRequestRetryCnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) 			mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) 			send_association_request(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) 	spin_unlock_irqrestore(&priv->irqlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) static void atmel_command_irq(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) 	u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) 	u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) 	int fast_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) 	union iwreq_data wrqu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) 	if (status == CMD_STATUS_IDLE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492) 	    status == CMD_STATUS_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495) 	switch (command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) 	case CMD_Start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) 		if (status == CMD_STATUS_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) 			priv->station_was_associated = priv->station_is_associated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499) 			atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) 				      (u8 *)priv->CurrentBSSID, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) 			atmel_enter_state(priv, STATION_STATE_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) 	case CMD_Scan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) 		fast_scan = priv->fast_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507) 		priv->fast_scan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) 		if (status != CMD_STATUS_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) 			atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512) 			int bss_index = retrieve_bss(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) 			int notify_scan_complete = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) 			if (bss_index != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515) 				atmel_join_bss(priv, bss_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) 			} else if (priv->operating_mode == IW_MODE_ADHOC &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517) 				   priv->SSID_size != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) 				start(priv, BSS_TYPE_AD_HOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520) 				priv->fast_scan = !fast_scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) 				atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) 				notify_scan_complete = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524) 			priv->site_survey_state = SITE_SURVEY_COMPLETED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) 			if (notify_scan_complete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526) 				wrqu.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) 				wrqu.data.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) 				wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) 	case CMD_SiteSurvey:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534) 		priv->fast_scan = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536) 		if (status != CMD_STATUS_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) 		priv->site_survey_state = SITE_SURVEY_COMPLETED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) 		if (priv->station_is_associated) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) 			atmel_enter_state(priv, STATION_STATE_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542) 			wrqu.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) 			wrqu.data.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) 			wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546) 			atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550) 	case CMD_Join:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) 		if (status == CMD_STATUS_COMPLETE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) 			if (priv->operating_mode == IW_MODE_ADHOC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) 				priv->station_was_associated = priv->station_is_associated;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) 				atmel_enter_state(priv, STATION_STATE_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) 				int auth = WLAN_AUTH_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) 				priv->AuthenticationRequestRetryCnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) 				atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) 				mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) 				priv->CurrentAuthentTransactionSeqNum = 0x0001;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) 				if (priv->wep_is_on && priv->exclude_unencrypted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) 					auth = WLAN_AUTH_SHARED_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) 				send_authentication_request(priv, auth, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) 		atmel_scan(priv, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) static int atmel_wakeup_firmware(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) 	struct host_info_struct *iface = &priv->host_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) 	u16 mr1, mr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) 	if (priv->card_type == CARD_TYPE_SPI_FLASH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) 		atmel_set_gcr(priv->dev, GCR_REMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) 	/* wake up on-board processor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) 	atmel_clear_gcr(priv->dev, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) 	atmel_write16(priv->dev, BSR, BSS_SRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) 	if (priv->card_type == CARD_TYPE_SPI_FLASH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) 		mdelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) 	/* and wait for it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) 	for (i = LOOP_RETRY_LIMIT; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) 		mr1 = atmel_read16(priv->dev, MR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592) 		mr3 = atmel_read16(priv->dev, MR3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) 		if (mr3 & MAC_BOOT_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) 		if (mr1 & MAC_BOOT_COMPLETE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597) 		    priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) 		printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606) 	if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) 		printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611) 	/* now check for completion of MAC initialization through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) 	   the FunCtrl field of the IFACE, poll MR1 to detect completion of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613) 	   MAC initialization, check completion status, set interrupt mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) 	   enables interrupts and calls Tx and Rx initialization functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616) 	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) 	for (i = LOOP_RETRY_LIMIT; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) 		mr1 = atmel_read16(priv->dev, MR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) 		mr3 = atmel_read16(priv->dev, MR3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) 		if (mr3 & MAC_INIT_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) 		if (mr1 & MAC_INIT_COMPLETE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) 		    priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) 		printk(KERN_ALERT "%s: MAC failed to initialise.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) 				priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) 	/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) 	if ((mr3 & MAC_INIT_COMPLETE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) 	    !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) 		printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) 	if ((mr1 & MAC_INIT_COMPLETE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) 	    !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643) 		printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647) 	atmel_copy_to_host(priv->dev, (unsigned char *)iface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) 			   priv->host_info_base, sizeof(*iface));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) 	iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651) 	iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) 	iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) 	iface->tx_desc_count = le16_to_cpu(iface->tx_desc_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) 	iface->rx_buff_pos = le16_to_cpu(iface->rx_buff_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) 	iface->rx_buff_size = le16_to_cpu(iface->rx_buff_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) 	iface->rx_desc_pos = le16_to_cpu(iface->rx_desc_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657) 	iface->rx_desc_count = le16_to_cpu(iface->rx_desc_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) 	iface->build_version = le16_to_cpu(iface->build_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) 	iface->command_pos = le16_to_cpu(iface->command_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660) 	iface->major_version = le16_to_cpu(iface->major_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) 	iface->minor_version = le16_to_cpu(iface->minor_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) 	iface->func_ctrl = le16_to_cpu(iface->func_ctrl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663) 	iface->mac_status = le16_to_cpu(iface->mac_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) /* determine type of memory and MAC address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) static int probe_atmel_card(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) 	/* reset pccard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675) 	if (priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) 		atmel_write16(dev, GCR, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678) 	atmel_write16(dev, GCR, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) 	msleep(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681) 	if (atmel_read16(dev, MR2) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) 		/* No stored firmware so load a small stub which just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) 		   tells us the MAC address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684) 		int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) 		priv->card_type = CARD_TYPE_EEPROM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) 		atmel_write16(dev, BSR, BSS_IRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) 		atmel_copy_to_card(dev, 0, mac_reader, sizeof(mac_reader));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) 		atmel_set_gcr(dev, GCR_REMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689) 		atmel_clear_gcr(priv->dev, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) 		atmel_write16(dev, BSR, BSS_SRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) 		for (i = LOOP_RETRY_LIMIT; i; i--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) 			if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694) 		if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) 			printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) 			atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) 			/* got address, now squash it again until the network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699) 			   interface is opened */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) 			if (priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) 				atmel_write16(dev, GCR, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) 			atmel_write16(dev, GCR, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) 			rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) 	} else if (atmel_read16(dev, MR4) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) 		/* Mac address easy in this case. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707) 		priv->card_type = CARD_TYPE_PARALLEL_FLASH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) 		atmel_write16(dev,  BSR, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709) 		atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) 		atmel_write16(dev,  BSR, 0x200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) 		rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) 		/* Standard firmware in flash, boot it up and ask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) 		   for the Mac Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) 		priv->card_type = CARD_TYPE_SPI_FLASH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) 		if (atmel_wakeup_firmware(priv) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) 			atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) 			/* got address, now squash it again until the network
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) 			   interface is opened */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) 			if (priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) 				atmel_write16(dev, GCR, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723) 			atmel_write16(dev, GCR, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) 			rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) 		if (dev->dev_addr[0] == 0xFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730) 			static const u8 default_mac[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) 				0x00, 0x04, 0x25, 0x00, 0x00, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732) 			};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) 			printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734) 			memcpy(dev->dev_addr, default_mac, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) /* Move the encyption information on the MIB structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742)    This routine is for the pre-WPA firmware: later firmware has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743)    a different format MIB and a different routine. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) static void build_wep_mib(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) 	struct { /* NB this is matched to the hardware, don't change. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) 		u8 wep_is_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) 		u8 default_key; /* 0..3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) 		u8 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) 		u8 exclude_unencrypted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) 		u32 WEPICV_error_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) 		u32 WEP_excluded_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) 		u8 wep_keys[MAX_ENCRYPTION_KEYS][13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) 		u8 encryption_level; /* 0, 1, 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) 		u8 reserved2[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) 	} mib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) 	mib.wep_is_on = priv->wep_is_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) 	if (priv->wep_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) 		if (priv->wep_key_len[priv->default_key] > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) 			mib.encryption_level = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766) 			mib.encryption_level = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) 		mib.encryption_level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771) 	mib.default_key = priv->default_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) 	mib.exclude_unencrypted = priv->exclude_unencrypted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) 	for (i = 0; i < MAX_ENCRYPTION_KEYS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) 		memcpy(mib.wep_keys[i], priv->wep_keys[i], 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777) 	atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780) static void build_wpa_mib(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) 	/* This is for the later (WPA enabled) firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) 	struct { /* NB this is matched to the hardware, don't change. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785) 		u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) 		u8 receiver_address[ETH_ALEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787) 		u8 wep_is_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788) 		u8 default_key; /* 0..3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) 		u8 group_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) 		u8 exclude_unencrypted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) 		u8 encryption_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) 		u8 reserved;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794) 		u32 WEPICV_error_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) 		u32 WEP_excluded_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) 		u8 key_RSC[4][8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) 	} mib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) 	mib.wep_is_on = priv->wep_is_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) 	mib.exclude_unencrypted = priv->exclude_unencrypted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804) 	memcpy(mib.receiver_address, priv->CurrentBSSID, ETH_ALEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) 	/* zero all the keys before adding in valid ones. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) 	memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) 	if (priv->wep_is_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) 		/* There's a comment in the Atmel code to the effect that this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) 		   is only valid when still using WEP, it may need to be set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) 		   something to use WPA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) 		memset(mib.key_RSC, 0, sizeof(mib.key_RSC));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) 		mib.default_key = mib.group_key = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) 		for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) 			if (priv->wep_key_len[i] > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) 				memcpy(mib.cipher_default_key_value[i], priv->wep_keys[i], MAX_ENCRYPTION_KEY_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) 				if (i == priv->default_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) 					mib.default_key = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) 					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) 					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) 					mib.group_key = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) 					priv->group_cipher_suite = priv->pairwise_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) 					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) 					mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) 		if (mib.default_key == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) 			mib.default_key = mib.group_key != 255 ? mib.group_key : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) 		if (mib.group_key == 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) 			mib.group_key = mib.default_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838) 	atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) static int reset_atmel_card(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843) 	/* do everything necessary to wake up the hardware, including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) 	   waiting for the lightning strike and throwing the knife switch....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) 	   set all the Mib values which matter in the card to match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) 	   their settings in the atmel_private structure. Some of these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) 	   can be altered on the fly, but many (WEP, infrastructure or ad-hoc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) 	   can only be changed by tearing down the world and coming back through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) 	   here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) 	   This routine is also responsible for initialising some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) 	   hardware-specific fields in the atmel_private structure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) 	   including a copy of the firmware's hostinfo structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) 	   which is the route into the rest of the firmware datastructures. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) 	struct atmel_private *priv = netdev_priv(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) 	u8 configuration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) 	int old_state = priv->station_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) 	/* data to add to the firmware names, in priority order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) 	   this implemenents firmware versioning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) 	static char *firmware_modifier[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) 		"-wpa",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) 		"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) 		NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) 	/* reset pccard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) 	if (priv->bus_type == BUS_TYPE_PCCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) 		atmel_write16(priv->dev, GCR, 0x0060);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) 	/* stop card , disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) 	atmel_write16(priv->dev, GCR, 0x0040);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878) 	if (priv->card_type == CARD_TYPE_EEPROM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) 		/* copy in firmware if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) 		const struct firmware *fw_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881) 		const unsigned char *fw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) 		int len = priv->firmware_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) 		if (!(fw = priv->firmware)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884) 			if (priv->firmware_type == ATMEL_FW_TYPE_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) 				if (strlen(priv->firmware_id) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) 					printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887) 					       "%s: card type is unknown: assuming at76c502 firmware is OK.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) 					       dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) 					printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890) 					       "%s: if not, use the firmware= module parameter.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) 					       dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) 					strcpy(priv->firmware_id, "atmel_at76c502.bin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) 				err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895) 				if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) 					printk(KERN_ALERT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) 					       "%s: firmware %s is missing, cannot continue.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898) 					       dev->name, priv->firmware_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) 					return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) 				int fw_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) 				int success = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905) 				/* get firmware filename entry based on firmware type ID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) 				while (fw_table[fw_index].fw_type != priv->firmware_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) 						&& fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) 					fw_index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) 				/* construct the actual firmware file name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911) 				if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) 					int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) 					for (i = 0; firmware_modifier[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914) 						snprintf(priv->firmware_id, 32, "%s%s.%s", fw_table[fw_index].fw_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) 							firmware_modifier[i], fw_table[fw_index].fw_file_ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) 						priv->firmware_id[31] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) 						if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) 							success = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) 							break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) 						}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) 				if (!success) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924) 					printk(KERN_ALERT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) 					       "%s: firmware %s is missing, cannot start.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) 					       dev->name, priv->firmware_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) 					priv->firmware_id[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) 					return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932) 			fw = fw_entry->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) 			len = fw_entry->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) 		if (len <= 0x6000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) 			atmel_write16(priv->dev, BSR, BSS_IRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) 			atmel_copy_to_card(priv->dev, 0, fw, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) 			atmel_set_gcr(priv->dev, GCR_REMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) 			/* Remap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) 			atmel_set_gcr(priv->dev, GCR_REMAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) 			atmel_write16(priv->dev, BSR, BSS_IRAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) 			atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) 			atmel_write16(priv->dev, BSR, 0x2ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) 			atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) 		release_firmware(fw_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) 	err = atmel_wakeup_firmware(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) 	if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) 	/* Check the version and set the correct flag for wpa stuff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957) 	   old and new firmware is incompatible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) 	   The pre-wpa 3com firmware reports major version 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) 	   the wpa 3com firmware is major version 4 and doesn't need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) 	   the 3com broken-ness filter. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) 	priv->use_wpa = (priv->host_info.major_version == 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) 	priv->radio_on_broken = (priv->host_info.major_version == 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964) 	/* unmask all irq sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) 	atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967) 	/* int Tx system and enable Tx */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) 	atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) 	atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970) 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) 	atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973) 	priv->tx_desc_free = priv->host_info.tx_desc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) 	priv->tx_desc_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) 	priv->tx_desc_tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976) 	priv->tx_desc_previous = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) 	priv->tx_free_mem = priv->host_info.tx_buff_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) 	priv->tx_buff_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) 	priv->tx_buff_tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) 	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) 	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) 				   configuration | FUNC_CTRL_TxENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) 	/* init Rx system and enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) 	priv->rx_desc_head = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) 	configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) 	atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) 				   configuration | FUNC_CTRL_RxENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) 	if (!priv->radio_on_broken) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) 		if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) 		    CMD_STATUS_REJECTED_RADIO_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995) 			printk(KERN_INFO "%s: cannot turn the radio on.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) 			       dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) 	/* set up enough MIB values to run. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) 	atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) 	atmel_set_mib8(priv, Local_Mib_Type,  LOCAL_MIB_TX_PROMISCUOUS_POS,  PROM_MODE_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) 	atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_RTS_THRESHOLD_POS, priv->rts_threshold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) 	atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_FRAG_THRESHOLD_POS, priv->frag_threshold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) 	atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) 	atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) 	atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) 	atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) 		      priv->dev->dev_addr, 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) 	atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) 	atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) 	atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_BEACON_PER_POS, priv->default_beacon_period);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) 	atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, atmel_basic_rates, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) 	atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep_is_on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) 	if (priv->use_wpa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) 		build_wpa_mib(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) 		build_wep_mib(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021) 	if (old_state == STATION_STATE_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) 		union iwreq_data wrqu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) 		wrqu.data.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) 		wrqu.data.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) 		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) 		eth_zero_addr(wrqu.ap_addr.sa_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) 		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) static void atmel_send_command(struct atmel_private *priv, int command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) 			       void *cmd, int cmd_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) 	if (cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) 		atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) 				   cmd, cmd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) 	atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042) 	atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) static int atmel_send_command_wait(struct atmel_private *priv, int command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) 				   void *cmd, int cmd_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) 	int i, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) 	atmel_send_command(priv, command, cmd, cmd_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) 	for (i = 5000; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) 		status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) 		if (status != CMD_STATUS_IDLE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) 		    status != CMD_STATUS_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) 		udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) 		printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) 		status =  CMD_STATUS_HOST_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) 		if (command != CMD_EnableRadio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) 			status = CMD_STATUS_COMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068) 	return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) 	struct get_set_mib m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) 	m.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) 	m.size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) 	m.index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) 	atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) 	return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) 	struct get_set_mib m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) 	m.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) 	m.size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) 	m.index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) 	m.data[0] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) 	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) 			    u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) 	struct get_set_mib m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) 	m.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) 	m.size = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) 	m.index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) 	m.data[0] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) 	m.data[1] = data >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) 	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) 			  u8 *data, int data_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) 	struct get_set_mib m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) 	m.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) 	m.size = data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) 	m.index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) 	if (data_len > MIB_MAX_DATA_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) 		printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) 	memcpy(m.data, data, data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) 	atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) 			  u8 *data, int data_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) 	struct get_set_mib m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) 	m.type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) 	m.size = data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) 	m.index = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) 	if (data_len > MIB_MAX_DATA_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) 		printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) 	atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) 	atmel_copy_to_host(priv->dev, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) 			   atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) static void atmel_writeAR(struct net_device *dev, u16 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) 	outw(data, dev->base_addr + AR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) 	/* Address register appears to need some convincing..... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) 	for (i = 0; data != inw(dev->base_addr + AR) && i < 10; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) 		outw(data, dev->base_addr + AR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) static void atmel_copy_to_card(struct net_device *dev, u16 dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) 			       const unsigned char *src, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) 	atmel_writeAR(dev, dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) 	if (dest % 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) 		atmel_write8(dev, DR, *src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) 		src++; len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) 	for (i = len; i > 1 ; i -= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) 		u8 lb = *src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) 		u8 hb = *src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) 		atmel_write16(dev, DR, lb | (hb << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) 	if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) 		atmel_write8(dev, DR, *src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) 			       u16 src, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) 	atmel_writeAR(dev, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) 	if (src % 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) 		*dest = atmel_read8(dev, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) 		dest++; len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) 	for (i = len; i > 1 ; i -= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) 		u16 hw = atmel_read16(dev, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) 		*dest++ = hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) 		*dest++ = hw >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) 	if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) 		*dest = atmel_read8(dev, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) static void atmel_set_gcr(struct net_device *dev, u16 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) 	outw(inw(dev->base_addr + GCR) | mask, dev->base_addr + GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) static void atmel_clear_gcr(struct net_device *dev, u16 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189) 	outw(inw(dev->base_addr + GCR) & ~mask, dev->base_addr + GCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) static int atmel_lock_mac(struct atmel_private *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) 	int i, j = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195)  retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196) 	for (i = 5000; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) 		if (!atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) 		udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) 	if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) 		return 0; /* timed out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) 	atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) 	if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) 		atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) 		if (!j--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) 			return 0; /* timed out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) 		goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) 	atmel_writeAR(priv->dev, pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) 	atmel_write16(priv->dev, DR, data); /* card is little-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) 	atmel_write16(priv->dev, DR, data >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) /***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) /* There follows the source form of the MAC address reading firmware       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) /***************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) /* Copyright 2003 Matthew T. Russotto                                      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) /* But derived from the Atmel 76C502 firmware written by Atmel and         */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) /* included in "atmel wireless lan drivers" package                        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232)     This file is part of net.russotto.AtmelMACFW, hereto referred to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233)     as AtmelMACFW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235)     AtmelMACFW is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236)     it under the terms of the GNU General Public License version 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237)     as published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239)     AtmelMACFW is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240)     but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241)     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242)     GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244)     You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245)     along with AtmelMACFW; if not, see <http://www.gnu.org/licenses/>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) ****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) /* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E        */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) /* It will probably work on the 76C504 and 76C502 RFMD_3COM                */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) /* It only works on SPI EEPROM versions of the card.                       */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) /* This firmware initializes the SPI controller and clock, reads the MAC   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) /* address from the EEPROM into SRAM, and puts the SRAM offset of the MAC  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) /* address in MR2, and sets MR3 to 0x10 to indicate it is done             */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) /* It also puts a complete copy of the EEPROM in SRAM with the offset in   */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) /* MR4, for investigational purposes (maybe we can determine chip type     */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) /* from that?)                                                             */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) 	.org 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260)     .set MRBASE, 0x8000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) 	.set CPSR_INITIAL, 0xD3 /* IRQ/FIQ disabled, ARM mode, Supervisor state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) 	.set CPSR_USER, 0xD1 /* IRQ/FIQ disabled, ARM mode, USER state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263) 	.set SRAM_BASE,  0x02000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) 	.set SP_BASE,    0x0F300000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) 	.set UNK_BASE,   0x0F000000 /* Some internal device, but which one? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266) 	.set SPI_CGEN_BASE,  0x0E000000 /* Some internal device, but which one? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) 	.set UNK3_BASE,  0x02014000 /* Some internal device, but which one? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) 	.set STACK_BASE, 0x5600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) 	.set SP_SR, 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) 	.set SP_TDRE, 2 /* status register bit -- TDR empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271) 	.set SP_RDRF, 1 /* status register bit -- RDR full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) 	.set SP_SWRST, 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) 	.set SP_SPIEN, 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274) 	.set SP_CR, 0   /* control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) 	.set SP_MR, 4   /* mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276) 	.set SP_RDR, 0x08 /* Read Data Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) 	.set SP_TDR, 0x0C /* Transmit Data Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) 	.set SP_CSR0, 0x30 /* chip select registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) 	.set SP_CSR1, 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) 	.set SP_CSR2, 0x38
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) 	.set SP_CSR3, 0x3C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) 	.set NVRAM_CMD_RDSR, 5 /* read status register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283) 	.set NVRAM_CMD_READ, 3 /* read data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) 	.set NVRAM_SR_RDY, 1 /* RDY bit.  This bit is inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) 	.set SPI_8CLOCKS, 0xFF /* Writing this to the TDR doesn't do anything to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) 				  serial output, since SO is normally high.  But it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287) 				  does cause 8 clock cycles and thus 8 bits to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) 				  clocked in to the chip.  See Atmel's SPI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) 				  controller (e.g. AT91M55800) timing and 4K
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) 				  SPI EEPROM manuals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) 	.set NVRAM_SCRATCH, 0x02000100  /* arbitrary area for scratchpad memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) 	.set NVRAM_IMAGE, 0x02000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) 	.set NVRAM_LENGTH, 0x0200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) 	.set MAC_ADDRESS_MIB, SRAM_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) 	.set MAC_ADDRESS_LENGTH, 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) 	.set MAC_BOOT_FLAG, 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298) 	.set MR1, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) 	.set MR2, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) 	.set MR3, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) 	.set MR4, 0xC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) RESET_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) 	b RESET_HANDLER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) UNDEF_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305) 	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) SWI_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) 	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308) IABORT_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) 	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) DABORT_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) RESERVED_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312) 	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) IRQ_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) 	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) FIQ_VECTOR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) 	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317) HALT1:	b HALT1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) RESET_HANDLER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) 	mov     r0, #CPSR_INITIAL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) 	msr	CPSR_c, r0	/* This is probably unnecessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) /* I'm guessing this is initializing clock generator electronics for SPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) 	ldr	r0, =SPI_CGEN_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324) 	mov	r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) 	mov	r1, r1, lsl #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) 	orr	r1, r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327) 	str	r1, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) 	ldr	r1, [r0, #28]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) 	bic	r1, r1, #16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) 	str	r1, [r0, #28]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331) 	mov	r1, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) 	str	r1, [r0, #8]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) 	ldr	r0, =MRBASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335) 	mov	r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) 	strh	r1, [r0, #MR1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) 	strh	r1, [r0, #MR2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) 	strh	r1, [r0, #MR3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339) 	strh	r1, [r0, #MR4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) 	mov	sp, #STACK_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) 	bl	SP_INIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343) 	mov	r0, #10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) 	bl	DELAY9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) 	bl	GET_MAC_ADDR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346) 	bl	GET_WHOLE_NVRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) 	ldr	r0, =MRBASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) 	ldr	r1, =MAC_ADDRESS_MIB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) 	strh	r1, [r0, #MR2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350) 	ldr	r1, =NVRAM_IMAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) 	strh	r1, [r0, #MR4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) 	mov	r1, #MAC_BOOT_FLAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353) 	strh	r1, [r0, #MR3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) HALT2:	b HALT2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) .func Get_Whole_NVRAM, GET_WHOLE_NVRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) GET_WHOLE_NVRAM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357) 	stmdb	sp!, {lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) 	mov	r2, #0 /* 0th bytes of NVRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359) 	mov	r3, #NVRAM_LENGTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360) 	mov	r1, #0		/* not used in routine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) 	ldr	r0, =NVRAM_IMAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) 	bl	NVRAM_XFER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) 	ldmia	sp!, {lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) .endfunc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367) .func Get_MAC_Addr, GET_MAC_ADDR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) GET_MAC_ADDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) 	stmdb	sp!, {lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) 	mov	r2, #0x120	/* address of MAC Address within NVRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371) 	mov	r3, #MAC_ADDRESS_LENGTH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) 	mov	r1, #0		/* not used in routine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) 	ldr	r0, =MAC_ADDRESS_MIB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374) 	bl	NVRAM_XFER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) 	ldmia	sp!, {lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) .endfunc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378) .ltorg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379) .func Delay9, DELAY9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380) DELAY9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381) 	adds	r0, r0, r0, LSL #3   /* r0 = r0 * 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) DELAYLOOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) 	beq	DELAY9_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384) 	subs	r0, r0, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) 	b	DELAYLOOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) DELAY9_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388) .endfunc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) .func SP_Init, SP_INIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391) SP_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) 	mov	r1, #SP_SWRST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) 	ldr	r0, =SP_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394) 	str	r1, [r0, #SP_CR] /* reset the SPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395) 	mov	r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396) 	str	r1, [r0, #SP_CR] /* release SPI from reset state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) 	mov	r1, #SP_SPIEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) 	str	r1, [r0, #SP_MR] /* set the SPI to MASTER mode*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) 	str	r1, [r0, #SP_CR] /* enable the SPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) /*  My guess would be this turns on the SPI clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402) 	ldr	r3, =SPI_CGEN_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) 	ldr	r1, [r3, #28]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) 	orr	r1, r1, #0x2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405) 	str	r1, [r3, #28]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) 	ldr	r1, =0x2000c01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408) 	str	r1, [r0, #SP_CSR0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) 	ldr	r1, =0x2000201
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410) 	str	r1, [r0, #SP_CSR1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) 	str	r1, [r0, #SP_CSR2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412) 	str	r1, [r0, #SP_CSR3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) 	ldr	r1, [r0, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) 	ldr	r0, [r0, #SP_RDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) .endfunc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417) .func NVRAM_Init, NVRAM_INIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) NVRAM_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419) 	ldr	r1, =SP_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) 	ldr	r0, [r1, #SP_RDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) 	mov	r0, #NVRAM_CMD_RDSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422) 	str	r0, [r1, #SP_TDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) SP_loop1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) 	ldr	r0, [r1, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) 	tst	r0, #SP_TDRE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426) 	beq	SP_loop1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) 	mov	r0, #SPI_8CLOCKS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) 	str	r0, [r1, #SP_TDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430) SP_loop2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) 	ldr	r0, [r1, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) 	tst	r0, #SP_TDRE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) 	beq	SP_loop2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) 	ldr	r0, [r1, #SP_RDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) SP_loop3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) 	ldr	r0, [r1, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438) 	tst	r0, #SP_RDRF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) 	beq	SP_loop3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) 	ldr	r0, [r1, #SP_RDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) 	and	r0, r0, #255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444) .endfunc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446) .func NVRAM_Xfer, NVRAM_XFER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447) 	/* r0 = dest address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) 	/* r1 = not used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) 	/* r2 = src address within NVRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450) 	/* r3 = length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) NVRAM_XFER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452) 	stmdb	sp!, {r4, r5, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453) 	mov	r5, r0		/* save r0 (dest address) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) 	mov	r4, r3		/* save r3 (length) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) 	mov	r0, r2, LSR #5 /*  SPI memories put A8 in the command field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456) 	and	r0, r0, #8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) 	add	r0, r0, #NVRAM_CMD_READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458) 	ldr	r1, =NVRAM_SCRATCH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) 	strb	r0, [r1, #0]	/* save command in NVRAM_SCRATCH[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) 	strb	r2, [r1, #1]    /* save low byte of source address in NVRAM_SCRATCH[1] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461) _local1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462) 	bl	NVRAM_INIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) 	tst	r0, #NVRAM_SR_RDY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464) 	bne	_local1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) 	mov	r0, #20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) 	bl	DELAY9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) 	mov	r2, r4		/* length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468) 	mov	r1, r5		/* dest address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) 	mov	r0, #2		/* bytes to transfer in command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470) 	bl	NVRAM_XFER2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) 	ldmia	sp!, {r4, r5, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) .endfunc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) .func NVRAM_Xfer2, NVRAM_XFER2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476) NVRAM_XFER2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) 	stmdb	sp!, {r4, r5, r6, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) 	ldr	r4, =SP_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479) 	mov	r3, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) 	cmp	r0, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481) 	bls	_local2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) 	ldr	r5, =NVRAM_SCRATCH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) _local4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) 	ldrb	r6, [r5, r3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) 	str	r6, [r4, #SP_TDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) _local3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) 	ldr	r6, [r4, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) 	tst	r6, #SP_TDRE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) 	beq	_local3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) 	add	r3, r3, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) 	cmp	r3, r0 /* r0 is # of bytes to send out (command+addr) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) 	blo	_local4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) _local2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) 	mov	r3, #SPI_8CLOCKS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) 	str	r3, [r4, #SP_TDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) 	ldr	r0, [r4, #SP_RDR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) _local5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) 	ldr	r0, [r4, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) 	tst	r0, #SP_RDRF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) 	beq	_local5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) 	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 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) 	mov	r0, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) 	cmp	r2, #0  /* r2 is # of bytes to copy in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) 	bls	_local6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) _local7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) 	ldr	r5, [r4, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) 	tst	r5, #SP_TDRE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508) 	beq	_local7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) 	str	r3, [r4, #SP_TDR]  /* r3 has SPI_8CLOCKS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) _local8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) 	ldr	r5, [r4, #SP_SR]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) 	tst	r5, #SP_RDRF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) 	beq	_local8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) 	ldr	r5, [r4, #SP_RDR] /* but didn't we read this byte above? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) 	strb	r5, [r1], #1 /* postindexed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) 	add	r0, r0, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) 	cmp	r0, r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) 	blo	_local7 /* since we don't send another address, the NVRAM must be capable of sequential reads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) _local6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) 	mov	r0, #200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521) 	bl	DELAY9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) 	ldmia	sp!, {r4, r5, r6, lr}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) 	bx	lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) #endif