Commit cca52de4 authored by Jeff Garzik's avatar Jeff Garzik

Merge redhat.com:/spare/repo/netdev-2.6/atmel

into redhat.com:/spare/repo/net-drivers-2.5
parents 2ed55743 435417ab
......@@ -282,7 +282,7 @@ config PCMCIA_ATMEL
one of these, you will need to provide a firmware image
to be loaded into the card by the driver. The Atmel
firmware package can be downloaded from
http://www.thekelleys.org.uk/atmel/atmel_firmware.tar.gz
http://www.thekelleys.org.uk/atmel
config PCMCIA_WL3501
tristate "Planet WL3501 PCMCIA cards"
......
......@@ -67,7 +67,7 @@
#include "ieee802_11.h"
#define DRIVER_MAJOR 0
#define DRIVER_MINOR 8
#define DRIVER_MINOR 9
MODULE_AUTHOR("Simon Kelley");
MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
......@@ -153,12 +153,15 @@ module_param(firmware, charp, 0);
#define C80211_MGMT_ElementID_ChallengeText 16
#define C80211_MGMT_CAPABILITY_ShortPreamble 0x0020
#define MIB_MAX_DATA_BYTES 212
#define MIB_HEADER_SIZE 4 /* first four fields */
struct get_set_mib {
u8 type;
u8 size;
u8 index;
u8 reserved;
u8 data[72];
u8 data[MIB_MAX_DATA_BYTES];
};
struct rx_desc {
......@@ -195,32 +198,40 @@ struct rx_desc {
struct tx_desc {
u32 NextDescriptor;
u16 TxStartOfFrame;
u16 TxLength;
u8 TxState;
u8 TxStatus;
u8 RetryCount;
u8 TxRate;
u32 TxTime;
u8 Reserved;
u8 PacketType;
u16 HostTxLength;
u32 NextDescriptor;
u16 TxStartOfFrame;
u16 TxLength;
u8 TxState;
u8 TxStatus;
u8 RetryCount;
u8 TxRate;
u8 KeyIndex;
u8 ChiperType;
u8 ChipreLength;
u8 Reserved1;
u8 Reserved;
u8 PacketType;
u16 HostTxLength;
};
#define TX_DESC_NEXT_OFFSET 0
#define TX_DESC_POS_OFFSET 4
#define TX_DESC_SIZE_OFFSET 6
#define TX_DESC_FLAGS_OFFSET 8
#define TX_DESC_STATUS_OFFSET 9
#define TX_DESC_RETRY_OFFSET 10
#define TX_DESC_RATE_OFFSET 11
#define TX_DESC_PACKET_TYPE_OFFSET 17
#define TX_DESC_HOST_LENGTH_OFFSET 18
#define TX_DESC_NEXT_OFFSET 0
#define TX_DESC_POS_OFFSET 4
#define TX_DESC_SIZE_OFFSET 6
#define TX_DESC_FLAGS_OFFSET 8
#define TX_DESC_STATUS_OFFSET 9
#define TX_DESC_RETRY_OFFSET 10
#define TX_DESC_RATE_OFFSET 11
#define TX_DESC_KEY_INDEX_OFFSET 12
#define TX_DESC_CIPHER_TYPE_OFFSET 13
#define TX_DESC_CIPHER_LENGTH_OFFSET 14
#define TX_DESC_PACKET_TYPE_OFFSET 17
#define TX_DESC_HOST_LENGTH_OFFSET 18
......@@ -324,6 +335,9 @@ struct tx_desc {
#define ACTIVE_MODE 1
#define PS_MODE 2
#define MAX_ENCRYPTION_KEYS 4
#define MAX_ENCRYPTION_KEY_SIZE 40
///////////////////////////////////////////////////////////////////////////
// 802.11 related definitions
///////////////////////////////////////////////////////////////////////////
......@@ -370,6 +384,14 @@ struct tx_desc {
#define IFACE_FUNC_CTRL_OFFSET 28
#define IFACE_MAC_STAT_OFFSET 30
#define IFACE_GENERIC_INT_TYPE_OFFSET 32
#define CIPHER_SUITE_NONE 0
#define CIPHER_SUITE_WEP_64 1
#define CIPHER_SUITE_TKIP 2
#define CIPHER_SUITE_AES 3
#define CIPHER_SUITE_CCX 4
#define CIPHER_SUITE_WEP_128 5
//
// IFACE MACROS & definitions
//
......@@ -432,6 +454,7 @@ struct atmel_private {
void *card; /* Bus dependent stucture varies for PCcard */
int (*present_callback)(void *); /* And callback which uses it */
char firmware_id[32];
char firmware_template[32];
unsigned char *firmware;
int firmware_length;
struct timer_list management_timer;
......@@ -457,20 +480,11 @@ struct atmel_private {
u16 frag_seq, frag_len, frag_no;
u8 frag_source[6];
int wep_key_len[4]; /* need to know these and not stored in Mib. */
struct { /* NB this is matched to the hardware, don't change. */
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[4][13];
u8 encryption_level; /* 0, 1, 2 */
u8 reserved2[3];
} wep;
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 use_wpa;
u16 host_info_base;
struct host_info_struct {
......@@ -510,8 +524,6 @@ struct atmel_private {
STATION_STATE_ASSOCIATING,
STATION_STATE_READY,
STATION_STATE_REASSOCIATING,
STATION_STATE_FORCED_JOINNING,
STATION_STATE_FORCED_JOIN_FAILURE,
STATION_STATE_DOWN,
STATION_STATE_NO_CARD,
STATION_STATE_MGMT_ERROR
......@@ -564,6 +576,7 @@ struct atmel_private {
static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
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);
......@@ -717,14 +730,54 @@ static u16 find_tx_buff(struct atmel_private *priv, u16 len)
return 0;
}
static void tx_update_descriptor(struct atmel_private *priv, 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);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len);
if (!priv->use_wpa)
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_tail), type);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RATE_OFFSET, priv->tx_desc_tail), priv->tx_rate);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RETRY_OFFSET, priv->tx_desc_tail), 0);
if (priv->use_wpa) {
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 )
cipher_length = 8;
else if (cipher_type == CIPHER_SUITE_TKIP)
cipher_length = 12;
else if (priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_64 ||
priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_128) {
cipher_type = priv->pairwise_cipher_suite;
cipher_length = 8;
} else {
cipher_type = CIPHER_SUITE_NONE;
cipher_length = 0;
}
} else {
cipher_type = priv->pairwise_cipher_suite;
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;
else if (priv->group_cipher_suite == CIPHER_SUITE_WEP_64 ||
priv->group_cipher_suite == CIPHER_SUITE_WEP_128) {
cipher_type = priv->group_cipher_suite;
cipher_length = 8;
} else {
cipher_type = CIPHER_SUITE_NONE;
cipher_length = 0;
}
}
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail),
cipher_type);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail),
cipher_length);
}
atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_tail), 0x80000000L);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_tail), TX_FIRM_OWN);
if (priv->tx_desc_previous != priv->tx_desc_tail)
......@@ -745,16 +798,19 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
struct ieee802_11_hdr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
if(priv->station_state != STATION_STATE_READY) {
u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
if (priv->station_state != STATION_STATE_READY) {
priv->stats.tx_errors++;
goto done;
dev_kfree_skb(skb);
return 0;
}
if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++;
goto done;
dev_kfree_skb(skb);
return 0;
}
/* first ensure the timer func cannot run */
......@@ -778,7 +834,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
frame_ctl = IEEE802_11_FTYPE_DATA;
header.duration_id = 0;
header.seq_ctl = 0;
if (priv->wep.wep_is_on)
if (priv->wep_is_on)
frame_ctl |= IEEE802_11_FCTL_WEP;
if (priv->operating_mode == IW_MODE_ADHOC) {
memcpy(&header.addr1, skb->data, 6);
......@@ -791,6 +847,9 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
memcpy(&header.addr3, skb->data, 6);
}
if (priv->use_wpa)
memcpy(&header.addr4, SNAP_RFC1024, 6);
header.frame_ctl = cpu_to_le16(frame_ctl);
/* Copy the wireless header into the card */
atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
......@@ -798,14 +857,13 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
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;
tx_update_descriptor(priv, len + 18, buff, TX_PACKET_TYPE_DATA);
/* 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);
done:
dev_kfree_skb(skb);
return 0;
......@@ -824,7 +882,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len);
priv->tx_buff_tail += len;
tx_update_descriptor(priv, len, buff, TX_PACKET_TYPE_MGMT);
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
static void fast_rx_path(struct atmel_private *priv, struct ieee802_11_hdr *header,
......@@ -1027,7 +1085,7 @@ static void rx_done_irq(struct atmel_private *priv)
/* 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.wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
if (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP)) {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
} else {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24);
......@@ -1042,7 +1100,7 @@ static void rx_done_irq(struct atmel_private *priv)
}
/* don't CRC header when WEP in use */
if (priv->do_rx_crc && (!priv->wep.wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE802_11_FCTL_WEP))) {
crc = crc32_le(0xffffffff, (unsigned char *)&header, 24);
}
msdu_size -= 24; /* header */
......@@ -1158,6 +1216,9 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
reset_irq_status(priv, ISR_IBSS_MERGE);
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)
build_wpa_mib(priv);
} else if (isr & ISR_GENERIC_IRQ) {
reset_irq_status(priv, ISR_GENERIC_IRQ);
printk(KERN_INFO "%s: Generic_irq recieved.\n", dev->name);
......@@ -1237,6 +1298,7 @@ static int atmel_close (struct net_device *dev)
{
struct atmel_private *priv = (struct atmel_private *) dev->priv;
netif_carrier_off(dev);
if (netif_running(dev))
netif_stop_queue(dev);
......@@ -1255,17 +1317,17 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
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 ",
p += sprintf(p, "Firmware version:\t%d.%d build %d\nFirmware location:\t",
priv->host_info.major_version,
priv->host_info.minor_version,
priv->host_info.build_version);
if (priv->card_type != CARD_TYPE_EEPROM)
p += sprintf(p, "[built-in]\n");
p += sprintf(p, "on card\n");
else if (priv->firmware)
p += sprintf(p, "[%s loaded by host]\n", priv->firmware_id);
p += sprintf(p, "%s loaded by host\n", priv->firmware_id);
else
p += sprintf(p, "[%s loaded by hotplug]\n", priv->firmware_id);
p += sprintf(p, "%s loaded by hotplug\n", priv->firmware_id);
switch(priv->card_type) {
case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;
......@@ -1289,6 +1351,8 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
p += sprintf(p, "Regulatory domain:\t%s\n", r);
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) {
......@@ -1299,8 +1363,6 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
case STATION_STATE_ASSOCIATING: s = "Associating"; break;
case STATION_STATE_READY: s = "Ready"; break;
case STATION_STATE_REASSOCIATING: s = "Reassociating"; break;
case STATION_STATE_FORCED_JOINNING: s = "Forced joining"; break;
case STATION_STATE_FORCED_JOIN_FAILURE: s = "Forced join failure"; break;
case STATION_STATE_NO_CARD: s = "No card"; break;
case STATION_STATE_MGMT_ERROR: s = "Management error"; break;
case STATION_STATE_DOWN: s = "Down"; break;
......@@ -1348,12 +1410,12 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
priv->present_callback = card_present;
priv->card = card;
priv->firmware = NULL;
priv->firmware_id[0] = '\0';
priv->firmware_template[0] = '\0';
if (firmware) /* module parameter */
strcpy(priv->firmware_id, firmware);
else if (firmware_id) /* from PCMCIA card-matching or PCI */
strcpy(priv->firmware_id, firmware_id);
else
priv->firmware_id[0] = '\0';
strcpy(priv->firmware_template, firmware_id);
priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
priv->station_state = STATION_STATE_DOWN;
priv->is3com = is3com;
......@@ -1389,9 +1451,16 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
priv->rts_threshold = 2347;
priv->short_retry = 7;
priv->long_retry = 4;
priv->wep.wep_is_on = 0;
priv->wep.default_key = 0;
priv->wep.encryption_level = 0;
priv->wep_is_on = 0;
priv->default_key = 0;
priv->encryption_level = 0;
priv->exclude_unencrypted = 0;
priv->group_cipher_suite = priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
priv->use_wpa = 0;
memset(priv->wep_keys, 0, sizeof(priv->wep_keys));
memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
priv->default_beacon_period = priv->beacon_period = 100;
priv->listen_interval = 1;
......@@ -1426,8 +1495,12 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
if (register_netdev(dev))
goto err_out_res;
if (!probe_atmel_card(dev))
if (!probe_atmel_card(dev)){
unregister_netdev(dev);
goto err_out_res;
}
netif_carrier_off(dev);
create_proc_read_entry ("driver/atmel", 0, 0, atmel_read_proc, priv);
......@@ -1443,7 +1516,7 @@ struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware
err_out_irq:
free_irq(dev->irq, dev);
err_out_free:
kfree(dev);
free_netdev(dev);
return NULL;
}
......@@ -1582,7 +1655,7 @@ static int atmel_set_encode(struct net_device *dev,
* don't do it. - Jean II */
if (dwrq->length > 0) {
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
int current_index = priv->wep.default_key;
int current_index = priv->default_key;
/* Check the size of the key */
if (dwrq->length > 13) {
return -EINVAL;
......@@ -1591,7 +1664,7 @@ static int atmel_set_encode(struct net_device *dev,
if (index < 0 || index >= 4)
index = current_index;
else
priv->wep.default_key = index;
priv->default_key = index;
/* Set the length */
if (dwrq->length > 5)
priv->wep_key_len[index] = 13;
......@@ -1604,27 +1677,30 @@ static int atmel_set_encode(struct net_device *dev,
/* Check if the key is not marked as invalid */
if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
/* Cleanup */
memset(priv->wep.wep_keys[index], 0, 13);
memset(priv->wep_keys[index], 0, 13);
/* Copy the key in the driver */
memcpy(priv->wep.wep_keys[index], extra, dwrq->length);
memcpy(priv->wep_keys[index], extra, dwrq->length);
}
/* 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 &&
priv->wep_key_len[index] > 0) {
priv->wep.wep_is_on = 1;
priv->wep.exclude_unencrypted = 1;
if (priv->wep_key_len[index] > 5)
priv->wep.encryption_level = 2;
else
priv->wep.encryption_level = 1;
priv->wep_is_on = 1;
priv->exclude_unencrypted = 1;
if (priv->wep_key_len[index] > 5) {
priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
priv->encryption_level = 2;
} else {
priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
priv->encryption_level = 1;
}
}
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if ( index>=0 && index < 4 ) {
priv->wep.default_key = index;
priv->default_key = index;
} else
/* Don't complain if only change the mode */
if(!dwrq->flags & IW_ENCODE_MODE) {
......@@ -1633,19 +1709,23 @@ static int atmel_set_encode(struct net_device *dev,
}
/* Read the flags */
if(dwrq->flags & IW_ENCODE_DISABLED) {
priv->wep.wep_is_on = 0;
priv->wep.encryption_level = 0;
priv->wep_is_on = 0;
priv->encryption_level = 0;
priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
} else {
priv->wep.wep_is_on = 1;
if (priv->wep_key_len[priv->wep.default_key] > 5)
priv->wep.encryption_level = 2;
else
priv->wep.encryption_level = 1;
priv->wep_is_on = 1;
if (priv->wep_key_len[priv->default_key] > 5) {
priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
priv->encryption_level = 2;
} else {
priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
priv->encryption_level = 1;
}
}
if(dwrq->flags & IW_ENCODE_RESTRICTED)
priv->wep.exclude_unencrypted = 1;
priv->exclude_unencrypted = 1;
if(dwrq->flags & IW_ENCODE_OPEN)
priv->wep.exclude_unencrypted = 0;
priv->exclude_unencrypted = 0;
return -EINPROGRESS; /* Call commit handler */
}
......@@ -1659,16 +1739,16 @@ static int atmel_get_encode(struct net_device *dev,
struct atmel_private *priv = dev->priv;
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if (!priv->wep.wep_is_on)
if (!priv->wep_is_on)
dwrq->flags = IW_ENCODE_DISABLED;
else if (priv->wep.exclude_unencrypted)
else if (priv->exclude_unencrypted)
dwrq->flags = IW_ENCODE_RESTRICTED;
else
dwrq->flags = IW_ENCODE_OPEN;
/* Which key do we want ? -1 -> tx index */
if (index < 0 || index >= 4)
index = priv->wep.default_key;
index = priv->default_key;
dwrq->flags |= index + 1;
/* Copy the key to the user buffer */
dwrq->length = priv->wep_key_len[index];
......@@ -1676,7 +1756,7 @@ static int atmel_get_encode(struct net_device *dev,
dwrq->length=0;
} else {
memset(extra, 0, 16);
memcpy(extra, priv->wep.wep_keys[index], dwrq->length);
memcpy(extra, priv->wep_keys[index], dwrq->length);
}
return 0;
......@@ -1711,10 +1791,10 @@ static int atmel_set_rate(struct net_device *dev,
} else {
/* Setting by frequency value */
switch (vwrq->value) {
case (int)1e6: priv->tx_rate = 0; break;
case (int)2e6: priv->tx_rate = 1; break;
case (int)5.5e6: priv->tx_rate = 2; break;
case (int)11e6: priv->tx_rate = 3; break;
case 1000000: priv->tx_rate = 0; break;
case 2000000: priv->tx_rate = 1; break;
case 5500000: priv->tx_rate = 2; break;
case 11000000: priv->tx_rate = 3; break;
default: return -EINVAL;
}
}
......@@ -1757,14 +1837,14 @@ static int atmel_get_rate(struct net_device *dev,
if (priv->auto_tx_rate) {
vwrq->fixed = 0;
vwrq->value = 11e6;
vwrq->value = 11000000;
} else {
vwrq->fixed = 1;
switch(priv->tx_rate) {
case 0: vwrq->value = 1e6; break;
case 1: vwrq->value = 2e6; break;
case 2: vwrq->value = 5.5e6; break;
case 3: vwrq->value = 11e6; break;
case 0: vwrq->value = 1000000; break;
case 1: vwrq->value = 2000000; break;
case 2: vwrq->value = 5500000; break;
case 3: vwrq->value = 11000000; break;
}
}
return 0;
......@@ -1982,6 +2062,7 @@ static int atmel_set_scan(struct net_device *dev,
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
del_timer_sync(&priv->management_timer);
priv->fast_scan = 0;
atmel_scan(priv, 0);
atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
......@@ -2073,10 +2154,10 @@ static int atmel_get_range(struct net_device *dev,
range->max_qual.noise = 0;
range->sensitivity = 0;
range->bitrate[0] = 1e6;
range->bitrate[1] = 2e6;
range->bitrate[2] = 5.5e6;
range->bitrate[3] = 11e6;
range->bitrate[0] = 1000000;
range->bitrate[1] = 2000000;
range->bitrate[2] = 5500000;
range->bitrate[3] = 11000000;
range->num_bitrates = 4;
range->min_rts = 0;
......@@ -2129,9 +2210,9 @@ static int atmel_set_wap(struct net_device *dev,
for(i=0; i<priv->BSS_list_entries; i++) {
if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
if (!priv->wep.wep_is_on && priv->BSSinfo[i].UsingWEP) {
if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) {
return -EINVAL;
} else if (priv->wep.wep_is_on && !priv->BSSinfo[i].UsingWEP) {
} else if (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) {
return -EINVAL;
} else
atmel_join_bss(priv, i);
......@@ -2313,10 +2394,13 @@ static void atmel_enter_state(struct atmel_private *priv, int new_state)
if (new_state == old_state)
return;
if (new_state == STATION_STATE_READY)
if (new_state == STATION_STATE_READY) {
netif_start_queue(priv->dev);
netif_carrier_on(priv->dev);
}
if (old_state == STATION_STATE_READY) {
netif_carrier_off(priv->dev);
netif_stop_queue(priv->dev);
priv->last_beacon_timestamp = 0;
}
......@@ -2453,7 +2537,7 @@ static void send_authentication_request(struct atmel_private *priv, u8 *challeng
memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
if (priv->wep.wep_is_on) {
if (priv->wep_is_on) {
auth.alg = C80211_MGMT_AAN_SHAREDKEY;
/* no WEP for authentication frames with TrSeqNo 1 */
if (priv->CurrentAuthentTransactionSeqNum != 1)
......@@ -2504,7 +2588,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
memcpy(header.addr3, priv->CurrentBSSID, 6);
body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
if (priv->wep.wep_is_on)
if (priv->wep_is_on)
body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_Privacy);
if (priv->preamble == SHORT_PREAMBLE)
body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
......@@ -2555,8 +2639,8 @@ static int retrieve_bss(struct atmel_private *priv)
priv->current_BSS = 0;
for(i=0; i<priv->BSS_list_entries; i++) {
if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
((!priv->wep.wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
(priv->wep.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;
......@@ -2630,7 +2714,7 @@ 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);
if (status == C80211_MGMT_SC_Success && !priv->wep.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);
......@@ -2643,7 +2727,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
}
if (status == C80211_MGMT_SC_Success && priv->wep.wep_is_on) {
if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
/* WEP */
if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
return;
......@@ -2765,6 +2849,10 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
memcpy(priv->CurrentBSSID, bss->BSSID, 6);
memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize);
/* 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 */
......@@ -2786,13 +2874,13 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
}
if (!priv->wep.wep_is_on && bss->UsingWEP) {
if (!priv->wep_is_on && bss->UsingWEP) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
return;
}
if (priv->wep.wep_is_on && !bss->UsingWEP) {
if (priv->wep_is_on && !bss->UsingWEP) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
return;
......@@ -3071,6 +3159,7 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->fast_scan = !fast_scan;
atmel_scan(priv, 1);
}
priv->site_survey_state = SITE_SURVEY_COMPLETED;
}
break;
......@@ -3104,12 +3193,8 @@ static void atmel_command_irq(struct atmel_private *priv)
return;
}
if (priv->station_state == STATION_STATE_FORCED_JOINNING) {
atmel_enter_state(priv, STATION_STATE_FORCED_JOIN_FAILURE);
} else {
atmel_scan(priv, 1);
}
atmel_scan(priv, 1);
}
}
......@@ -3275,7 +3360,7 @@ static int probe_atmel_card(struct net_device *dev)
printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name);
memcpy(dev->dev_addr, default_mac, 6);
}
printk(KERN_INFO "%s: MAC address %x:%x:%x:%x:%x:%x\n",
printk(KERN_INFO "%s: MAC address %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
dev->name,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
......@@ -3285,6 +3370,105 @@ static int probe_atmel_card(struct net_device *dev)
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. */
{
struct { /* NB this is matched to the hardware, don't change. */
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];
} mib;
int i;
mib.wep_is_on = priv->wep_is_on;
if (priv->wep_is_on) {
if (priv->wep_key_len[priv->default_key] > 5)
mib.encryption_level = 2;
else
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++)
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. */
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 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 */
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) {
memcpy(mib.cipher_default_key_value[i], priv->wep_keys[i], MAX_ENCRYPTION_KEY_SIZE);
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;
} 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;
}
}
}
if (mib.default_key == 255)
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));
}
int reset_atmel_card(struct net_device *dev)
{
/* do everything necessary to wake up the hardware, including
......@@ -3305,6 +3489,15 @@ int reset_atmel_card(struct net_device *dev)
struct atmel_private *priv = dev->priv;
u8 configuration;
/* data to add to the firmware names, in priority order
this implemenents firmware versioning */
static char *firmware_modifier[] = {
"-wpa",
"",
NULL
};
if (priv->station_state == STATION_STATE_NO_CARD ||
priv->station_state == STATION_STATE_DOWN)
return 0;
......@@ -3341,21 +3534,41 @@ int reset_atmel_card(struct net_device *dev)
unsigned char *fw;
int len = priv->firmware_length;
if (!(fw = priv->firmware)) {
if (strlen(priv->firmware_id) == 0) {
printk(KERN_INFO
"%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",
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 start.\n",
dev->name, priv->firmware_id);
return 0;
if (strlen(priv->firmware_template) == 0) {
if (strlen(priv->firmware_id) == 0) {
printk(KERN_INFO
"%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",
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",
dev->name, priv->firmware_id);
return 0;
}
} else {
int i;
for (i = 0; firmware_modifier[i]; i++) {
sprintf(priv->firmware_id, priv->firmware_template, firmware_modifier[i]);
if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0)
break;
}
if (!firmware_modifier[i]) {
printk(KERN_ALERT
"%s: firmware %s is missing, cannot start.\n",
dev->name, priv->firmware_id);
priv->firmware_id[0] = '\0';
return 0;
}
priv->firmware_template[0] = '\0';
}
fw = fw_entry->data;
len = fw_entry->size;
}
......@@ -3379,6 +3592,10 @@ int reset_atmel_card(struct net_device *dev)
if (!atmel_wakeup_firmware(priv))
return 0;
/* Check the version and set the correct flag for wpa stuff,
old and new firmware is incompatible. */
priv->use_wpa = (priv->host_info.major_version >= 4);
/* unmask all irq sources */
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
......@@ -3447,9 +3664,12 @@ int reset_atmel_card(struct net_device *dev)
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_BEACON_PER_POS, priv->default_beacon_period);
atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, atmel_basic_rates, 4);
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep.wep_is_on);
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&priv->wep, sizeof(priv->wep));
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep_is_on);
if (priv->use_wpa)
build_wpa_mib(priv);
else
build_wep_mib(priv);
atmel_scan(priv, 1);
atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
......@@ -3500,8 +3720,8 @@ static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index)
m.size = 1;
m.index = index;
atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, sizeof(m));
return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + 4));
atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE));
}
static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data)
......@@ -3512,7 +3732,7 @@ static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 dat
m.index = index;
m.data[0] = data;
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
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)
......@@ -3524,7 +3744,7 @@ static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 d
m.data[0] = data;
m.data[1] = data >> 8;
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
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)
......@@ -3534,8 +3754,11 @@ static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *dat
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);
memcpy(m.data, data, data_len);
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, sizeof(m));
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)
......@@ -3545,10 +3768,14 @@ static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *dat
m.size = data_len;
m.index = index;
atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, sizeof(m));
atmel_copy_to_host(priv->dev, data, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + 4), data_len);
}
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_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len);
}
static void atmel_writeAR(struct net_device *dev, u16 data)
{
int i;
......
......@@ -330,20 +330,20 @@ static struct {
char *firmware;
char *name;
} card_table[] = {
{ 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d.bin", "Actiontec 802CAT1" },
{ 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502.bin", "NoName-RFMD" },
{ 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d.bin", "NoName-revD" },
{ 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e.bin", "NoName-revE" },
{ 0, 0, "ATMEL/AT76C504", "atmel_at76c504.bin", "NoName-504" },
{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com.bin", "3com 3CRWE62092B" },
{ MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com.bin", "3com 3CRSHPW_96" },
{ 0, 0, "SMC/2632W-V2", "atmel_at76c502.bin", "SMC 2632W-V2" },
{ 0, 0, "SMC/2632W", "atmel_at76c502d.bin", "SMC 2632W-V3" },
{ 0xd601, 0x0007, NULL, "atmel_at76c502.bin", "Sitecom WLAN-011"}, /* suspect - from a usenet posting. */
{ 0x01bf, 0x3302, NULL, "atmel_at76c502d.bin", "Belkin F5D6060u"}, /* " " " " " */
{ 0, 0, "BT/Voyager 1020 Laptop Adapter", "atmel_at76c502.bin", "BT Voyager 1020"},
{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", "atmel_at76c502.bin", "Siemens Gigaset PC Card II" },
{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", "atmel_at76c502e.bin", "CNet CNWLC-811ARL" }
{ 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d%s.bin", "Actiontec 802CAT1" },
{ 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502%s.bin", "NoName-RFMD" },
{ 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d%s.bin", "NoName-revD" },
{ 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e%s.bin", "NoName-revE" },
{ 0, 0, "ATMEL/AT76C504", "atmel_at76c504%s.bin", "NoName-504" },
{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRWE62092B" },
{ MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW_96" },
{ 0, 0, "SMC/2632W-V2", "atmel_at76c502%s.bin", "SMC 2632W-V2" },
{ 0, 0, "SMC/2632W", "atmel_at76c502d%s.bin", "SMC 2632W-V3" },
{ 0xd601, 0x0007, NULL, "atmel_at76c502%s.bin", "Sitecom WLAN-011"}, /* suspect - from a usenet posting. */
{ 0x01bf, 0x3302, NULL, "atmel_at76c502d%s.bin", "Belkin F5D6060u"}, /* " " " " " */
{ 0, 0, "BT/Voyager 1020 Laptop Adapter", "atmel_at76c502%s.bin", "BT Voyager 1020"},
{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", "atmel_at76c502%s.bin", "Siemens Gigaset PC Card II" },
{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", "atmel_at76c502e%s.bin", "CNet CNWLC-811ARL" }
};
/* This is strictly temporary, until PCMCIA devices get integrated into the device model. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment