提交 1f8fc993 编写于 作者: J Jeff Garzik

Merge branch 'upstream-jgarzik' of git://git.tuxdriver.com/git/netdev-jwl

......@@ -60,7 +60,6 @@ extern SK_U64 SkOsGetTime(SK_AC*);
extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32);
extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
......
......@@ -130,14 +130,12 @@ typedef struct s_vpd_key {
#ifndef VPD_DO_IO
#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val)
#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val)
#define VPD_OUT32(pAC,IoC,Addr,Val) (void)SkPciWriteCfgDWord(pAC,Addr,Val)
#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal)
#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal)
#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal)
#else /* VPD_DO_IO */
#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val)
#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val)
#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(Addr),Val)
#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal)
#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal)
#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal)
......@@ -155,12 +153,6 @@ typedef struct s_vpd_key {
else \
SK_OUT16(pAC,PCI_C(Addr),Val); \
}
#define VPD_OUT32(pAC,Ioc,Addr,Val) { \
if ((pAC)->DgT.DgUseCfgCycle) \
SkPciWriteCfgDWord(pAC,Addr,Val); \
else \
SK_OUT32(pAC,PCI_C(Addr),Val); \
}
#define VPD_IN8(pAC,Ioc,Addr,pVal) { \
if ((pAC)->DgT.DgUseCfgCycle) \
SkPciReadCfgByte(pAC,Addr,pVal); \
......
......@@ -277,6 +277,27 @@ extern struct ethtool_ops SkGeEthtoolOps;
static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
/*****************************************************************************
*
* SkPciWriteCfgDWord - write a 32 bit value to pci config space
*
* Description:
* This routine writes a 32 bit value to the pci configuration
* space.
*
* Returns:
* 0 - indicate everything worked ok.
* != 0 - error indication
*/
static inline int SkPciWriteCfgDWord(
SK_AC *pAC, /* Adapter Control structure pointer */
int PciAddr, /* PCI register address */
SK_U32 Val) /* pointer to store the read value */
{
pci_write_config_dword(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgDWord */
/*****************************************************************************
*
* SkGeInitPCI - Init the PCI resources
......@@ -4083,28 +4104,6 @@ SK_U8 *pVal) /* pointer to store the read value */
} /* SkPciReadCfgByte */
/*****************************************************************************
*
* SkPciWriteCfgDWord - write a 32 bit value to pci config space
*
* Description:
* This routine writes a 32 bit value to the pci configuration
* space.
*
* Returns:
* 0 - indicate everything worked ok.
* != 0 - error indication
*/
int SkPciWriteCfgDWord(
SK_AC *pAC, /* Adapter Control structure pointer */
int PciAddr, /* PCI register address */
SK_U32 Val) /* pointer to store the read value */
{
pci_write_config_dword(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgDWord */
/*****************************************************************************
*
* SkPciWriteCfgWord - write a 16 bit value to pci config space
......
#ifndef _LMC_PROTO_H_
#define _LMC_PROTO_H_
void lmc_proto_init(lmc_softc_t * const)
void lmc_proto_attach(lmc_softc_t *sc const)
void lmc_proto_detach(lmc_softc *sc const)
void lmc_proto_reopen(lmc_softc_t *sc const)
int lmc_proto_ioctl(lmc_softc_t *sc const, struct ifreq *ifr, int cmd)
void lmc_proto_open(lmc_softc_t *sc const)
void lmc_proto_close(lmc_softc_t *sc const)
unsigned short lmc_proto_type(lmc_softc_t *sc const, struct skbuff *skb)
#endif
......@@ -5,9 +5,9 @@
Copyright 2000-2001 ATMEL Corporation.
Copyright 2003-2004 Simon Kelley.
This code was developed from version 2.1.1 of the Atmel drivers,
released by Atmel corp. under the GPL in December 2002. It also
includes code from the Linux aironet drivers (C) Benjamin Reed,
This code was developed from version 2.1.1 of the Atmel drivers,
released by Atmel corp. under the GPL in December 2002. It also
includes code from the Linux aironet drivers (C) Benjamin Reed,
and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
extensions, (C) Jean Tourrilhes.
......@@ -31,7 +31,7 @@
along with Atmel wireless lan drivers; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For all queries about this code, please contact the current author,
For all queries about this code, please contact the current author,
Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
Credit is due to HP UK and Cambridge Online Systems Ltd for supplying
......@@ -79,13 +79,13 @@ MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.")
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
/* The name of the firmware file to be loaded
/* The name of the firmware file to be loaded
over-rides any automatic selection */
static char *firmware = NULL;
module_param(firmware, charp, 0);
/* table of firmware file names */
static struct {
static struct {
AtmelFWType fw_type;
const char *fw_file;
const char *fw_file_ext;
......@@ -104,17 +104,17 @@ static struct {
#define MAX_SSID_LENGTH 32
#define MGMT_JIFFIES (256 * HZ / 100)
#define MAX_BSS_ENTRIES 64
#define MAX_BSS_ENTRIES 64
/* registers */
#define GCR 0x00 // (SIR0) General Configuration Register
#define BSR 0x02 // (SIR1) Bank Switching Select Register
#define GCR 0x00 // (SIR0) General Configuration Register
#define BSR 0x02 // (SIR1) Bank Switching Select Register
#define AR 0x04
#define DR 0x08
#define MR1 0x12 // Mirror Register 1
#define MR2 0x14 // Mirror Register 2
#define MR3 0x16 // Mirror Register 3
#define MR4 0x18 // Mirror Register 4
#define MR1 0x12 // Mirror Register 1
#define MR2 0x14 // Mirror Register 2
#define MR3 0x16 // Mirror Register 3
#define MR4 0x18 // Mirror Register 4
#define GPR1 0x0c
#define GPR2 0x0e
......@@ -123,9 +123,9 @@ static struct {
// Constants for the GCR register.
//
#define GCR_REMAP 0x0400 // Remap internal SRAM to 0
#define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset)
#define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset)
#define GCR_CORES 0x0060 // Core Reset (ARM and PAI are reset)
#define GCR_ENINT 0x0002 // Enable Interrupts
#define GCR_ENINT 0x0002 // Enable Interrupts
#define GCR_ACKINT 0x0008 // Acknowledge Interrupts
#define BSS_SRAM 0x0200 // AMBA module selection --> SRAM
......@@ -190,7 +190,7 @@ struct rx_desc {
u32 Next;
u16 MsduPos;
u16 MsduSize;
u8 State;
u8 Status;
u8 Rate;
......@@ -199,7 +199,6 @@ struct rx_desc {
u8 PreambleType;
u16 Duration;
u32 RxTime;
};
#define RX_DESC_FLAG_VALID 0x80
......@@ -218,16 +217,15 @@ struct rx_desc {
#define RX_DESC_DURATION_OFFSET 14
#define RX_DESC_RX_TIME_OFFSET 16
struct tx_desc {
u32 NextDescriptor;
u16 TxStartOfFrame;
u16 TxLength;
u8 TxState;
u8 TxStatus;
u8 RetryCount;
u8 TxRate;
u8 KeyIndex;
......@@ -238,10 +236,8 @@ struct tx_desc {
u8 Reserved;
u8 PacketType;
u16 HostTxLength;
};
#define TX_DESC_NEXT_OFFSET 0
#define TX_DESC_POS_OFFSET 4
#define TX_DESC_SIZE_OFFSET 6
......@@ -255,8 +251,6 @@ struct tx_desc {
#define TX_DESC_PACKET_TYPE_OFFSET 17
#define TX_DESC_HOST_LENGTH_OFFSET 18
///////////////////////////////////////////////////////
// Host-MAC interface
///////////////////////////////////////////////////////
......@@ -266,7 +260,6 @@ struct tx_desc {
#define TX_FIRM_OWN 0x80
#define TX_DONE 0x40
#define TX_ERROR 0x01
#define TX_PACKET_TYPE_DATA 0x01
......@@ -280,8 +273,7 @@ struct tx_desc {
#define ISR_COMMAND_COMPLETE 0x10 // command completed
#define ISR_OUT_OF_RANGE 0x20 // command completed
#define ISR_IBSS_MERGE 0x40 // (4.1.2.30): IBSS merge
#define ISR_GENERIC_IRQ 0x80
#define ISR_GENERIC_IRQ 0x80
#define Local_Mib_Type 0x01
#define Mac_Address_Mib_Type 0x02
......@@ -317,7 +309,6 @@ struct tx_desc {
#define LOCAL_MIB_PREAMBLE_TYPE 9
#define MAC_ADDR_MIB_MAC_ADDR_POS 0
#define CMD_Set_MIB_Vars 0x01
#define CMD_Get_MIB_Vars 0x02
#define CMD_Scan 0x03
......@@ -338,7 +329,6 @@ struct tx_desc {
#define CMD_STATUS_HOST_ERROR 0xFF
#define CMD_STATUS_BUSY 0xFE
#define CMD_BLOCK_COMMAND_OFFSET 0
#define CMD_BLOCK_STATUS_OFFSET 1
#define CMD_BLOCK_PARAMETERS_OFFSET 4
......@@ -347,15 +337,15 @@ struct tx_desc {
#define MGMT_FRAME_BODY_OFFSET 24
#define MAX_AUTHENTICATION_RETRIES 3
#define MAX_ASSOCIATION_RETRIES 3
#define MAX_ASSOCIATION_RETRIES 3
#define AUTHENTICATION_RESPONSE_TIME_OUT 1000
#define MAX_WIRELESS_BODY 2316 /* mtu is 2312, CRC is 4 */
#define LOOP_RETRY_LIMIT 500000
#define ACTIVE_MODE 1
#define PS_MODE 2
#define ACTIVE_MODE 1
#define PS_MODE 2
#define MAX_ENCRYPTION_KEYS 4
#define MAX_ENCRYPTION_KEY_SIZE 40
......@@ -377,7 +367,7 @@ struct tx_desc {
#define REG_DOMAIN_MKK1 0x41 //Channel 1-14 Japan(MKK1)
#define REG_DOMAIN_ISRAEL 0x50 //Channel 3-9 ISRAEL
#define BSS_TYPE_AD_HOC 1
#define BSS_TYPE_AD_HOC 1
#define BSS_TYPE_INFRASTRUCTURE 2
#define SCAN_TYPE_ACTIVE 0
......@@ -389,7 +379,7 @@ struct tx_desc {
#define DATA_FRAME_WS_HEADER_SIZE 30
/* promiscuous mode control */
/* promiscuous mode control */
#define PROM_MODE_OFF 0x0
#define PROM_MODE_UNKNOWN 0x1
#define PROM_MODE_CRC_FAILED 0x2
......@@ -398,8 +388,7 @@ struct tx_desc {
#define PROM_MODE_CTRL 0x10
#define PROM_MODE_BAD_PROTOCOL 0x20
#define IFACE_INT_STATUS_OFFSET 0
#define IFACE_INT_STATUS_OFFSET 0
#define IFACE_INT_MASK_OFFSET 1
#define IFACE_LOCKOUT_HOST_OFFSET 2
#define IFACE_LOCKOUT_MAC_OFFSET 3
......@@ -407,7 +396,7 @@ struct tx_desc {
#define IFACE_MAC_STAT_OFFSET 30
#define IFACE_GENERIC_INT_TYPE_OFFSET 32
#define CIPHER_SUITE_NONE 0
#define CIPHER_SUITE_NONE 0
#define CIPHER_SUITE_WEP_64 1
#define CIPHER_SUITE_TKIP 2
#define CIPHER_SUITE_AES 3
......@@ -419,11 +408,11 @@ struct tx_desc {
//
//
// FuncCtrl field:
// FuncCtrl field:
//
#define FUNC_CTRL_TxENABLE 0x10
#define FUNC_CTRL_RxENABLE 0x20
#define FUNC_CTRL_INIT_COMPLETE 0x01
#define FUNC_CTRL_INIT_COMPLETE 0x01
/* A stub firmware image which reads the MAC address from NVRAM on the card.
For copyright information and source see the end of this file. */
......@@ -486,10 +475,10 @@ struct atmel_private {
struct net_device_stats stats; // device stats
spinlock_t irqlock, timerlock; // spinlocks
enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
enum {
CARD_TYPE_PARALLEL_FLASH,
enum {
CARD_TYPE_PARALLEL_FLASH,
CARD_TYPE_SPI_FLASH,
CARD_TYPE_EEPROM
CARD_TYPE_EEPROM
} card_type;
int do_rx_crc; /* If we need to CRC incoming packets */
int probe_crc; /* set if we don't yet know */
......@@ -497,18 +486,18 @@ struct atmel_private {
u16 rx_desc_head;
u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
u16 tx_free_mem, tx_buff_head, tx_buff_tail;
u16 frag_seq, frag_len, frag_no;
u8 frag_source[6];
u8 frag_source[6];
u8 wep_is_on, default_key, exclude_unencrypted, encryption_level;
u8 group_cipher_suite, pairwise_cipher_suite;
u8 wep_keys[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
int wep_key_len[MAX_ENCRYPTION_KEYS];
int wep_key_len[MAX_ENCRYPTION_KEYS];
int use_wpa, radio_on_broken; /* firmware dependent stuff. */
u16 host_info_base;
struct host_info_struct {
struct host_info_struct {
/* NB this is matched to the hardware, don't change. */
u8 volatile int_status;
u8 volatile int_mask;
......@@ -524,20 +513,20 @@ struct atmel_private {
u16 rx_buff_size;
u16 rx_desc_pos;
u16 rx_desc_count;
u16 build_version;
u16 command_pos;
u16 command_pos;
u16 major_version;
u16 minor_version;
u16 func_ctrl;
u16 mac_status;
u16 generic_IRQ_type;
u8 reserved[2];
} host_info;
enum {
enum {
STATION_STATE_SCANNING,
STATION_STATE_JOINNING,
STATION_STATE_AUTHENTICATING,
......@@ -547,7 +536,7 @@ struct atmel_private {
STATION_STATE_DOWN,
STATION_STATE_MGMT_ERROR
} station_state;
int operating_mode, power_mode;
time_t last_qual;
int beacons_this_sec;
......@@ -560,18 +549,18 @@ struct atmel_private {
int long_retry, short_retry;
int preamble;
int default_beacon_period, beacon_period, listen_interval;
int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
enum {
SITE_SURVEY_IDLE,
SITE_SURVEY_IN_PROGRESS,
SITE_SURVEY_COMPLETED
SITE_SURVEY_COMPLETED
} site_survey_state;
time_t last_survey;
int station_was_associated, station_is_associated;
int fast_scan;
struct bss_info {
int channel;
int SSIDsize;
......@@ -584,13 +573,12 @@ struct atmel_private {
u8 SSID[MAX_SSID_LENGTH];
} BSSinfo[MAX_BSS_ENTRIES];
int BSS_list_entries, current_BSS;
int connect_to_any_BSS;
int connect_to_any_BSS;
int SSID_size, new_SSID_size;
u8 CurrentBSSID[6], BSSID[6];
u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
u64 last_beacon_timestamp;
u8 rx_buf[MAX_WIRELESS_BODY];
};
static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
......@@ -598,39 +586,49 @@ static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
static const struct {
int reg_domain;
int min, max;
char *name;
char *name;
} channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
{ REG_DOMAIN_DOC, 1, 11, "Canada" },
{ REG_DOMAIN_ETSI, 1, 13, "Europe" },
{ REG_DOMAIN_SPAIN, 10, 11, "Spain" },
{ REG_DOMAIN_FRANCE, 10, 13, "France" },
{ REG_DOMAIN_FRANCE, 10, 13, "France" },
{ REG_DOMAIN_MKK, 14, 14, "MKK" },
{ REG_DOMAIN_MKK1, 1, 14, "MKK1" },
{ REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
static void build_wpa_mib(struct atmel_private *priv);
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len);
static void atmel_copy_to_card(struct net_device *dev, u16 dest,
unsigned char *src, u16 len);
static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
u16 src, u16 len);
static void atmel_set_gcr(struct net_device *dev, u16 mask);
static void atmel_clear_gcr(struct net_device *dev, u16 mask);
static int atmel_lock_mac(struct atmel_private *priv);
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
static void atmel_command_irq(struct atmel_private *priv);
static int atmel_validate_channel(struct atmel_private *priv, int channel);
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
static void atmel_management_frame(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi);
static void atmel_management_timer(u_long a);
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size);
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size);
static void atmel_transmit_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
static void atmel_send_command(struct atmel_private *priv, int command,
void *cmd, int cmd_size);
static int atmel_send_command_wait(struct atmel_private *priv, int command,
void *cmd, int cmd_size);
static void atmel_transmit_management_frame(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data);
static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data);
static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index,
u8 data);
static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
u16 data);
static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len);
static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len);
static void atmel_scan(struct atmel_private *priv, int specific_ssid);
static void atmel_join_bss(struct atmel_private *priv, int bss_index);
static void atmel_smooth_qual(struct atmel_private *priv);
......@@ -650,12 +648,12 @@ static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
return priv->host_info.command_pos + offset;
}
static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
{
return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
}
static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
{
return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
}
......@@ -682,25 +680,25 @@ static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
{
atmel_writeAR(priv->dev, pos);
atmel_writeAR(priv->dev, pos);
return atmel_read8(priv->dev, DR);
}
static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
{
atmel_writeAR(priv->dev, pos);
atmel_writeAR(priv->dev, pos);
atmel_write8(priv->dev, DR, data);
}
static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
{
atmel_writeAR(priv->dev, pos);
atmel_writeAR(priv->dev, pos);
return atmel_read16(priv->dev, DR);
}
static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
{
atmel_writeAR(priv->dev, pos);
atmel_writeAR(priv->dev, pos);
atmel_write16(priv->dev, DR, data);
}
......@@ -710,11 +708,10 @@ static void tx_done_irq(struct atmel_private *priv)
{
int i;
for (i = 0;
for (i = 0;
atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
i < priv->host_info.tx_desc_count;
i++) {
u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
......@@ -728,16 +725,16 @@ static void tx_done_irq(struct atmel_private *priv)
priv->tx_buff_head = 0;
else
priv->tx_buff_head += msdu_size;
if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
priv->tx_desc_head++ ;
priv->tx_desc_head++ ;
else
priv->tx_desc_head = 0;
if (type == TX_PACKET_TYPE_DATA) {
if (status == TX_STATUS_SUCCESS)
priv->stats.tx_packets++;
else
else
priv->stats.tx_errors++;
netif_wake_queue(priv->dev);
}
......@@ -748,21 +745,22 @@ static u16 find_tx_buff(struct atmel_private *priv, u16 len)
{
u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
return 0;
if (bottom_free >= len)
return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
if (priv->tx_free_mem - bottom_free >= len) {
priv->tx_buff_tail = 0;
return priv->host_info.tx_buff_pos;
}
return 0;
}
static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 len, u16 buff, u8 type)
static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
u16 len, u16 buff, u8 type)
{
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
......@@ -775,8 +773,8 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
int cipher_type, cipher_length;
if (is_bcast) {
cipher_type = priv->group_cipher_suite;
if (cipher_type == CIPHER_SUITE_WEP_64 ||
cipher_type == CIPHER_SUITE_WEP_128 )
if (cipher_type == CIPHER_SUITE_WEP_64 ||
cipher_type == CIPHER_SUITE_WEP_128)
cipher_length = 8;
else if (cipher_type == CIPHER_SUITE_TKIP)
cipher_length = 12;
......@@ -790,8 +788,8 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
}
} else {
cipher_type = priv->pairwise_cipher_suite;
if (cipher_type == CIPHER_SUITE_WEP_64 ||
cipher_type == CIPHER_SUITE_WEP_128 )
if (cipher_type == CIPHER_SUITE_WEP_64 ||
cipher_type == CIPHER_SUITE_WEP_128)
cipher_length = 8;
else if (cipher_type == CIPHER_SUITE_TKIP)
cipher_length = 12;
......@@ -804,9 +802,9 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
cipher_length = 0;
}
}
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail),
cipher_type);
cipher_type);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail),
cipher_length);
}
......@@ -815,46 +813,46 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
if (priv->tx_desc_previous != priv->tx_desc_tail)
atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
priv->tx_desc_previous = priv->tx_desc_tail;
if (priv->tx_desc_tail < (priv->host_info.tx_desc_count -1 ))
if (priv->tx_desc_tail < (priv->host_info.tx_desc_count - 1))
priv->tx_desc_tail++;
else
priv->tx_desc_tail = 0;
priv->tx_desc_free--;
priv->tx_free_mem -= len;
}
static int start_tx (struct sk_buff *skb, struct net_device *dev)
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
struct ieee80211_hdr_4addr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
if (priv->card && priv->present_callback &&
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
if (priv->station_state != STATION_STATE_READY) {
priv->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
/* first ensure the timer func cannot run */
spin_lock_bh(&priv->timerlock);
spin_lock_bh(&priv->timerlock);
/* then stop the hardware ISR */
spin_lock_irqsave(&priv->irqlock, flags);
spin_lock_irqsave(&priv->irqlock, flags);
/* nb doing the above in the opposite order will deadlock */
/* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
12 first bytes (containing DA/SA) and put them in the appropriate fields of
the Wireless Header. Thus the packet length is then the initial + 18 (+30-12) */
12 first bytes (containing DA/SA) and put them in the appropriate
fields of the Wireless Header. Thus the packet length is then the
initial + 18 (+30-12) */
if (!(buff = find_tx_buff(priv, len + 18))) {
priv->stats.tx_dropped++;
spin_unlock_irqrestore(&priv->irqlock, flags);
......@@ -862,7 +860,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
return 1;
}
frame_ctl = IEEE80211_FTYPE_DATA;
header.duration_id = 0;
header.seq_ctl = 0;
......@@ -878,7 +876,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
memcpy(&header.addr2, dev->dev_addr, 6);
memcpy(&header.addr3, skb->data, 6);
}
if (priv->use_wpa)
memcpy(&header.addr4, SNAP_RFC1024, 6);
......@@ -888,27 +886,27 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
/* Copy the packet sans its 802.3 header addresses which have been replaced */
atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
/* low bit of first byte of destination tells us if broadcast */
tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
dev->trans_start = jiffies;
priv->stats.tx_bytes += len;
spin_unlock_irqrestore(&priv->irqlock, flags);
spin_unlock_bh(&priv->timerlock);
dev_kfree_skb(skb);
return 0;
return 0;
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
static void atmel_transmit_management_frame(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u8 *body, int body_len)
{
u16 buff;
int len = MGMT_FRAME_BODY_OFFSET + body_len;
if (!(buff = find_tx_buff(priv, len)))
int len = MGMT_FRAME_BODY_OFFSET + body_len;
if (!(buff = find_tx_buff(priv, len)))
return;
atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
......@@ -916,24 +914,25 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
priv->tx_buff_tail += len;
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
static void fast_rx_path(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
u8 mac4[6];
struct sk_buff *skb;
u8 mac4[6];
struct sk_buff *skb;
unsigned char *skbp;
/* get the final, mac 4 header field, this tells us encapsulation */
atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
msdu_size -= 6;
if (priv->do_rx_crc) {
crc = crc32_le(crc, mac4, 6);
msdu_size -= 4;
}
if (!(skb = dev_alloc_skb(msdu_size + 14))) {
priv->stats.rx_dropped++;
return;
......@@ -942,7 +941,7 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
skb_reserve(skb, 2);
skbp = skb_put(skb, msdu_size + 12);
atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
if (priv->do_rx_crc) {
u32 netcrc;
crc = crc32_le(crc, skbp + 12, msdu_size);
......@@ -953,24 +952,25 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
return;
}
}
memcpy(skbp, header->addr1, 6); /* destination address */
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(&skbp[6], header->addr3, 6);
else
memcpy(&skbp[6], header->addr2, 6); /* source address */
priv->dev->last_rx=jiffies;
priv->dev->last_rx = jiffies;
skb->dev = priv->dev;
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
priv->stats.rx_bytes += 12 + msdu_size;
priv->stats.rx_packets++;
}
/* Test to see if the packet in card memory at packet_loc has a valid CRC
It doesn't matter that this is slow: it is only used to proble the first few packets. */
It doesn't matter that this is slow: it is only used to proble the first few
packets. */
static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
{
int i = msdu_size - 4;
......@@ -980,7 +980,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return 0;
atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
atmel_writeAR(priv->dev, packet_loc);
while (i--) {
u8 octet = atmel_read8(priv->dev, DR);
......@@ -990,20 +990,22 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return (crc ^ 0xffffffff) == netcrc;
}
static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
static void frag_rx_path(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
u8 frag_no, int more_frags)
{
u8 mac4[6];
u8 mac4[6];
u8 source[6];
struct sk_buff *skb;
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(source, header->addr3, 6);
else
memcpy(source, header->addr2, 6);
memcpy(source, header->addr2, 6);
rx_packet_loc += 24; /* skip header */
if (priv->do_rx_crc)
msdu_size -= 4;
......@@ -1012,16 +1014,16 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
msdu_size -= 6;
rx_packet_loc += 6;
if (priv->do_rx_crc)
if (priv->do_rx_crc)
crc = crc32_le(crc, mac4, 6);
priv->frag_seq = seq_no;
priv->frag_no = 1;
priv->frag_len = msdu_size;
memcpy(priv->frag_source, source, 6);
memcpy(priv->frag_source, source, 6);
memcpy(&priv->rx_buf[6], source, 6);
memcpy(priv->rx_buf, header->addr1, 6);
atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
if (priv->do_rx_crc) {
......@@ -1033,17 +1035,17 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
memset(priv->frag_source, 0xff, 6);
}
}
} else if (priv->frag_no == frag_no &&
priv->frag_seq == seq_no &&
memcmp(priv->frag_source, source, 6) == 0) {
atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
rx_packet_loc, msdu_size);
if (priv->do_rx_crc) {
u32 netcrc;
crc = crc32_le(crc,
&priv->rx_buf[12 + priv->frag_len],
crc = crc32_le(crc,
&priv->rx_buf[12 + priv->frag_len],
msdu_size);
atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
if ((crc ^ 0xffffffff) != netcrc) {
......@@ -1052,7 +1054,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
more_frags = 1; /* don't send broken assembly */
}
}
priv->frag_len += msdu_size;
priv->frag_no++;
......@@ -1062,60 +1064,60 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
priv->stats.rx_dropped++;
} else {
skb_reserve(skb, 2);
memcpy(skb_put(skb, priv->frag_len + 12),
memcpy(skb_put(skb, priv->frag_len + 12),
priv->rx_buf,
priv->frag_len + 12);
priv->dev->last_rx = jiffies;
skb->dev = priv->dev;
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
priv->stats.rx_bytes += priv->frag_len + 12;
priv->stats.rx_packets++;
}
}
} else
priv->wstats.discard.fragment++;
}
static void rx_done_irq(struct atmel_private *priv)
{
int i;
struct ieee80211_hdr_4addr header;
for (i = 0;
for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
i < priv->host_info.rx_desc_count;
i++) {
u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
u32 crc = 0xffffffff;
if (status != RX_STATUS_SUCCESS) {
if (status == 0xc1) /* determined by experiment */
priv->wstats.discard.nwid++;
else
priv->stats.rx_errors++;
priv->stats.rx_errors++;
goto next;
}
msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
if (msdu_size < 30) {
priv->stats.rx_errors++;
priv->stats.rx_errors++;
goto next;
}
/* Get header as far as end of seq_ctl */
atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
frame_ctl = le16_to_cpu(header.frame_ctl);
seq_control = le16_to_cpu(header.seq_ctl);
/* probe for CRC use here if needed once five packets have arrived with
the same crc status, we assume we know what's happening and stop probing */
/* probe for CRC use here if needed once five packets have
arrived with the same crc status, we assume we know what's
happening and stop probing */
if (priv->probe_crc) {
if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
......@@ -1130,34 +1132,33 @@ static void rx_done_irq(struct atmel_private *priv)
priv->probe_crc = 0;
}
}
/* don't CRC header when WEP in use */
if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) {
crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
}
msdu_size -= 24; /* header */
if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS;
u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG;
u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4;
if (!more_fragments && packet_fragment_no == 0 ) {
if (!more_fragments && packet_fragment_no == 0) {
fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
} else {
frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
packet_sequence_no, packet_fragment_no, more_fragments);
}
}
if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
/* copy rest of packet into buffer */
atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size);
/* we use the same buffer for frag reassembly and control packets */
memset(priv->frag_source, 0xff, 6);
if (priv->do_rx_crc) {
/* last 4 octets is crc */
msdu_size -= 4;
......@@ -1170,18 +1171,18 @@ static void rx_done_irq(struct atmel_private *priv)
atmel_management_frame(priv, &header, msdu_size,
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
}
}
next:
next:
/* release descriptor */
atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
priv->rx_desc_head++;
priv->rx_desc_head++;
else
priv->rx_desc_head = 0;
}
}
}
static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
......@@ -1189,7 +1190,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
struct atmel_private *priv = netdev_priv(dev);
u8 isr;
int i = -1;
static u8 irq_order[] = {
static u8 irq_order[] = {
ISR_OUT_OF_RANGE,
ISR_RxCOMPLETE,
ISR_TxCOMPLETE,
......@@ -1199,20 +1200,19 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
ISR_IBSS_MERGE,
ISR_GENERIC_IRQ
};
if (priv->card && priv->present_callback &&
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card))
return IRQ_HANDLED;
/* In this state upper-level code assumes it can mess with
the card unhampered by interrupts which may change register state.
Note that even though the card shouldn't generate interrupts
the inturrupt line may be shared. This allows card setup
the inturrupt line may be shared. This allows card setup
to go on without disabling interrupts for a long time. */
if (priv->station_state == STATION_STATE_DOWN)
return IRQ_NONE;
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
while (1) {
......@@ -1221,36 +1221,36 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED;
}
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
if (!isr) {
atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
return i == -1 ? IRQ_NONE : IRQ_HANDLED;
}
atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)
if (isr & irq_order[i])
break;
if (!atmel_lock_mac(priv)) {
/* failed to contact card */
printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED;
}
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
isr ^= irq_order[i];
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
switch (irq_order[i]) {
case ISR_OUT_OF_RANGE:
if (priv->operating_mode == IW_MODE_INFRA &&
case ISR_OUT_OF_RANGE:
if (priv->operating_mode == IW_MODE_INFRA &&
priv->station_state == STATION_STATE_READY) {
priv->station_is_associated = 0;
atmel_scan(priv, 1);
......@@ -1261,24 +1261,24 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
priv->wstats.discard.misc++;
/* fall through */
case ISR_RxCOMPLETE:
rx_done_irq(priv);
rx_done_irq(priv);
break;
case ISR_TxCOMPLETE:
tx_done_irq(priv);
tx_done_irq(priv);
break;
case ISR_FATAL_ERROR:
printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
break;
case ISR_COMMAND_COMPLETE:
case ISR_COMMAND_COMPLETE:
atmel_command_irq(priv);
break;
case ISR_IBSS_MERGE:
atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
priv->CurrentBSSID, 6);
/* The WPA stuff cares about the current AP address */
if (priv->use_wpa)
......@@ -1288,24 +1288,23 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
printk(KERN_INFO "%s: Generic_irq received.\n", dev->name);
break;
}
}
}
}
static struct net_device_stats *atmel_get_stats (struct net_device *dev)
static struct net_device_stats *atmel_get_stats(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
return &priv->stats;
}
static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
/* update the link quality here in case we are seeing no beacons
/* update the link quality here in case we are seeing no beacons
at all to drive the process */
atmel_smooth_qual(priv);
priv->wstats.status = priv->station_state;
if (priv->operating_mode == IW_MODE_INFRA) {
......@@ -1328,8 +1327,8 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
| IW_QUAL_NOISE_INVALID;
priv->wstats.miss.beacon = 0;
}
return (&priv->wstats);
return &priv->wstats;
}
static int atmel_change_mtu(struct net_device *dev, int new_mtu)
......@@ -1343,21 +1342,21 @@ static int atmel_change_mtu(struct net_device *dev, int new_mtu)
static int atmel_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
return atmel_open(dev);
}
EXPORT_SYMBOL(atmel_open);
int atmel_open (struct net_device *dev)
int atmel_open(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
int i, channel;
/* any scheduled timer is no longer needed and might screw things up.. */
del_timer_sync(&priv->management_timer);
/* Interrupts will not touch the card once in this state... */
priv->station_state = STATION_STATE_DOWN;
......@@ -1377,7 +1376,7 @@ int atmel_open (struct net_device *dev)
priv->site_survey_state = SITE_SURVEY_IDLE;
priv->station_is_associated = 0;
if (!reset_atmel_card(dev))
if (!reset_atmel_card(dev))
return -EAGAIN;
if (priv->config_reg_domain) {
......@@ -1391,26 +1390,26 @@ int atmel_open (struct net_device *dev)
if (i == sizeof(channel_table)/sizeof(channel_table[0])) {
priv->reg_domain = REG_DOMAIN_MKK1;
printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
}
}
}
if ((channel = atmel_validate_channel(priv, priv->channel)))
priv->channel = channel;
/* this moves station_state on.... */
atmel_scan(priv, 1);
/* this moves station_state on.... */
atmel_scan(priv, 1);
atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
return 0;
}
static int atmel_close (struct net_device *dev)
static int atmel_close(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
atmel_enter_state(priv, STATION_STATE_DOWN);
if (priv->bus_type == BUS_TYPE_PCCARD)
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
return 0;
......@@ -1438,43 +1437,46 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
int i;
char *p = buf;
char *s, *r, *c;
p += sprintf(p, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
p += sprintf(p, "Driver version:\t\t%d.%d\n",
DRIVER_MAJOR, DRIVER_MINOR);
if (priv->station_state != STATION_STATE_DOWN) {
p += sprintf(p, "Firmware version:\t%d.%d build %d\nFirmware location:\t",
p += sprintf(p, "Firmware version:\t%d.%d build %d\n"
"Firmware location:\t",
priv->host_info.major_version,
priv->host_info.minor_version,
priv->host_info.build_version);
if (priv->card_type != CARD_TYPE_EEPROM)
if (priv->card_type != CARD_TYPE_EEPROM)
p += sprintf(p, "on card\n");
else if (priv->firmware)
p += sprintf(p, "%s loaded by host\n", priv->firmware_id);
else if (priv->firmware)
p += sprintf(p, "%s loaded by host\n",
priv->firmware_id);
else
p += sprintf(p, "%s loaded by hotplug\n", priv->firmware_id);
switch(priv->card_type) {
p += sprintf(p, "%s loaded by hotplug\n",
priv->firmware_id);
switch (priv->card_type) {
case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;
case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break;
case CARD_TYPE_EEPROM: c = "EEPROM"; break;
default: c = "<unknown>";
}
r = "<unknown>";
for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
if (priv->reg_domain == channel_table[i].reg_domain)
r = channel_table[i].name;
p += sprintf(p, "MAC memory type:\t%s\n", c);
p += sprintf(p, "Regulatory domain:\t%s\n", r);
p += sprintf(p, "Host CRC checking:\t%s\n",
p += sprintf(p, "Host CRC checking:\t%s\n",
priv->do_rx_crc ? "On" : "Off");
p += sprintf(p, "WPA-capable firmware:\t%s\n",
priv->use_wpa ? "Yes" : "No");
}
switch(priv->station_state) {
case STATION_STATE_SCANNING: s = "Scanning"; break;
case STATION_STATE_JOINNING: s = "Joining"; break;
......@@ -1486,9 +1488,9 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
case STATION_STATE_DOWN: s = "Down"; break;
default: s = "<unknown>";
}
p += sprintf(p, "Current state:\t\t%s\n", s);
return p - buf;
return p - buf;
}
static int atmel_read_proc(char *page, char **start, off_t off,
......@@ -1504,9 +1506,12 @@ static int atmel_read_proc(char *page, char **start, off_t off,
return len;
}
struct net_device *init_atmel_card( unsigned short irq, unsigned long port, const AtmelFWType fw_type,
struct device *sys_dev, int (*card_present)(void *), void *card)
struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
const AtmelFWType fw_type,
struct device *sys_dev,
int (*card_present)(void *), void *card)
{
struct proc_dir_entry *ent;
struct net_device *dev;
struct atmel_private *priv;
int rc;
......@@ -1514,11 +1519,11 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
/* Create the network device object. */
dev = alloc_etherdev(sizeof(*priv));
if (!dev) {
printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n");
printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n");
return NULL;
}
if (dev_alloc_name(dev, dev->name) < 0) {
printk(KERN_ERR "atmel: Couldn't get name!\n");
printk(KERN_ERR "atmel: Couldn't get name!\n");
goto err_out_free;
}
......@@ -1550,7 +1555,7 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
memset(priv->BSSID, 0, 6);
priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
priv->station_was_associated = 0;
priv->last_survey = jiffies;
priv->preamble = LONG_PREAMBLE;
priv->operating_mode = IW_MODE_INFRA;
......@@ -1586,7 +1591,7 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
spin_lock_init(&priv->timerlock);
priv->management_timer.function = atmel_management_timer;
priv->management_timer.data = (unsigned long) dev;
dev->open = atmel_open;
dev->stop = atmel_close;
dev->change_mtu = atmel_change_mtu;
......@@ -1597,44 +1602,46 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
dev->do_ioctl = atmel_ioctl;
dev->irq = irq;
dev->base_addr = port;
SET_NETDEV_DEV(dev, sys_dev);
if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) {
printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc );
printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc);
goto err_out_free;
}
if (!request_region(dev->base_addr, 32,
if (!request_region(dev->base_addr, 32,
priv->bus_type == BUS_TYPE_PCCARD ? "atmel_cs" : "atmel_pci")) {
goto err_out_irq;
}
if (register_netdev(dev))
goto err_out_res;
if (!probe_atmel_card(dev)){
unregister_netdev(dev);
goto err_out_res;
}
netif_carrier_off(dev);
create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
ent = create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
if (!ent)
printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
dev->name, DRIVER_MAJOR, DRIVER_MINOR,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
SET_MODULE_OWNER(dev);
return dev;
err_out_res:
err_out_res:
release_region( dev->base_addr, 32);
err_out_irq:
err_out_irq:
free_irq(dev->irq, dev);
err_out_free:
err_out_free:
free_netdev(dev);
return NULL;
}
......@@ -1644,12 +1651,12 @@ EXPORT_SYMBOL(init_atmel_card);
void stop_atmel_card(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
/* put a brick on it... */
if (priv->bus_type == BUS_TYPE_PCCARD)
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
del_timer_sync(&priv->management_timer);
unregister_netdev(dev);
remove_proc_entry("driver/atmel", NULL);
......@@ -1675,13 +1682,13 @@ static int atmel_set_essid(struct net_device *dev,
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
priv->connect_to_any_BSS = 0;
/* Check the size of the string */
if (dwrq->length > MAX_SSID_LENGTH + 1)
return -E2BIG ;
return -E2BIG;
if (index != 0)
return -EINVAL;
memcpy(priv->new_SSID, extra, dwrq->length - 1);
priv->new_SSID_size = dwrq->length - 1;
}
......@@ -1706,7 +1713,7 @@ static int atmel_get_essid(struct net_device *dev,
extra[priv->SSID_size] = '\0';
dwrq->length = priv->SSID_size + 1;
}
dwrq->flags = !priv->connect_to_any_BSS; /* active */
return 0;
......@@ -1768,7 +1775,7 @@ static int atmel_set_encode(struct net_device *dev,
/* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later)
* This is also how "iwconfig ethX key on" works */
if (index == current_index &&
if (index == current_index &&
priv->wep_key_len[index] > 0) {
priv->wep_is_on = 1;
priv->exclude_unencrypted = 1;
......@@ -1783,18 +1790,18 @@ static int atmel_set_encode(struct net_device *dev,
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if ( index>=0 && index < 4 ) {
if (index >= 0 && index < 4) {
priv->default_key = index;
} else
/* Don't complain if only change the mode */
if(!dwrq->flags & IW_ENCODE_MODE) {
if (!dwrq->flags & IW_ENCODE_MODE) {
return -EINVAL;
}
}
/* Read the flags */
if(dwrq->flags & IW_ENCODE_DISABLED) {
if (dwrq->flags & IW_ENCODE_DISABLED) {
priv->wep_is_on = 0;
priv->encryption_level = 0;
priv->encryption_level = 0;
priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
} else {
priv->wep_is_on = 1;
......@@ -1806,15 +1813,14 @@ static int atmel_set_encode(struct net_device *dev,
priv->encryption_level = 1;
}
}
if(dwrq->flags & IW_ENCODE_RESTRICTED)
if (dwrq->flags & IW_ENCODE_RESTRICTED)
priv->exclude_unencrypted = 1;
if(dwrq->flags & IW_ENCODE_OPEN)
if(dwrq->flags & IW_ENCODE_OPEN)
priv->exclude_unencrypted = 0;
return -EINPROGRESS; /* Call commit handler */
}
static int atmel_get_encode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
......@@ -1822,7 +1828,7 @@ static int atmel_get_encode(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if (!priv->wep_is_on)
dwrq->flags = IW_ENCODE_DISABLED;
else {
......@@ -1843,7 +1849,7 @@ static int atmel_get_encode(struct net_device *dev,
memset(extra, 0, 16);
memcpy(extra, priv->wep_keys[index], dwrq->length);
}
return 0;
}
......@@ -1862,17 +1868,17 @@ static int atmel_set_rate(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
if (vwrq->fixed == 0) {
priv->tx_rate = 3;
priv->auto_tx_rate = 1;
} else {
priv->auto_tx_rate = 0;
/* Which type of value ? */
if((vwrq->value < 4) && (vwrq->value >= 0)) {
if ((vwrq->value < 4) && (vwrq->value >= 0)) {
/* Setting by rate index */
priv->tx_rate = vwrq->value;
priv->tx_rate = vwrq->value;
} else {
/* Setting by frequency value */
switch (vwrq->value) {
......@@ -1899,7 +1905,7 @@ static int atmel_set_mode(struct net_device *dev,
return -EINVAL;
priv->operating_mode = *uwrq;
return -EINPROGRESS;
return -EINPROGRESS;
}
static int atmel_get_mode(struct net_device *dev,
......@@ -1908,7 +1914,7 @@ static int atmel_get_mode(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
*uwrq = priv->operating_mode;
return 0;
}
......@@ -1962,9 +1968,9 @@ static int atmel_set_retry(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
if(!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
if(vwrq->flags & IW_RETRY_MAX)
if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
if (vwrq->flags & IW_RETRY_MAX)
priv->long_retry = vwrq->value;
else if (vwrq->flags & IW_RETRY_MIN)
priv->short_retry = vwrq->value;
......@@ -1973,9 +1979,9 @@ static int atmel_set_retry(struct net_device *dev,
priv->long_retry = vwrq->value;
priv->short_retry = vwrq->value;
}
return -EINPROGRESS;
return -EINPROGRESS;
}
return -EINVAL;
}
......@@ -1989,13 +1995,13 @@ static int atmel_get_retry(struct net_device *dev,
vwrq->disabled = 0; /* Can't be disabled */
/* Note : by default, display the min retry number */
if((vwrq->flags & IW_RETRY_MAX)) {
if (vwrq->flags & IW_RETRY_MAX) {
vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
vwrq->value = priv->long_retry;
} else {
vwrq->flags = IW_RETRY_LIMIT;
vwrq->value = priv->short_retry;
if(priv->long_retry != priv->short_retry)
if (priv->long_retry != priv->short_retry)
vwrq->flags |= IW_RETRY_MIN;
}
......@@ -2010,13 +2016,13 @@ static int atmel_set_rts(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
int rthr = vwrq->value;
if(vwrq->disabled)
if (vwrq->disabled)
rthr = 2347;
if((rthr < 0) || (rthr > 2347)) {
if ((rthr < 0) || (rthr > 2347)) {
return -EINVAL;
}
priv->rts_threshold = rthr;
return -EINPROGRESS; /* Call commit handler */
}
......@@ -2026,7 +2032,7 @@ static int atmel_get_rts(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
vwrq->value = priv->rts_threshold;
vwrq->disabled = (vwrq->value >= 2347);
vwrq->fixed = 1;
......@@ -2042,14 +2048,14 @@ static int atmel_set_frag(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
int fthr = vwrq->value;
if(vwrq->disabled)
if (vwrq->disabled)
fthr = 2346;
if((fthr < 256) || (fthr > 2346)) {
if ((fthr < 256) || (fthr > 2346)) {
return -EINVAL;
}
fthr &= ~0x1; /* Get an even value - is it really needed ??? */
priv->frag_threshold = fthr;
return -EINPROGRESS; /* Call commit handler */
}
......@@ -2077,21 +2083,21 @@ static int atmel_set_freq(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
int rc = -EINPROGRESS; /* Call commit handler */
/* If setting by frequency, convert to a channel */
if((fwrq->e == 1) &&
(fwrq->m >= (int) 241200000) &&
(fwrq->m <= (int) 248700000)) {
if ((fwrq->e == 1) &&
(fwrq->m >= (int) 241200000) &&
(fwrq->m <= (int) 248700000)) {
int f = fwrq->m / 100000;
int c = 0;
while((c < 14) && (f != frequency_list[c]))
while ((c < 14) && (f != frequency_list[c]))
c++;
/* Hack to fall through... */
fwrq->e = 0;
fwrq->m = c + 1;
}
/* Setting by channel number */
if((fwrq->m > 1000) || (fwrq->e > 0))
if ((fwrq->m > 1000) || (fwrq->e > 0))
rc = -EOPNOTSUPP;
else {
int channel = fwrq->m;
......@@ -2099,7 +2105,7 @@ static int atmel_set_freq(struct net_device *dev,
priv->channel = channel;
} else {
rc = -EINVAL;
}
}
}
return rc;
}
......@@ -2130,7 +2136,7 @@ static int atmel_set_scan(struct net_device *dev,
* This is not an error, while the device perform scanning,
* traffic doesn't flow, so it's a perfect DoS...
* Jean II */
if (priv->station_state == STATION_STATE_DOWN)
return -EAGAIN;
......@@ -2142,15 +2148,15 @@ static int atmel_set_scan(struct net_device *dev,
/* Initiate a scan command */
if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
return -EBUSY;
del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
priv->fast_scan = 0;
atmel_scan(priv, 0);
spin_unlock_irqrestore(&priv->irqlock, flags);
return 0;
}
......@@ -2163,11 +2169,11 @@ static int atmel_get_scan(struct net_device *dev,
int i;
char *current_ev = extra;
struct iw_event iwe;
if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
return -EAGAIN;
for(i=0; i<priv->BSS_list_entries; i++) {
for (i = 0; i < priv->BSS_list_entries; i++) {
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
......@@ -2179,16 +2185,16 @@ static int atmel_get_scan(struct net_device *dev,
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
iwe.cmd = SIOCGIWMODE;
iwe.u.mode = priv->BSSinfo[i].BSStype;
current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = priv->BSSinfo[i].channel;
iwe.u.freq.e = 0;
current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
iwe.cmd = SIOCGIWENCODE;
if (priv->BSSinfo[i].UsingWEP)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
......@@ -2196,13 +2202,12 @@ static int atmel_get_scan(struct net_device *dev,
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
}
/* Length of data */
dwrq->length = (current_ev - extra);
dwrq->flags = 0;
dwrq->flags = 0;
return 0;
}
......@@ -2213,7 +2218,7 @@ static int atmel_get_range(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
struct iw_range *range = (struct iw_range *) extra;
int k,i,j;
int k, i, j;
dwrq->length = sizeof(struct iw_range);
memset(range, 0, sizeof(struct iw_range));
......@@ -2226,14 +2231,14 @@ static int atmel_get_range(struct net_device *dev,
break;
}
if (range->num_channels != 0) {
for(k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
range->freq[k].i = i; /* List index */
range->freq[k].m = frequency_list[i-1] * 100000;
range->freq[k].m = frequency_list[i - 1] * 100000;
range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
}
range->num_frequency = k;
}
range->max_qual.qual = 100;
range->max_qual.level = 100;
range->max_qual.noise = 0;
......@@ -2261,11 +2266,11 @@ static int atmel_get_range(struct net_device *dev,
range->encoding_size[1] = 13;
range->num_encoding_sizes = 2;
range->max_encoding_tokens = 4;
range->pmp_flags = IW_POWER_ON;
range->pmt_flags = IW_POWER_ON;
range->pm_capa = 0;
range->we_version_source = WIRELESS_EXT;
range->we_version_compiled = WIRELESS_EXT;
range->retry_capa = IW_RETRY_LIMIT ;
......@@ -2289,7 +2294,7 @@ static int atmel_set_wap(struct net_device *dev,
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
if (memcmp(bcast, awrq->sa_data, 6) == 0) {
del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
......@@ -2297,8 +2302,8 @@ static int atmel_set_wap(struct net_device *dev,
spin_unlock_irqrestore(&priv->irqlock, flags);
return 0;
}
for(i=0; i<priv->BSS_list_entries; i++) {
for (i = 0; i < priv->BSS_list_entries; i++) {
if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) {
return -EINVAL;
......@@ -2313,10 +2318,10 @@ static int atmel_set_wap(struct net_device *dev,
}
}
}
return -EINVAL;
}
static int atmel_config_commit(struct net_device *dev,
struct iw_request_info *info, /* NULL */
void *zwrq, /* NULL */
......@@ -2325,18 +2330,18 @@ static int atmel_config_commit(struct net_device *dev,
return atmel_open(dev);
}
static const iw_handler atmel_handler[] =
static const iw_handler atmel_handler[] =
{
(iw_handler) atmel_config_commit, /* SIOCSIWCOMMIT */
(iw_handler) atmel_get_name, /* SIOCGIWNAME */
(iw_handler) atmel_get_name, /* SIOCGIWNAME */
(iw_handler) NULL, /* SIOCSIWNWID */
(iw_handler) NULL, /* SIOCGIWNWID */
(iw_handler) atmel_set_freq, /* SIOCSIWFREQ */
(iw_handler) atmel_get_freq, /* SIOCGIWFREQ */
(iw_handler) atmel_set_mode, /* SIOCSIWMODE */
(iw_handler) atmel_get_mode, /* SIOCGIWMODE */
(iw_handler) NULL, /* SIOCSIWSENS */
(iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL, /* SIOCSIWSENS */
(iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL, /* SIOCSIWRANGE */
(iw_handler) atmel_get_range, /* SIOCGIWRANGE */
(iw_handler) NULL, /* SIOCSIWPRIV */
......@@ -2350,13 +2355,13 @@ static const iw_handler atmel_handler[] =
(iw_handler) atmel_set_wap, /* SIOCSIWAP */
(iw_handler) atmel_get_wap, /* SIOCGIWAP */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* SIOCGIWAPLIST */
(iw_handler) NULL, /* SIOCGIWAPLIST */
(iw_handler) atmel_set_scan, /* SIOCSIWSCAN */
(iw_handler) atmel_get_scan, /* SIOCGIWSCAN */
(iw_handler) atmel_set_essid, /* SIOCSIWESSID */
(iw_handler) atmel_get_essid, /* SIOCGIWESSID */
(iw_handler) NULL, /* SIOCSIWNICKN */
(iw_handler) NULL, /* SIOCGIWNICKN */
(iw_handler) NULL, /* SIOCSIWNICKN */
(iw_handler) NULL, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) atmel_set_rate, /* SIOCSIWRATE */
......@@ -2365,8 +2370,8 @@ static const iw_handler atmel_handler[] =
(iw_handler) atmel_get_rts, /* SIOCGIWRTS */
(iw_handler) atmel_set_frag, /* SIOCSIWFRAG */
(iw_handler) atmel_get_frag, /* SIOCGIWFRAG */
(iw_handler) NULL, /* SIOCSIWTXPOW */
(iw_handler) NULL, /* SIOCGIWTXPOW */
(iw_handler) NULL, /* SIOCSIWTXPOW */
(iw_handler) NULL, /* SIOCGIWTXPOW */
(iw_handler) atmel_set_retry, /* SIOCSIWRETRY */
(iw_handler) atmel_get_retry, /* SIOCGIWRETRY */
(iw_handler) atmel_set_encode, /* SIOCSIWENCODE */
......@@ -2375,39 +2380,51 @@ static const iw_handler atmel_handler[] =
(iw_handler) atmel_get_power, /* SIOCGIWPOWER */
};
static const iw_handler atmel_private_handler[] =
static const iw_handler atmel_private_handler[] =
{
NULL, /* SIOCIWFIRSTPRIV */
};
typedef struct atmel_priv_ioctl {
char id[32];
unsigned char __user *data;
unsigned short len;
unsigned char __user *data;
unsigned short len;
} atmel_priv_ioctl;
#define ATMELFWL SIOCIWFIRSTPRIV
#define ATMELIDIFC ATMELFWL + 1
#define ATMELRD ATMELFWL + 2
#define ATMELMAGIC 0x51807
#define ATMELFWL SIOCIWFIRSTPRIV
#define ATMELIDIFC ATMELFWL + 1
#define ATMELRD ATMELFWL + 2
#define ATMELMAGIC 0x51807
#define REGDOMAINSZ 20
static const struct iw_priv_args atmel_private_args[] = {
/*{ cmd, set_args, get_args, name } */
{ ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
{ ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
{ ATMELRD, IW_PRIV_TYPE_CHAR | REGDOMAINSZ, IW_PRIV_TYPE_NONE, "regdomain" },
{
.cmd = ATMELFWL,
.set_args = IW_PRIV_TYPE_BYTE
| IW_PRIV_SIZE_FIXED
| sizeof (atmel_priv_ioctl),
.get_args = IW_PRIV_TYPE_NONE,
.name = "atmelfwl"
}, {
.cmd = ATMELIDIFC,
.set_args = IW_PRIV_TYPE_NONE,
.get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
.name = "atmelidifc"
}, {
.cmd = ATMELRD,
.set_args = IW_PRIV_TYPE_CHAR | REGDOMAINSZ,
.get_args = IW_PRIV_TYPE_NONE,
.name = "regdomain"
},
};
static const struct iw_handler_def atmel_handler_def =
static const struct iw_handler_def atmel_handler_def =
{
.num_standard = sizeof(atmel_handler)/sizeof(iw_handler),
.num_private = sizeof(atmel_private_handler)/sizeof(iw_handler),
.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
.num_private = sizeof(atmel_private_handler)/sizeof(iw_handler),
.num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
.standard = (iw_handler *) atmel_handler,
.private = (iw_handler *) atmel_private_handler,
.private = (iw_handler *) atmel_private_handler,
.private_args = (struct iw_priv_args *) atmel_private_args,
.get_wireless_stats = atmel_get_wireless_stats
};
......@@ -2419,13 +2436,13 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
atmel_priv_ioctl com;
struct iwreq *wrq = (struct iwreq *) rq;
unsigned char *new_firmware;
char domain[REGDOMAINSZ+1];
char domain[REGDOMAINSZ + 1];
switch (cmd) {
case ATMELIDIFC:
wrq->u.param.value = ATMELMAGIC;
wrq->u.param.value = ATMELMAGIC;
break;
case ATMELFWL:
if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
rc = -EFAULT;
......@@ -2449,7 +2466,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
kfree(priv->firmware);
priv->firmware = new_firmware;
priv->firmware_length = com.len;
strncpy(priv->firmware_id, com.id, 31);
......@@ -2461,7 +2478,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = -EFAULT;
break;
}
if (!capable(CAP_NET_ADMIN)) {
rc = -EPERM;
break;
......@@ -2484,15 +2501,15 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = 0;
}
}
if (rc == 0 && priv->station_state != STATION_STATE_DOWN)
rc = atmel_open(dev);
break;
default:
rc = -EOPNOTSUPP;
}
return rc;
}
......@@ -2503,17 +2520,17 @@ struct auth_body {
u8 el_id;
u8 chall_text_len;
u8 chall_text[253];
};
};
static void atmel_enter_state(struct atmel_private *priv, int new_state)
{
int old_state = priv->station_state;
if (new_state == old_state)
return;
priv->station_state = new_state;
if (new_state == STATION_STATE_READY) {
netif_start_queue(priv->dev);
netif_carrier_on(priv->dev);
......@@ -2540,7 +2557,7 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
u8 options;
u8 SSID_size;
} cmd;
memset(cmd.BSSID, 0xff, 6);
if (priv->fast_scan) {
......@@ -2554,17 +2571,17 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
cmd.min_channel_time = cpu_to_le16(10);
cmd.max_channel_time = cpu_to_le16(120);
}
cmd.options = 0;
if (!specific_ssid)
cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
cmd.channel = (priv->channel & 0x7f);
cmd.channel = (priv->channel & 0x7f);
cmd.scan_type = SCAN_TYPE_ACTIVE;
cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
/* This must come after all hardware access to avoid being messed up
......@@ -2591,16 +2608,15 @@ static void join(struct atmel_private *priv, int type)
cmd.BSS_type = type;
cmd.timeout = cpu_to_le16(2000);
atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
}
static void start(struct atmel_private *priv, int type)
{
struct {
u8 BSSID[6];
u8 SSID[MAX_SSID_LENGTH];
u8 BSS_type;
u8 BSS_type;
u8 channel;
u8 SSID_size;
u8 reserved[3];
......@@ -2612,13 +2628,14 @@ static void start(struct atmel_private *priv, int type)
cmd.BSS_type = type;
cmd.channel = (priv->channel & 0x7f);
atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
}
static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 channel)
static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
u8 channel)
{
int rejoin = 0;
int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
SHORT_PREAMBLE : LONG_PREAMBLE;
if (priv->preamble != new) {
......@@ -2626,48 +2643,48 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
rejoin = 1;
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
}
if (priv->channel != channel) {
priv->channel = channel;
rejoin = 1;
atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
}
if (rejoin) {
priv->station_is_associated = 0;
atmel_enter_state(priv, STATION_STATE_JOINNING);
if (priv->operating_mode == IW_MODE_INFRA)
join(priv, BSS_TYPE_INFRASTRUCTURE);
else
else
join(priv, BSS_TYPE_AD_HOC);
}
}
}
static void send_authentication_request(struct atmel_private *priv, u16 system, u8 *challenge, int challenge_len)
static void send_authentication_request(struct atmel_private *priv, u16 system,
u8 *challenge, int challenge_len)
{
struct ieee80211_hdr_4addr header;
struct auth_body auth;
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
header.duration_id = cpu_to_le16(0x8000);
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
header.duration_id = cpu_to_le16(0x8000);
header.seq_ctl = 0;
memcpy(header.addr1, priv->CurrentBSSID, 6);
memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
/* no WEP for authentication frames with TrSeqNo 1 */
header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
auth.alg = cpu_to_le16(system);
auth.alg = cpu_to_le16(system);
auth.status = 0;
auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
priv->CurrentAuthentTransactionSeqNum += 2;
if (challenge_len != 0) {
auth.el_id = 16; /* challenge_text */
auth.chall_text_len = challenge_len;
......@@ -2685,7 +2702,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
struct ieee80211_hdr_4addr header;
struct ass_req_format {
u16 capability;
u16 listen_interval;
u16 listen_interval;
u8 ap[6]; /* nothing after here directly accessible */
u8 ssid_el_id;
u8 ssid_len;
......@@ -2694,15 +2711,15 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
u8 sup_rates_len;
u8 rates[4];
} body;
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
(is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
header.duration_id = cpu_to_le16(0x8000);
header.seq_ctl = 0;
memcpy(header.addr1, priv->CurrentBSSID, 6);
memcpy(header.addr1, priv->CurrentBSSID, 6);
memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
if (priv->wep_is_on)
......@@ -2711,18 +2728,18 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
/* current AP address - only in reassoc frame */
if (is_reassoc) {
memcpy(body.ap, priv->CurrentBSSID, 6);
memcpy(body.ap, priv->CurrentBSSID, 6);
ssid_el_p = (u8 *)&body.ssid_el_id;
bodysize = 18 + priv->SSID_size;
} else {
ssid_el_p = (u8 *)&body.ap[0];
bodysize = 12 + priv->SSID_size;
}
ssid_el_p[0]= C80211_MGMT_ElementID_SSID;
ssid_el_p[0] = C80211_MGMT_ElementID_SSID;
ssid_el_p[1] = priv->SSID_size;
memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
......@@ -2732,7 +2749,8 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize);
}
static int is_frame_from_current_bss(struct atmel_private *priv, struct ieee80211_hdr_4addr *header)
static int is_frame_from_current_bss(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header)
{
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
......@@ -2745,29 +2763,29 @@ static int retrieve_bss(struct atmel_private *priv)
int i;
int max_rssi = -128;
int max_index = -1;
if (priv->BSS_list_entries == 0)
return -1;
if (priv->connect_to_any_BSS) {
/* Select a BSS with the max-RSSI but of the same type and of the same WEP mode
and that it is not marked as 'bad' (i.e. we had previously failed to connect to
this BSS with the settings that we currently use) */
/* Select a BSS with the max-RSSI but of the same type and of
the same WEP mode and that it is not marked as 'bad' (i.e.
we had previously failed to connect to this BSS with the
settings that we currently use) */
priv->current_BSS = 0;
for(i=0; i<priv->BSS_list_entries; i++) {
for (i = 0; i < priv->BSS_list_entries; i++) {
if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
(priv->wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
!(priv->BSSinfo[i].channel & 0x80)) {
max_rssi = priv->BSSinfo[i].RSSI;
priv->current_BSS = max_index = i;
}
}
return max_index;
}
for(i=0; i<priv->BSS_list_entries; i++) {
for (i = 0; i < priv->BSS_list_entries; i++) {
if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
priv->operating_mode == priv->BSSinfo[i].BSStype &&
......@@ -2781,19 +2799,19 @@ static int retrieve_bss(struct atmel_private *priv)
return max_index;
}
static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 capability, u16 beacon_period, u8 channel, u8 rssi,
u8 ssid_len, u8 *ssid, int is_beacon)
static void store_bss_info(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header, u16 capability,
u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
u8 *ssid, int is_beacon)
{
u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
int i, index;
for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
index = i;
/* If we process a probe and an entry from this BSS exists
/* If we process a probe and an entry from this BSS exists
we will update the BSS entry with the info from this BSS.
If we process a beacon we will only update RSSI */
......@@ -2820,8 +2838,8 @@ static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4add
priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
else if (capability & C80211_MGMT_CAPABILITY_ESS)
priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
SHORT_PREAMBLE : LONG_PREAMBLE;
}
......@@ -2831,8 +2849,8 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
u16 status = le16_to_cpu(auth->status);
u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
u16 system = le16_to_cpu(auth->alg);
if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
/* no WEP */
if (priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
......@@ -2842,20 +2860,20 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
send_association_request(priv, 0);
return;
}
}
}
if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
/* WEP */
if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
return;
if (trans_seq_no == 0x0002 &&
auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
return;
}
if (trans_seq_no == 0x0004) {
if(priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
......@@ -2865,10 +2883,10 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
send_association_request(priv, 0);
return;
}
}
}
}
}
if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
/* Do opensystem first, then try sharedkey */
if (system == C80211_MGMT_AAN_OPENSYSTEM) {
......@@ -2876,17 +2894,16 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
} else if (priv->connect_to_any_BSS) {
int bss_index;
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
if ((bss_index = retrieve_bss(priv)) != -1) {
atmel_join_bss(priv, bss_index);
return;
}
}
}
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
......@@ -2902,38 +2919,44 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
u8 length;
u8 rates[4];
} *ass_resp = (struct ass_resp_format *)priv->rx_buf;
u16 status = le16_to_cpu(ass_resp->status);
u16 status = le16_to_cpu(ass_resp->status);
u16 ass_id = le16_to_cpu(ass_resp->ass_id);
u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
if (frame_len < 8 + rates_len)
return;
if (status == C80211_MGMT_SC_Success) {
if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
priv->AssociationRequestRetryCnt = 0;
else
priv->ReAssociationRequestRetryCnt = 0;
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
atmel_set_mib(priv, Phy_Mib_Type,
PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
if (priv->power_mode == 0) {
priv->listen_interval = 1;
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
} else {
priv->listen_interval = 2;
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, PS_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_PS_MODE_POS, PS_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
}
priv->station_is_associated = 1;
priv->station_was_associated = 1;
atmel_enter_state(priv, STATION_STATE_READY);
return;
}
if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
status != C80211_MGMT_SC_AssDeniedBSSRate &&
status != C80211_MGMT_SC_SupportCapabilities &&
......@@ -2943,7 +2966,7 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
send_association_request(priv, 0);
return;
}
if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
status != C80211_MGMT_SC_AssDeniedBSSRate &&
status != C80211_MGMT_SC_SupportCapabilities &&
......@@ -2953,17 +2976,16 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
send_association_request(priv, 1);
return;
}
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
if(priv->connect_to_any_BSS) {
if (priv->connect_to_any_BSS) {
int bss_index;
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
if ((bss_index = retrieve_bss(priv)) != -1)
if ((bss_index = retrieve_bss(priv)) != -1)
atmel_join_bss(priv, bss_index);
}
}
......@@ -2977,7 +2999,7 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
/* The WPA stuff cares about the current AP address */
if (priv->use_wpa)
build_wpa_mib(priv);
/* When switching to AdHoc turn OFF Power Save if needed */
if (bss->BSStype == IW_MODE_ADHOC &&
......@@ -2985,25 +3007,28 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
priv->power_mode) {
priv->power_mode = 0;
priv->listen_interval = 1;
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
}
priv->operating_mode = bss->BSStype;
priv->channel = bss->channel & 0x7f;
priv->channel = bss->channel & 0x7f;
priv->beacon_period = bss->beacon_period;
if (priv->preamble != bss->preamble) {
priv->preamble = bss->preamble;
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
atmel_set_mib8(priv, Local_Mib_Type,
LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
}
if (!priv->wep_is_on && bss->UsingWEP) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
return;
}
if (priv->wep_is_on && !bss->UsingWEP) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
......@@ -3011,30 +3036,28 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
}
atmel_enter_state(priv, STATION_STATE_JOINNING);
if (priv->operating_mode == IW_MODE_INFRA)
join(priv, BSS_TYPE_INFRASTRUCTURE);
else
else
join(priv, BSS_TYPE_AD_HOC);
}
static void restart_search(struct atmel_private *priv)
{
int bss_index;
if (!priv->connect_to_any_BSS) {
atmel_scan(priv, 1);
} else {
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
if ((bss_index = retrieve_bss(priv)) != -1)
if ((bss_index = retrieve_bss(priv)) != -1)
atmel_join_bss(priv, bss_index);
else
atmel_scan(priv, 0);
}
}
}
}
static void smooth_rssi(struct atmel_private *priv, u8 rssi)
{
......@@ -3050,21 +3073,21 @@ static void smooth_rssi(struct atmel_private *priv, u8 rssi)
}
rssi = rssi * 100 / max_rssi;
if((rssi + old) % 2)
priv->wstats.qual.level = ((rssi + old)/2) + 1;
if ((rssi + old) % 2)
priv->wstats.qual.level = (rssi + old) / 2 + 1;
else
priv->wstats.qual.level = ((rssi + old)/2);
priv->wstats.qual.level = (rssi + old) / 2;
priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID;
}
static void atmel_smooth_qual(struct atmel_private *priv)
{
unsigned long time_diff = (jiffies - priv->last_qual)/HZ;
unsigned long time_diff = (jiffies - priv->last_qual) / HZ;
while (time_diff--) {
priv->last_qual += HZ;
priv->wstats.qual.qual = priv->wstats.qual.qual/2;
priv->wstats.qual.qual +=
priv->wstats.qual.qual = priv->wstats.qual.qual / 2;
priv->wstats.qual.qual +=
priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
priv->beacons_this_sec = 0;
}
......@@ -3073,15 +3096,17 @@ static void atmel_smooth_qual(struct atmel_private *priv)
}
/* deals with incoming managment frames. */
static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi)
static void atmel_management_frame(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u16 frame_len, u8 rssi)
{
u16 subtype;
switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE) {
case C80211_SUBTYPE_MGMT_BEACON :
subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
switch (subtype) {
case C80211_SUBTYPE_MGMT_BEACON:
case C80211_SUBTYPE_MGMT_ProbeResponse:
/* beacon frame has multiple variable-length fields -
never let an engineer loose with a data structure design. */
{
......@@ -3099,7 +3124,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
u8 ds_length;
/* ds here */
} *beacon = (struct beacon_format *)priv->rx_buf;
u8 channel, rates_length, ssid_length;
u64 timestamp = le64_to_cpu(beacon->timestamp);
u16 beacon_interval = le16_to_cpu(beacon->interval);
......@@ -3107,7 +3132,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
u8 *beaconp = priv->rx_buf;
ssid_length = beacon->ssid_length;
/* this blows chunks. */
if (frame_len < 14 || frame_len < ssid_length + 15)
if (frame_len < 14 || frame_len < ssid_length + 15)
return;
rates_length = beaconp[beacon->ssid_length + 15];
if (frame_len < ssid_length + rates_length + 18)
......@@ -3115,10 +3140,10 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
if (ssid_length > MAX_SSID_LENGTH)
return;
channel = beaconp[ssid_length + rates_length + 18];
if (priv->station_state == STATION_STATE_READY) {
smooth_rssi(priv, rssi);
if (is_frame_from_current_bss(priv, header)) {
if (is_frame_from_current_bss(priv, header)) {
priv->beacons_this_sec++;
atmel_smooth_qual(priv);
if (priv->last_beacon_timestamp) {
......@@ -3132,41 +3157,43 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
handle_beacon_probe(priv, capability, channel);
}
}
if (priv->station_state == STATION_STATE_SCANNING )
store_bss_info(priv, header, capability, beacon_interval, channel,
rssi, ssid_length, &beacon->rates_el_id,
subtype == C80211_SUBTYPE_MGMT_BEACON) ;
if (priv->station_state == STATION_STATE_SCANNING)
store_bss_info(priv, header, capability,
beacon_interval, channel, rssi,
ssid_length,
&beacon->rates_el_id,
subtype == C80211_SUBTYPE_MGMT_BEACON);
}
break;
case C80211_SUBTYPE_MGMT_Authentication:
if (priv->station_state == STATION_STATE_AUTHENTICATING)
authenticate(priv, frame_len);
break;
case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
if (priv->station_state == STATION_STATE_ASSOCIATING ||
if (priv->station_state == STATION_STATE_ASSOCIATING ||
priv->station_state == STATION_STATE_REASSOCIATING)
associate(priv, frame_len, subtype);
break;
case C80211_SUBTYPE_MGMT_DISASSOSIATION:
if (priv->station_is_associated &&
priv->operating_mode == IW_MODE_INFRA &&
if (priv->station_is_associated &&
priv->operating_mode == IW_MODE_INFRA &&
is_frame_from_current_bss(priv, header)) {
priv->station_was_associated = 0;
priv->station_is_associated = 0;
atmel_enter_state(priv, STATION_STATE_JOINNING);
join(priv, BSS_TYPE_INFRASTRUCTURE);
}
break;
case C80211_SUBTYPE_MGMT_Deauthentication:
......@@ -3177,7 +3204,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
atmel_enter_state(priv, STATION_STATE_JOINNING);
join(priv, BSS_TYPE_INFRASTRUCTURE);
}
break;
}
}
......@@ -3185,76 +3212,73 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
/* run when timer expires */
static void atmel_management_timer(u_long a)
{
struct net_device *dev = (struct net_device *) a;
struct atmel_private *priv = netdev_priv(dev);
unsigned long flags;
/* Check if the card has been yanked. */
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card))
return;
spin_lock_irqsave(&priv->irqlock, flags);
switch (priv->station_state) {
case STATION_STATE_AUTHENTICATING:
if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
priv->AuthenticationRequestRetryCnt = 0;
restart_search(priv);
} else {
priv->AuthenticationRequestRetryCnt++;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
}
break;
struct net_device *dev = (struct net_device *) a;
struct atmel_private *priv = netdev_priv(dev);
unsigned long flags;
case STATION_STATE_ASSOCIATING:
if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
priv->AssociationRequestRetryCnt = 0;
restart_search(priv);
} else {
priv->AssociationRequestRetryCnt++;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_association_request(priv, 0);
}
/* Check if the card has been yanked. */
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card))
return;
break;
case STATION_STATE_REASSOCIATING:
if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
priv->ReAssociationRequestRetryCnt = 0;
restart_search(priv);
} else {
priv->ReAssociationRequestRetryCnt++;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_association_request(priv, 1);
}
spin_lock_irqsave(&priv->irqlock, flags);
switch (priv->station_state) {
case STATION_STATE_AUTHENTICATING:
if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
priv->AuthenticationRequestRetryCnt = 0;
restart_search(priv);
} else {
priv->AuthenticationRequestRetryCnt++;
priv->CurrentAuthentTransactionSeqNum = 0x0001;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
}
break;
default:
case STATION_STATE_ASSOCIATING:
if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
priv->AssociationRequestRetryCnt = 0;
restart_search(priv);
} else {
priv->AssociationRequestRetryCnt++;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_association_request(priv, 0);
}
break;
}
spin_unlock_irqrestore(&priv->irqlock, flags);
case STATION_STATE_REASSOCIATING:
if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
priv->ReAssociationRequestRetryCnt = 0;
restart_search(priv);
} else {
priv->ReAssociationRequestRetryCnt++;
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
send_association_request(priv, 1);
}
break;
default:
break;
}
spin_unlock_irqrestore(&priv->irqlock, flags);
}
static void atmel_command_irq(struct atmel_private *priv)
{
u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
int fast_scan;
if (status == CMD_STATUS_IDLE ||
if (status == CMD_STATUS_IDLE ||
status == CMD_STATUS_IN_PROGRESS)
return;
......@@ -3266,20 +3290,20 @@ static void atmel_command_irq(struct atmel_private *priv)
atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
(u8 *)priv->CurrentBSSID, 6);
atmel_enter_state(priv, STATION_STATE_READY);
}
}
break;
case CMD_Scan:
fast_scan = priv->fast_scan;
priv->fast_scan = 0;
if (status != CMD_STATUS_COMPLETE) {
atmel_scan(priv, 1);
} else {
int bss_index = retrieve_bss(priv);
if (bss_index != -1) {
atmel_join_bss(priv, bss_index);
} else if (priv->operating_mode == IW_MODE_ADHOC &&
} else if (priv->operating_mode == IW_MODE_ADHOC &&
priv->SSID_size != 0) {
start(priv, BSS_TYPE_AD_HOC);
} else {
......@@ -3289,16 +3313,16 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->site_survey_state = SITE_SURVEY_COMPLETED;
}
break;
case CMD_SiteSurvey:
priv->fast_scan = 0;
if (status != CMD_STATUS_COMPLETE)
return;
priv->site_survey_state = SITE_SURVEY_COMPLETED;
if (priv->station_is_associated) {
atmel_enter_state(priv, STATION_STATE_READY);
atmel_enter_state(priv, STATION_STATE_READY);
} else {
atmel_scan(priv, 1);
}
......@@ -3312,16 +3336,15 @@ static void atmel_command_irq(struct atmel_private *priv)
} else {
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->CurrentAuthentTransactionSeqNum = 0x0001;
send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
}
return;
}
atmel_scan(priv, 1);
}
}
......@@ -3333,20 +3356,20 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
if (priv->card_type == CARD_TYPE_SPI_FLASH)
atmel_set_gcr(priv->dev, GCR_REMAP);
/* wake up on-board processor */
atmel_clear_gcr(priv->dev, 0x0040);
atmel_write16(priv->dev, BSR, BSS_SRAM);
if (priv->card_type == CARD_TYPE_SPI_FLASH)
mdelay(100);
/* and wait for it */
for (i = LOOP_RETRY_LIMIT; i; i--) {
for (i = LOOP_RETRY_LIMIT; i; i--) {
mr1 = atmel_read16(priv->dev, MR1);
mr3 = atmel_read16(priv->dev, MR3);
if (mr3 & MAC_BOOT_COMPLETE)
if (mr3 & MAC_BOOT_COMPLETE)
break;
if (mr1 & MAC_BOOT_COMPLETE &&
priv->bus_type == BUS_TYPE_PCCARD)
......@@ -3357,35 +3380,36 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
return 0;
}
if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
return 0;
}
/* now check for completion of MAC initialization through
the FunCtrl field of the IFACE, poll MR1 to detect completion of
MAC initialization, check completion status, set interrupt mask,
enables interrupts and calls Tx and Rx initialization functions */
/* now check for completion of MAC initialization through
the FunCtrl field of the IFACE, poll MR1 to detect completion of
MAC initialization, check completion status, set interrupt mask,
enables interrupts and calls Tx and Rx initialization functions */
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
for (i = LOOP_RETRY_LIMIT; i; i--) {
for (i = LOOP_RETRY_LIMIT; i; i--) {
mr1 = atmel_read16(priv->dev, MR1);
mr3 = atmel_read16(priv->dev, MR3);
if (mr3 & MAC_INIT_COMPLETE)
if (mr3 & MAC_INIT_COMPLETE)
break;
if (mr1 & MAC_INIT_COMPLETE &&
priv->bus_type == BUS_TYPE_PCCARD)
break;
}
if (i == 0) {
printk(KERN_ALERT "%s: MAC failed to initialise.\n", priv->dev->name);
printk(KERN_ALERT "%s: MAC failed to initialise.\n",
priv->dev->name);
return 0;
}
/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
if ((mr3 & MAC_INIT_COMPLETE) &&
!(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
......@@ -3398,9 +3422,9 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
return 0;
}
atmel_copy_to_host(priv->dev, (unsigned char *)iface,
atmel_copy_to_host(priv->dev, (unsigned char *)iface,
priv->host_info_base, sizeof(*iface));
iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
......@@ -3424,16 +3448,16 @@ static int probe_atmel_card(struct net_device *dev)
{
int rc = 0;
struct atmel_private *priv = netdev_priv(dev);
/* reset pccard */
if (priv->bus_type == BUS_TYPE_PCCARD)
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
mdelay(500);
if (atmel_read16(dev, MR2) == 0) {
/* No stored firmware so load a small stub which just
/* No stored firmware so load a small stub which just
tells us the MAC address */
int i;
priv->card_type = CARD_TYPE_EEPROM;
......@@ -3442,7 +3466,7 @@ static int probe_atmel_card(struct net_device *dev)
atmel_set_gcr(dev, GCR_REMAP);
atmel_clear_gcr(priv->dev, 0x0040);
atmel_write16(dev, BSR, BSS_SRAM);
for (i = LOOP_RETRY_LIMIT; i; i--)
for (i = LOOP_RETRY_LIMIT; i; i--)
if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
break;
if (i == 0) {
......@@ -3451,7 +3475,7 @@ static int probe_atmel_card(struct net_device *dev)
atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
/* got address, now squash it again until the network
interface is opened */
if (priv->bus_type == BUS_TYPE_PCCARD)
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
rc = 1;
......@@ -3459,7 +3483,7 @@ static int probe_atmel_card(struct net_device *dev)
} else if (atmel_read16(dev, MR4) == 0) {
/* Mac address easy in this case. */
priv->card_type = CARD_TYPE_PARALLEL_FLASH;
atmel_write16(dev, BSR, 1);
atmel_write16(dev, BSR, 1);
atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
atmel_write16(dev, BSR, 0x200);
rc = 1;
......@@ -3469,16 +3493,16 @@ static int probe_atmel_card(struct net_device *dev)
priv->card_type = CARD_TYPE_SPI_FLASH;
if (atmel_wakeup_firmware(priv)) {
atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
/* got address, now squash it again until the network
interface is opened */
if (priv->bus_type == BUS_TYPE_PCCARD)
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
rc = 1;
}
}
if (rc) {
if (dev->dev_addr[0] == 0xFF) {
u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00};
......@@ -3486,27 +3510,27 @@ static int probe_atmel_card(struct net_device *dev)
memcpy(dev->dev_addr, default_mac, 6);
}
}
return rc;
}
static void build_wep_mib(struct atmel_private *priv)
/* Move the encyption information on the MIB structure.
This routine is for the pre-WPA firmware: later firmware has
a different format MIB and a different routine. */
static void build_wep_mib(struct atmel_private *priv)
{
struct { /* NB this is matched to the hardware, don't change. */
u8 wep_is_on;
u8 wep_is_on;
u8 default_key; /* 0..3 */
u8 reserved;
u8 exclude_unencrypted;
u32 WEPICV_error_count;
u32 WEP_excluded_count;
u8 wep_keys[MAX_ENCRYPTION_KEYS][13];
u8 encryption_level; /* 0, 1, 2 */
u8 reserved2[3];
u8 encryption_level; /* 0, 1, 2 */
u8 reserved2[3];
} mib;
int i;
......@@ -3515,54 +3539,55 @@ static void build_wep_mib(struct atmel_private *priv)
if (priv->wep_key_len[priv->default_key] > 5)
mib.encryption_level = 2;
else
mib.encryption_level = 1;
mib.encryption_level = 1;
} else {
mib.encryption_level = 0;
}
mib.default_key = priv->default_key;
mib.exclude_unencrypted = priv->exclude_unencrypted;
for(i = 0; i < MAX_ENCRYPTION_KEYS; i++)
for (i = 0; i < MAX_ENCRYPTION_KEYS; i++)
memcpy(mib.wep_keys[i], priv->wep_keys[i], 13);
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
}
static void build_wpa_mib(struct atmel_private *priv)
{
/* This is for the later (WPA enabled) firmware. */
/* This is for the later (WPA enabled) firmware. */
struct { /* NB this is matched to the hardware, don't change. */
u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
u8 receiver_address[6];
u8 wep_is_on;
u8 wep_is_on;
u8 default_key; /* 0..3 */
u8 group_key;
u8 exclude_unencrypted;
u8 encryption_type;
u8 reserved;
u32 WEPICV_error_count;
u32 WEP_excluded_count;
u8 key_RSC[4][8];
} mib;
int i;
mib.wep_is_on = priv->wep_is_on;
mib.exclude_unencrypted = priv->exclude_unencrypted;
memcpy(mib.receiver_address, priv->CurrentBSSID, 6);
/* zero all the keys before adding in valid ones. */
memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value));
if (priv->wep_is_on) {
/* There's a comment in the Atmel code to the effect that this is only valid
when still using WEP, it may need to be set to something to use WPA */
/* There's a comment in the Atmel code to the effect that this
is only valid when still using WEP, it may need to be set to
something to use WPA */
memset(mib.key_RSC, 0, sizeof(mib.key_RSC));
mib.default_key = mib.group_key = 255;
for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) {
if (priv->wep_key_len[i] > 0) {
......@@ -3570,12 +3595,12 @@ static void build_wpa_mib(struct atmel_private *priv)
if (i == priv->default_key) {
mib.default_key = i;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 7;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
} else {
mib.group_key = i;
priv->group_cipher_suite = priv->pairwise_cipher_suite;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
}
}
}
......@@ -3583,47 +3608,47 @@ static void build_wpa_mib(struct atmel_private *priv)
mib.default_key = mib.group_key != 255 ? mib.group_key : 0;
if (mib.group_key == 255)
mib.group_key = mib.default_key;
}
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
}
static int reset_atmel_card(struct net_device *dev)
static int reset_atmel_card(struct net_device *dev)
{
/* do everything necessary to wake up the hardware, including
waiting for the lightning strike and throwing the knife switch....
set all the Mib values which matter in the card to match
set all the Mib values which matter in the card to match
their settings in the atmel_private structure. Some of these
can be altered on the fly, but many (WEP, infrastucture or ad-hoc)
can only be changed by tearing down the world and coming back through
here.
This routine is also responsible for initialising some
hardware-specific fields in the atmel_private structure,
This routine is also responsible for initialising some
hardware-specific fields in the atmel_private structure,
including a copy of the firmware's hostinfo stucture
which is the route into the rest of the firmare datastructures. */
struct atmel_private *priv = netdev_priv(dev);
u8 configuration;
/* data to add to the firmware names, in priority order
this implemenents firmware versioning */
static char *firmware_modifier[] = {
"-wpa",
"",
NULL
};
/* reset pccard */
if (priv->bus_type == BUS_TYPE_PCCARD)
if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(priv->dev, GCR, 0x0060);
/* stop card , disable interrupts */
atmel_write16(priv->dev, GCR, 0x0040);
if (priv->card_type == CARD_TYPE_EEPROM) {
/* copy in firmware if needed */
const struct firmware *fw_entry = NULL;
......@@ -3636,13 +3661,13 @@ static int reset_atmel_card(struct net_device *dev)
"%s: card type is unknown: assuming at76c502 firmware is OK.\n",
dev->name);
printk(KERN_INFO
"%s: if not, use the firmware= module parameter.\n",
"%s: if not, use the firmware= module parameter.\n",
dev->name);
strcpy(priv->firmware_id, "atmel_at76c502.bin");
}
if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) != 0) {
printk(KERN_ALERT
"%s: firmware %s is missing, cannot continue.\n",
printk(KERN_ALERT
"%s: firmware %s is missing, cannot continue.\n",
dev->name, priv->firmware_id);
return 0;
}
......@@ -3654,7 +3679,7 @@ static int reset_atmel_card(struct net_device *dev)
while (fw_table[fw_index].fw_type != priv->firmware_type
&& fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
fw_index++;
/* construct the actual firmware file name */
if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
int i;
......@@ -3669,24 +3694,24 @@ static int reset_atmel_card(struct net_device *dev)
}
}
if (!success) {
printk(KERN_ALERT
"%s: firmware %s is missing, cannot start.\n",
printk(KERN_ALERT
"%s: firmware %s is missing, cannot start.\n",
dev->name, priv->firmware_id);
priv->firmware_id[0] = '\0';
return 0;
return 0;
}
}
fw = fw_entry->data;
len = fw_entry->size;
}
if (len <= 0x6000) {
atmel_write16(priv->dev, BSR, BSS_IRAM);
atmel_copy_to_card(priv->dev, 0, fw, len);
atmel_set_gcr(priv->dev, GCR_REMAP);
} else {
/* Remap */
/* Remap */
atmel_set_gcr(priv->dev, GCR_REMAP);
atmel_write16(priv->dev, BSR, BSS_IRAM);
atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
......@@ -3708,45 +3733,45 @@ static int reset_atmel_card(struct net_device *dev)
the 3com broken-ness filter. */
priv->use_wpa = (priv->host_info.major_version == 4);
priv->radio_on_broken = (priv->host_info.major_version == 5);
/* unmask all irq sources */
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
/* int Tx system and enable Tx */
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
priv->tx_desc_free = priv->host_info.tx_desc_count;
priv->tx_desc_head = 0;
priv->tx_desc_tail = 0;
priv->tx_desc_free = priv->host_info.tx_desc_count;
priv->tx_desc_head = 0;
priv->tx_desc_tail = 0;
priv->tx_desc_previous = 0;
priv->tx_free_mem = priv->host_info.tx_buff_size;
priv->tx_buff_head = 0;
priv->tx_buff_tail = 0;
configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
priv->tx_buff_head = 0;
priv->tx_buff_tail = 0;
configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration | FUNC_CTRL_TxENABLE);
/* init Rx system and enable */
priv->rx_desc_head = 0;
configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration | FUNC_CTRL_RxENABLE);
if (!priv->radio_on_broken) {
if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
CMD_STATUS_REJECTED_RADIO_OFF) {
printk(KERN_INFO
printk(KERN_INFO
"%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
dev->name);
return 0;
}
}
/* set up enough MIB values to run. */
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_TX_PROMISCUOUS_POS, PROM_MODE_OFF);
......@@ -3755,7 +3780,7 @@ static int reset_atmel_card(struct net_device *dev)
atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
priv->dev->dev_addr, 6);
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
......@@ -3766,42 +3791,44 @@ static int reset_atmel_card(struct net_device *dev)
build_wpa_mib(priv);
else
build_wep_mib(priv);
return 1;
}
static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
static void atmel_send_command(struct atmel_private *priv, int command,
void *cmd, int cmd_size)
{
if (cmd)
atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
cmd, cmd_size);
atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
}
static int atmel_send_command_wait(struct atmel_private *priv, int command, void *cmd, int cmd_size)
static int atmel_send_command_wait(struct atmel_private *priv, int command,
void *cmd, int cmd_size)
{
int i, status;
atmel_send_command(priv, command, cmd, cmd_size);
for (i = 5000; i; i--) {
status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
if (status != CMD_STATUS_IDLE &&
if (status != CMD_STATUS_IDLE &&
status != CMD_STATUS_IN_PROGRESS)
break;
udelay(20);
}
if (i == 0) {
printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
status = CMD_STATUS_HOST_ERROR;
} else {
} else {
if (command != CMD_EnableRadio)
status = CMD_STATUS_COMPLETE;
}
return status;
}
......@@ -3827,7 +3854,8 @@ static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 dat
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
}
static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data)
static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
u16 data)
{
struct get_set_mib m;
m.type = type;
......@@ -3839,7 +3867,8 @@ static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 d
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 2);
}
static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len)
{
struct get_set_mib m;
m.type = type;
......@@ -3848,23 +3877,24 @@ static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *dat
if (data_len > MIB_MAX_DATA_BYTES)
printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
memcpy(m.data, data, data_len);
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
}
static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
u8 *data, int data_len)
{
struct get_set_mib m;
m.type = type;
m.size = data_len;
m.index = index;
if (data_len > MIB_MAX_DATA_BYTES)
printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
atmel_copy_to_host(priv->dev, data,
atmel_copy_to_host(priv->dev, data,
atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len);
}
......@@ -3873,11 +3903,12 @@ static void atmel_writeAR(struct net_device *dev, u16 data)
int i;
outw(data, dev->base_addr + AR);
/* Address register appears to need some convincing..... */
for (i = 0; data != inw(dev->base_addr + AR) && i<10; i++)
for (i = 0; data != inw(dev->base_addr + AR) && i < 10; i++)
outw(data, dev->base_addr + AR);
}
static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len)
static void atmel_copy_to_card(struct net_device *dev, u16 dest,
unsigned char *src, u16 len)
{
int i;
atmel_writeAR(dev, dest);
......@@ -3894,7 +3925,8 @@ static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *
atmel_write8(dev, DR, *src);
}
static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len)
static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
u16 src, u16 len)
{
int i;
atmel_writeAR(dev, src);
......@@ -3930,22 +3962,24 @@ static int atmel_lock_mac(struct atmel_private *priv)
break;
udelay(20);
}
if (!i) return 0; /* timed out */
if (!i)
return 0; /* timed out */
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
if (!j--) return 0; /* timed out */
if (!j--)
return 0; /* timed out */
goto retry;
}
return 1;
}
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
{
atmel_writeAR(priv->dev, pos);
atmel_writeAR(priv->dev, pos);
atmel_write16(priv->dev, DR, data); /* card is little-endian */
atmel_write16(priv->dev, DR, data >> 16);
}
......@@ -4017,9 +4051,9 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
serial output, since SO is normally high. But it
does cause 8 clock cycles and thus 8 bits to be
clocked in to the chip. See Atmel's SPI
controller (e.g. AT91M55800) timing and 4K
controller (e.g. AT91M55800) timing and 4K
SPI EEPROM manuals */
.set NVRAM_SCRATCH, 0x02000100 /* arbitrary area for scratchpad memory */
.set NVRAM_IMAGE, 0x02000200
.set NVRAM_LENGTH, 0x0200
......@@ -4032,24 +4066,24 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
.set MR4, 0xC
RESET_VECTOR:
b RESET_HANDLER
UNDEF_VECTOR:
UNDEF_VECTOR:
b HALT1
SWI_VECTOR:
SWI_VECTOR:
b HALT1
IABORT_VECTOR:
IABORT_VECTOR:
b HALT1
DABORT_VECTOR:
RESERVED_VECTOR:
DABORT_VECTOR:
RESERVED_VECTOR:
b HALT1
IRQ_VECTOR:
IRQ_VECTOR:
b HALT1
FIQ_VECTOR:
FIQ_VECTOR:
b HALT1
HALT1: b HALT1
RESET_HANDLER:
mov r0, #CPSR_INITIAL
msr CPSR_c, r0 /* This is probably unnecessary */
/* I'm guessing this is initializing clock generator electronics for SPI */
ldr r0, =SPI_CGEN_BASE
mov r1, #0
......@@ -4061,7 +4095,7 @@ HALT1: b HALT1
str r1, [r0, #28]
mov r1, #1
str r1, [r0, #8]
ldr r0, =MRBASE
mov r1, #0
strh r1, [r0, #MR1]
......@@ -4094,7 +4128,7 @@ HALT2: b HALT2
ldmia sp!, {lr}
bx lr
.endfunc
.func Get_MAC_Addr, GET_MAC_ADDR
GET_MAC_ADDR:
stmdb sp!, {lr}
......@@ -4110,13 +4144,13 @@ HALT2: b HALT2
.func Delay9, DELAY9
DELAY9:
adds r0, r0, r0, LSL #3 /* r0 = r0 * 9 */
DELAYLOOP:
DELAYLOOP:
beq DELAY9_done
subs r0, r0, #1
b DELAYLOOP
DELAY9_done:
DELAY9_done:
bx lr
.endfunc
.endfunc
.func SP_Init, SP_INIT
SP_INIT:
......@@ -4145,26 +4179,26 @@ HALT2: b HALT2
ldr r0, [r0, #SP_RDR]
bx lr
.endfunc
.func NVRAM_Init, NVRAM_INIT
.func NVRAM_Init, NVRAM_INIT
NVRAM_INIT:
ldr r1, =SP_BASE
ldr r0, [r1, #SP_RDR]
mov r0, #NVRAM_CMD_RDSR
str r0, [r1, #SP_TDR]
SP_loop1:
SP_loop1:
ldr r0, [r1, #SP_SR]
tst r0, #SP_TDRE
beq SP_loop1
mov r0, #SPI_8CLOCKS
str r0, [r1, #SP_TDR]
SP_loop2:
str r0, [r1, #SP_TDR]
SP_loop2:
ldr r0, [r1, #SP_SR]
tst r0, #SP_TDRE
beq SP_loop2
ldr r0, [r1, #SP_RDR]
SP_loop3:
SP_loop3:
ldr r0, [r1, #SP_SR]
tst r0, #SP_RDRF
beq SP_loop3
......@@ -4173,7 +4207,7 @@ HALT2: b HALT2
and r0, r0, #255
bx lr
.endfunc
.func NVRAM_Xfer, NVRAM_XFER
/* r0 = dest address */
/* r1 = not used */
......@@ -4185,11 +4219,11 @@ HALT2: b HALT2
mov r4, r3 /* save r3 (length) */
mov r0, r2, LSR #5 /* SPI memories put A8 in the command field */
and r0, r0, #8
add r0, r0, #NVRAM_CMD_READ
add r0, r0, #NVRAM_CMD_READ
ldr r1, =NVRAM_SCRATCH
strb r0, [r1, #0] /* save command in NVRAM_SCRATCH[0] */
strb r2, [r1, #1] /* save low byte of source address in NVRAM_SCRATCH[1] */
_local1:
_local1:
bl NVRAM_INIT
tst r0, #NVRAM_SR_RDY
bne _local1
......@@ -4211,7 +4245,7 @@ HALT2: b HALT2
cmp r0, #0
bls _local2
ldr r5, =NVRAM_SCRATCH
_local4:
_local4:
ldrb r6, [r5, r3]
str r6, [r4, #SP_TDR]
_local3:
......@@ -4225,7 +4259,7 @@ HALT2: b HALT2
mov r3, #SPI_8CLOCKS
str r3, [r4, #SP_TDR]
ldr r0, [r4, #SP_RDR]
_local5:
_local5:
ldr r0, [r4, #SP_SR]
tst r0, #SP_RDRF
beq _local5
......@@ -4233,12 +4267,12 @@ HALT2: b HALT2
mov r0, #0
cmp r2, #0 /* r2 is # of bytes to copy in */
bls _local6
_local7:
_local7:
ldr r5, [r4, #SP_SR]
tst r5, #SP_TDRE
beq _local7
str r3, [r4, #SP_TDR] /* r3 has SPI_8CLOCKS */
_local8:
_local8:
ldr r5, [r4, #SP_SR]
tst r5, #SP_RDRF
beq _local8
......
hostap-y := hostap_main.o
obj-$(CONFIG_HOSTAP) += hostap.o
obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册