#include <linux/interrupt.h>
#include <linux/in.h>
#include <linux/bitops.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
#include <asm/io.h>
#include <asm/system.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
+#include "airo.h"
+
#ifdef CONFIG_PCI
static struct pci_device_id card_ids[] = {
{ 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
#include <linux/delay.h>
#endif
-/* Support Cisco MIC feature */
-#define MICSUPPORT
-
-#if defined(MICSUPPORT) && !defined(CONFIG_CRYPTO)
-#warning MIC support requires Crypto API
-#undef MICSUPPORT
-#endif
-
/* Hack to do some power saving */
#define POWER_ON_DOWN
u16 atimWindow;
} BSSListRid;
+typedef struct {
+ BSSListRid bss;
+ struct list_head list;
+} BSSListElement;
+
typedef struct {
u8 rssipct;
u8 rssidBm;
unsigned char __user *data; // d-data
} aironet_ioctl;
-static char *swversion = "2.1";
+static char swversion[] = "2.1";
#endif /* CISCO_EXT */
#define NUM_MODULES 2
#define MIC_MSGLEN_MAX 2400
#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
+#define AIRO_DEF_MTU 2312
typedef struct {
u32 size; // size
u16 status;
} WifiCtlHdr;
-WifiCtlHdr wifictlhdr8023 = {
+static WifiCtlHdr wifictlhdr8023 = {
.ctlhdr = {
.ctl = HOST_DONT_RLSE,
}
};
-#ifdef WIRELESS_EXT
// Frequency list (map channels to frequencies)
static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484 };
/* List of Wireless Handlers (new API) */
static const struct iw_handler_def airo_handler_def;
-#endif /* WIRELESS_EXT */
static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
static int airo_thread(void *data);
static void timer_func( struct net_device *dev );
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#ifdef WIRELESS_EXT
-struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
+static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
static void airo_read_wireless_stats (struct airo_info *local);
-#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
static int readrids(struct net_device *dev, aironet_ioctl *comp);
static int writerids(struct net_device *dev, aironet_ioctl *comp);
-int flashcard(struct net_device *dev, aironet_ioctl *comp);
+static int flashcard(struct net_device *dev, aironet_ioctl *comp);
#endif /* CISCO_EXT */
-#ifdef MICSUPPORT
static void micinit(struct airo_info *ai);
static int micsetup(struct airo_info *ai);
static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
-#include <linux/crypto.h>
-#endif
+static void airo_networks_free(struct airo_info *ai);
struct airo_info {
struct net_device_stats stats;
#define FLAG_COMMIT 13
#define FLAG_RESET 14
#define FLAG_FLASHING 15
-#define JOB_MASK 0x1ff0000
+#define JOB_MASK 0x2ff0000
#define JOB_DIE 16
#define JOB_XMIT 17
#define JOB_XMIT11 18
#define JOB_EVENT 22
#define JOB_AUTOWEP 23
#define JOB_WSTATS 24
+#define JOB_SCAN_RESULTS 25
int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
int whichbap);
unsigned short *flash;
int fid;
} xmit, xmit11;
struct net_device *wifidev;
-#ifdef WIRELESS_EXT
struct iw_statistics wstats; // wireless stats
- unsigned long scan_timestamp; /* Time started to scan */
+ unsigned long scan_timeout; /* Time scan should be read */
struct iw_spy_data spy_data;
struct iw_public_data wireless_data;
-#endif /* WIRELESS_EXT */
-#ifdef MICSUPPORT
/* MIC stuff */
struct crypto_tfm *tfm;
mic_module mod[2];
mic_statistics micstats;
-#endif
HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
HostTxDesc txfids[MPI_MAX_FIDS];
HostRidDesc config_desc;
unsigned char __iomem *pciaux;
unsigned char *shared;
dma_addr_t shared_dma;
- int power;
+ pm_message_t power;
SsidRid *SSID;
APListRid *APList;
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
char proc_name[IFNAMSIZ];
+
+ struct list_head network_list;
+ struct list_head network_free_list;
+ BSSListElement *networks;
};
static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
static int takedown_proc_entry( struct net_device *dev,
struct airo_info *apriv );
-#ifdef MICSUPPORT
+static int cmdreset(struct airo_info *ai);
+static int setflashmode (struct airo_info *ai);
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
+static int flashputbuf(struct airo_info *ai);
+static int flashrestart(struct airo_info *ai,struct net_device *dev);
+
+#define airo_print(type, name, fmt, args...) \
+ { printk(type "airo(%s): " fmt "\n", name, ##args); }
+
+#define airo_print_info(name, fmt, args...) \
+ airo_print(KERN_INFO, name, fmt, ##args)
+
+#define airo_print_dbg(name, fmt, args...) \
+ airo_print(KERN_DEBUG, name, fmt, ##args)
+
+#define airo_print_warn(name, fmt, args...) \
+ airo_print(KERN_WARNING, name, fmt, ##args)
+
+#define airo_print_err(name, fmt, args...) \
+ airo_print(KERN_ERR, name, fmt, ##args)
+
+
/***********************************************************************
* MIC ROUTINES *
***********************************************************************
static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
static void MoveWindow(miccntx *context, u32 micSeq);
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
-void emmh32_init(emmh32_context *context);
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
-void emmh32_final(emmh32_context *context, u8 digest[4]);
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
+static void emmh32_init(emmh32_context *context);
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
+static void emmh32_final(emmh32_context *context, u8 digest[4]);
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
/* micinit - Initialize mic seed */
int i;
if (ai->tfm == NULL)
- ai->tfm = crypto_alloc_tfm("aes", 0);
+ ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);
if (ai->tfm == NULL) {
- printk(KERN_ERR "airo: failed to load transform for AES\n");
+ airo_print_err(ai->dev->name, "failed to load transform for AES");
return ERROR;
}
return SUCCESS;
}
-char micsnap[]= {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
/*===========================================================================
* Description: Mic a packet
static unsigned char aes_counter[16];
/* expand the key to fill the MMH coefficient array */
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
{
/* take the keying material, expand if necessary, truncate at 16-bytes */
/* run through AES counter mode to generate context->coeff[] */
aes_counter[12] = (u8)(counter >> 24);
counter++;
memcpy (plain, aes_counter, 16);
- sg[0].page = virt_to_page(plain);
- sg[0].offset = ((long) plain & ~PAGE_MASK);
- sg[0].length = 16;
+ sg_set_buf(sg, plain, 16);
crypto_cipher_encrypt(tfm, sg, sg, 16);
- cipher = kmap(sg[0].page) + sg[0].offset;
+ cipher = kmap(sg->page) + sg->offset;
for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
j += 4;
}
/* prepare for calculation of a new mic */
-void emmh32_init(emmh32_context *context)
+static void emmh32_init(emmh32_context *context)
{
/* prepare for new mic calculation */
context->accum = 0;
}
/* add some bytes to the mic calculation */
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
{
int coeff_position, byte_position;
static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
/* calculate the mic */
-void emmh32_final(emmh32_context *context, u8 digest[4])
+static void emmh32_final(emmh32_context *context, u8 digest[4])
{
int coeff_position, byte_position;
u32 val;
digest[2] = (val>>8) & 0xFF;
digest[3] = val & 0xFF;
}
-#endif
static int readBSSListRid(struct airo_info *ai, int first,
BSSListRid *list) {
wkr.kindex = cpu_to_le16(wkr.kindex);
wkr.klen = cpu_to_le16(wkr.klen);
rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);
- if (rc!=SUCCESS) printk(KERN_ERR "airo: WEP_TEMP set %x\n", rc);
+ if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
if (perm) {
rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);
if (rc!=SUCCESS) {
- printk(KERN_ERR "airo: WEP_PERM set %x\n", rc);
+ airo_print_err(ai->dev->name, "WEP_PERM set %x", rc);
}
}
return rc;
struct airo_info *ai = dev->priv;
if (!skb) {
- printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__);
+ airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
return 0;
}
npacks = skb_queue_len (&ai->txq);
/* get a packet to send */
if ((skb = skb_dequeue(&ai->txq)) == 0) {
- printk (KERN_ERR
- "airo: %s: Dequeue'd zero in send_packet()\n",
+ airo_print_err(dev->name,
+ "%s: Dequeue'd zero in send_packet()",
__FUNCTION__);
return 0;
}
* Firmware automaticly puts 802 header on so
* we don't need to account for it in the length
*/
-#ifdef MICSUPPORT
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
(ntohs(((u16 *)buffer)[6]) != 0x888E)) {
MICBuffer pMic;
memcpy (sendbuf, &pMic, sizeof(pMic));
sendbuf += sizeof(pMic);
memcpy (sendbuf, buffer, len - sizeof(etherHead));
- } else
-#endif
- {
+ } else {
*payloadLen = cpu_to_le16(len - sizeof(etherHead));
dev->trans_start = jiffies;
return 1;
}
-static void get_tx_error(struct airo_info *ai, u32 fid)
+static void get_tx_error(struct airo_info *ai, s32 fid)
{
u16 status;
u32 *fids = priv->fids;
if ( skb == NULL ) {
- printk( KERN_ERR "airo: skb == NULL!!!\n" );
+ airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
return 0;
}
}
if ( skb == NULL ) {
- printk( KERN_ERR "airo: skb == NULL!!!\n" );
+ airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
return 0;
}
u32 *vals = stats_rid.vals;
clear_bit(JOB_STATS, &ai->flags);
- if (ai->power) {
+ if (ai->power.event) {
up(&ai->sem);
return;
}
ai->stats.rx_fifo_errors = vals[0];
}
-struct net_device_stats *airo_get_stats(struct net_device *dev)
+static struct net_device_stats *airo_get_stats(struct net_device *dev)
{
struct airo_info *local = dev->priv;
/*
* Clean out tx queue
*/
- if (test_bit(FLAG_MPI, &ai->flags) && skb_queue_len (&ai->txq) > 0) {
+ if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) {
struct sk_buff *skb = NULL;
for (;(skb = skb_dequeue(&ai->txq));)
dev_kfree_skb(skb);
}
- if (ai->flash)
- kfree(ai->flash);
- if (ai->rssi)
- kfree(ai->rssi);
- if (ai->APList)
- kfree(ai->APList);
- if (ai->SSID)
- kfree(ai->SSID);
+ airo_networks_free (ai);
+
+ kfree(ai->flash);
+ kfree(ai->rssi);
+ kfree(ai->APList);
+ kfree(ai->SSID);
if (freeres) {
/* PCMCIA frees this stuff, so only for PCI and ISA */
release_region( dev->base_addr, 64 );
ai->shared, ai->shared_dma);
}
}
-#ifdef MICSUPPORT
- if (ai->tfm)
- crypto_free_tfm(ai->tfm);
-#endif
+ crypto_free_tfm(ai->tfm);
del_airo_dev( dev );
free_netdev( dev );
}
static int add_airo_dev( struct net_device *dev );
-int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
+static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
return ETH_ALEN;
cmd.parm2 = MPI_MAX_FIDS;
rc=issuecommand(ai, &cmd, &rsp);
if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate RX FID\n");
+ airo_print_err(ai->dev->name, "Couldn't allocate RX FID");
return rc;
}
rc=issuecommand(ai, &cmd, &rsp);
if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate TX FID\n");
+ airo_print_err(ai->dev->name, "Couldn't allocate TX FID");
return rc;
}
cmd.parm2 = 1; /* Magic number... */
rc=issuecommand(ai, &cmd, &rsp);
if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate RID\n");
+ airo_print_err(ai->dev->name, "Couldn't allocate RID");
return rc;
}
unsigned long mem_start, mem_len, aux_start, aux_len;
int rc = -1;
int i;
- unsigned char *busaddroff,*vpackoff;
+ dma_addr_t busaddroff;
+ unsigned char *vpackoff;
unsigned char __iomem *pciaddroff;
mem_start = pci_resource_start(pci, 1);
aux_len = AUXMEMSIZE;
if (!request_mem_region(mem_start, mem_len, name)) {
- printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
(int)mem_start, (int)mem_len, name);
goto out;
}
if (!request_mem_region(aux_start, aux_len, name)) {
- printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
(int)aux_start, (int)aux_len, name);
goto free_region1;
}
ai->pcimem = ioremap(mem_start, mem_len);
if (!ai->pcimem) {
- printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
(int)mem_start, (int)mem_len, name);
goto free_region2;
}
ai->pciaux = ioremap(aux_start, aux_len);
if (!ai->pciaux) {
- printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n",
+ airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
(int)aux_start, (int)aux_len, name);
goto free_memmap;
}
/* Reserve PKTSIZE for each fid and 2K for the Rids */
ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
if (!ai->shared) {
- printk(KERN_ERR "airo: Couldn't alloc_consistent %d\n",
+ airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
PCI_SHARED_LEN);
goto free_auxmap;
}
/*
* Setup descriptor RX, TX, CONFIG
*/
- busaddroff = (unsigned char *)ai->shared_dma;
+ busaddroff = ai->shared_dma;
pciaddroff = ai->pciaux + AUX_OFFSET;
vpackoff = ai->shared;
ai->rxfids[i].pending = 0;
ai->rxfids[i].card_ram_off = pciaddroff;
ai->rxfids[i].virtual_host_addr = vpackoff;
- ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->rxfids[i].rx_desc.host_addr = busaddroff;
ai->rxfids[i].rx_desc.valid = 1;
ai->rxfids[i].rx_desc.len = PKTSIZE;
ai->rxfids[i].rx_desc.rdy = 0;
ai->txfids[i].card_ram_off = pciaddroff;
ai->txfids[i].virtual_host_addr = vpackoff;
ai->txfids[i].tx_desc.valid = 1;
- ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
+ ai->txfids[i].tx_desc.host_addr = busaddroff;
memcpy(ai->txfids[i].virtual_host_addr,
&wifictlhdr8023, sizeof(wifictlhdr8023));
/* Rid descriptor setup */
ai->config_desc.card_ram_off = pciaddroff;
ai->config_desc.virtual_host_addr = vpackoff;
- ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
- ai->ridbus = (dma_addr_t)busaddroff;
+ ai->config_desc.rid_desc.host_addr = busaddroff;
+ ai->ridbus = busaddroff;
ai->config_desc.rid_desc.rid = 0;
ai->config_desc.rid_desc.len = RIDSIZE;
ai->config_desc.rid_desc.valid = 1;
dev->get_stats = &airo_get_stats;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
-#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
dev->type = ARPHRD_IEEE80211;
dev->hard_header_len = ETH_HLEN;
- dev->mtu = 2312;
+ dev->mtu = AIRO_DEF_MTU;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 100;
dev->priv = ethdev->priv;
dev->irq = ethdev->irq;
dev->base_addr = ethdev->base_addr;
-#ifdef WIRELESS_EXT
dev->wireless_data = ethdev->wireless_data;
-#endif /* WIRELESS_EXT */
memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
err = register_netdev(dev);
if (err<0) {
return dev;
}
-int reset_card( struct net_device *dev , int lock) {
+static int reset_card( struct net_device *dev , int lock) {
struct airo_info *ai = dev->priv;
if (lock && down_interruptible(&ai->sem))
return 0;
}
-struct net_device *_init_airo_card( unsigned short irq, int port,
- int is_pcmcia, struct pci_dev *pci,
- struct device *dmdev )
+#define MAX_NETWORK_COUNT 64
+static int airo_networks_allocate(struct airo_info *ai)
+{
+ if (ai->networks)
+ return 0;
+
+ ai->networks =
+ kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement),
+ GFP_KERNEL);
+ if (!ai->networks) {
+ airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void airo_networks_free(struct airo_info *ai)
+{
+ if (!ai->networks)
+ return;
+ kfree(ai->networks);
+ ai->networks = NULL;
+}
+
+static void airo_networks_initialize(struct airo_info *ai)
+{
+ int i;
+
+ INIT_LIST_HEAD(&ai->network_free_list);
+ INIT_LIST_HEAD(&ai->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ list_add_tail(&ai->networks[i].list,
+ &ai->network_free_list);
+}
+
+static struct net_device *_init_airo_card( unsigned short irq, int port,
+ int is_pcmcia, struct pci_dev *pci,
+ struct device *dmdev )
{
struct net_device *dev;
struct airo_info *ai;
/* Create the network device object. */
dev = alloc_etherdev(sizeof(*ai));
if (!dev) {
- printk(KERN_ERR "airo: Couldn't alloc_etherdev\n");
+ airo_print_err("", "Couldn't alloc_etherdev");
return NULL;
}
if (dev_alloc_name(dev, dev->name) < 0) {
- printk(KERN_ERR "airo: Couldn't get name!\n");
+ airo_print_err("", "Couldn't get name!");
goto err_out_free;
}
ai = dev->priv;
ai->wifidev = NULL;
ai->flags = 0;
+ ai->dev = dev;
if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
- printk(KERN_DEBUG "airo: Found an MPI350 card\n");
+ airo_print_dbg(dev->name, "Found an MPI350 card");
set_bit(FLAG_MPI, &ai->flags);
}
- ai->dev = dev;
spin_lock_init(&ai->aux_lock);
sema_init(&ai->sem, 1);
ai->config.len = 0;
ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
if (ai->thr_pid < 0)
goto err_out_free;
-#ifdef MICSUPPORT
ai->tfm = NULL;
-#endif
rc = add_airo_dev( dev );
if (rc)
goto err_out_thr;
+ if (airo_networks_allocate (ai))
+ goto err_out_unlink;
+ airo_networks_initialize (ai);
+
/* The Airo-specific entries in the device structure. */
if (test_bit(FLAG_MPI,&ai->flags)) {
skb_queue_head_init (&ai->txq);
dev->set_multicast_list = &airo_set_multicast_list;
dev->set_mac_address = &airo_set_mac_address;
dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
dev->wireless_handlers = &airo_handler_def;
ai->wireless_data.spy_data = &ai->spy_data;
dev->wireless_data = &ai->wireless_data;
-#endif /* WIRELESS_EXT */
dev->change_mtu = &airo_change_mtu;
dev->open = &airo_open;
dev->stop = &airo_close;
SET_NETDEV_DEV(dev, dmdev);
-
- if (test_bit(FLAG_MPI,&ai->flags))
- reset_card (dev, 1);
+ reset_card (dev, 1);
+ msleep(400);
rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev );
if (rc) {
- printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc );
+ airo_print_err(dev->name, "register interrupt %d failed, rc %d",
+ irq, rc);
goto err_out_unlink;
}
if (!is_pcmcia) {
if (!request_region( dev->base_addr, 64, dev->name )) {
rc = -EBUSY;
- printk(KERN_ERR "airo: Couldn't request region\n");
+ airo_print_err(dev->name, "Couldn't request region");
goto err_out_irq;
}
}
if (test_bit(FLAG_MPI,&ai->flags)) {
if (mpi_map_card(ai, pci, dev->name)) {
- printk(KERN_ERR "airo: Could not map memory\n");
+ airo_print_err(dev->name, "Could not map memory");
goto err_out_res;
}
}
if (probe) {
if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
- printk( KERN_ERR "airo: MAC could not be enabled\n" );
+ airo_print_err(dev->name, "MAC could not be enabled" );
rc = -EIO;
goto err_out_map;
}
rc = register_netdev(dev);
if (rc) {
- printk(KERN_ERR "airo: Couldn't register_netdev\n");
+ airo_print_err(dev->name, "Couldn't register_netdev");
goto err_out_map;
}
ai->wifidev = init_wifidev(ai, dev);
set_bit(FLAG_REGISTERED,&ai->flags);
- printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
- dev->name,
+ airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
/* Allocate the transmit buffers */
if (probe && !test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ )
- ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2);
+ ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
netif_start_queue(dev);
return -1;
if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) {
- printk( KERN_ERR "airo: MAC could not be enabled\n" );
+ airo_print_err(dev->name, "MAC could not be enabled");
return -1;
}
- printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", dev->name,
+ airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
/* Allocate the transmit buffers if needed */
if (!test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ )
- ai->fids[i] = transmit_allocate (ai,2312,i>=MAX_FIDS/2);
+ ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
enable_interrupts( ai );
netif_wake_queue(dev);
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
}
+static void airo_process_scan_results (struct airo_info *ai) {
+ union iwreq_data wrqu;
+ BSSListRid BSSList;
+ int rc;
+ BSSListElement * loop_net;
+ BSSListElement * tmp_net;
+
+ /* Blow away current list of scan results */
+ list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) {
+ list_move_tail (&loop_net->list, &ai->network_free_list);
+ /* Don't blow away ->list, just BSS data */
+ memset (loop_net, 0, sizeof (loop_net->bss));
+ }
+
+ /* Try to read the first entry of the scan result */
+ rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0);
+ if((rc) || (BSSList.index == 0xffff)) {
+ /* No scan results */
+ goto out;
+ }
+
+ /* Read and parse all entries */
+ tmp_net = NULL;
+ while((!rc) && (BSSList.index != 0xffff)) {
+ /* Grab a network off the free list */
+ if (!list_empty(&ai->network_free_list)) {
+ tmp_net = list_entry(ai->network_free_list.next,
+ BSSListElement, list);
+ list_del(ai->network_free_list.next);
+ }
+
+ if (tmp_net != NULL) {
+ memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss));
+ list_add_tail(&tmp_net->list, &ai->network_list);
+ tmp_net = NULL;
+ }
+
+ /* Read next entry */
+ rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
+ &BSSList, sizeof(BSSList), 0);
+ }
+
+out:
+ ai->scan_timeout = 0;
+ clear_bit(JOB_SCAN_RESULTS, &ai->flags);
+ up(&ai->sem);
+
+ /* Send an empty event to user space.
+ * We don't send the received data on
+ * the event because it would require
+ * us to do complex transcoding, and
+ * we want to minimise the work done in
+ * the irq handler. Use a request to
+ * extract the data - Jean II */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
static int airo_thread(void *data) {
struct net_device *dev = data;
struct airo_info *ai = dev->priv;
flush_signals(current);
/* make swsusp happy with our thread */
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
if (test_bit(JOB_DIE, &ai->flags))
break;
set_current_state(TASK_INTERRUPTIBLE);
if (ai->flags & JOB_MASK)
break;
- if (ai->expires) {
- if (time_after_eq(jiffies,ai->expires)){
+ if (ai->expires || ai->scan_timeout) {
+ if (ai->scan_timeout &&
+ time_after_eq(jiffies,ai->scan_timeout)){
+ set_bit(JOB_SCAN_RESULTS,&ai->flags);
+ break;
+ } else if (ai->expires &&
+ time_after_eq(jiffies,ai->expires)){
set_bit(JOB_AUTOWEP,&ai->flags);
break;
}
if (!signal_pending(current)) {
- schedule_timeout(ai->expires - jiffies);
+ unsigned long wake_at;
+ if (!ai->expires || !ai->scan_timeout) {
+ wake_at = max(ai->expires,
+ ai->scan_timeout);
+ } else {
+ wake_at = min(ai->expires,
+ ai->scan_timeout);
+ }
+ schedule_timeout(wake_at - jiffies);
continue;
}
} else if (!signal_pending(current)) {
break;
}
- if (ai->power || test_bit(FLAG_FLASHING, &ai->flags)) {
+ if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) {
up(&ai->sem);
continue;
}
airo_read_wireless_stats(ai);
else if (test_bit(JOB_PROMISC, &ai->flags))
airo_set_promisc(ai);
-#ifdef MICSUPPORT
else if (test_bit(JOB_MIC, &ai->flags))
micinit(ai);
-#endif
else if (test_bit(JOB_EVENT, &ai->flags))
airo_send_event(dev);
else if (test_bit(JOB_AUTOWEP, &ai->flags))
timer_func(dev);
+ else if (test_bit(JOB_SCAN_RESULTS, &ai->flags))
+ airo_process_scan_results(ai);
+ else /* Shouldn't get here, but we make sure to unlock */
+ up(&ai->sem);
}
complete_and_exit (&ai->thr_exited, 0);
}
if ( status & EV_MIC ) {
OUT4500( apriv, EVACK, EV_MIC );
-#ifdef MICSUPPORT
if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
set_bit(JOB_MIC, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
}
-#endif
}
if ( status & EV_LINK ) {
union iwreq_data wrqu;
+ int scan_forceloss = 0;
/* The link status has changed, if you want to put a
monitor hook in, do it here. (Remember that
interrupts are still disabled!)
code) */
#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
code) */
-#define ASSOCIATED 0x0400 /* Assocatied */
+#define ASSOCIATED 0x0400 /* Associated */
+#define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */
#define RC_RESERVED 0 /* Reserved return code */
#define RC_NOREASON 1 /* Unspecified reason */
#define RC_AUTHINV 2 /* Previous authentication invalid */
leaving BSS */
#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
Authenticated with the responding station */
- if (newStatus != ASSOCIATED) {
- if (auto_wep && !apriv->expires) {
- apriv->expires = RUN_AT(3*HZ);
- wake_up_interruptible(&apriv->thr_wait);
- }
- } else {
- struct task_struct *task = apriv->task;
+ if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
+ scan_forceloss = 1;
+ if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
if (auto_wep)
apriv->expires = 0;
- if (task)
- wake_up_process (task);
+ if (apriv->task)
+ wake_up_process (apriv->task);
set_bit(FLAG_UPDATE_UNI, &apriv->flags);
set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
- }
- /* Question : is ASSOCIATED the only status
- * that is valid ? We want to catch handover
- * and reassociations as valid status
- * Jean II */
- if(newStatus == ASSOCIATED) {
- if (apriv->scan_timestamp) {
- /* Send an empty event to user space.
- * We don't send the received data on
- * the event because it would require
- * us to do complex transcoding, and
- * we want to minimise the work done in
- * the irq handler. Use a request to
- * extract the data - Jean II */
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
- apriv->scan_timestamp = 0;
- }
+
if (down_trylock(&apriv->sem) != 0) {
set_bit(JOB_EVENT, &apriv->flags);
wake_up_interruptible(&apriv->thr_wait);
} else
airo_send_event(dev);
- } else {
- memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ } else if (!scan_forceloss) {
+ if (auto_wep && !apriv->expires) {
+ apriv->expires = RUN_AT(3*HZ);
+ wake_up_interruptible(&apriv->thr_wait);
+ }
/* Send event to user space */
+ memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
}
}
}
len = le16_to_cpu(hdr.len);
- if (len > 2312) {
- printk( KERN_ERR "airo: Bad size %d\n", len );
+ if (len > AIRO_DEF_MTU) {
+ airo_print_err(apriv->dev->name, "Bad size %d", len);
goto badrx;
}
if (len == 0)
bap_read (apriv, &gap, sizeof(gap), BAP0);
gap = le16_to_cpu(gap);
if (gap) {
- if (gap <= 8)
+ if (gap <= 8) {
bap_read (apriv, tmpbuf, gap, BAP0);
- else
- printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n");
+ } else {
+ airo_print_err(apriv->dev->name, "gaplen too "
+ "big. Problems will follow...");
+ }
}
bap_read (apriv, buffer + hdrlen/2, len, BAP0);
} else {
-#ifdef MICSUPPORT
MICBuffer micbuf;
-#endif
bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-#ifdef MICSUPPORT
if (apriv->micstats.enabled) {
bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
if (ntohs(micbuf.typelen) > 0x05DC)
skb_trim (skb, len + hdrlen);
}
}
-#endif
bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-#ifdef MICSUPPORT
if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
badmic:
dev_kfree_skb_irq (skb);
-#else
- if (0) {
-#endif
badrx:
OUT4500( apriv, EVACK, EV_RX);
goto exitrx;
wstats.noise = apriv->wstats.qual.noise;
wstats.updated = IW_QUAL_LEVEL_UPDATED
| IW_QUAL_QUAL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
+ | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(dev, sa, &wstats);
}
if (status & EV_TXEXC)
get_tx_error(apriv, -1);
spin_lock_irqsave(&apriv->aux_lock, flags);
- if (skb_queue_len (&apriv->txq)) {
+ if (!skb_queue_empty(&apriv->txq)) {
spin_unlock_irqrestore(&apriv->aux_lock,flags);
mpi_send_packet (dev);
} else {
}
} else {
OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
- printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" );
+ airo_print_err(apriv->dev->name, "Unallocated FID was "
+ "used to xmit" );
}
}
exittx:
if ( status & ~STATUS_INTS & ~IGNORE_INTS )
- printk( KERN_WARNING "airo: Got weird status %x\n",
+ airo_print_warn(apriv->dev->name, "Got weird status %x",
status & ~STATUS_INTS & ~IGNORE_INTS );
}
up(&ai->sem);
if (rc)
- printk(KERN_ERR "%s: Cannot enable MAC, err=%d\n",
- __FUNCTION__,rc);
+ airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
+ __FUNCTION__, rc);
return rc;
}
int len = 0;
struct sk_buff *skb;
char *buffer;
-#ifdef MICSUPPORT
int off = 0;
MICBuffer micbuf;
-#endif
memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
/* Make sure we got something */
goto badrx;
}
buffer = skb_put(skb,len);
-#ifdef MICSUPPORT
memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2);
if (ai->micstats.enabled) {
memcpy(&micbuf,
dev_kfree_skb_irq (skb);
goto badrx;
}
-#else
- memcpy(buffer, ai->rxfids[0].virtual_host_addr, len);
-#endif
#ifdef WIRELESS_SPY
if (ai->spy_data.spy_number > 0) {
char *sa;
if (ai->wifidev == NULL)
hdr.len = 0;
len = le16_to_cpu(hdr.len);
- if (len > 2312) {
- printk( KERN_ERR "airo: Bad size %d\n", len );
+ if (len > AIRO_DEF_MTU) {
+ airo_print_err(ai->dev->name, "Bad size %d", len);
goto badrx;
}
if (len == 0)
if (gap <= 8)
ptr += gap;
else
- printk(KERN_ERR
- "airo: gaplen too big. Problems will follow...\n");
+ airo_print_err(ai->dev->name,
+ "gaplen too big. Problems will follow...");
}
memcpy ((char *)buffer + hdrlen, ptr, len);
ptr += len;
wstats.noise = ai->wstats.qual.noise;
wstats.updated = IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
+ | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(ai->dev, sa, &wstats);
}
int rc;
memset( &mySsid, 0, sizeof( mySsid ) );
- if (ai->flash) {
- kfree (ai->flash);
- ai->flash = NULL;
- }
+ kfree (ai->flash);
+ ai->flash = NULL;
/* The NOP is the first step in getting the card going */
cmd.cmd = NOP;
if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
if (lock)
up(&ai->sem);
- printk(KERN_ERR "airo: Error checking for AUX port\n");
+ airo_print_err(ai->dev->name, "Error checking for AUX port");
return ERROR;
}
if (!aux_bap || rsp.status & 0xff00) {
ai->bap_read = fast_bap_read;
- printk(KERN_DEBUG "airo: Doing fast bap_reads\n");
+ airo_print_dbg(ai->dev->name, "Doing fast bap_reads");
} else {
ai->bap_read = aux_bap_read;
- printk(KERN_DEBUG "airo: Doing AUX bap_reads\n");
+ airo_print_dbg(ai->dev->name, "Doing AUX bap_reads");
}
}
if (lock)
tdsRssiRid rssi_rid;
CapabilityRid cap_rid;
- if (ai->APList) {
- kfree(ai->APList);
- ai->APList = NULL;
- }
- if (ai->SSID) {
- kfree(ai->SSID);
- ai->SSID = NULL;
- }
+ kfree(ai->APList);
+ ai->APList = NULL;
+ kfree(ai->SSID);
+ ai->SSID = NULL;
// general configuration (read/modify/write)
status = readConfigRid(ai, lock);
if ( status != SUCCESS ) return ERROR;
memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
}
else {
- if (ai->rssi) {
- kfree(ai->rssi);
- ai->rssi = NULL;
- }
+ kfree(ai->rssi);
+ ai->rssi = NULL;
if (cap_rid.softCap & 8)
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
- printk(KERN_WARNING "airo: unknown received signal level scale\n");
+ airo_print_warn(ai->dev->name, "unknown received signal "
+ "level scale");
}
ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
ai->config.authType = AUTH_OPEN;
ai->config.modulation = MOD_CCK;
-#ifdef MICSUPPORT
if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
(micsetup(ai) == SUCCESS)) {
ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
}
-#endif
/* Save off the MAC */
for( i = 0; i < ETH_ALEN; i++ ) {
status = enable_MAC(ai, &rsp, lock);
if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
- printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+ airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
+ " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
return ERROR;
}
}
if ( max_tries == -1 ) {
- printk( KERN_ERR
- "airo: Max tries exceeded when issueing command\n" );
+ airo_print_err(ai->dev->name,
+ "Max tries exceeded when issueing command");
if (IN4500(ai, COMMAND) & COMMAND_BUSY)
OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
return ERROR;
pRsp->rsp1 = IN4500(ai, RESP1);
pRsp->rsp2 = IN4500(ai, RESP2);
if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) {
- printk (KERN_ERR "airo: cmd= %x\n", pCmd->cmd);
- printk (KERN_ERR "airo: status= %x\n", pRsp->status);
- printk (KERN_ERR "airo: Rsp0= %x\n", pRsp->rsp0);
- printk (KERN_ERR "airo: Rsp1= %x\n", pRsp->rsp1);
- printk (KERN_ERR "airo: Rsp2= %x\n", pRsp->rsp2);
+ airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd);
+ airo_print_err(ai->dev->name, "status= %x\n", pRsp->status);
+ airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0);
+ airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1);
+ airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2);
}
// clear stuck command busy if necessary
}
} else if ( status & BAP_ERR ) {
/* invalid rid or offset */
- printk( KERN_ERR "airo: BAP error %x %d\n",
+ airo_print_err(ai->dev->name, "BAP error %x %d",
status, whichbap );
return ERROR;
} else if (status & BAP_DONE) { // success
return SUCCESS;
}
if ( !(max_tries--) ) {
- printk( KERN_ERR
- "airo: BAP setup error too many retries\n" );
+ airo_print_err(ai->dev->name,
+ "airo: BAP setup error too many retries\n");
return ERROR;
}
// -- PC4500 missed it, try again
len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2;
if ( len <= 2 ) {
- printk( KERN_ERR
- "airo: Rid %x has a length of %d which is too short\n",
+ airo_print_err(ai->dev->name,
+ "Rid %x has a length of %d which is too short",
(int)rid, (int)len );
rc = ERROR;
goto done;
Cmd cmd;
Resp rsp;
- if (test_bit(FLAG_ENABLED, &ai->flags))
- printk(KERN_ERR
- "%s: MAC should be disabled (rid=%04x)\n",
+ if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
+ airo_print_err(ai->dev->name,
+ "%s: MAC should be disabled (rid=%04x)",
__FUNCTION__, rid);
memset(&cmd, 0, sizeof(cmd));
memset(&rsp, 0, sizeof(rsp));
&ai->config_desc.rid_desc, sizeof(Rid));
if (len < 4 || len > 2047) {
- printk(KERN_ERR "%s: len=%d\n",__FUNCTION__,len);
+ airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
rc = -1;
} else {
memcpy((char *)ai->config_desc.virtual_host_addr,
rc = issuecommand(ai, &cmd, &rsp);
if ((rc & 0xff00) != 0) {
- printk(KERN_ERR "%s: Write rid Error %d\n",
- __FUNCTION__,rc);
- printk(KERN_ERR "%s: Cmd=%04x\n",
- __FUNCTION__,cmd.cmd);
+ airo_print_err(ai->dev->name, "%s: Write rid Error %d",
+ __FUNCTION__, rc);
+ airo_print_err(ai->dev->name, "%s: Cmd=%04x",
+ __FUNCTION__, cmd.cmd);
}
if ((rsp.status & 0x7f00))
len >>= 16;
if (len <= ETH_ALEN * 2) {
- printk( KERN_WARNING "Short packet %d\n", len );
+ airo_print_warn(ai->dev->name, "Short packet %d", len);
return ERROR;
}
len -= ETH_ALEN * 2;
-#ifdef MICSUPPORT
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
(ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
return ERROR;
miclen = sizeof(pMic);
}
-#endif
-
// packet is destination[6], source[6], payload[len-12]
// write the payload length and dst/src/payload
if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
}
if (len < hdrlen) {
- printk( KERN_WARNING "Short packet %d\n", len );
+ airo_print_warn(ai->dev->name, "Short packet %d", len);
return ERROR;
}
StatusRid status_rid;
int i;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
data = (struct proc_data *)file->private_data;
if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
int i, j;
u32 *vals = stats.vals;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
data = (struct proc_data *)file->private_data;
if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
i*4<stats.len; i++){
if (!statsLabels[i]) continue;
if (j+strlen(statsLabels[i])+16>4096) {
- printk(KERN_WARNING
- "airo: Potentially disasterous buffer overflow averted!\n");
+ airo_print_warn(apriv->dev->name,
+ "Potentially disasterous buffer overflow averted!");
break;
}
j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]);
}
if (i*4>=stats.len){
- printk(KERN_WARNING
- "airo: Got a short rid\n");
+ airo_print_warn(apriv->dev->name, "Got a short rid");
}
data->readlen = j;
return 0;
line += 14;
v = get_dec_u16(line, &i, 4);
- v = (v<0) ? 0 : ((v>2312) ? 2312 : v);
+ v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
ai->config.rtsThres = (u16)v;
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
line += 15;
v = get_dec_u16(line, &i, 4);
- v = (v<256) ? 256 : ((v>2312) ? 2312 : v);
+ v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
v = v & 0xfffe; /* Make sure its even */
ai->config.fragThresh = (u16)v;
set_bit (FLAG_COMMIT, &ai->flags);
case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break;
case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break;
case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break;
- default:
- printk( KERN_WARNING "airo: Unknown modulation\n" );
+ default: airo_print_warn(ai->dev->name, "Unknown modulation");
}
} else if (!strncmp(line, "Preamble: ", 10)) {
line += 10;
case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break;
case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break;
case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break;
- default: printk(KERN_WARNING "airo: Unknown preamble\n");
+ default: airo_print_warn(ai->dev->name, "Unknown preamble");
}
} else {
- printk( KERN_WARNING "Couldn't figure out %s\n", line );
+ airo_print_warn(ai->dev->name, "Couldn't figure out %s", line);
}
while( line[0] && line[0] != '\n' ) line++;
if ( line[0] ) line++;
struct airo_info *ai = dev->priv;
int i;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
data = (struct proc_data *)file->private_data;
if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
return -ENOMEM;
}
- if ((data->wbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
+ if ((data->wbuffer = kzalloc( 2048, GFP_KERNEL )) == NULL) {
kfree (data->rbuffer);
kfree (file->private_data);
return -ENOMEM;
}
- memset( data->wbuffer, 0, 2048 );
data->maxwritelen = 2048;
data->on_close = proc_config_on_close;
enable_MAC(ai, &rsp, 1);
}
-inline static u8 hexVal(char c) {
+static inline u8 hexVal(char c) {
if (c>='0' && c<='9') return c -= '0';
if (c>='a' && c<='f') return c -= 'a'-10;
if (c>='A' && c<='F') return c -= 'A'-10;
wkr.len = sizeof(wkr);
wkr.kindex = 0xffff;
wkr.mac[0] = (char)index;
- if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index);
if (perm) ai->defindex = (char)index;
} else {
// We are actually setting the key
wkr.klen = keylen;
memcpy( wkr.key, key, keylen );
memcpy( wkr.mac, macaddr, ETH_ALEN );
- printk(KERN_INFO "Setting key %d\n", index);
}
- disable_MAC(ai, lock);
+ if (perm) disable_MAC(ai, lock);
writeWepKeyRid(ai, &wkr, perm, lock);
- enable_MAC(ai, &rsp, lock);
+ if (perm) enable_MAC(ai, &rsp, lock);
return 0;
}
}
j = 2;
} else {
- printk(KERN_ERR "airo: WepKey passed invalid key index\n");
+ airo_print_err(ai->dev->name, "WepKey passed invalid key index");
return;
}
int j=0;
int rc;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
memset(&wkr, 0, sizeof(wkr));
data = (struct proc_data *)file->private_data;
- if ((data->rbuffer = kmalloc( 180, GFP_KERNEL )) == NULL) {
+ if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
return -ENOMEM;
}
- memset(data->rbuffer, 0, 180);
data->writelen = 0;
data->maxwritelen = 80;
- if ((data->wbuffer = kmalloc( 80, GFP_KERNEL )) == NULL) {
+ if ((data->wbuffer = kzalloc( 80, GFP_KERNEL )) == NULL) {
kfree (data->rbuffer);
kfree (file->private_data);
return -ENOMEM;
}
- memset( data->wbuffer, 0, 80 );
data->on_close = proc_wepkey_on_close;
ptr = data->rbuffer;
char *ptr;
SsidRid SSID_rid;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
data = (struct proc_data *)file->private_data;
if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
}
data->writelen = 0;
data->maxwritelen = 33*3;
- if ((data->wbuffer = kmalloc( 33*3, GFP_KERNEL )) == NULL) {
+ if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) {
kfree (data->rbuffer);
kfree (file->private_data);
return -ENOMEM;
}
- memset( data->wbuffer, 0, 33*3 );
data->on_close = proc_SSID_on_close;
readSsidRid(ai, &SSID_rid);
char *ptr;
APListRid APList_rid;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
data = (struct proc_data *)file->private_data;
if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
}
data->writelen = 0;
data->maxwritelen = 4*6*3;
- if ((data->wbuffer = kmalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
+ if ((data->wbuffer = kzalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
kfree (data->rbuffer);
kfree (file->private_data);
return -ENOMEM;
}
- memset( data->wbuffer, 0, data->maxwritelen );
data->on_close = proc_APList_on_close;
readAPListRid(ai, &APList_rid);
/* If doLoseSync is not 1, we won't do a Lose Sync */
int doLoseSync = -1;
- if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+ if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
- memset(file->private_data, 0, sizeof(struct proc_data));
data = (struct proc_data *)file->private_data;
if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
kfree (file->private_data);
static int proc_close( struct inode *inode, struct file *file )
{
- struct proc_data *data = (struct proc_data *)file->private_data;
- if ( data->on_close != NULL ) data->on_close( inode, file );
- if ( data->rbuffer ) kfree( data->rbuffer );
- if ( data->wbuffer ) kfree( data->wbuffer );
- kfree( data );
+ struct proc_data *data = file->private_data;
+
+ if (data->on_close != NULL)
+ data->on_close(inode, file);
+ kfree(data->rbuffer);
+ kfree(data->wbuffer);
+ kfree(data);
return 0;
}
cmd.cmd=HOSTSLEEP;
issuecommand(ai, &cmd, &rsp);
- pci_enable_wake(pdev, state, 1);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
pci_save_state(pdev);
- return pci_set_power_state(pdev, state);
+ return pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
static int airo_pci_resume(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
struct airo_info *ai = dev->priv;
Resp rsp;
+ pci_power_t prev_state = pdev->current_state;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- pci_enable_wake(pdev, ai->power, 0);
+ pci_enable_wake(pdev, PCI_D0, 0);
- if (ai->power > 1) {
+ if (prev_state != PCI_D1) {
reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
}
writeConfigRid(ai, 0);
enable_MAC(ai, &rsp, 0);
- ai->power = 0;
+ ai->power = PMSG_ON;
netif_device_attach(dev);
netif_wake_queue(dev);
enable_interrupts(ai);
airo_entry->gid = proc_gid;
for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
- printk( KERN_INFO
- "airo: Trying to configure ISA adapter at irq=%d io=0x%x\n",
- irq[i], io[i] );
+ airo_print_info("", "Trying to configure ISA adapter at irq=%d "
+ "io=0x%x", irq[i], io[i] );
if (init_airo_card( irq[i], io[i], 0, NULL ))
have_isa_dev = 1;
}
#ifdef CONFIG_PCI
- printk( KERN_INFO "airo: Probing for PCI adapters\n" );
+ airo_print_info("", "Probing for PCI adapters");
pci_register_driver(&airo_driver);
- printk( KERN_INFO "airo: Finished probing for PCI adapters\n" );
+ airo_print_info("", "Finished probing for PCI adapters");
#endif
/* Always exit with success, as we are a library module
static void __exit airo_cleanup_module( void )
{
while( airo_devices ) {
- printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name );
+ airo_print_info(airo_devices->dev->name, "Unregistering...\n");
stop_airo_card( airo_devices->dev, 1 );
}
#ifdef CONFIG_PCI
remove_proc_entry("aironet", proc_root_driver);
}
-#ifdef WIRELESS_EXT
/*
* Initial Wireless Extension code for Aironet driver by :
* Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
int channel = fwrq->m;
/* We should do a better check than that,
* based on the card capability !!! */
- if((channel < 1) || (channel > 16)) {
- printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
+ if((channel < 1) || (channel > 14)) {
+ airo_print_dbg(dev->name, "New channel value of %d is invalid!",
+ fwrq->m);
rc = -EINVAL;
} else {
readConfigRid(local, 1);
/* Yes ! We can set it !!! */
- local->config.channelSet = (u16)(channel - 1);
+ local->config.channelSet = (u16) channel;
set_bit (FLAG_COMMIT, &local->flags);
}
}
{
struct airo_info *local = dev->priv;
StatusRid status_rid; /* Card status info */
+ int ch;
readConfigRid(local, 1);
if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
else
readStatusRid(local, &status_rid, 1);
-#ifdef WEXT_USECHANNELS
- fwrq->m = ((int)status_rid.channel) + 1;
- fwrq->e = 0;
-#else
- {
- int f = (int)status_rid.channel;
- fwrq->m = frequency_list[f] * 100000;
+ ch = (int)status_rid.channel;
+ if((ch > 0) && (ch < 15)) {
+ fwrq->m = frequency_list[ch - 1] * 100000;
fwrq->e = 1;
+ } else {
+ fwrq->m = ch;
+ fwrq->e = 0;
}
-#endif
return 0;
}
/* If none, we may want to get the one that was set */
/* Push it out ! */
- dwrq->length = status_rid.SSIDlen + 1;
+ dwrq->length = status_rid.SSIDlen;
dwrq->flags = 1; /* active */
return 0;
Cmd cmd;
Resp rsp;
APListRid APList_rid;
- static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
+ static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
- else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
+ else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
+ !memcmp(off, awrq->sa_data, ETH_ALEN)) {
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LOSE_SYNC;
if (down_interruptible(&local->sem))
int rthr = vwrq->value;
if(vwrq->disabled)
- rthr = 2312;
- if((rthr < 0) || (rthr > 2312)) {
+ rthr = AIRO_DEF_MTU;
+ if((rthr < 0) || (rthr > AIRO_DEF_MTU)) {
return -EINVAL;
}
readConfigRid(local, 1);
readConfigRid(local, 1);
vwrq->value = local->config.rtsThres;
- vwrq->disabled = (vwrq->value >= 2312);
+ vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
vwrq->fixed = 1;
return 0;
int fthr = vwrq->value;
if(vwrq->disabled)
- fthr = 2312;
- if((fthr < 256) || (fthr > 2312)) {
+ fthr = AIRO_DEF_MTU;
+ if((fthr < 256) || (fthr > AIRO_DEF_MTU)) {
return -EINVAL;
}
fthr &= ~0x1; /* Get an even value - is it really needed ??? */
readConfigRid(local, 1);
vwrq->value = local->config.fragThresh;
- vwrq->disabled = (vwrq->value >= 2312);
+ vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
vwrq->fixed = 1;
return 0;
{
struct airo_info *local = dev->priv;
CapabilityRid cap_rid; /* Card capability info */
+ int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+ u16 currentAuthType = local->config.authType;
/* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1);
/* Copy the key in the driver */
memcpy(key.key, extra, dwrq->length);
/* Send the key to the card */
- set_wep_key(local, index, key.key, key.len, 1, 1);
+ set_wep_key(local, index, key.key, key.len, perm, 1);
}
/* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later)
if((index == current_index) && (key.len > 0) &&
(local->config.authType == AUTH_OPEN)) {
local->config.authType = AUTH_ENCRYPT;
- set_bit (FLAG_COMMIT, &local->flags);
}
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
- set_wep_key(local, index, NULL, 0, 1, 1);
+ set_wep_key(local, index, NULL, 0, perm, 1);
} else
/* Don't complain if only change the mode */
if(!dwrq->flags & IW_ENCODE_MODE) {
if(dwrq->flags & IW_ENCODE_OPEN)
local->config.authType = AUTH_ENCRYPT; // Only Wep
/* Commit the changes to flags if needed */
- if(dwrq->flags & IW_ENCODE_MODE)
+ if (local->config.authType != currentAuthType)
set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
}
return 0;
}
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended Encryption parameters
+ */
+static int airo_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ CapabilityRid cap_rid; /* Card capability info */
+ int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
+ u16 currentAuthType = local->config.authType;
+ int idx, key_len, alg = ext->alg, set_key = 1;
+ wep_key_t key;
+
+ /* Is WEP supported ? */
+ readCapabilityRid(local, &cap_rid, 1);
+ /* Older firmware doesn't support this...
+ if(!(cap_rid.softCap & 2)) {
+ return -EOPNOTSUPP;
+ } */
+ readConfigRid(local, 1);
+
+ /* Determine and validate the key index */
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ return -EINVAL;
+ idx--;
+ } else
+ idx = get_wep_key(local, 0xffff);
+
+ if (encoding->flags & IW_ENCODE_DISABLED)
+ alg = IW_ENCODE_ALG_NONE;
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ /* Only set transmit key index here, actual
+ * key is set below if needed.
+ */
+ set_wep_key(local, idx, NULL, 0, perm, 1);
+ set_key = ext->key_len > 0 ? 1 : 0;
+ }
+
+ if (set_key) {
+ /* Set the requested key first */
+ memset(key.key, 0, MAX_KEY_SIZE);
+ switch (alg) {
+ case IW_ENCODE_ALG_NONE:
+ key.len = 0;
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > MIN_KEY_SIZE) {
+ key.len = MAX_KEY_SIZE;
+ } else if (ext->key_len > 0) {
+ key.len = MIN_KEY_SIZE;
+ } else {
+ return -EINVAL;
+ }
+ key_len = min (ext->key_len, key.len);
+ memcpy(key.key, ext->key, key_len);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Send the key to the card */
+ set_wep_key(local, idx, key.key, key.len, perm, 1);
+ }
+
+ /* Read the flags */
+ if(encoding->flags & IW_ENCODE_DISABLED)
+ local->config.authType = AUTH_OPEN; // disable encryption
+ if(encoding->flags & IW_ENCODE_RESTRICTED)
+ local->config.authType = AUTH_SHAREDKEY; // Only Both
+ if(encoding->flags & IW_ENCODE_OPEN)
+ local->config.authType = AUTH_ENCRYPT; // Only Wep
+ /* Commit the changes to flags if needed */
+ if (local->config.authType != currentAuthType)
+ set_bit (FLAG_COMMIT, &local->flags);
+
+ return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended Encryption parameters
+ */
+static int airo_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ CapabilityRid cap_rid; /* Card capability info */
+ int idx, max_key_len;
+
+ /* Is it supported ? */
+ readCapabilityRid(local, &cap_rid, 1);
+ if(!(cap_rid.softCap & 2)) {
+ return -EOPNOTSUPP;
+ }
+ readConfigRid(local, 1);
+
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ return -EINVAL;
+ idx--;
+ } else
+ idx = get_wep_key(local, 0xffff);
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ /* Check encryption mode */
+ switch(local->config.authType) {
+ case AUTH_ENCRYPT:
+ encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+ break;
+ case AUTH_SHAREDKEY:
+ encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+ break;
+ default:
+ case AUTH_OPEN:
+ encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED;
+ break;
+ }
+ /* We can't return the key, so set the proper flag and return zero */
+ encoding->flags |= IW_ENCODE_NOKEY;
+ memset(extra, 0, 16);
+
+ /* Copy the key to the user buffer */
+ ext->key_len = get_wep_key(local, idx);
+ if (ext->key_len > 16) {
+ ext->key_len=0;
+ }
+
+ return 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended authentication parameters
+ */
+static int airo_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_param *param = &wrqu->param;
+ u16 currentAuthType = local->config.authType;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ /*
+ * airo does not use these parameters
+ */
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ if (param->value) {
+ /* Only change auth type if unencrypted */
+ if (currentAuthType == AUTH_OPEN)
+ local->config.authType = AUTH_ENCRYPT;
+ } else {
+ local->config.authType = AUTH_OPEN;
+ }
+
+ /* Commit the changes to flags if needed */
+ if (local->config.authType != currentAuthType)
+ set_bit (FLAG_COMMIT, &local->flags);
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG: {
+ /* FIXME: What about AUTH_OPEN? This API seems to
+ * disallow setting our auth to AUTH_OPEN.
+ */
+ if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+ local->config.authType = AUTH_SHAREDKEY;
+ } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ local->config.authType = AUTH_ENCRYPT;
+ } else
+ return -EINVAL;
+ break;
+
+ /* Commit the changes to flags if needed */
+ if (local->config.authType != currentAuthType)
+ set_bit (FLAG_COMMIT, &local->flags);
+ }
+
+ case IW_AUTH_WPA_ENABLED:
+ /* Silently accept disable of WPA */
+ if (param->value > 0)
+ return -EOPNOTSUPP;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended authentication parameters
+ */
+static int airo_get_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct airo_info *local = dev->priv;
+ struct iw_param *param = &wrqu->param;
+ u16 currentAuthType = local->config.authType;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_DROP_UNENCRYPTED:
+ switch (currentAuthType) {
+ case AUTH_SHAREDKEY:
+ case AUTH_ENCRYPT:
+ param->value = 1;
+ break;
+ default:
+ param->value = 0;
+ break;
+ }
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ switch (currentAuthType) {
+ case AUTH_SHAREDKEY:
+ param->value = IW_AUTH_ALG_SHARED_KEY;
+ break;
+ case AUTH_ENCRYPT:
+ default:
+ param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+ }
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ param->value = 0;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set Tx-Power
range->max_qual.qual = 100; /* % */
else
range->max_qual.qual = airo_get_max_quality(&cap_rid);
- range->max_qual.level = 0; /* 0 means we use dBm */
- range->max_qual.noise = 0;
- range->max_qual.updated = 0;
+ range->max_qual.level = 0x100 - 120; /* -120 dBm */
+ range->max_qual.noise = 0x100 - 120; /* -120 dBm */
/* Experimental measurements - boundary 11/5.5 Mb/s */
/* Note : with or without the (local->rssi), results
* are somewhat different. - Jean II */
if (local->rssi) {
- range->avg_qual.qual = 50; /* % */
- range->avg_qual.level = 186; /* -70 dBm */
+ range->avg_qual.qual = 50; /* % */
+ range->avg_qual.level = 0x100 - 70; /* -70 dBm */
} else {
range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
- range->avg_qual.level = 176; /* -80 dBm */
+ range->avg_qual.level = 0x100 - 80; /* -80 dBm */
}
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 0;
+ range->avg_qual.noise = 0x100 - 85; /* -85 dBm */
for(i = 0 ; i < 8 ; i++) {
range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
range->throughput = 1500 * 1000;
range->min_rts = 0;
- range->max_rts = 2312;
+ range->max_rts = AIRO_DEF_MTU;
range->min_frag = 256;
- range->max_frag = 2312;
+ range->max_frag = AIRO_DEF_MTU;
if(cap_rid.softCap & 2) {
// WEP: RC4 40 bits
if (local->rssi) {
qual[i].level = 0x100 - BSSList.dBm;
qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
- qual[i].updated = IW_QUAL_QUAL_UPDATED;
+ qual[i].updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
} else {
qual[i].level = (BSSList.dBm + 321) / 2;
qual[i].qual = 0;
- qual[i].updated = IW_QUAL_QUAL_INVALID;
+ qual[i].updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
}
qual[i].noise = local->wstats.qual.noise;
- qual[i].updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
if (BSSList.index == 0xffff)
break;
}
struct airo_info *ai = dev->priv;
Cmd cmd;
Resp rsp;
+ int wake = 0;
/* Note : you may have realised that, as this is a SET operation,
* this is privileged and therefore a normal user can't
* Jean II */
if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
+ if (down_interruptible(&ai->sem))
+ return -ERESTARTSYS;
+
+ /* If there's already a scan in progress, don't
+ * trigger another one. */
+ if (ai->scan_timeout > 0)
+ goto out;
+
/* Initiate a scan command */
+ ai->scan_timeout = RUN_AT(3*HZ);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd=CMD_LISTBSS;
- if (down_interruptible(&ai->sem))
- return -ERESTARTSYS;
issuecommand(ai, &cmd, &rsp);
- ai->scan_timestamp = jiffies;
- up(&ai->sem);
-
- /* At this point, just return to the user. */
+ wake = 1;
+out:
+ up(&ai->sem);
+ if (wake)
+ wake_up_interruptible(&ai->thr_wait);
return 0;
}
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
- iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+ /* iwe.u.freq.m containt the channel (starting 1), our
+ * frequency_list array start at index 0...
+ */
+ iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
if (ai->rssi) {
iwe.u.qual.level = 0x100 - bss->dBm;
iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
} else {
iwe.u.qual.level = (bss->dBm + 321) / 2;
iwe.u.qual.qual = 0;
- iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
+ iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_DBM;
}
iwe.u.qual.noise = ai->wstats.qual.noise;
- iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_UPDATED;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
/* Add encryption capability */
char *extra)
{
struct airo_info *ai = dev->priv;
- BSSListRid BSSList;
- int rc;
+ BSSListElement *net;
+ int err = 0;
char *current_ev = extra;
- /* When we are associated again, the scan has surely finished.
- * Just in case, let's make sure enough time has elapsed since
- * we started the scan. - Javier */
- if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) {
- /* Important note : we don't want to block the caller
- * until results are ready for various reasons.
- * First, managing wait queues is complex and racy
- * (there may be multiple simultaneous callers).
- * Second, we grab some rtnetlink lock before comming
- * here (in dev_ioctl()).
- * Third, the caller can wait on the Wireless Event
- * - Jean II */
+ /* If a scan is in-progress, return -EAGAIN */
+ if (ai->scan_timeout > 0)
return -EAGAIN;
- }
- ai->scan_timestamp = 0;
-
- /* There's only a race with proc_BSSList_open(), but its
- * consequences are begnign. So I don't bother fixing it - Javier */
- /* Try to read the first entry of the scan result */
- rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1);
- if((rc) || (BSSList.index == 0xffff)) {
- /* Client error, no scan results...
- * The caller need to restart the scan. */
- return -ENODATA;
- }
+ if (down_interruptible(&ai->sem))
+ return -EAGAIN;
- /* Read and parse all entries */
- while((!rc) && (BSSList.index != 0xffff)) {
+ list_for_each_entry (net, &ai->network_list, list) {
/* Translate to WE format this entry */
current_ev = airo_translate_scan(dev, current_ev,
extra + dwrq->length,
- &BSSList);
+ &net->bss);
/* Check if there is space for one more entry */
if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
/* Ask user space to try again with a bigger buffer */
- return -E2BIG;
+ err = -E2BIG;
+ goto out;
}
-
- /* Read next entry */
- rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
- &BSSList, sizeof(BSSList), 1);
}
+
/* Length of data */
dwrq->length = (current_ev - extra);
dwrq->flags = 0; /* todo */
- return 0;
+out:
+ up(&ai->sem);
+ return err;
}
/*------------------------------------------------------------------*/
(iw_handler) airo_get_encode, /* SIOCGIWENCODE */
(iw_handler) airo_set_power, /* SIOCSIWPOWER */
(iw_handler) airo_get_power, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWGENIE */
+ (iw_handler) NULL, /* SIOCGIWGENIE */
+ (iw_handler) airo_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) airo_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
};
/* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
.get_wireless_stats = airo_get_wireless_stats,
};
-#endif /* WIRELESS_EXT */
-
/*
* This defines the configuration part of the Wireless Extensions
* Note : irq and spinlock protection will occur in the subroutines
int rc = 0;
struct airo_info *ai = (struct airo_info *)dev->priv;
- if (ai->power)
+ if (ai->power.event)
return 0;
switch (cmd) {
return rc;
}
-#ifdef WIRELESS_EXT
/*
* Get the Wireless stats out of the driver
* Note : irq and spinlock protection will occur in the subroutines
/* Get stats out of the card */
clear_bit(JOB_WSTATS, &local->flags);
- if (local->power) {
+ if (local->power.event) {
up(&local->sem);
return;
}
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
}
- local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
if (status_rid.len >= 124) {
local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
- local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
+ local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
} else {
local->wstats.qual.noise = 0;
- local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+ local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM;
}
/* Packets discarded in the wireless adapter due to wireless
local->wstats.miss.beacon = vals[34];
}
-struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
{
struct airo_info *local = dev->priv;
return &local->wstats;
}
-#endif /* WIRELESS_EXT */
#ifdef CISCO_EXT
/*
case AIROGSTAT: ridcode = RID_STATUS; break;
case AIROGSTATSD32: ridcode = RID_STATSDELTA; break;
case AIROGSTATSC32: ridcode = RID_STATS; break;
-#ifdef MICSUPPORT
case AIROGMICSTATS:
if (copy_to_user(comp->data, &ai->micstats,
min((int)comp->len,(int)sizeof(ai->micstats))))
return -EFAULT;
return 0;
-#endif
case AIRORRID: ridcode = comp->ridnum; break;
default:
return -EINVAL;
static int writerids(struct net_device *dev, aironet_ioctl *comp) {
struct airo_info *ai = dev->priv;
int ridcode;
-#ifdef MICSUPPORT
int enabled;
-#endif
Resp rsp;
static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
unsigned char *iobuf;
PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1);
-#ifdef MICSUPPORT
enabled = ai->micstats.enabled;
memset(&ai->micstats,0,sizeof(ai->micstats));
ai->micstats.enabled = enabled;
-#endif
if (copy_to_user(comp->data, iobuf,
min((int)comp->len, (int)RIDSIZE))) {
* Flash command switch table
*/
-int flashcard(struct net_device *dev, aironet_ioctl *comp) {
+static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
int z;
- int cmdreset(struct airo_info *);
- int setflashmode(struct airo_info *);
- int flashgchar(struct airo_info *,int,int);
- int flashpchar(struct airo_info *,int,int);
- int flashputbuf(struct airo_info *);
- int flashrestart(struct airo_info *,struct net_device *);
/* Only super-user can modify flash */
if (!capable(CAP_NET_ADMIN))
* card.
*/
-int cmdreset(struct airo_info *ai) {
+static int cmdreset(struct airo_info *ai) {
disable_MAC(ai, 1);
if(!waitbusy (ai)){
- printk(KERN_INFO "Waitbusy hang before RESET\n");
+ airo_print_info(ai->dev->name, "Waitbusy hang before RESET");
return -EBUSY;
}
ssleep(1); /* WAS 600 12/7/00 */
if(!waitbusy (ai)){
- printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
+ airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET");
return -EBUSY;
}
return 0;
* mode
*/
-int setflashmode (struct airo_info *ai) {
+static int setflashmode (struct airo_info *ai) {
set_bit (FLAG_FLASHING, &ai->flags);
OUT4500(ai, SWS0, FLASH_COMMAND);
if(!waitbusy(ai)) {
clear_bit (FLAG_FLASHING, &ai->flags);
- printk(KERN_INFO "Waitbusy hang after setflash mode\n");
+ airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode");
return -EIO;
}
return 0;
* x 50us for echo .
*/
-int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
int echo;
int waittime;
/* timeout for busy clear wait */
if(waittime <= 0 ){
- printk(KERN_INFO "flash putchar busywait timeout! \n");
+ airo_print_info(ai->dev->name, "flash putchar busywait timeout!");
return -EBUSY;
}
* Get a character from the card matching matchbyte
* Step 3)
*/
-int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
int rchar;
unsigned char rbyte=0;
* send to the card
*/
-int flashputbuf(struct airo_info *ai){
+static int flashputbuf(struct airo_info *ai){
int nwords;
/* Write stuff */
/*
*
*/
-int flashrestart(struct airo_info *ai,struct net_device *dev){
+static int flashrestart(struct airo_info *ai,struct net_device *dev){
int i,status;
ssleep(1); /* Added 12/7/00 */
if (!test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ ) {
ai->fids[i] = transmit_allocate
- ( ai, 2312, i >= MAX_FIDS / 2 );
+ ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 );
}
ssleep(1); /* Added 12/7/00 */