#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
infront of the label, that statistic will not be included in the list
of statistics in the /proc filesystem */
-#define IGNLABEL(comment) 0
+#define IGNLABEL(comment) NULL
static char *statsLabels[] = {
"RxOverrun",
IGNLABEL("RxPlcpCrcErr"),
#define AIROGMICRID 11
#define AIROGMICSTATS 12
#define AIROGFLAGS 13
+#define AIROGID 14
#define AIRORRID 15
+#define AIRORSWVERSION 17
/* Leave gap of 40 commands after AIROGSTATSD32 for future */
#define AUXMEMSIZE (256 * 1024)
typedef struct aironet_ioctl {
- unsigned short command; // What to do
+ unsigned short command; // What to do
unsigned short len; // Len of data
- unsigned char *data; // d-data
+ unsigned short ridnum; // rid number
+ unsigned char __user *data; // d-data
} aironet_ioctl;
+
+static char *swversion = "2.1";
#endif /* CISCO_EXT */
#define NUM_MODULES 2
static int mpi_send_packet (struct net_device *dev);
static void mpi_unmap_card(struct pci_dev *pci);
static void mpi_receive_802_3(struct airo_info *ai);
+static void mpi_receive_802_11(struct airo_info *ai);
static int waitbusy (struct airo_info *ai);
static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
SsidRid *SSID;
APListRid *APList;
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
+ u32 pci_state[16];
+ char proc_name[IFNAMSIZ];
};
static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
if (!test_bit (FLAG_COMMIT, &ai->flags))
return SUCCESS;
- clear_bit (FLAG_COMMIT | FLAG_RESET, &ai->flags);
+ clear_bit (FLAG_COMMIT, &ai->flags);
+ clear_bit (FLAG_RESET, &ai->flags);
checkThrottle(ai);
cfgr = ai->config;
if ((skb = skb_dequeue(&ai->txq)) == 0) {
printk (KERN_ERR
- "airo_mpi: %s: Dequeue'd zero in send_packet()\n",
+ "airo: %s: Dequeue'd zero in send_packet()\n",
__FUNCTION__);
return 0;
}
ai->txfids[0].tx_desc.eoc = 1;
ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);
- memcpy((char *)ai->txfids[0].card_ram_off,
- (char *)&ai->txfids[0].tx_desc, sizeof(TxFid));
-
/*
* Magic, the cards firmware needs a length count (2 bytes) in the host buffer
* right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
return ERROR;
*payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic));
+ ai->txfids[0].tx_desc.len += sizeof(pMic);
/* copy data into airo dma buffer */
memcpy (sendbuf, buffer, sizeof(etherHead));
buffer += sizeof(etherHead);
memcpy(sendbuf, buffer, len);
}
+ memcpy((char *)ai->txfids[0].card_ram_off,
+ (char *)&ai->txfids[0].tx_desc, sizeof(TxFid));
+
OUT4500(ai, EVACK, 8);
dev_kfree_skb_any(skb);
struct airo_info *priv = dev->priv;
u32 *fids = priv->fids;
+ if (test_bit(FLAG_MPI, &priv->flags)) {
+ /* Not implemented yet for MPI350 */
+ netif_stop_queue(dev);
+ return -ENETDOWN;
+ }
+
if ( skb == NULL ) {
printk( KERN_ERR "airo: skb == NULL!!!\n" );
return 0;
{
struct airo_info *local = dev->priv;
- /* Get stats out of the card if available */
- if (down_trylock(&local->sem) != 0) {
- set_bit(JOB_STATS, &local->flags);
- wake_up_interruptible(&local->thr_wait);
- } else
- airo_read_stats(local);
+ if (!test_bit(JOB_STATS, &local->flags)) {
+ /* Get stats out of the card if available */
+ if (down_trylock(&local->sem) != 0) {
+ set_bit(JOB_STATS, &local->flags);
+ wake_up_interruptible(&local->thr_wait);
+ } else
+ airo_read_stats(local);
+ }
return &local->stats;
}
void stop_airo_card( struct net_device *dev, int freeres )
{
struct airo_info *ai = dev->priv;
+
+ set_bit(FLAG_RADIO_DOWN, &ai->flags);
+ disable_MAC(ai, 1);
disable_interrupts(ai);
free_irq( dev->irq, dev );
takedown_proc_entry( dev, ai );
if (ai->wifidev) {
unregister_netdev(ai->wifidev);
free_netdev(ai->wifidev);
- ai->wifidev = 0;
+ ai->wifidev = NULL;
}
clear_bit(FLAG_REGISTERED, &ai->flags);
}
* Clean out tx queue
*/
if (test_bit(FLAG_MPI, &ai->flags) && skb_queue_len (&ai->txq) > 0) {
- struct sk_buff *skb = 0;
+ struct sk_buff *skb = NULL;
for (;(skb = skb_dequeue(&ai->txq));)
dev_kfree_skb(skb);
}
cmd.parm0 = FID_TX;
cmd.parm1 = (ai->txfids[0].card_ram_off - ai->pciaux);
cmd.parm2 = MPI_MAX_FIDS;
- rc=issuecommand(ai, &cmd, &rsp);
- if (rc != SUCCESS) {
- printk(KERN_ERR "airo: Couldn't allocate TX FID\n");
- return rc;
- }
for (i=0; i<MPI_MAX_FIDS; i++) {
ai->txfids[i].tx_desc.valid = 1;
memcpy((char *)ai->txfids[i].card_ram_off,
&ai->txfids[i].tx_desc, sizeof(TxFid));
}
+ ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */
+
+ rc=issuecommand(ai, &cmd, &rsp);
+ if (rc != SUCCESS) {
+ printk(KERN_ERR "airo: Couldn't allocate TX FID\n");
+ return rc;
+ }
/* Alloc card Rid descriptor */
memset(&rsp,0,sizeof(rsp));
static void wifi_setup(struct net_device *dev)
{
- dev->hard_header = 0;
- dev->rebuild_header = 0;
- dev->hard_header_cache = 0;
- dev->header_cache_update= 0;
+ dev->hard_header = NULL;
+ dev->rebuild_header = NULL;
+ dev->hard_header_cache = NULL;
+ dev->header_cache_update= NULL;
dev->hard_header_parse = wll_header_parse;
dev->hard_start_xmit = &airo_start_xmit11;
return dev;
}
-int reset_mpi_card( struct net_device *dev , int lock) {
+int reset_card( struct net_device *dev , int lock) {
struct airo_info *ai = dev->priv;
if (lock && down_interruptible(&ai->sem))
}
ai = dev->priv;
- ai->wifidev = 0;
+ ai->wifidev = NULL;
ai->flags = 0;
if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
printk(KERN_DEBUG "airo: Found an MPI350 card\n");
}
if (test_bit(FLAG_MPI,&ai->flags))
- reset_mpi_card (dev, 1);
+ reset_card (dev, 1);
rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev );
if (rc) {
printk(KERN_ERR "airo: Couldn't register_netdev\n");
goto err_out_map;
}
- if (!test_bit(FLAG_MPI,&ai->flags))
- ai->wifidev = init_wifidev(ai, dev);
+ 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",
struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia )
{
- return _init_airo_card ( irq, port, is_pcmcia, 0);
+ return _init_airo_card ( irq, port, is_pcmcia, NULL);
}
EXPORT_SYMBOL(init_airo_card);
int i;
struct airo_info *ai = dev->priv;
- if (reset_mpi_card (dev, 1))
+ if (reset_card (dev, 1))
return -1;
if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) {
u16 *buffer;
if (test_bit(FLAG_MPI,&apriv->flags)) {
- mpi_receive_802_3(apriv);
+ if (test_bit(FLAG_802_11, &apriv->flags))
+ mpi_receive_802_11(apriv);
+ else
+ mpi_receive_802_3(apriv);
OUT4500(apriv, EVACK, EV_RX);
goto exitrx;
}
} else
hdrlen = ETH_ALEN * 2;
- skb = dev_alloc_skb( len + hdrlen + 2 );
+ skb = dev_alloc_skb( len + hdrlen + 2 + 2 );
if ( !skb ) {
apriv->stats.rx_dropped++;
goto badrx;
}
+ skb_reserve(skb, 2); /* This way the IP header is aligned */
buffer = (u16*)skb_put (skb, len + hdrlen);
if (test_bit(FLAG_802_11, &apriv->flags)) {
buffer[0] = fc;
}
static void enable_interrupts( struct airo_info *ai ) {
- /* Reset the status register */
- u16 status = IN4500( ai, EVSTAT );
- OUT4500( ai, EVACK, status );
/* Enable the interrupts */
OUT4500( ai, EVINTEN, STATUS_INTS );
- /* Note there is a race condition between the last two lines that
- I don't know how to get rid of right now... */
}
static void disable_interrupts( struct airo_info *ai ) {
memcpy(buffer + ETH_ALEN * 2,
ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off,
len - ETH_ALEN * 2 - off);
- if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off)) {
+ if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) {
badmic:
dev_kfree_skb_irq (skb);
goto badrx;
}
}
+void mpi_receive_802_11 (struct airo_info *ai)
+{
+ RxFid rxd;
+ struct sk_buff *skb = NULL;
+ u16 fc, len, hdrlen = 0;
+#pragma pack(1)
+ struct {
+ u16 status, len;
+ u8 rssi[2];
+ u8 rate;
+ u8 freq;
+ u16 tmp[4];
+ } hdr;
+#pragma pack()
+ u16 gap;
+ u16 *buffer;
+ char *ptr = ai->rxfids[0].virtual_host_addr+4;
+
+ memcpy ((char *)&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
+ memcpy ((char *)&hdr, ptr, sizeof(hdr));
+ ptr += sizeof(hdr);
+ /* Bad CRC. Ignore packet */
+ if (le16_to_cpu(hdr.status) & 2)
+ hdr.len = 0;
+ 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 );
+ goto badrx;
+ }
+ if (len == 0)
+ goto badrx;
+
+ memcpy ((char *)&fc, ptr, sizeof(fc));
+ fc = le16_to_cpu(fc);
+ switch (fc & 0xc) {
+ case 4:
+ if ((fc & 0xe0) == 0xc0)
+ hdrlen = 10;
+ else
+ hdrlen = 16;
+ break;
+ case 8:
+ if ((fc&0x300)==0x300){
+ hdrlen = 30;
+ break;
+ }
+ default:
+ hdrlen = 24;
+ }
+
+ skb = dev_alloc_skb( len + hdrlen + 2 );
+ if ( !skb ) {
+ ai->stats.rx_dropped++;
+ goto badrx;
+ }
+ buffer = (u16*)skb_put (skb, len + hdrlen);
+ memcpy ((char *)buffer, ptr, hdrlen);
+ ptr += hdrlen;
+ if (hdrlen == 24)
+ ptr += 6;
+ memcpy ((char *)&gap, ptr, sizeof(gap));
+ ptr += sizeof(gap);
+ gap = le16_to_cpu(gap);
+ if (gap) {
+ if (gap <= 8)
+ ptr += gap;
+ else
+ printk(KERN_ERR
+ "airo: gaplen too big. Problems will follow...\n");
+ }
+ memcpy ((char *)buffer + hdrlen, ptr, len);
+ ptr += len;
+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
+ if (ai->spy_data.spy_number > 0) {
+ char *sa;
+ struct iw_quality wstats;
+ /* Prepare spy data : addr + qual */
+ sa = (char*)buffer + 10;
+ wstats.qual = hdr.rssi[0];
+ if (ai->rssi)
+ wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
+ else
+ wstats.level = (hdr.rssi[1] + 321) / 2;
+ wstats.updated = 3;
+ /* Update spy records */
+ wireless_spy_update(ai->dev, sa, &wstats);
+ }
+#endif /* IW_WIRELESS_SPY */
+ skb->mac.raw = skb->data;
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->dev = ai->wifidev;
+ skb->protocol = htons(ETH_P_802_2);
+ skb->dev->last_rx = jiffies;
+ skb->ip_summed = CHECKSUM_NONE;
+ netif_rx( skb );
+badrx:
+ if (rxd.valid == 0) {
+ rxd.valid = 1;
+ rxd.rdy = 0;
+ rxd.len = PKTSIZE;
+ memcpy (ai->rxfids[0].card_ram_off, (char *)&rxd, sizeof(rxd));
+ }
+}
+
static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
{
Cmd cmd;
status = readCapabilityRid(ai, &cap_rid, lock);
if ( status != SUCCESS ) return ERROR;
- if (test_bit(FLAG_MPI, &ai->flags) &&
- strcmp (cap_rid.prodVer, "5.00.01") &&
- strcmp (cap_rid.prodVer, "5.00.03") &&
- strcmp (cap_rid.prodVer, "5b00.08"))
- printk(KERN_ERR "airo: Firmware version %s is not supported. Use it at your own risk!\n", cap_rid.prodVer);
-
status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
if ( status == SUCCESS ) {
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
/* Check to see if there are any insmod configured
rates to add */
- if ( rates ) {
+ if ( rates[0] ) {
int i = 0;
- if ( rates[0] ) memset(ai->config.rates,0,sizeof(ai->config.rates));
+ memset(ai->config.rates,0,sizeof(ai->config.rates));
for( i = 0; i < 8 && rates[i]; i++ ) {
ai->config.rates[i] = rates[i];
}
static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
// Im really paranoid about letting it run forever!
int max_tries = 600000;
- u16 cmd;
if (IN4500(ai, EVSTAT) & EV_CMD)
OUT4500(ai, EVACK, EV_CMD);
OUT4500(ai, PARAM1, pCmd->parm1);
OUT4500(ai, PARAM2, pCmd->parm2);
OUT4500(ai, COMMAND, pCmd->cmd);
- while ( max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0 &&
- (cmd = IN4500(ai, COMMAND)) != 0 )
- if (cmd == pCmd->cmd)
- // PC4500 didn't notice command, try again
- OUT4500(ai, COMMAND, pCmd->cmd);
- if ( max_tries == -1 ) {
- printk( KERN_ERR
- "airo: Max tries exceeded when issueing command\n" );
- return ERROR;
- }
while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
+ if ((IN4500(ai, COMMAND)) == pCmd->cmd)
+ // PC4500 didn't notice command, try again
+ OUT4500(ai, COMMAND, pCmd->cmd);
if (!in_atomic() && (max_tries & 255) == 0)
schedule();
}
+
if ( max_tries == -1 ) {
printk( KERN_ERR
- "airo: Max tries exceeded waiting for command\n" );
- return ERROR;
+ "airo: Max tries exceeded when issueing command\n" );
+ if (IN4500(ai, COMMAND) & COMMAND_BUSY)
+ OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
+ return ERROR;
}
+
// command completed
pRsp->status = IN4500(ai, STATUS);
pRsp->rsp0 = IN4500(ai, RESP0);
Resp rsp;
if (test_bit(FLAG_ENABLED, &ai->flags))
- printk(KERN_ERR "%s: MAC should be disabled (rid=%d)\n",
+ printk(KERN_ERR
+ "%s: MAC should be disabled (rid=%04x)\n",
__FUNCTION__, rid);
memset(&cmd, 0, sizeof(cmd));
memset(&rsp, 0, sizeof(rsp));
ai->config_desc.rid_desc.valid = 1;
- ai->config_desc.rid_desc.len = RIDSIZE;
+ ai->config_desc.rid_desc.len = *((u16 *)pBuf);
ai->config_desc.rid_desc.rid = 0;
cmd.cmd = CMD_WRITERID;
*/
static ssize_t proc_read( struct file *file,
- char *buffer,
+ char __user *buffer,
size_t len,
loff_t *offset);
static ssize_t proc_write( struct file *file,
- const char *buffer,
+ const char __user *buffer,
size_t len,
loff_t *offset );
static int proc_close( struct inode *inode, struct file *file );
.release = proc_close
};
-static struct proc_dir_entry *airo_entry = 0;
+static struct proc_dir_entry *airo_entry;
struct proc_data {
int release_buffer;
struct airo_info *apriv ) {
struct proc_dir_entry *entry;
/* First setup the device directory */
- apriv->proc_entry = create_proc_entry(dev->name,
+ strcpy(apriv->proc_name,dev->name);
+ apriv->proc_entry = create_proc_entry(apriv->proc_name,
S_IFDIR|airo_perm,
airo_entry);
apriv->proc_entry->uid = proc_uid;
remove_proc_entry("APList",apriv->proc_entry);
remove_proc_entry("BSSList",apriv->proc_entry);
remove_proc_entry("WepKey",apriv->proc_entry);
- remove_proc_entry(dev->name,airo_entry);
+ remove_proc_entry(apriv->proc_name,airo_entry);
return 0;
}
* to supply the data.
*/
static ssize_t proc_read( struct file *file,
- char *buffer,
+ char __user *buffer,
size_t len,
loff_t *offset )
{
- int i;
- int pos;
+ loff_t pos = *offset;
struct proc_data *priv = (struct proc_data*)file->private_data;
- if( !priv->rbuffer ) return -EINVAL;
+ if (!priv->rbuffer)
+ return -EINVAL;
- pos = *offset;
- for( i = 0; i+pos < priv->readlen && i < len; i++ ) {
- if (put_user( priv->rbuffer[i+pos], buffer+i ))
- return -EFAULT;
- }
- *offset += i;
- return i;
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= priv->readlen)
+ return 0;
+ if (len > priv->readlen - pos)
+ len = priv->readlen - pos;
+ if (copy_to_user(buffer, priv->rbuffer + pos, len))
+ return -EFAULT;
+ *offset = pos + len;
+ return len;
}
/*
* to supply the data.
*/
static ssize_t proc_write( struct file *file,
- const char *buffer,
+ const char __user *buffer,
size_t len,
loff_t *offset )
{
- int i;
- int pos;
+ loff_t pos = *offset;
struct proc_data *priv = (struct proc_data*)file->private_data;
- if ( !priv->wbuffer ) {
+ if (!priv->wbuffer)
return -EINVAL;
- }
- pos = *offset;
-
- for( i = 0; i + pos < priv->maxwritelen &&
- i < len; i++ ) {
- if (get_user( priv->wbuffer[i+pos], buffer + i ))
- return -EFAULT;
- }
- if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos;
- *offset += i;
- return i;
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= priv->maxwritelen)
+ return 0;
+ if (len > priv->maxwritelen - pos)
+ len = priv->maxwritelen - pos;
+ if (copy_from_user(priv->wbuffer + pos, buffer, len))
+ return -EFAULT;
+ if ( pos + len > priv->writelen )
+ priv->writelen = len + file->f_pos;
+ *offset = pos + len;
+ return len;
}
static int proc_status_open( struct inode *inode, struct file *file ) {
(data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
index = data->wbuffer[0] - '0';
if (data->wbuffer[1] == '\n') {
- set_wep_key(ai, index, 0, 0, 1, 1);
+ set_wep_key(ai, index, NULL, 0, 1, 1);
return;
}
j = 2;
}
data->writelen = 0;
data->maxwritelen = 0;
- data->wbuffer = 0;
- data->on_close = 0;
+ data->wbuffer = NULL;
+ data->on_close = NULL;
if (file->f_mode & FMODE_WRITE) {
if (!(file->f_mode & FMODE_READ)) {
static struct net_device_list {
struct net_device *dev;
struct net_device_list *next;
-} *airo_devices = 0;
+} *airo_devices;
/* Since the card doesn't automatically switch to the right WEP mode,
we will make it do it. If the card isn't associated, every secs we
break;
case AUTH_SHAREDKEY:
if (apriv->keyindex < auto_wep) {
- set_wep_key(apriv, apriv->keyindex, 0, 0, 0, 0);
+ set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0);
apriv->config.authType = AUTH_SHAREDKEY;
apriv->keyindex++;
} else {
/* Drop to ENCRYPT */
apriv->keyindex = 0;
- set_wep_key(apriv, apriv->defindex, 0, 0, 0, 0);
+ set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0);
apriv->config.authType = AUTH_ENCRYPT;
}
break;
Cmd cmd;
Resp rsp;
- printk(KERN_DEBUG "%s: airo_mpi entering sleep mode (state=%d)\n",
- dev->name, state);
-
if ((ai->APList == NULL) &&
(ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL)
return -ENOMEM;
ai->power = state;
cmd.cmd=HOSTSLEEP;
issuecommand(ai, &cmd, &rsp);
- return 0;
+
+ pci_enable_wake(pdev, state, 1);
+ pci_save_state(pdev, ai->pci_state);
+ return pci_set_power_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;
- int err;
-
- printk(KERN_DEBUG "%s: airo_mpi waking up\n", dev->name);
- if (!ai->power)
- return 0;
+ pci_set_power_state(pdev, 0);
+ pci_restore_state(pdev, ai->pci_state);
+ pci_enable_wake(pdev, ai->power, 0);
if (ai->power > 1) {
- err = reset_mpi_card(dev, 0);
- if (err) {
- printk(KERN_ERR "%s: Error %d resetting on %s()\n",
- dev->name, err, __FUNCTION__);
- return err;
- }
- schedule_timeout (HZ/2);
+ reset_card(dev, 0);
mpi_init_descriptors(ai);
setup_card(ai, dev->dev_addr, 0);
clear_bit(FLAG_RADIO_OFF, &ai->flags);
- clear_bit(FLAG_RADIO_DOWN, &ai->flags);
clear_bit(FLAG_PENDING_XMIT, &ai->flags);
} else {
OUT4500(ai, EVACK, EV_AWAKEN);
* would not work at all... - Jean II
*/
+static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
+{
+ int quality = 0;
+
+ if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
+ if (memcmp(cap_rid->prodName, "350", 3))
+ if (status_rid->signalQuality > 0x20)
+ quality = 0;
+ else
+ quality = 0x20 - status_rid->signalQuality;
+ else
+ if (status_rid->signalQuality > 0xb0)
+ quality = 0;
+ else if (status_rid->signalQuality < 0x10)
+ quality = 0xa0;
+ else
+ quality = 0xb0 - status_rid->signalQuality;
+ }
+ return quality;
+}
+
+#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0)
+#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50);
+
/*------------------------------------------------------------------*/
/*
* Wireless Handler : get protocol name
/* 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, 0, 0, 1, 1);
+ set_wep_key(local, index, NULL, 0, 1, 1);
} else
/* Don't complain if only change the mode */
if(!dwrq->flags & IW_ENCODE_MODE) {
readCapabilityRid(local, &cap_rid, 1);
if (vwrq->disabled) {
- set_bit (FLAG_RADIO_OFF | FLAG_COMMIT, &local->flags);
+ set_bit (FLAG_RADIO_OFF, &local->flags);
+ set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
}
if (vwrq->flags != IW_TXPOW_MWATT) {
range->num_frequency = k;
/* Hum... Should put the right values there */
- range->max_qual.qual = 10;
+ range->max_qual.qual = airo_get_max_quality(&cap_rid);
range->max_qual.level = 0x100 - 120; /* -120 dBm */
range->max_qual.noise = 0;
range->sensitivity = 65535;
/* Experimental measurements - boundary 11/5.5 Mb/s */
/* Note : with or without the (local->rssi), results
* are somewhat different. - Jean II */
- range->avg_qual.qual = 6;
+ range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
if (local->rssi)
range->avg_qual.level = 186; /* -70 dBm */
else
readAPListRid(local, &APList_rid);
readSsidRid(local, &SSID_rid);
- reset_airo_card(dev);
+ if (test_bit(FLAG_MPI,&local->flags))
+ setup_card(local, dev->dev_addr, 1 );
+ else
+ reset_airo_card(dev);
disable_MAC(local, 1);
writeSsidRid(local, &SSID_rid, 1);
writeAPListRid(local, &APList_rid, 1);
/* Separate R/W functions bracket legality here
*/
- if ( com.command <= AIRORRID )
+ if ( com.command == AIRORSWVERSION ) {
+ if (copy_to_user(com.data, swversion, sizeof(swversion)))
+ rc = -EFAULT;
+ else
+ rc = 0;
+ }
+ else if ( com.command <= AIRORRID)
rc = readrids(dev,&com);
- else if ( com.command >= AIROPCAP && com.command <= AIROPLEAPUSR )
+ else if ( com.command >= AIROPCAP && com.command <= (AIROPLEAPUSR+2) )
rc = writerids(dev,&com);
else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART )
rc = flashcard(dev,&com);
{
StatusRid status_rid;
StatsRid stats_rid;
+ CapabilityRid cap_rid;
u32 *vals = stats_rid.vals;
/* Get stats out of the card */
up(&local->sem);
return;
}
+ readCapabilityRid(local, &cap_rid, 0);
readStatusRid(local, &status_rid, 0);
readStatsRid(local, &stats_rid, RID_STATS, 0);
up(&local->sem);
local->wstats.status = status_rid.mode;
/* Signal quality and co. But where is the noise level ??? */
- local->wstats.qual.qual = status_rid.signalQuality;
+ local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
if (local->rssi)
local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
else
{
struct airo_info *local = dev->priv;
- /* Get stats out of the card if available */
- if (down_trylock(&local->sem) != 0) {
- set_bit(JOB_WSTATS, &local->flags);
- wake_up_interruptible(&local->thr_wait);
- } else
- airo_read_wireless_stats(local);
+ if (!test_bit(JOB_WSTATS, &local->flags)) {
+ /* Get stats out of the card if available */
+ if (down_trylock(&local->sem) != 0) {
+ set_bit(JOB_WSTATS, &local->flags);
+ wake_up_interruptible(&local->thr_wait);
+ } else
+ airo_read_wireless_stats(local);
+ }
return &local->wstats;
}
unsigned char *iobuf;
int len;
struct airo_info *ai = dev->priv;
+ Resp rsp;
if (test_bit(FLAG_FLASHING, &ai->flags))
return -EIO;
switch(comp->command)
{
case AIROGCAP: ridcode = RID_CAPABILITIES; break;
- case AIROGCFG: writeConfigRid (ai, 1);
- ridcode = RID_CONFIG; break;
+ case AIROGCFG: ridcode = RID_CONFIG;
+ if (test_bit(FLAG_COMMIT, &ai->flags)) {
+ disable_MAC (ai, 1);
+ writeConfigRid (ai, 1);
+ enable_MAC (ai, &rsp, 1);
+ }
+ break;
case AIROGSLIST: ridcode = RID_SSID; break;
case AIROGVLIST: ridcode = RID_APLIST; break;
case AIROGDRVNAM: ridcode = RID_DRVNAME; break;
return -EFAULT;
return 0;
#endif
- case AIRORRID: ridcode = comp->len; break;
+ case AIRORRID: ridcode = comp->ridnum; break;
default:
return -EINVAL;
break;
* then return it to the user
* 9/22/2000 Honor user given length
*/
- if (comp->command == AIRORRID)
- len = le16_to_cpu(*(unsigned short *)iobuf); /* Yuck! */
- else
- len = comp->len;
+ len = comp->len;
if (copy_to_user(comp->data, iobuf, min(len, (int)RIDSIZE))) {
kfree (iobuf);
case AIROPCAP: ridcode = RID_CAPABILITIES; break;
case AIROPAPLIST: ridcode = RID_APLIST; break;
case AIROPCFG: ai->config.len = 0;
+ clear_bit(FLAG_COMMIT, &ai->flags);
ridcode = RID_CONFIG; break;
case AIROPWEPKEYNV: ridcode = RID_WEP_PERM; break;
case AIROPLEAPUSR: ridcode = RID_LEAPUSERNAME; break;
case AIROPLEAPPWD: ridcode = RID_LEAPPASSWORD; break;
case AIROPWEPKEY: ridcode = RID_WEP_TEMP; writer = PC4500_writerid;
break;
+ case AIROPLEAPUSR+1: ridcode = 0xFF2A; break;
+ case AIROPLEAPUSR+2: ridcode = 0xFF2B; break;
/* this is not really a rid but a command given to the card
* same with MAC off
set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (HZ); /* Added 12/7/00 */
clear_bit (FLAG_FLASHING, &ai->flags);
+ if (test_bit(FLAG_MPI, &ai->flags)) {
+ status = mpi_init_descriptors(ai);
+ if (status != SUCCESS)
+ return status;
+ }
status = setup_card(ai, dev->dev_addr, 1);
if (!test_bit(FLAG_MPI,&ai->flags))