^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